Hi,
Played around a bit with kvmtool. Got annonyed because you can't just pass it a guest image to boot from. Decided to check what it takes to run seabios in kvmtool, so it can load the guest kernel from the disk image. So, here are the results ...
There isn't much work involved at the seabios side. Add a new config option. Tweak kconfig. Some basic windup on the code. Loads kernel from disk. Yea! Success!
Well. That only uncovers a bunch of issues in kvmtool ...
(1) There seems to be no way to figure the amout of memory available. For now I've hardcoded 128 MB in seabios. See patch #3.
(2) Something corrupts virtio rings. Not clear yet whenever seabios or kvmtool is at fault here. See patch #7.
(3) kvmtool doesn't emulate a pci host bridge. Linux kernel is unhappy and throws an error on pci initialization. kvmtool tackles that by appending "pci=conf1" to the command line when booting a kernel directly. Which of course doesn't fly if you wanna boot the fedora cloud image downloaded from the internet as-is. Booting the image once in qemu to tweak the boot loader config gets over it.
(4) Linux kernel fails on virtio-blk initialization. Bummer. /me suspects kvmtool doesn't implement proper virtio device reset, so the device handover from seabios to linux kernel doesn't work.
So, the kernel boots fine but fails to mount the root filesystem. After a while dracut decides to not wait any longer for the root filesystem to show up and drops into the emergency shell, where you can play around a bit.
enjoy, Gerd
Patches also available in the git repository at:
git://git.kraxel.org/seabios kvmtool
---------------------------------------------------------------- Gerd Hoffmann (7): kvmtool: initial support kvmtool: tweak kconfig for emulated hardware kvmtool: add (fake) ram detection kvmtool: detect pci devices kvmtool: uses mmio for legacy bar 0 kvmtool: no keyboard, don't need boot menu kvmtool: support larger virtio queues
Makefile | 1 + src/Kconfig | 24 ++++++++++++++++++++++-- src/fw/paravirt.c | 20 ++++++++++++++++++++ src/fw/paravirt.h | 3 +++ src/hw/virtio-pci.c | 11 ++++++++--- src/hw/virtio-ring.h | 2 +- src/post.c | 4 +++- 7 files changed, 58 insertions(+), 7 deletions(-)
Add CONFIG_KVMTOOL, some initial preparations so seabios at least prints some debug messages on the serial line.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- Makefile | 1 + src/Kconfig | 7 +++++++ src/post.c | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index e287530..d7053a6 100644 --- a/Makefile +++ b/Makefile @@ -87,6 +87,7 @@ endif
target-y := target-$(CONFIG_QEMU) += $(OUT)bios.bin +target-$(CONFIG_KVMTOOL) += $(OUT)bios.bin target-$(CONFIG_CSM) += $(OUT)Csm16.bin target-$(CONFIG_COREBOOT) += $(OUT)bios.bin.elf target-$(CONFIG_BUILD_VGABIOS) += $(OUT)vgabios.bin diff --git a/src/Kconfig b/src/Kconfig index 14c38fb..7620067 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -25,6 +25,12 @@ choice Configure to be used by EFI firmware as Compatibility Support module (CSM) to provide legacy BIOS services.
+ config KVMTOOL + bool "Build for kvmtool" + select DEBUG_SERIAL + help + Configure for an emulated machine (kvmtool). + endchoice
config QEMU_HARDWARE @@ -130,6 +136,7 @@ endchoice
config ROM_SIZE int "ROM size (in KB)" + default 128 if KVMTOOL default 0 help Set the ROM size. Say '0' here to make seabios figure the diff --git a/src/post.c b/src/post.c index 6157b50..65a3c9c 100644 --- a/src/post.c +++ b/src/post.c @@ -327,7 +327,7 @@ dopost(void) void VISIBLE32FLAT handle_post(void) { - if (!CONFIG_QEMU && !CONFIG_COREBOOT) + if (!CONFIG_QEMU && !CONFIG_COREBOOT && !CONFIG_KVMTOOL) return;
serial_debug_preinit();
Disable stuff not emulated by kvmtool, no need to waste time and code for that.
Enable virtio-blk and virtio-scsi.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/Kconfig | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig index 7620067..2bb90c0 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -151,6 +151,7 @@ endmenu menu "Hardware support" config ATA depends on DRIVES + depends on !KVMTOOL bool "ATA controllers" default y help @@ -169,6 +170,7 @@ menu "Hardware support" Use 32bit PIO accesses on ATA (minor optimization on PCI transfers). config AHCI depends on DRIVES + depends on !KVMTOOL bool "AHCI controllers" default y help @@ -180,13 +182,13 @@ menu "Hardware support" help Support for SD cards on PCI host controllers. config VIRTIO_BLK - depends on DRIVES && QEMU_HARDWARE + depends on DRIVES && (QEMU_HARDWARE || KVMTOOL) bool "virtio-blk controllers" default y help Support boot from virtio-blk storage. config VIRTIO_SCSI - depends on DRIVES && QEMU_HARDWARE + depends on DRIVES && (QEMU_HARDWARE || KVMTOOL) bool "virtio-scsi controllers" default y help @@ -217,12 +219,14 @@ menu "Hardware support" Support boot from qemu-emulated lsi53c895a scsi storage. config MEGASAS depends on DRIVES + depends on !KVMTOOL bool "LSI MegaRAID SAS controllers" default y help Support boot from LSI MegaRAID SAS scsi storage. config FLOPPY depends on DRIVES + depends on !KVMTOOL bool "Floppy controller" default y help @@ -230,6 +234,7 @@ menu "Hardware support"
config PS2PORT depends on KEYBOARD || MOUSE + depends on !KVMTOOL bool "PS/2 port" default y help @@ -237,6 +242,7 @@ menu "Hardware support"
config USB bool "USB" + depends on !KVMTOOL default y help Support USB devices. @@ -323,6 +329,7 @@ menu "Hardware support" help Initialize the Memory Type Range Registers (on emulators). config PMTIMER + depends on !KVMTOOL bool "Use ACPI timer" default y help @@ -367,6 +374,7 @@ menu "BIOS interfaces" config OPTIONROMS bool "Option ROMS" default y + depends on !KVMTOOL help Support finding and running option roms during POST. config OPTIONROMS_DEPLOYED @@ -437,6 +445,7 @@ menu "BIOS interfaces"
config TCGBIOS depends on S3_RESUME + depends on !KVMTOOL bool "TPM support and TCG BIOS extensions" default y help @@ -464,6 +473,7 @@ menu "BIOS Tables" sometimes called DMI. config ACPI bool "ACPI" + depends on !KVMTOOL default y help Support generation of ACPI tables.
FIXME. No idea how to figure how much ram we have.
For now claim we have 128 MB. That is the minimum kvmtool uses if you don't specify something via -m (if I read the code correctly). So things should at least work, even though we might leave memory unused.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/fw/paravirt.c | 11 +++++++++++ src/fw/paravirt.h | 2 ++ src/post.c | 1 + 3 files changed, 14 insertions(+)
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index db22ae8..efd9848 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -446,3 +446,14 @@ void qemu_cfg_init(void) dprintf(1, "Moving pm_base to 0x%x\n", acpi_pm_base); } } + +void +kvmtool_preinit(void) +{ + if (!CONFIG_KVMTOOL) + return; + + /* FIXME: claim we have 128 MB */ + RamSize = 128 * 1024 * 1024; + add_e820(0, RamSize, E820_RAM); +} diff --git a/src/fw/paravirt.h b/src/fw/paravirt.h index 95ffb92..7caca4d 100644 --- a/src/fw/paravirt.h +++ b/src/fw/paravirt.h @@ -34,4 +34,6 @@ void qemu_preinit(void); void qemu_platform_setup(void); void qemu_cfg_init(void);
+void kvmtool_preinit(void); + #endif diff --git a/src/post.c b/src/post.c index 65a3c9c..36cc5d7 100644 --- a/src/post.c +++ b/src/post.c @@ -314,6 +314,7 @@ dopost(void) { // Detect ram and setup internal malloc. qemu_preinit(); + kvmtool_preinit(); coreboot_preinit(); malloc_preinit();
Make a pci bus scan, so we find the virtio devices. Tested with virtio-blk only (kvmtool uses that by default).
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/fw/paravirt.c | 9 +++++++++ src/fw/paravirt.h | 1 + src/post.c | 1 + 3 files changed, 11 insertions(+)
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index efd9848..28d47d2 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -457,3 +457,12 @@ kvmtool_preinit(void) RamSize = 128 * 1024 * 1024; add_e820(0, RamSize, E820_RAM); } + +void +kvmtool_platform_setup(void) +{ + if (!CONFIG_KVMTOOL) + return; + + pci_probe_devices(); +} diff --git a/src/fw/paravirt.h b/src/fw/paravirt.h index 7caca4d..3078af6 100644 --- a/src/fw/paravirt.h +++ b/src/fw/paravirt.h @@ -35,5 +35,6 @@ void qemu_platform_setup(void); void qemu_cfg_init(void);
void kvmtool_preinit(void); +void kvmtool_platform_setup(void);
#endif diff --git a/src/post.c b/src/post.c index 36cc5d7..f6b8b8e 100644 --- a/src/post.c +++ b/src/post.c @@ -173,6 +173,7 @@ platform_hardware_setup(void)
// Platform specific setup qemu_platform_setup(); + kvmtool_platform_setup(); coreboot_platform_setup();
// Initialize TPM
Hmm. Doesn't match virtio spec. But easy to check and handle.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/hw/virtio-pci.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/hw/virtio-pci.c b/src/hw/virtio-pci.c index 6df5194..465deb9 100644 --- a/src/hw/virtio-pci.c +++ b/src/hw/virtio-pci.c @@ -267,9 +267,14 @@ void vp_init_simple(struct vp_device *vp, struct pci_device *pci) dprintf(1, "pci dev %x:%x using legacy (0.9.5) virtio mode\n", pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf)); vp->legacy.bar = 0; - vp->legacy.addr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) & - PCI_BASE_ADDRESS_IO_MASK; - vp->legacy.is_io = 1; + addr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0); + if (addr & PCI_BASE_ADDRESS_SPACE_IO) { + vp->legacy.addr = addr & PCI_BASE_ADDRESS_IO_MASK; + vp->legacy.is_io = 1; + } else { + vp->legacy.addr = addr & PCI_BASE_ADDRESS_MEM_MASK; + vp->legacy.is_io = 0; + } }
vp_reset(vp);
seabios uses the serial line one-way. Only debug output, no keyboard input. So the boot menu is pointless, you can't pick something anyway. So turn it off.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/Kconfig | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/src/Kconfig b/src/Kconfig index 2bb90c0..74d93bb 100644 --- a/src/Kconfig +++ b/src/Kconfig @@ -61,18 +61,21 @@ endchoice
config BOOTMENU depends on BOOT + depends on !KVMTOOL bool "Bootmenu" default y help Support an interactive boot menu at end of post. config BOOTSPLASH depends on BOOTMENU + depends on !KVMTOOL bool "Graphical boot splash screen" default y help Support showing a graphical boot splash screen. config BOOTORDER depends on BOOT + depends on !KVMTOOL bool "Boot ordering" default y help
They have 256 entries on kvmtool, support that. Need more memory for virtqueues now. But with the move to 32bit drivers this should not be a big issue.
FIXME: Must bump to 260 to make things actually work. There seems to be some corruption otherwise and kvmtool complains about invalid requests. Not yet debugged who is at fault here.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/hw/virtio-ring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/hw/virtio-ring.h b/src/hw/virtio-ring.h index 7df9004..3a143e0 100644 --- a/src/hw/virtio-ring.h +++ b/src/hw/virtio-ring.h @@ -28,7 +28,7 @@ /* v1.0 compliant. */ #define VIRTIO_F_VERSION_1 32
-#define MAX_QUEUE_NUM (128) +#define MAX_QUEUE_NUM (260)
#define VRING_DESC_F_NEXT 1 #define VRING_DESC_F_WRITE 2