Posts Tagged ‘qemu’

Summer is over, so put away the white pants and start submitting patches!

Thursday, September 10th, 2009

It’s been a while since my last update. What can I say… summer was nice.

But now, back to business! I’ve just committed some long overdue patches to the upstream GNU tools:

This gets us to booting the kernel, loading BusyBox, running some shell code and… crashing on the first fork. No problemo. Nothing a small matter of programming can’t fix. However, there are some other distractions…

Verilog is lots of fun! It looks like regular programming, but it feels more like building a kinetic sculpture.

There’s also the small matter of not having an interrupt controller! So there’s some work here to design an interrupt controller, implement it in verilog, simulate it qemu (and possibly the gdb sim), and port the kernel over to using it. This should be interesting…

Kernel update: device trees and kernel threads

Saturday, July 25th, 2009

I’ve spent a lot of time in airports/planes/hotels recently, which is good news for the moxie linux port. It runs about 6.5M instructions, booting up to the point where a couple of kernel threads are created. However, a few context switches later it all comes tumbling down. I didn’t have any of my kernel books with me, so I stopped hacking at that point rather than try to guess/decode how some of the internals are supposed to work.

My port is using a device tree to describe the system architecture. This makes it easier to build a single kernel image that can boot on multiple moxie implementations. There’s a good paper on this relatively new infrastructure here: http://ols.fedoraproject.org/OLS/Reprints-2008/likely2-reprint.pdf. If you’ve been following this project, you may recall that console I/O is implemented differently on the gdb and qemu simulators. For the gdb simulator we use a software interrupt instruction (swi) to escape to the simulator, but the qemu port uses a real simulated serial device. This means they need different console devices in the kernel to print boot messages. The device tree is a nice way to describe differences like this and have a single kernel image to boot in both environments.

Also, as predicted, I actually used moxie gdb’s reverse debugging feature to help debug my kernel bring-up. It was really useful a couple of times and has probably saved me the amount of effort required to implement it in the first place already!

The next week is going to be very busy for me, so I don’t expect to get much done. We’ll see…

Quick update…

Wednesday, April 29th, 2009

A few quick MoxieDev updates…

  • The verilog output patch is in binutils
  • The moxie ports for binutils, newlib, libgloss and gdb are all upstream. Waiting on sim and gcc reviews.
  • The upstream qemu team have switched to git, so I’ve rebased MoxieDev’s qemu against this new repository.

Also, I’ve been reading the new OpenSPARC Internals book. It’s not quite what I was hoping it would be, but Chapter 7, OpenSPARC Design Verification Methodology, is fantastic. You can download it for free from this page.

I, however, bought this book from Amazon. And what’s interesting here is that it was printed by Bob Young‘s self-publishing startup, Lulu. It looks/smells/feels like a real book. I don’t know why I find this amazing, but I do. Bravo Bob!

Adding a Real Time Clock

Tuesday, March 17th, 2009

After a UART, one of the most useful and interesting peripherals you can add to a board is a Real Time Clock (RTC). Qemu comes with a simulation of Freescale’s MC146818 RTC chip. Adding it to our qemu-defined board was as simple as….


   rtc_mm_init(0x400, 0, 0, 0);

This makes the MC146818 available as a memory mapped port at 0x400 on our target board. The simplest way to use this is to implement a qemu specific time() function in the qemu BSP that pulls the current time from the 0x400-mapped port. I won’t include the code here, but it’s quite simple, and found in
moxiedev/src/libgloss/moxie/qemu-time.c. Now functions like gettimeofday() work as expected, making the whole platform a little more real.

After an RTC, I think the next most interesting peripheral is an interrupt controller, but this will require more thought about the system architecture and how moxie will handle exceptions.

Board Support Packages

Tuesday, March 17th, 2009

Today we’re introducing the notion of Board Support Packages (BSPs) to the moxie toolchain.

A BSP provides all of the configuration data and code requires to target a specific hardware platform. This mostly involves linker scripts, platform initialization code, and hardware abstraction support libraries.

