Skip to contentSkip to conversation

Test framwork ported to qemu -kernel

PATCH New Avi Kivity 1 participant 35 messages Sep 16, 2009

Subsystems (2)
lore
Share & tools
lore

Avi Kivity

author
#0 lore raw

cover Test framwork ported to qemu -kernel

This patchset ports the test framework to qemu's multiboot support with -kernel. You can now run tests using the following command:

qemu -chardev stdio,id=test -device testdev,chardev=test
-kernel kvm/user/test/x86/apic.flat

the test device is transitional an I plan to remove it in the future, replacing it with native qemu devices.

Avi Kivity (33):
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
test: Allow adding mode vmexit latency tests
test: Add vmcall latency test
test: add cr8 latency tests
test: Mask PIC interrupts before APIC test
test-device: add support for irq injection
test: Use function table for APIC access
test: use new apic_icr_write() to issue IPI
test: add x2apic test
test: add support for the firmware configuration interface
test: Add fwcfg interface for getting the cpu count
test: vm: map mmio 1:1
test: apic: use 1:1 mapping for apic
test: Move apic functions to libcflat
test: switch 64-bit smp startup to real APIC
test: add apic_id() accessor
test: Use xapic_write() to enable xapic()
test: initialize idt on all processors
test: initialize apic/x2apic on all processors
test: wait for all processors to complete initialization
test: port smp runtime to real apic
test: drop irq.flat
test: fix autodependencies
test: Fix compilation rule for assembly files wrt autodependencies
test: avoid deleting intermediate .o files

Gerd Hoffmann (1):
Add test device

 Makefile.target                                   |    1 +
 hw/pc.c                                           |    3 +
 hw/testdev.c                                      |   63 +++++++++
 kvm/user/Makefile                                 |    2 +-
 kvm/user/config-x86-common.mak                    |   16 ++-
 kvm/user/config-x86_64.mak                        |    2 +-
 kvm/user/flat.lds                                 |    4 +-
 kvm/user/test/{x86/apic.h => lib/x86/apic-defs.h} |    0
 kvm/user/test/lib/x86/apic.c                      |  149 +++++++++++++++++++++
 kvm/user/test/lib/x86/apic.h                      |   34 +++++
 kvm/user/test/lib/x86/fwcfg.c                     |   40 ++++++
 kvm/user/test/lib/x86/fwcfg.h                     |   44 ++++++
 kvm/user/test/lib/x86/smp.c                       |   68 ++--------
 kvm/user/test/lib/x86/smp.h                       |    2 +-
 kvm/user/test/x86/access.c                        |    4 +-
 kvm/user/test/x86/apic.c                          |   70 +++-------
 kvm/user/test/x86/cstart.S                        |    9 ++
 kvm/user/test/x86/cstart64.S                      |  114 +++++++++++-----
 kvm/user/test/x86/irq.S                           |  118 ----------------
 kvm/user/test/x86/realmode.c                      |   54 ++++++--
 kvm/user/test/x86/realmode.lds                    |    6 +-
 kvm/user/test/x86/smptest.c                       |   10 +-
 kvm/user/test/x86/vm.c                            |    3 +
 kvm/user/test/x86/vmexit.c                        |   56 +++++++-
 24 files changed, 573 insertions(+), 299 deletions(-)
 create mode 100644 hw/testdev.c
 rename kvm/user/test/{x86/apic.h => lib/x86/apic-defs.h} (100%)
 create mode 100644 kvm/user/test/lib/x86/apic.c
 create mode 100644 kvm/user/test/lib/x86/apic.h
 create mode 100644 kvm/user/test/lib/x86/fwcfg.c
 create mode 100644 kvm/user/test/lib/x86/fwcfg.h
 delete mode 100644 kvm/user/test/x86/irq.S
author
#1 lore raw

PATCH 1/34 Add test device

From: Gerd Hoffmann <[email protected]>

Add a test device which supports the kvmctl ioports, for running the test suite.

Usage:

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

---
 Makefile.target |    1 +
 hw/testdev.c    |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 0 deletions(-)
 create mode 100644 hw/testdev.c
Makefile.target +1 -0
index c8c9568..a08e432 100644
@@ -216,6 +216,7 @@ obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += extboot.o
 obj-i386-y += piix4.o
 obj-i386-y += ne2000-isa.o
+obj-i386-y += testdev.o
 ifeq ($(USE_KVM_PIT), 1)
 obj-i386-y += i8254-kvm.o
 endif
hw/testdev.c new file +55 -0

55 lines not on this page · raw message

Signature · 1 line
1.6.4.1
author
#2 lore raw

PATCH 2/34 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.4.1
author
#3 lore raw

PATCH 3/34 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.4.1
author
#4 lore raw

PATCH 4/34 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.4.1
author
#5 lore raw

PATCH 5/34 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.4.1
author
#6 lore raw

PATCH 6/34 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.4.1
author
#7 lore raw

PATCH 7/34 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.4.1
author
#8 lore raw

PATCH 8/34 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.4.1
author
#9 lore raw

PATCH 9/34 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.4.1
author
#10 lore raw

PATCH 10/34 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.4.1
author
#11 lore raw

PATCH 11/34 test: Allow adding mode vmexit latency tests

In reply to Avi Kivity

Make the latency test run on an array of function pointers, which can be expanded with more tests.

---
 kvm/user/test/x86/vmexit.c |   32 ++++++++++++++++++++++++++++----
 1 files changed, 28 insertions(+), 4 deletions(-)
kvm/user/test/x86/vmexit.c +28 -4
index 981d6c1..364837f 100644
@@ -24,16 +24,40 @@ static inline unsigned long long rdtsc()
 #  define R "e"
 #endif
 
