$ ./run ./utils/boot-benchmark/boot-benchmark Warming up the libguestfs cache ... Running the tests ... test version: libguestfs 1.33.28 test passes: 10 host version: Linux moo.home.annexia.org 4.4.4-301.fc23.x86_64 #1 SMP Fri Mar 4 17:42:42 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux host CPU: Intel(R) Core(TM) i7-5600U CPU @ 2.60GHz backend: direct [to change set $LIBGUESTFS_BACKEND] qemu: /home/rjones/d/qemu/x86_64-softmmu/qemu-system-x86_64 [to change set $LIBGUESTFS_HV] qemu version: QEMU emulator version 2.5.94, Copyright (c) 2003-2008 Fabrice Bellard smp: 1 [to change use --smp option] memsize: 500 [to change use --memsize option] append: [to change use --append option] Result: 575.9ms ±5.3ms
There are various tricks here:
- I’m using the (still!) not upstream qemu DMA patches.
- I’ve compiled my own very minimal guest Linux kernel.
- I’m using my nearly upstream
"crypto: Add a flag allowing the self-tests to be disabled at runtime."patch.
- I’ve got two sets of non-upstream libguestfs patches 1, 2
- I am not using libvirt, but if you do want to use libvirt, make sure you use the very latest version since it contains an important performance patch.
I’ve written before about how you can use qemu + gdb to debug a guest. Today I was wondering how I was going to debug a problem in a BIOS option ROM, when Stefan Hajnoczi mentioned this tip: Insert
1: jmp 1b
into the code as a “poor man’s breakpoint”. In case you don’t know what that assembly code does, it causes a jump back (
b) to the previous
1 label. In other words, an infinite loop.
After inserting that into the option ROM, recompiling and rebooting the virtual machine, it hangs in the boot, and hitting
^C in gdb gets me straight to the place where I inserted the loop.
(gdb) target remote localhost:1234 Remote debugging using localhost:1234 0x0000fff0 in ?? () (gdb) set architecture i8086 The target architecture is assumed to be i8086 (gdb) cont Continuing. ^C Program received signal SIGINT, Interrupt. 0x00000045 in ?? () (gdb) info registers eax 0xc100 49408 ecx 0x0 0 edx 0x0 0 ebx 0x0 0 esp 0x6f30 0x6f30 ebp 0x6f30 0x6f30 esi 0x0 0 edi 0x0 0 eip 0x45 0x45 eflags 0x2 [ ] cs 0xc100 49408 ss 0x0 0 ds 0xc100 49408 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb) disassemble 0xc1000,0xc1050 Dump of assembler code from 0xc1000 to 0xc1050: ... 0x000c103c: mov %cs,%ax 0x000c103e: mov %ax,%ds 0x000c1040: mov %esp,%ebp 0x000c1043: cli 0x000c1044: cld 0x000c1045: jmp 0xc1045 0x000c1047: jmp 0xc162c 0x000c104a: sub $0x4,%esp 0x000c104e: mov 0xc(%esp),%eax End of assembler dump.
Look, my infinite loop!
I can then jump over the loop and keep single stepping*:
(gdb) set $eip=0x47 (gdb) si 0x0000062c in ?? () (gdb) si 0x0000062e in ?? () (gdb) si 0x00000632 in ?? ()
I did wonder if I could take Stefan’s idea further and insert an actual breakpoint (
int $3) into the code, but that didn’t work for me.
Note to set breakpoints, the regular gdb
break command doesn’t work. You have to use hardware-assisted breakpoints instead:
(gdb) hbreak *0xc164a Hardware assisted breakpoint 1 at 0xc164a (gdb) cont Continuing. Program received signal SIGTRAP, Trace/breakpoint trap. 0x0000064a in ?? ()
* If you find that single stepping doesn’t work, make sure you are using qemu in TCG mode (
-M accel=tcg), as KVM code apparently cannot be single-stepped.
Almost completely free as in freedom laptop on top, with very non-free laptop underneath:
Only a few notes about this, except the obvious which is you must have an old Thinkpad X60s which you’re prepared to risk bricking:
- The instructions for installing libreboot are incredibly strange, contradictory, and out of date.
- I used: https://en.wikibooks.org/wiki/Libreboot/ThinkPad_X60
- I used these old sources which roughly correspond to the above instructions: https://libreboot.org/release/20140711/
- You need to have Debian installed on the laptop.
- To make it completely free, I will need to dismantle the laptop and replace the wifi card.
22:59 < rjones> well, you know, I actually want some enhancements to /dev/port (on x86) 23:00 < rjones> for example, it's not possible to specify if you want byte/word/.. access 23:00 < rjones> which of course means its not possible to access certain devices which are expecting non-byte- sized reads or writes .. 23:01 < rjones> somehow no one has added these important ioctls to /dev/port in the 20+ years its been around 23:01 < rjones> I suspect because no one has realized the importance of writing device drivers in shell script 23:06 < dmick> where's that vomit emoticon when you need it
Tianocore, the basis for many UEFI firmware implementations, has long been nearly free software. Low level hardware initialization is provided by CPU and motherboard manufacturers as binary blobs, but this part doesn’t matter for virtualization where we don’t need these blobs.