Skip to contentSkip to conversation

Port test suite to multiboot

PATCH In review Avi Kivity 3 participants 16 messages Sep 13, 2009 – Sep 14, 2009

Subsystems (2)
lore
Share & tools
lore

Avi Kivity

author
#0 lore raw

cover Port test suite to multiboot

Currently the test suite uses a custom control program and BIOS as a loader. This is clumsy and annoying to work with.

This patch series ports the test suite to load with the multiboot support provided by qemu -kernel. Test binaries are now ordinary elf objects (though still with the extension .flat). A -test-device option is added to qemu to support output, memory size, and exit. With the exception of exit these can be ported to use existing qemu facilities.

To use the new tests, type

qemu-system-x86_64 -test-device -kernel /path/to/vmexit.flat

Avi Kivity (10):
Add test device for use with the test suite
test: load image immediately after program headers
test: Set up a default stack
test: add multiboot headers to startup files
test: Map 4GB of memory
test: use real APIC instead of fake APIC
test: switch output format to elf
test: Remove smp support from access.c
test: fix realmode test print_serial() direction flag
test: port readmode tests to multiboot

 hw/pc.c                        |   28 ++++++++++++++++++++
 kvm/user/flat.lds              |    4 +--
 kvm/user/test/x86/access.c     |    4 +-
 kvm/user/test/x86/cstart.S     |    9 ++++++
 kvm/user/test/x86/cstart64.S   |   26 +++++++++++++++---
 kvm/user/test/x86/realmode.c   |   54 +++++++++++++++++++++++++++++++--------
 kvm/user/test/x86/realmode.lds |    6 +---
 qemu-options.hx                |    2 +
 vl.c                           |    4 +++
 9 files changed, 111 insertions(+), 26 deletions(-)
author
#1 lore raw

PATCH 1/10 Add test device for use with the test suite

The test device implements:
- a serial port (0xf1)
- an exit port (0xf4)
- a memory size port (0xd1)

It is planned to replace these with the standard serial and firmware configuration ports.

---
 hw/pc.c         |   28 ++++++++++++++++++++++++++++
 qemu-options.hx |    2 ++
 vl.c            |    4 ++++
 3 files changed, 34 insertions(+), 0 deletions(-)
hw/pc.c +28 -0
index 5e384d0..360dbfb 100644
@@ -1116,6 +1116,29 @@ CPUState *pc_new_cpu(const char *cpu_model)
     return env;
 }
 