-int main()
+static void cpuid(void)
+{
+	asm volatile ("push %%"R "bx; cpuid; pop %%"R "bx"
+		      : : : "eax", "ecx", "edx");
+}
+
+static struct test {
+	void (*func)(void);
+	const char *name;
+} tests[] = {
+	{ cpuid, "cpuid", },
+};
+
+static void do_test(struct test *test)
 {
 	int i;
 	unsigned long long t1, t2;
+        void (*func)(void) = test->func;
 
 	t1 = rdtsc();
 	for (i = 0; i < N; ++i)
-		asm volatile ("push %%"R "bx; cpuid; pop %%"R "bx"
-			      : : : "eax", "ecx", "edx");
+            func();
 	t2 = rdtsc();
-	printf("vmexit latency: %d\n", (int)((t2 - t1) / N));
+	printf("%s %d\n", test->name, (int)((t2 - t1) / N));
+}
+
+#define ARRAY_SIZE(_x) (sizeof(_x) / sizeof((_x)[0]))
+
+int main(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tests); ++i)
+		do_test(&tests[i]);
+
 	return 0;
 }
Signature · 1 line
1.6.4.1
author
#12 lore raw

PATCH 12/34 test: Add vmcall latency test

In reply to Avi Kivity
---
 kvm/user/test/x86/vmexit.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
kvm/user/test/x86/vmexit.c +8 -0
index 364837f..bd1895f 100644
@@ -30,11 +30,19 @@ static void cpuid(void)
 		      : : : "eax", "ecx", "edx");
 }
 
+static void vmcall(void)
+{
+	unsigned long a = 0, b, c, d;
+
+	asm volatile ("vmcall" : "+a"(a), "=b"(b), "=c"(c), "=d"(d));
+}
+
 static struct test {
 	void (*func)(void);
 	const char *name;
 } tests[] = {
 	{ cpuid, "cpuid", },
+	{ vmcall, "vmcall", },
 };
 
 static void do_test(struct test *test)
Signature · 1 line
1.6.4.1
author
#13 lore raw

PATCH 13/34 test: add cr8 latency tests

In reply to Avi Kivity

In light of the recent cr8/ept problem.

---
 kvm/user/test/x86/vmexit.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
kvm/user/test/x86/vmexit.c +16 -0
index bd1895f..cce26d9 100644
@@ -37,12 +37,28 @@ static void vmcall(void)
 	asm volatile ("vmcall" : "+a"(a), "=b"(b), "=c"(c), "=d"(d));
 }
 
+static void mov_from_cr8(void)
+{
+	unsigned long cr8;
+
+	asm volatile ("mov %%cr8, %0" : "=r"(cr8));
+}
+
+static void mov_to_cr8(void)
+{
+	unsigned long cr8 = 0;
+
+	asm volatile ("mov %0, %%cr8" : : "r"(cr8));
+}
+
 static struct test {
 	void (*func)(void);
 	const char *name;
 } tests[] = {
 	{ cpuid, "cpuid", },
 	{ vmcall, "vmcall", },
+	{ mov_from_cr8, "mov_from_cr8" },
+	{ mov_to_cr8, "mov_to_cr8" },
 };
 
 static void do_test(struct test *test)
Signature · 1 line
1.6.4.1
author
#14 lore raw

PATCH 14/34 test: Mask PIC interrupts before APIC test

In reply to Avi Kivity

We aren't ready to handle PIC interrupts, so mask them.

---
 kvm/user/test/x86/apic.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)
kvm/user/test/x86/apic.c +13 -0
index 7794615..b712ef8 100644
@@ -102,6 +102,11 @@ static idt_entry_t idt[256];
 static int g_fail;
 static int g_tests;
 