Until recently the gdb sim was our only target platform. Now we also have qemu, which needs to use an alternate _write implementation in order to send output to a memory mapped UART. What we really need to do is to define a “qemu” BSP that targets the default “board” defined in qemu. This BSP will provide a support library with the UART version of _write, and the original gdb sim version will live in a “sim” BSP.

In the world of the GNU toolchain, BSPs live in libgloss. The libgloss tree now contains BSP specific linker scripts which you must use in order to pull in either of the BSP support libraries needed by newlib. So if you want to target qemu, you run…

$ moxie-elf-gcc -o hello.x hello.c -Tqemu.ld

..and if you want to target the gdb sim, you have to go…

$ moxie-elf-gcc -o hello.x hello.c -Tsim.ld

This will make more sense down the line as we add more target boards with different memory maps and peripherals.

Speaking of peripherals…. I’ve also added a Real Time Clock device to the qemu board definition which I’ll talk about in my next posting.

Debugging with the moxie qemu simulator

Saturday, March 14th, 2009

I’ve finally cracked the gdb+qemu puzzle, so now we can debug code running on the qemu moxie simulator!

The last little gotcha was that the simulated $pc wasn’t being updated after single-stepping. This will get you nowhere fast! But it’s all fixed now, and here’s how it works…

$ qemu-system-moxie -s -S -kernel hello.x

This tells qemu to load our hello world program, hello.x. The “-s” option tells it to wait for a connection from GDB on port 1234. The -S option tells it to freeze on startup, and wait for a “continue” command from the debugger.

Now, in a different terminal, fire up moxie-elf-gdb on hello.x and connect to qemu like so:

(gdb) target remote localhost:1234

GDB and qemu should be talking now, and the debugger will report that the sim is waiting on __start, the entry point to our hello.x ELF file. Put a breakpoint on main, and hit ‘c’ to continue. You should be debugging as usual now. I normally run moxie-elf-gdb within emacs in order to get a nice UI, but invoking it from ddd or Eclipse should work just as well.

Everything has been committed MoxieDev. Now it’s time to enjoy this sunny day!

Progress…

Thursday, March 12th, 2009

I made some progress on using moxie-elf-gdb with qemu the other day. Qemu has an integrated gdb stub, so GDB speaks to it via the remote protocol. It’s still not quite there, but getting close. I’m anxious to get it working, as it’s the last step before hacking on the Linux kernel port.

I’ve also tweaked the “ant srpm” target, so it creates clean SRPMs for binutils, newlib, gcc, gdb and qemu. Well, sort of. When building GCC from scratch you actually have to build it twice: once to build newlib, and the second time with the installed newlib. This is easy enough to handle in MoxieDev where I have a single tree and full control over the build sequence. It’s a little bit weirder in RPM-land because of the circular dependencies between packages. I was able to bootstrap it on my system, but it’s a hack. I may resort to merging the newlib sources into the GCC SPRM, and then make newlib a subpackage of gcc. Release engineering is the suck!

And, finally, I’ve merged the latest and greatest trunk revisions of gcc and src into MoxieDev. Woooo – it all still works! Check out the commit logs in the blog sidebar.

Qemu says Hello, World!

Saturday, March 7th, 2009

Virtually all of the simulation done so far was with the GDB instruction set simulator. As a basic instruction set simulator, it was limited to executing instructions found in typical “user level” applications. And, if you recall, all interaction with the outside world happened through magic software interrupts that were intercepted by the simulator. I wrote about this interaction way back here: http://spindazzle.org/greenblog/index.php?/archives/107-ggx-Hello-World!.html.

Instruction set simulators are interesting for one reason: they’re easy to write! It’s simple to whip up a sim in the early stages of toolchain development in order to test your tools. In fact, almost every GCC port has a corresponding instruction set simulator to test the compiler’s output. On the other hand, the basic instruction set simulator is not capable of running more interesting software, like operating system kernels, because they don’t simulate any of the ancillary features of a microprocessor: peripherals, timers, interrupt controllers, MMUs, etc. This is where system simulators come into play.