+static void test_device_serial_write(void *opaque, uint32_t addr, uint32_t data)
+{
+    putchar(data);
+}
+
+static void test_device_exit(void *opaque, uint32_t addr, uint32_t data)
+{
+    exit(data);
+}
+
+static uint32_t test_device_memsize_read(void *opaque, uint32_t addr)
+{
+    return (intptr_t)opaque;
+}
+
+static void create_test_device(ram_addr_t ram_size)
+{
+    register_ioport_write(0xf1, 1, 1, test_device_serial_write, NULL);
+    register_ioport_write(0xf4, 1, 4, test_device_exit, NULL);
+    register_ioport_read(0xd1, 1, 4, test_device_memsize_read,
+                         (void *)(intptr_t)ram_size);
+}
+
 /* PC hardware initialisation */
 static void pc_init1(ram_addr_t ram_size,
                      const char *boot_device,
@@ -1144,6 +1167,11 @@ static void pc_init1(ram_addr_t ram_size,
     BlockDriverState *fd[MAX_FD];
     int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
     void *fw_cfg;
+    extern int testdevice;
+
+    if (testdevice) {
+        create_test_device(ram_size);
+    }
 
     if (ram_size >= 0xe0000000 ) {
         above_4g_mem_size = ram_size - 0xe0000000;
qemu-options.hx +2 -0
index f2e602a..42a3096 100644
@@ -1693,3 +1693,5 @@ DEF("mem-path", HAS_ARG, QEMU_OPTION_mempath,
 DEF("mem-prealloc", 0, QEMU_OPTION_mem_prealloc,
     "-mem-prealloc        preallocate guest memory (use with -mempath)\n")
 #endif
+DEF("test-device", 0, QEMU_OPTION_testdevice,
+    "-test-device         include testsuite support device")
vl.c +4 -0
index 4d186e5..2a3629d 100644
@@ -251,6 +251,7 @@ const char *mem_path = NULL;
 #ifdef MAP_POPULATE
 int mem_prealloc = 1;	/* force preallocation of physical target memory */
 #endif
+int testdevice;
 #ifdef TARGET_ARM
 int old_param = 0;
 #endif
@@ -5559,6 +5560,9 @@ int main(int argc, char **argv, char **envp)
 		mem_prealloc = !mem_prealloc;
 		break;
 #endif
+            case QEMU_OPTION_testdevice:
+                testdevice = 1;
+                break;
             case QEMU_OPTION_name:
                 qemu_name = qemu_strdup(optarg);
 		 {
Signature · 1 line
1.6.1.1
#2 lore raw

Re: [PATCH 01/10] Add test device for use with the test suite

Quoted 13 lines · Avi Kivity

The test device implements:
- a serial port (0xf1)
- an exit port (0xf4)
- a memory size port (0xd1)

+++ b/hw/pc.c

(quoted diff) +5 -0
+    extern int testdevice;
+
+    if (testdevice) {
+        create_test_device(ram_size);
+    }
 

Review

Quoted 10 lines
(quoted diff) +7 -0
+++ b/qemu-options.hx
 
+DEF("test-device", 0, QEMU_OPTION_testdevice,
+    "-test-device         include testsuite support device")
 
+++ b/vl.c
 
+            case QEMU_OPTION_testdevice:
+                testdevice = 1;
+                break;

This is lame, isn't it?
We have qdev now!

Quoted 1 line

From 7c2b03ba5ac73ccf961febb727dc2b28a159c2ed Mon Sep 17 00:00:00 2001

From: Gerd Hoffmann <[email protected]>
Date: Mon, 14 Sep 2009 09:35:15 +0200
Subject: [PATCH] add test device

Don't pollute command line option namespace without reason. Use qdev instead. It is such a nice small example device! Also we have -chardev upstream now which makes it super easy to redirect the output anywhere you want.

-chardev file,path=/log/file/some/where,id=testlog -device testdev,chardev=testlog

---
 Makefile.target |    2 +-
 hw/testdev.c    |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletions(-)
 create mode 100644 hw/testdev.c
Makefile.target +1 -1
index 0fe8b6a..9867cde 100644
@@ -189,7 +189,7 @@ obj-i386-y += fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
 obj-i386-y += cirrus_vga.o apic.o ioapic.o parallel.o acpi.o piix_pci.o
 obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
-obj-i386-y += ne2000-isa.o
+obj-i386-y += ne2000-isa.o testdev.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/isa.o ide/pci.o ide/macio.o
hw/testdev.c new file +55 -0

55 lines not on this page · raw message

Signature · 1 line
1.6.2.5
author
#3 lore raw

Re: [PATCH 01/10] Add test device for use with the test suite

Quoted 2 lines · Gerd Hoffmann

This is lame, isn't it?
We have qdev now!

Yes. But who knows how to use it?

In my defence, this is a temporary hack and is not intended to be merged upstream. The serial device will be replaced by the standard serial port (or virtio-console), memory size by firmware config, and exit port by ACPI shutdown and TBD for the exit code.

Signature · 1 line
error compiling committee.c: too many arguments to function
author
#4 lore raw

Re: [PATCH 01/10] Add test device for use with the test suite

Quoted 5 lines · Avi Kivity
Quoted 2 lines · Gerd Hoffmann

This is lame, isn't it?
We have qdev now!

Yes. But who knows how to use it?

Didn't notice you had a patch there. Thanks. Will repost with your patch.

Signature · 1 line
error compiling committee.c: too many arguments to function
#5 lore raw

Re: [PATCH 01/10] Add test device for use with the test suite

In reply to Avi Kivity
Quoted 10 lines · Avi Kivity

The test device implements:
- a serial port (0xf1)
- an exit port (0xf4)
- a memory size port (0xd1)

It is planned to replace these with the standard serial and firmware configuration ports.

Should be a qdev-based ISA device. Then a new option wouldn't be needed as you could just use -device.

These tests should all be runnable against upstream tcg, no?

Regards,

Anthony Liguori

author
#6 lore raw

Re: [PATCH 01/10] Add test device for use with the test suite

Quoted 6 lines · Anthony Liguori
Quoted 5 lines · Avi Kivity

The test device implements:
- a serial port (0xf1)
- an exit port (0xf4)
- a memory size port (0xd1)

Quoted 6 lines
Quoted 4 lines

It is planned to replace these with the standard serial and firmware configuration ports.

Should be a qdev-based ISA device. Then a new option wouldn't be needed as you could just use -device.

It really shouldn't be at all. It's for transition only.

Quoted 1 line

These tests should all be runnable against upstream tcg, no?

Yes, and I plan to eventually submit them against qemu upstream. Note the access test fails, though it might be due to the test itself, not qemu.

Signature · 1 line
error compiling committee.c: too many arguments to function
author
#7 lore raw

PATCH 2/10 test: load image immediately after program headers

In reply to Avi Kivity

Otherwise, ld places the image somewhere where multiboot can't find the multiboot headers.

---
 kvm/user/flat.lds |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kvm/user/flat.lds +1 -1
index 61f1057..d61bec3 100644
@@ -2,7 +2,7 @@ OUTPUT_FORMAT(binary)
 
 SECTIONS
 {
-    . = 1M;
+    . = 4M + SIZEOF_HEADERS;
     stext = .;
     .text : { *(.init) *(.text) *(.text.*) }
     . = ALIGN(4K);
Signature · 1 line
1.6.1.1
author
#8 lore raw

PATCH 3/10 test: Set up a default stack

In reply to Avi Kivity

multiboot doesn't give us any stack, so we need to set one up.

---
 kvm/user/test/x86/cstart64.S |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
kvm/user/test/x86/cstart64.S +1 -0
index 432a3dc..4f116f9 100644
@@ -69,6 +69,7 @@ tss_end:
 .section .init
 
 .code32
+	mov $stacktop, %esp
 	call prepare_64
 	jmpl $8, $start64
 
Signature · 1 line
1.6.1.1
author
#9 lore raw

PATCH 4/10 test: add multiboot headers to startup files

In reply to Avi Kivity

With these headers, multiboot can launch us directly in protected mode.

---
 kvm/user/test/x86/cstart.S   |    9 +++++++++
 kvm/user/test/x86/cstart64.S |    9 +++++++++
 2 files changed, 18 insertions(+), 0 deletions(-)
kvm/user/test/x86/cstart.S +9 -0
index 69a6262..0471b92 100644
@@ -3,6 +3,15 @@
 .bss
 
 .section .init
+
+mb_magic = 0x1BADB002
+mb_flags = 0x0
+
+	# multiboot header
+	.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
+
+.globl start
+start:
 	call main
 	push %eax
 	call exit
kvm/user/test/x86/cstart64.S +9 -0
index 4f116f9..805938b 100644
@@ -69,6 +69,15 @@ tss_end:
 .section .init
 
 .code32
+
+mb_magic = 0x1BADB002
+mb_flags = 0x0
+
+	# multiboot header
+	.long mb_magic, mb_flags, 0 - (mb_magic + mb_flags)
+
+.globl start
+start:
 	mov $stacktop, %esp
 	call prepare_64
 	jmpl $8, $start64
Signature · 1 line
1.6.1.1
author
#10 lore raw

PATCH 5/10 test: Map 4GB of memory

In reply to Avi Kivity

Needed so the APIC can be accessed at address 0xfee00000.

---
 kvm/user/test/x86/cstart64.S |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)
kvm/user/test/x86/cstart64.S +5 -2
index 805938b..3f193a3 100644
@@ -22,14 +22,17 @@ ring0stacktop:
 .align 4096
 ptl2:
 i = 0
-	.rept 512
+	.rept 512 * 4
 	.quad 0x1e7 | (i << 21)
 	i = i + 1
 	.endr
 
 .align 4096
 ptl3:
-	.quad ptl2 + 7
+	.quad ptl2 + 7 + 0 * 4096
+	.quad ptl2 + 7 + 1 * 4096
+	.quad ptl2 + 7 + 2 * 4096
+	.quad ptl2 + 7 + 3 * 4096
 
 .align 4096
 ptl4:
Signature · 1 line
1.6.1.1
author
#11 lore raw

PATCH 6/10 test: use real APIC instead of fake APIC

In reply to Avi Kivity

smp temporarily disabled

---
 kvm/user/test/x86/cstart64.S |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)
kvm/user/test/x86/cstart64.S +6 -3
index 3f193a3..912bcf8 100644
@@ -1,5 +1,5 @@
 
-#include "fake-apic.h"
+#include "apic.h"
 
 boot_idt = 0
 
@@ -131,8 +131,9 @@ start64:
 load_tss:
 	mov $0, %eax
 	mov %ax, %ss
-	mov $(APIC_BASE + APIC_REG_ID), %dx
-	in %dx, %eax
+	mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
+	mov (%rax), %eax
+	shr $24, %eax
 	mov %eax, %ebx
 	shl $4, %ebx
 	mov $((tss_end - tss) / max_cpus), %edx
@@ -150,6 +151,7 @@ load_tss:
 	ret
 
 smp_init:
+#if 0
 	lea boot_idt + ipi_vector * 8, %rdi
 	mov $smp_init_ipi, %eax
 	mov %ax, (%rdi)
@@ -178,4 +180,5 @@ smp_loop:
 	inc %esi
 	jmp smp_loop
 smp_init_done:
+#endif
 	ret
Signature · 1 line
1.6.1.1
author
#12 lore raw

PATCH 7/10 test: switch output format to elf

In reply to Avi Kivity

This can be loaded by multiboot (qemu -kernel ...)

---
 kvm/user/flat.lds |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)
kvm/user/flat.lds +0 -2
index d61bec3..4120595 100644
@@ -1,5 +1,3 @@
-OUTPUT_FORMAT(binary)
-
 SECTIONS
 {
     . = 4M + SIZEOF_HEADERS;
Signature · 1 line
1.6.1.1
author
#13 lore raw

PATCH 8/10 test: Remove smp support from access.c

In reply to Avi Kivity

Doesn't do anthing anyway.

---
 kvm/user/test/x86/access.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
kvm/user/test/x86/access.c +2 -2
index 272a4ef..5eadff8 100644
@@ -1,6 +1,7 @@
 
 #include "libcflat.h"
-#include "smp.h"
+
+#define smp_id() 0
 
 #define true 1
 #define false 0
@@ -598,7 +599,6 @@ int main()
     int r;
 
     printf("starting test\n\n");
-    smp_init((void(*)(void))ac_test_run);
     r = ac_test_run();
     return r ? 0 : 1;
 }
Signature · 1 line
1.6.1.1
author
#14 lore raw

PATCH 9/10 test: fix realmode test print_serial() direction flag

In reply to Avi Kivity

Clear the direction flag to get the correct output.

---
 kvm/user/test/x86/realmode.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kvm/user/test/x86/realmode.c +1 -1
index 0db09b8..f9e303f 100644
@@ -26,7 +26,7 @@ static void print_serial(const char *buf)
 {
 	unsigned long len = strlen(buf);
 
-	asm volatile ("addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
+	asm volatile ("cld; addr32/rep/outsb" : "+S"(buf), "+c"(len) : "d"(0xf1));
 }
 
 static void exit(int code)
Signature · 1 line
1.6.1.1
author
#15 lore raw

PATCH 10/10 test: port readmode tests to multiboot

In reply to Avi Kivity
---
 kvm/user/test/x86/realmode.c   |   52 ++++++++++++++++++++++++++++++++-------
 kvm/user/test/x86/realmode.lds |    6 +----
 2 files changed, 43 insertions(+), 15 deletions(-)
kvm/user/test/x86/realmode.c +42 -10
index f9e303f..9bf6cb0 100644
@@ -549,7 +549,7 @@ void test_null(void)
 		print_serial("null test: FAIL\n");
 }
 
-void start(void)
+void realmode_start(void)
 {
 	test_null();
 
@@ -570,23 +570,55 @@ void start(void)
 	exit(0);
 }
 
+unsigned long long r_gdt[] = { 0, 0x9b000000ffff, 0x93000000ffff };
+
+struct __attribute__((packed)) {
+	unsigned short limit;
+	void *base;
+} r_gdt_descr = { sizeof(r_gdt) - 1, &r_gdt };
+
 asm(
+	".section .init \n\t"
+
+	".code32 \n\t"
+
+	"mb_magic = 0x1BADB002 \n\t"
+	"mb_flags = 0x0 \n\t"
+
+	"# multiboot header \n\t"
+	".long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) \n\t"
+
+	".globl start \n\t"
 	".data \n\t"
 	". = . + 4096 \n\t"
 	"stacktop: \n\t"
+
 	".text \n\t"
-	"init: \n\t"
+	"start: \n\t"
+	"lgdt r_gdt_descr \n\t"
+	"ljmp $8, $1f; 1: \n\t"
+	".code16gcc \n\t"
+	"mov $16, %eax \n\t"
+	"mov %ax, %ds \n\t"
+	"mov %ax, %es \n\t"
+	"mov %ax, %fs \n\t"
+	"mov %ax, %gs \n\t"
+	"mov %ax, %ss \n\t"
+	"mov %cr0, %eax \n\t"
+	"btc $0, %eax \n\t"
+	"mov %eax, %cr0 \n\t"
+	"ljmp $0, $realmode_entry \n\t"
+
+	"realmode_entry: \n\t"
+
 	"xor %ax, %ax \n\t"
 	"mov %ax, %ds \n\t"
 	"mov %ax, %es \n\t"
 	"mov %ax, %ss \n\t"
-	"mov $0x4000, %cx \n\t"
-	"xor %esi, %esi \n\t"
-	"mov %esi, %edi \n\t"
-	"rep/addr32/cs/movsl \n\t"
+	"mov %ax, %fs \n\t"
+	"mov %ax, %gs \n\t"
 	"mov $stacktop, %sp\n\t"
-	"ljmp $0, $start \n\t"
-	".pushsection .boot, \"ax\" \n\t"
-	"ljmp $0xf000, $init \n\t"
-	".popsection"
+	"ljmp $0, $realmode_start \n\t"
+
+	".code16gcc \n\t"
 	);
kvm/user/test/x86/realmode.lds +1 -5
index c9cdd7d..c7386b8 100644
@@ -1,16 +1,12 @@
-OUTPUT_FORMAT(binary)
-
 SECTIONS
 {
-    . = 0;
+    . = 16K;
     stext = .;
     .text : { *(.init) *(.text) }
     . = ALIGN(4K);
     .data : { *(.data) *(.rodata*) }
     . = ALIGN(16);
     .bss : { *(.bss) }
-    . = 0xfff0;
-    .boot : { *(.boot) }
     edata = .;
 }
 
Signature · 1 line
1.6.1.1