+static void outb(unsigned char data, unsigned short port)
+{
+    asm volatile ("out %0, %1" : : "a"(data), "d"(port));
+}
+
 static void report(const char *msg, int pass)
 {
     ++g_tests;
@@ -325,9 +330,16 @@ static void test_ioapic_simultaneous(void)
 
 static void enable_apic(void)
 {
+    printf("enabling apic\n");
     apic_write(0xf0, 0x1ff); /* spurious vector register */
 }
 
+static void mask_pic_interrupts(void)
+{
+    outb(0xff, 0x21);
+    outb(0xff, 0xa1);
+}
+
 int main()
 {
     setup_vm();
@@ -337,6 +349,7 @@ int main()
 
     test_lapic_existence();
 
+    mask_pic_interrupts();
     enable_apic();
     init_idt();
 
Signature · 1 line
1.6.4.1
author
#15 lore raw

PATCH 15/34 test-device: add support for irq injection

In reply to Avi Kivity

This allows apic.flat to pass.

Direct access to the ioapic is required, which is not supported by qdev at this time, so we pass the isa_irq array using a hack.

---
 hw/pc.c      |    3 +++
 hw/testdev.c |    8 ++++++++
 2 files changed, 11 insertions(+), 0 deletions(-)
hw/pc.c +3 -0
index db426f6..5f892c7 100644
@@ -68,6 +68,8 @@ static RTCState *rtc_state;
 static PITState *pit;
 static PCII440FXState *i440fx_state;
 
+qemu_irq *ioapic_irq_hack;
+
 typedef struct rom_reset_data {
     uint8_t *data;
     target_phys_addr_t addr;
@@ -1340,6 +1342,7 @@ static void pc_init1(ram_addr_t ram_size,
 
     if (pci_enabled) {
         isa_irq_state->ioapic = ioapic_init();
+        ioapic_irq_hack = isa_irq;
     }
 #ifdef USE_KVM_PIT
     if (kvm_enabled() && qemu_kvm_pit_in_kernel())
hw/testdev.c +8 -0
index 199731e..ac5b9cd 100644
@@ -27,6 +27,13 @@ static uint32_t test_device_memsize_read(void *opaque, uint32_t addr)
     return ram_size;
 }
 
+static void test_device_irq_line(void *opaque, uint32_t addr, uint32_t data)
+{
+    extern qemu_irq *ioapic_irq_hack;
+
+    qemu_set_irq(ioapic_irq_hack[addr - 0x2000], !!data);
+}
+
 static int init_test_device(ISADevice *isa)
 {
     struct testdev *dev = DO_UPCAST(struct testdev, dev, isa);
@@ -34,6 +41,7 @@ static int init_test_device(ISADevice *isa)
     register_ioport_write(0xf1, 1, 1, test_device_serial_write, dev);
     register_ioport_write(0xf4, 1, 4, test_device_exit, dev);
     register_ioport_read(0xd1, 1, 4, test_device_memsize_read, dev);
+    register_ioport_write(0x2000, 24, 1, test_device_irq_line, NULL);
     return 0;
 }
 
Signature · 1 line
1.6.4.1
author
#16 lore raw

PATCH 16/34 test: Use function table for APIC access

In reply to Avi Kivity

Prepare for x2apic.

---
 kvm/user/test/x86/apic.c |   41 +++++++++++++++++++++++++++++++++++++++--
 1 files changed, 39 insertions(+), 2 deletions(-)
kvm/user/test/x86/apic.c +39 -2
index b712ef8..72dd963 100644
@@ -102,6 +102,12 @@ static idt_entry_t idt[256];
 static int g_fail;
 static int g_tests;
 
+struct apic_ops {
+    u32 (*reg_read)(unsigned reg);
+    void (*reg_write)(unsigned reg, u32 val);
+    void (*icr_write)(u32 val, u32 dest);
+};
+
 static void outb(unsigned char data, unsigned short port)
 {
     asm volatile ("out %0, %1" : : "a"(data), "d"(port));
@@ -115,16 +121,47 @@ static void report(const char *msg, int pass)
         ++g_fail;
 }
 
-static u32 apic_read(unsigned reg)
+static u32 xapic_read(unsigned reg)
 {
     return *(volatile u32 *)(g_apic + reg);
 }
 
-static void apic_write(unsigned reg, u32 val)
+static void xapic_write(unsigned reg, u32 val)
 {
     *(volatile u32 *)(g_apic + reg) = val;
 }
 
+static void xapic_icr_write(u32 val, u32 dest)
+{
+    while (xapic_read(APIC_ICR) & APIC_ICR_BUSY)
+        ;
+    xapic_write(APIC_ICR2, dest << 24);
+    xapic_write(APIC_ICR, val);
+}
+
+static const struct apic_ops xapic_ops = {
+    .reg_read = xapic_read,
+    .reg_write = xapic_write,
+    .icr_write = xapic_icr_write,
+};
+
+static const struct apic_ops *apic_ops = &xapic_ops;
+
+static u32 apic_read(unsigned reg)
+{
+    return apic_ops->reg_read(reg);
+}
+
+static void apic_write(unsigned reg, u32 val)
+{
+    apic_ops->reg_write(reg, val);
+}
+
+static void apic_icr_write(u32 val, u32 dest)
+{
+    apic_ops->icr_write(val, dest);
+}
+
 static void test_lapic_existence(void)
 {
     u32 lvr;
Signature · 1 line
1.6.4.1
author
#17 lore raw

PATCH 17/34 test: use new apic_icr_write() to issue IPI

In reply to Avi Kivity
---
 kvm/user/test/x86/apic.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
kvm/user/test/x86/apic.c +2 -2
index 72dd963..fdeec4c 100644
@@ -260,8 +260,8 @@ static void test_self_ipi(void)
 
     set_idt_entry(vec, self_ipi_isr);
     irq_enable();
-    apic_write(APIC_ICR,
-               APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | vec);
+    apic_icr_write(APIC_DEST_SELF | APIC_DEST_PHYSICAL | APIC_DM_FIXED | vec,
+                   0);
     asm volatile ("nop");
     report("self ipi", ipi_count == 1);
 }
Signature · 1 line
1.6.4.1
author
#18 lore raw

PATCH 18/34 test: add x2apic test

In reply to Avi Kivity
---
 kvm/user/test/x86/apic.c |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 46 insertions(+), 0 deletions(-)
kvm/user/test/x86/apic.c +46 -0
index fdeec4c..504def2 100644
@@ -9,6 +9,7 @@ typedef unsigned char u8;
 typedef unsigned short u16;
 typedef unsigned u32;
 typedef unsigned long ulong;
+typedef unsigned long long u64;
 
 typedef struct {
     unsigned short offset0;
@@ -147,6 +148,31 @@ static const struct apic_ops xapic_ops = {
 
 static const struct apic_ops *apic_ops = &xapic_ops;
 
+static u32 x2apic_read(unsigned reg)
+{
+    unsigned a, d;
+
+    asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(APIC_BASE_MSR + reg/16));
+    return a | (u64)d << 32;
+}
+
+static void x2apic_write(unsigned reg, u32 val)
+{
+    asm volatile ("wrmsr" : : "a"(val), "d"(0), "c"(APIC_BASE_MSR + reg/16));
+}
+
+static void x2apic_icr_write(u32 val, u32 dest)
+{
+    asm volatile ("wrmsr" : : "a"(val), "d"(dest),
+                  "c"(APIC_BASE_MSR + APIC_ICR/16));
+}
+
+static const struct apic_ops x2apic_ops = {
+    .reg_read = x2apic_read,
+    .reg_write = x2apic_write,
+    .icr_write = x2apic_icr_write,
+};
+
 static u32 apic_read(unsigned reg)
 {
     return apic_ops->reg_read(reg);
@@ -171,6 +197,25 @@ static void test_lapic_existence(void)
     report("apic existence", (u16)lvr == 0x14);
 }
 
+#define MSR_APIC_BASE 0x0000001b
+
+static void enable_x2apic(void)
+{
+    unsigned a, b, c, d;
+
+    asm ("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(1));
+
+    if (c & (1 << 21)) {
+        asm ("rdmsr" : "=a"(a), "=d"(d) : "c"(MSR_APIC_BASE));
+        a |= 1 << 10;
+        asm ("wrmsr" : : "a"(a), "d"(d), "c"(MSR_APIC_BASE));
+        apic_ops = &x2apic_ops;
+        printf("x2apic enabled\n");
+    } else {
+        printf("x2apic not detected\n");
+    }
+}
+
 static u16 read_cs(void)
 {
     u16 v;
@@ -388,6 +433,7 @@ int main()
 
     mask_pic_interrupts();
     enable_apic();
+    enable_x2apic();
     init_idt();
 
     test_self_ipi();
Signature · 1 line
1.6.4.1
author
#19 lore raw

PATCH 19/34 test: add support for the firmware configuration interface

In reply to Avi Kivity
---
 kvm/user/config-x86-common.mak |    2 +
 kvm/user/test/lib/x86/fwcfg.c  |   35 +++++++++++++++++++++++++++++++++
 kvm/user/test/lib/x86/fwcfg.h  |   42 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+), 0 deletions(-)
 create mode 100644 kvm/user/test/lib/x86/fwcfg.c
 create mode 100644 kvm/user/test/lib/x86/fwcfg.h
kvm/user/config-x86-common.mak +2 -0
index 2f59bb5..22a18b2 100644
@@ -11,6 +11,8 @@ cflatobjs += \
 	test/lib/x86/io.o \
 	test/lib/x86/smp.o
 
+cflatobjs += test/lib/x86/fwcfg.o
+
 $(libcflat): LDFLAGS += -nostdlib
 $(libcflat): CFLAGS += -ffreestanding -I test/lib
 
kvm/user/test/lib/x86/fwcfg.c new file +35 -0
new file mode 100644
index 0000000..a9a2ce2
@@ -0,0 +1,35 @@
+#include "fwcfg.h"
+
+uint64_t fwcfg_get_u(uint16_t index, int bytes)
+{
+    uint64_t r = 0;
+    uint8_t b;
+    int i;
+
+    asm volatile ("out %0, %1" : : "a"(index), "d"((uint16_t)BIOS_CFG_IOPORT));
+    for (i = 0; i < bytes; ++i) {
+        asm volatile ("in %1, %0" : "=a"(b) : "d"((uint16_t)(BIOS_CFG_IOPORT + 1)));
+        r |= (uint64_t)b << (i * 8);
+    }
+    return r;
+}
+
+uint8_t fwcfg_get_u8(unsigned index)
+{
+    return fwcfg_get_u(index, 1);
+}
+
+uint16_t fwcfg_get_u16(unsigned index)
+{
+    return fwcfg_get_u(index, 2);
+}
+
+uint32_t fwcfg_get_u32(unsigned index)
+{
+    return fwcfg_get_u(index, 4);
+}
+
+uint64_t fwcfg_get_u64(unsigned index)
+{
+    return fwcfg_get_u(index, 8);
+}
kvm/user/test/lib/x86/fwcfg.h new file +42 -0

42 lines not on this page · raw message

Signature · 1 line
1.6.4.1
author
#20 lore raw

PATCH 20/34 test: Add fwcfg interface for getting the cpu count

In reply to Avi Kivity
---
 kvm/user/test/lib/x86/fwcfg.c |    5 +++++
 kvm/user/test/lib/x86/fwcfg.h |    2 ++
 2 files changed, 7 insertions(+), 0 deletions(-)
kvm/user/test/lib/x86/fwcfg.c +5 -0
index a9a2ce2..2cf7cec 100644
@@ -33,3 +33,8 @@ uint64_t fwcfg_get_u64(unsigned index)
 {
     return fwcfg_get_u(index, 8);
 }
+
+unsigned fwcfg_get_nb_cpus(void)
+{
+    return fwcfg_get_u16(FW_CFG_NB_CPUS);
+}
kvm/user/test/lib/x86/fwcfg.h +2 -0
index c7245e2..e0836ca 100644
@@ -38,5 +38,7 @@ uint16_t fwcfg_get_u16(unsigned index);
 uint32_t fwcfg_get_u32(unsigned index);
 uint64_t fwcfg_get_u64(unsigned index);
 
+unsigned fwcfg_get_nb_cpus(void);
+
 #endif
 
Signature · 1 line
1.6.4.1
author
#21 lore raw

PATCH 21/34 test: vm: map mmio 1:1

In reply to Avi Kivity

With this assumption, the apic code will be able to run either before or after the vm is set up.

---
 kvm/user/test/x86/vm.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
kvm/user/test/x86/vm.c +3 -0
index 03c7354..ec9c145 100644
@@ -189,6 +189,9 @@ static void setup_mmu(unsigned long len)
     unsigned long *cr3 = alloc_page();
     unsigned long phys = 0;
 
+    if (len < (1ul << 32))
+        len = 1ul << 32;  /* map mmio 1:1 */
+
     memset(cr3, 0, PAGE_SIZE);
     while (phys + LARGE_PAGE_SIZE <= len) {
 	install_large_page(cr3, phys, (void *)phys);
Signature · 1 line
1.6.4.1
author
#22 lore raw

PATCH 22/34 test: apic: use 1:1 mapping for apic

In reply to Avi Kivity

This allows the apic code to be run early, before virtual memory is set up.

---
 kvm/user/test/x86/apic.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
kvm/user/test/x86/apic.c +2 -2
index 504def2..63d326d 100644
@@ -426,8 +426,8 @@ int main()
 {
     setup_vm();
 
-    g_apic = vmap(0xfee00000, 0x1000);
-    g_ioapic = vmap(0xfec00000, 0x1000);
+    g_apic = (void *)0xfee00000;
+    g_ioapic = (void *)0xfec00000;
 
     test_lapic_existence();
 
Signature · 1 line
1.6.4.1
author
#23 lore raw

PATCH 23/34 test: Move apic functions to libcflat

In reply to Avi Kivity
---
 kvm/user/config-x86-common.mak                    |    1 +
 kvm/user/test/{x86/apic.h => lib/x86/apic-defs.h} |    0
 kvm/user/test/lib/x86/apic.c                      |  131 +++++++++++++++++++++
 kvm/user/test/lib/x86/apic.h                      |   33 +++++
 kvm/user/test/x86/apic.c                          |  130 +--------------------
 kvm/user/test/x86/cstart64.S                      |    2 +-
 6 files changed, 169 insertions(+), 128 deletions(-)
 rename kvm/user/test/{x86/apic.h => lib/x86/apic-defs.h} (100%)
 create mode 100644 kvm/user/test/lib/x86/apic.c
 create mode 100644 kvm/user/test/lib/x86/apic.h
kvm/user/config-x86-common.mak +1 -0
index 22a18b2..de9e9e8 100644
@@ -12,6 +12,7 @@ cflatobjs += \
 	test/lib/x86/smp.o
 
 cflatobjs += test/lib/x86/fwcfg.o
+cflatobjs += test/lib/x86/apic.o
 
 $(libcflat): LDFLAGS += -nostdlib
 $(libcflat): CFLAGS += -ffreestanding -I test/lib
kvm/user/test/lib/x86/apic-defs.h renamed from kvm/user/test/x86/apic.h +0 -0
similarity index 100%
rename from kvm/user/test/x86/apic.h
rename to kvm/user/test/lib/x86/apic-defs.h
kvm/user/test/lib/x86/apic.c new file +131 -0

131 lines not on this page · raw message

kvm/user/test/lib/x86/apic.h new file +33 -0
new file mode 100644
index 0000000..0115ba4
@@ -0,0 +1,33 @@
+#ifndef CFLAT_APIC_H
+#define CFLAT_APIC_H
+
+#include <stdint.h>
+#include "apic-defs.h"
+
+typedef struct {
+    uint8_t vector;
+    uint8_t delivery_mode:3;
+    uint8_t dest_mode:1;
+    uint8_t delivery_status:1;
+    uint8_t polarity:1;
+    uint8_t remote_irr:1;
+    uint8_t trig_mode:1;
+    uint8_t mask:1;
+    uint8_t reserve:7;
+    uint8_t reserved[4];
+    uint8_t dest_id;
+} ioapic_redir_entry_t;
+
+void mask_pic_interrupts(void);
+
+void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e);
+void ioapic_write_reg(unsigned reg, uint32_t value);
+
+void enable_apic(void);
+uint32_t apic_read(unsigned reg);
+void apic_write(unsigned reg, uint32_t val);
+void apic_icr_write(uint32_t val, uint32_t dest);
+
+int enable_x2apic(void);
+
+#endif
kvm/user/test/x86/apic.c +3 -127

175 lines not on this page · raw message

kvm/user/test/x86/cstart64.S +1 -1
index 912bcf8..14bb98c 100644
@@ -1,5 +1,5 @@
 
-#include "apic.h"
+#include "apic-defs.h"
 
 boot_idt = 0
 
Signature · 1 line
1.6.4.1
author
#24 lore raw

PATCH 24/34 test: switch 64-bit smp startup to real APIC

In reply to Avi Kivity
---
 kvm/user/test/x86/cstart64.S |   74 ++++++++++++++++++++++++-----------------
 1 files changed, 43 insertions(+), 31 deletions(-)
kvm/user/test/x86/cstart64.S +43 -31
index 14bb98c..278465b 100644
@@ -107,10 +107,42 @@ efer = 0xc0000080
 	mov %eax, %cr0
 	ret
 
+smp_stacktop:	.long 0xa0000
 
-smp_init_ipi:
+.align 16
+
+gdt32:
+	.quad 0
+	.quad 0x00cf9b000000ffff // flat 32-bit code segment
+	.quad 0x00cf93000000ffff // flat 32-bit data segment
+gdt32_end:
+
+.code16
+sipi_entry:
+	mov %cr0, %eax
+	or $1, %eax
+	mov %eax, %cr0
+	lgdtl gdt32_descr - sipi_entry
+	ljmpl $8, $ap_start32
+
+gdt32_descr:
+	.word gdt32_end - gdt32 - 1
+	.long gdt32
+
+sipi_end:
+
+.code32
+ap_start32:
+	mov $0x10, %ax
+	mov %ax, %ds
+	mov %ax, %es
+	mov %ax, %fs
+	mov %ax, %gs
+	mov %ax, %ss
+	mov $-4096, %esp
+	lock/xaddl %esp, smp_stacktop
 	call prepare_64
-	jmpl $8, $ap_start64
+	ljmpl $8, $ap_start64
 
 .code64
 ap_start64:
@@ -151,34 +183,14 @@ load_tss:
 	ret
 
 smp_init:
-#if 0
-	lea boot_idt + ipi_vector * 8, %rdi
-	mov $smp_init_ipi, %eax
-	mov %ax, (%rdi)
-	mov %cs, %ax
-	mov %ax, 2(%rdi)
-	movw $0x8e00, 4(%rdi)
-	shr $16, %eax
-	mov %ax, 6(%rdi)
-
-	mov $(APIC_BASE + APIC_REG_IPI_VECTOR), %dx
-	mov $ipi_vector, %eax
-	out %eax, %dx
-
-	mov $(APIC_BASE + APIC_REG_NCPU), %dx
-	in %dx, %eax
-	mov %eax, %ecx
-	mov $1, %esi
-smp_loop:
-	cmp %esi, %ecx
-	je smp_init_done
-
-	mov $(APIC_BASE + APIC_REG_SEND_IPI), %dx
-	mov %esi, %eax
-	out %eax, %dx
-
-	inc %esi
-	jmp smp_loop
+	cld
+	lea sipi_entry, %rsi
+	xor %rdi, %rdi
+	mov $(sipi_end - sipi_entry), %rcx
+	rep/movsb
+	mov $APIC_DEFAULT_PHYS_BASE, %eax
+	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%rax)
+	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT), APIC_ICR(%rax)
+	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%rax)
 smp_init_done:
-#endif
 	ret
Signature · 1 line
1.6.4.1
author
#25 lore raw

PATCH 25/34 test: add apic_id() accessor

In reply to Avi Kivity

apic and x2apic have different formats for the ID register, so we need an accessor for it.

---
 kvm/user/test/lib/x86/apic.c |   18 ++++++++++++++++++
 kvm/user/test/lib/x86/apic.h |    1 +
 2 files changed, 19 insertions(+), 0 deletions(-)
kvm/user/test/lib/x86/apic.c +18 -0
index 25517ef..16e51bc 100644
@@ -14,6 +14,7 @@ struct apic_ops {
     u32 (*reg_read)(unsigned reg);
     void (*reg_write)(unsigned reg, u32 val);
     void (*icr_write)(u32 val, u32 dest);
+    u32 (*id)(void);
 };
 
 static void outb(unsigned char data, unsigned short port)
@@ -39,10 +40,16 @@ static void xapic_icr_write(u32 val, u32 dest)
     xapic_write(APIC_ICR, val);
 }
 
+static uint32_t xapic_id(void)
+{
+    return xapic_read(APIC_ID) >> 24;
+}
+
 static const struct apic_ops xapic_ops = {
     .reg_read = xapic_read,
     .reg_write = xapic_write,
     .icr_write = xapic_icr_write,
+    .id = xapic_id,
 };
 
 static const struct apic_ops *apic_ops = &xapic_ops;
@@ -66,10 +73,16 @@ static void x2apic_icr_write(u32 val, u32 dest)
                   "c"(APIC_BASE_MSR + APIC_ICR/16));
 }
 