For the moxie toolchain, I’ve selected the popular qemu simulator. Several months ago I wrote about my start with qemu here: http://spindazzle.org/greenblog/index.php?/archives/123-qemu-ggx-softmmu-starts-crawling.html. Well, a lot of that work had to be rewritten for the new qemu (version 0.10 was just released last week). Qemu switched from a simple template compiler to using a real C compiler backend from the Tiny C Compiler project. The template compiler (dyngen) stitched together fragments of pre-compiled code at runtime, while the new TCG backend is a proper x86 compiler with simple optimization passes.

In practice, this wasn’t a huge amount of work. The translator still looks like a huge switch statement where we handle each opcode. For instance, here’s a register-to-register move:


 case 0x02:  /* mov (register-to-register) */
   {
     int dest = (opcode >> 4) & 0xf;
     int src = opcode & 0xf;
     tcg_gen_mov_i32(REG(dest), REG(src));
   }

tcg_gen_mov_i32 generates the intermediate code to move the value between registers.

Once I had implemented support for enough instructions, I was able to run a trivial Hello World program straight through:

$ cat hello.c
#include <stdio.h>

int main()
{
  puts ("Hello World!");
  return 0;
}
$ moxie-elf-gcc -o hello.x hello.c
$ qemu-system-moxie -nographic -kernel hello.x
qemu: fatal: Trying to execute code outside RAM or ROM at 0x00000000

pc=0x00000000
$fp=0x00000000 $sp=0x0000000c $r0=0x00000001 $r1=0x000055c4
$r2=0x00000000 $r3=0x00000000 $r4=0x001ffff4 $r5=0x00000000
$r6=0x00000000 $r7=0x00000000 $r8=0x00000000 $r9=0x00000000
$r10=0x00000000 $r11=0x00000000 $r12=0x00000000 $r13=0xfffffff4
Aborted


Oops. Two problems: no “Hello, World” output and the fatal error. The fatal error is simple to explain. The moxie qemu port defines a virtual hardware platform, with physical memory mapped way up at 0×8000000. Somehow the simulator is trying to execute code outside of our physical memory range. The reason turns out to be simple. Unlike our simple instruction set simulator, system simulators like qemu don’t expect to run programs that “exit”. They’re designed to run operating systems that start running and never finish. If you look carefully above you’ll see that I’m asking qemu to run a “kernel” called hello.x. Well, hello.x is actually just a regular user program that exits. In this case, the processor is running off of the end of the __init entry point and pulling an uninitialized return address off of the stack, sending us off to execute code at 0×00000000.

But where is “Hello, World”? We’re still linking in libgloss, which is trying to “_write” output with our special software interrupt. That’s not going to work here. We don’t want to implement magic IO in a system simulator. We want to simulate real IO! One of the beautiful things about qemu is that it comes with a wealth of simulated peripherals that you can hook up to your processor. So, for now, let’s just send all output to a simulated serial port. Qemu makes this very simple. In the module that defines our hardware platform, we just add:

    /* A single 16450 sits at offset 0x3f8.  */
    if (serial_hds[0])
      serial_mm_init(0x3f8, 0, env->irq[4], 8000000/16, serial_hds[0], 1);


Now we just have to override the _write in libgloss to write to the 16450 UART which has been mapped to memory at 0x3f8. Qemu’s default setting has all serial port output going to the console. So now….

$ cat hello.c
#include <stdio.h>

int _write (int fd, char *buf, int len)
{
  int i = 0;
  while (i < len)
    *(char *)0x3f8 = buf[i++];
  return len;
}

int main()
{
  puts ("Hello World!");
  return 0;
}
$ moxie-elf-gcc -o hello.x hello.c
$ ./qemu-system-moxie -nographic -kernel hello.x
Hello World!qemu: fatal: Trying to execute code outside RAM or ROM at 0x00000000

pc=0x00000000
$fp=0x00000000 $sp=0x0000000c $r0=0x00000001 $r1=0x000055c4
$r2=0x00000000 $r3=0x00000000 $r4=0x001ffff4 $r5=0x00000000
$r6=0x00000000 $r7=0x00000000 $r8=0x00000000 $r9=0x00000000
$r10=0x00000000 $r11=0x00000000 $r12=0x00000000 $r13=0xfffffff4
Aborted

Very nice!