+static uint32_t x2apic_id(void)
+{
+    return xapic_read(APIC_ID);
+}
+
 static const struct apic_ops x2apic_ops = {
     .reg_read = x2apic_read,
     .reg_write = x2apic_write,
     .icr_write = x2apic_icr_write,
+    .id = x2apic_id,
 };
 
 u32 apic_read(unsigned reg)
@@ -87,6 +100,11 @@ void apic_icr_write(u32 val, u32 dest)
     apic_ops->icr_write(val, dest);
 }
 
+uint32_t apic_id(void)
+{
+    return apic_ops->id();
+}
+
 #define MSR_APIC_BASE 0x0000001b
 
 int enable_x2apic(void)
kvm/user/test/lib/x86/apic.h +1 -0
index 0115ba4..e325e9a 100644
@@ -27,6 +27,7 @@ void enable_apic(void);
 uint32_t apic_read(unsigned reg);
 void apic_write(unsigned reg, uint32_t val);
 void apic_icr_write(uint32_t val, uint32_t dest);
+uint32_t apic_id(void);
 
 int enable_x2apic(void);
 
Signature · 1 line
1.6.4.1
author
#26 lore raw

PATCH 26/34 test: Use xapic_write() to enable xapic()

In reply to Avi Kivity

apic_write() depends on apic_ops, which is shared among cpus and can be modified if another cpu enabled x2apic. Use xapic_write() which is race-proof.

---
 kvm/user/test/lib/x86/apic.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kvm/user/test/lib/x86/apic.c +1 -1
index 16e51bc..1fc3888 100644
@@ -139,7 +139,7 @@ void ioapic_write_redir(unsigned line, ioapic_redir_entry_t e)
 void enable_apic(void)
 {
     printf("enabling apic\n");
-    apic_write(0xf0, 0x1ff); /* spurious vector register */
+    xapic_write(0xf0, 0x1ff); /* spurious vector register */
 }
 
 void mask_pic_interrupts(void)
Signature · 1 line
1.6.4.1
author
#27 lore raw

PATCH 27/34 test: initialize idt on all processors

In reply to Avi Kivity
---
 kvm/user/test/x86/cstart64.S |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
kvm/user/test/x86/cstart64.S +6 -0
index 278465b..a55ad50 100644
@@ -1,6 +1,7 @@
 
 #include "apic-defs.h"
 
+.globl boot_idt
 boot_idt = 0
 
 ipi_vector = 0x20
@@ -160,7 +161,12 @@ start64:
 	mov %eax, %edi
 	call exit
 
+idt_descr:
+	.word 16 * 256 - 1
+	.quad boot_idt
+
 load_tss:
+	lidtq idt_descr
 	mov $0, %eax
 	mov %ax, %ss
 	mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
Signature · 1 line
1.6.4.1
author
#28 lore raw

PATCH 28/34 test: initialize apic/x2apic on all processors

In reply to Avi Kivity
---
 kvm/user/test/x86/cstart64.S |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)
kvm/user/test/x86/cstart64.S +5 -0
index a55ad50..54b721f 100644
@@ -148,6 +148,8 @@ ap_start32:
 .code64
 ap_start64:
 	call load_tss
+	call enable_apic
+	call enable_x2apic
 	sti
 	nop
 
@@ -156,7 +158,10 @@ ap_start64:
 
 start64:
 	call load_tss
+	call mask_pic_interrupts
+	call enable_apic
 	call smp_init
+	call enable_x2apic
 	call main
 	mov %eax, %edi
 	call exit
Signature · 1 line
1.6.4.1
author
#29 lore raw

PATCH 29/34 test: wait for all processors to complete initialization

In reply to Avi Kivity

so we can start blasting them with IPIs.

---
 kvm/user/test/x86/cstart64.S |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)
kvm/user/test/x86/cstart64.S +7 -0
index 54b721f..e5554ba 100644
@@ -152,6 +152,7 @@ ap_start64:
 	call enable_x2apic
 	sti
 	nop
+	lock incw cpu_online_count
 
 1:	hlt
 	jmp 1b
@@ -203,5 +204,11 @@ smp_init:
 	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%rax)
 	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT), APIC_ICR(%rax)
 	movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%rax)
+	call fwcfg_get_nb_cpus
+1:	pause
+	cmpw %ax, cpu_online_count
+	jne 1b
 smp_init_done:
 	ret
+
+cpu_online_count:	.word 1
Signature · 1 line
1.6.4.1
author
#30 lore raw

PATCH 30/34 test: port smp runtime to real apic

In reply to Avi Kivity

instead of the old fake apic.

---
 kvm/user/test/lib/x86/smp.c |   68 ++++++-------------------------------------
 kvm/user/test/lib/x86/smp.h |    2 +-
 kvm/user/test/x86/smptest.c |   10 +-----
 3 files changed, 12 insertions(+), 68 deletions(-)
kvm/user/test/lib/x86/smp.c +9 -59
index 92ebada..a3a5472 100644
@@ -1,46 +1,11 @@
 
 #include <libcflat.h>
 #include "smp.h"
-#include "fake-apic.h"
+#include "apic.h"
+#include "fwcfg.h"
 
 #define IPI_VECTOR 0x20
 
-static int apic_read(int reg)
-{
-    unsigned short port = APIC_BASE + reg;
-    unsigned v;
-
-    asm volatile ("in %1, %0" : "=a"(v) : "d"(port));
-    return v;
-}
-
-static void apic_write(int reg, unsigned v)
-{
-    unsigned short port = APIC_BASE + reg;
-
-    asm volatile ("out %0, %1" : : "a"(v), "d"(port));
-}
-
-static int apic_get_cpu_count()
-{
-    return apic_read(APIC_REG_NCPU);
-}
-
-static int apic_get_id()
-{
-    return apic_read(APIC_REG_ID);
-}
-
-static void apic_set_ipi_vector(int vector)
-{
-    apic_write(APIC_REG_IPI_VECTOR, vector);
-}
-
-static void apic_send_ipi(int cpu)
-{
-    apic_write(APIC_REG_SEND_IPI, cpu);
-}
-
 static struct spinlock ipi_lock;
 static void (*ipi_function)(void *data);
 static void *ipi_data;
@@ -100,23 +65,25 @@ void spin_unlock(struct spinlock *lock)
 
 int cpu_count(void)
 {
-    return apic_get_cpu_count();
+    return fwcfg_get_nb_cpus();
 }
 
 int smp_id(void)
 {
-    return apic_get_id();
+    return apic_read(APIC_ID);
 }
 
 void on_cpu(int cpu, void (*function)(void *data), void *data)
 {
     spin_lock(&ipi_lock);
-    if (cpu == apic_get_id())
+    if (cpu == apic_id())
 	function(data);
     else {
 	ipi_function = function;
 	ipi_data = data;
-	apic_send_ipi(cpu);
+	apic_icr_write(APIC_INT_ASSERT | APIC_DEST_PHYSICAL | APIC_DM_FIXED
+                       | IPI_VECTOR,
+                       cpu);
 	while (!ipi_done)
 	    ;
 	ipi_done = 0;
@@ -124,27 +91,10 @@ void on_cpu(int cpu, void (*function)(void *data), void *data)
     spin_unlock(&ipi_lock);
 }
 
-static void (*smp_main_func)(void);
-static volatile int smp_main_running;
-
-asm ("smp_init_entry: \n"
-     "incl smp_main_running \n"
-     "sti \n"
-     "call *smp_main_func");
-
-void smp_init(void (*smp_main)(void))
+void smp_init(void)
 {
     int i;
-    void smp_init_entry(void);
     void ipi_entry(void);
 
-    apic_set_ipi_vector(IPI_VECTOR);
-    set_ipi_descriptor(smp_init_entry);
-    smp_main_func = smp_main;
-    for (i = 1; i < cpu_count(); ++i) {
-	apic_send_ipi(i);
-	while (smp_main_running < i)
-	    ;
-    }
     set_ipi_descriptor(ipi_entry);
 }
kvm/user/test/lib/x86/smp.h +1 -1
index bcf76a3..bac7e14 100644
@@ -5,7 +5,7 @@ struct spinlock {
     int v;
 };
 
-void smp_init(void (*smp_main)(void));
+void smp_init(void);
 
 int cpu_count(void);
 int smp_id(void);
kvm/user/test/x86/smptest.c +2 -8
index 7b1ba49..3780599 100644
@@ -10,19 +10,13 @@ static void ipi_test(void *data)
 	printf("but wrong cpu %d\n", smp_id());
 }
 
-static void smp_main(void)
-{
-    printf("smp main %d\n", smp_id());
-    while (1)
-	asm volatile ("hlt" : : : "memory");
-}
-
 int main()
 {
     int ncpus;
     int i;
 
-    smp_init(smp_main);
+    smp_init();
+
     ncpus = cpu_count();
     printf("found %d cpus\n", ncpus);
     for (i = 0; i < ncpus; ++i)
Signature · 1 line
1.6.4.1
author
#31 lore raw

PATCH 31/34 test: drop irq.flat

In reply to Avi Kivity

Obsolete.

---
 kvm/user/config-x86-common.mak |    2 -
 kvm/user/config-x86_64.mak     |    2 +-
 kvm/user/test/x86/irq.S        |  118 ----------------------------------------
 3 files changed, 1 insertions(+), 121 deletions(-)
 delete mode 100644 kvm/user/test/x86/irq.S
kvm/user/config-x86-common.mak +0 -2
index de9e9e8..41e8c8d 100644
@@ -35,8 +35,6 @@ $(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I test/lib -I test/lib/x86
 $(TEST_DIR)/bootstrap: $(TEST_DIR)/bootstrap.o
 	$(CC) -nostdlib -o $@ -Wl,-T,bootstrap.lds $^
  
-$(TEST_DIR)/irq.flat: $(TEST_DIR)/print.o
- 
 $(TEST_DIR)/access.flat: $(cstart.o) $(TEST_DIR)/access.o $(TEST_DIR)/print.o
  
 $(TEST_DIR)/hypercall.flat: $(cstart.o) $(TEST_DIR)/hypercall.o $(TEST_DIR)/print.o
kvm/user/config-x86_64.mak +1 -1
index d88f54c..97990bb 100644
@@ -4,7 +4,7 @@ bits = 64
 ldarch = elf64-x86-64
 CFLAGS += -D__x86_64__
 
-tests = $(TEST_DIR)/access.flat $(TEST_DIR)/irq.flat $(TEST_DIR)/sieve.flat \
+tests = $(TEST_DIR)/access.flat $(TEST_DIR)/sieve.flat \
       $(TEST_DIR)/simple.flat $(TEST_DIR)/stringio.flat \
       $(TEST_DIR)/memtest1.flat $(TEST_DIR)/emulator.flat \
       $(TEST_DIR)/hypercall.flat $(TEST_DIR)/apic.flat
kvm/user/test/x86/irq.S deleted +0 -118

118 lines not on this page · raw message

Signature · 1 line
1.6.4.1
author
#32 lore raw

PATCH 32/34 test: fix autodependencies

In reply to Avi Kivity

The autodependencies files were generated, but not included.

---
 kvm/user/config-x86-common.mak |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
kvm/user/config-x86-common.mak +2 -0
index 41e8c8d..9d6d281 100644
@@ -67,3 +67,5 @@ $(TEST_DIR)/msr.flat: $(cstart.o) $(TEST_DIR)/msr.o
 arch_clean:
 	$(RM) $(TEST_DIR)/bootstrap $(TEST_DIR)/*.o $(TEST_DIR)/*.flat \
 	$(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o
+
+-include $(TEST_DIR)/.*.d test/lib/.*.d test/lib/x86/.*.d
Signature · 1 line
1.6.4.1
author
#33 lore raw

PATCH 33/34 test: Fix compilation rule for assembly files wrt autodependencies

In reply to Avi Kivity

Only compile the first dependency (the source file), not the rest (headers).

---
 kvm/user/Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
kvm/user/Makefile +1 -1
index d9fbf17..ed462bb 100644
@@ -52,7 +52,7 @@ $(libcflat): $(cflatobjs)
 	$(AR) rcs $@ $^
 
 %.o: %.S
-	$(CC) $(CFLAGS) -c -nostdlib -o $@ $^
+	$(CC) $(CFLAGS) -c -nostdlib -o $@ $<
 
 -include .*.d
 
Signature · 1 line
1.6.4.1
author
#34 lore raw

PATCH 34/34 test: avoid deleting intermediate .o files

In reply to Avi Kivity

If make doesn't see an intermediate file mentioned explicitly, it deletes it after making the target. This silly behaviour causes needless rebuilds.

Add all intermediates as explicit dependncies to prevent this behaviour.

---
 kvm/user/config-x86-common.mak |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)
kvm/user/config-x86-common.mak +8 -1
index 9d6d281..3f279ed 100644
@@ -48,7 +48,8 @@ $(TEST_DIR)/test32.flat: $(TEST_DIR)/test32.o
 
 $(TEST_DIR)/smptest.flat: $(cstart.o) $(TEST_DIR)/smptest.o
  
-$(TEST_DIR)/emulator.flat: $(cstart.o) $(TEST_DIR)/vm.o $(TEST_DIR)/print.o
+$(TEST_DIR)/emulator.flat: $(cstart.o) $(TEST_DIR)/emulator.o \
+			   $(TEST_DIR)/vm.o $(TEST_DIR)/print.o
 
 $(TEST_DIR)/port80.flat: $(cstart.o) $(TEST_DIR)/port80.o
 
@@ -62,6 +63,12 @@ $(TEST_DIR)/realmode.flat: $(TEST_DIR)/realmode.o
 
 $(TEST_DIR)/realmode.o: bits = 32
 
+$(TEST_DIR)/memtest1.flat: $(TEST_DIR)/memtest1.o
+
+$(TEST_DIR)/stringio.flat: $(TEST_DIR)/stringio.o
+
+$(TEST_DIR)/simple.flat: $(TEST_DIR)/simple.o
+
 $(TEST_DIR)/msr.flat: $(cstart.o) $(TEST_DIR)/msr.o
 
 arch_clean:
Signature · 1 line
1.6.4.1