Minor cleanup and fix for 32bit test
cover Minor cleanup and fix for 32bit test
The following series do some minor cleanup and fix for the 32bit test.
---
Jason Wang (10):
Do not track config.mak and kvmtrace
Remove trailing whitespaces
Makefile cleanup
Correct the path in README
Drop print.S
Remove the duplicated rdmsr/wrmsr
Correct the tss size
Check whether in long mode before testing vmexit caused by cr8 access Do not test IA32_EFER in 32bit mode.
Add the 32bit smp initialization code
Makefile | 9 -- README | 10 +-- config-x86-common.mak | 21 +++--- config.mak | 8 -- kvmtrace | Bin x86/access.c | 2 - x86/cstart.S | 179 +++++++++++++++++++++++++++++++++++++++++++++++-- x86/cstart64.S | 6 +- x86/msr.c | 18 +---- x86/print.S | 31 -------- x86/sieve.c | 2 - x86/vm.c | 6 +- x86/vmexit.c | 34 ++++----- 13 files changed, 215 insertions(+), 111 deletions(-) delete mode 100644 config.mak delete mode 100755 kvmtrace delete mode 100644 x86/print.S
Signature · 1 line
Jason Wang
PATCH 1/10 Do not track config.mak and kvmtrace
config.mak was generated by configure and kvmtrace were compiled throuh makefile.
--- config.mak | 8 -------- kvmtrace | Bin 2 files changed, 0 insertions(+), 8 deletions(-) delete mode 100644 config.mak delete mode 100755 kvmtrace
config.mak deleted +0 -8
@@ -1,8 +0,0 @@ -PREFIX=/usr/local -KERNELDIR=/home/avi/kvm/linux-2.6 -ARCH=x86_64 -PROCESSOR=x86_64 -CC=gcc -LD=ld -OBJCOPY=objcopy -AR=ar
kvmtrace deleted binary +0 -0
PATCH 2/10 Remove trailing whitespaces
In reply to Jason Wang--- config-x86-common.mak | 14 +++++++------- x86/access.c | 2 +- x86/cstart64.S | 4 ++-- x86/print.S | 6 +++--- x86/sieve.c | 2 +- x86/vm.c | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-)
config-x86-common.mak +7 -7
@@ -32,18 +32,18 @@ tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg test_cases: $(tests-common) $(tests) $(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib -I lib/x86 - + $(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)/sieve.flat: $(cstart.o) $(TEST_DIR)/sieve.o \ $(TEST_DIR)/vm.o - + $(TEST_DIR)/vmexit.flat: $(cstart.o) $(TEST_DIR)/vmexit.o - + $(TEST_DIR)/smptest.flat: $(cstart.o) $(TEST_DIR)/smptest.o - + $(TEST_DIR)/emulator.flat: $(cstart.o) $(TEST_DIR)/emulator.o \ $(TEST_DIR)/vm.o $(TEST_DIR)/print.o
@@ -52,7 +52,7 @@ $(TEST_DIR)/port80.flat: $(cstart.o) $(TEST_DIR)/port80.o $(TEST_DIR)/tsc.flat: $(cstart.o) $(TEST_DIR)/tsc.o $(TEST_DIR)/apic.flat: $(cstart.o) $(TEST_DIR)/apic.o $(TEST_DIR)/vm.o \ - $(TEST_DIR)/print.o + $(TEST_DIR)/print.o $(TEST_DIR)/realmode.flat: $(TEST_DIR)/realmode.o $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^
x86/access.c +1 -1
@@ -157,7 +157,7 @@ static void ac_test_show(ac_test_t *at);void lidt (idt_entry_t *idt,int nentries) {descriptor_table_t dt; - + dt.limit = nentries *sizeof (*idt) -1 ; dt.linear_addr = (unsigned long )idt; asmvolatile ("lidt %0" : :"m" (dt));
x86/cstart64.S +2 -2
@@ -19,7 +19,7 @@ stacktop: ring0stacktop: .data - + .align 4096 ptl2: i = 0
@@ -38,7 +38,7 @@ ptl3: .align 4096 ptl4: .quad ptl3 + 7 - + .align 4096 gdt64_desc:
x86/print.S +3 -3
@@ -3,12 +3,12 @@ #define PSEUDO_SERIAL_PORT 0xf1 - + .text PRINT "boo" hlt 1: jmp 1b - + .globl print print: push %rax
@@ -24,7 +24,7 @@ putchar: outsb jmp putchar done: - + pop %rdx pop %rsi pop %rax
x86/sieve.c +1 -1
@@ -46,6 +46,6 @@ int main()test_sieve ("virtual" , v,VSIZE );vfree (v); } - +return 0 ; }
x86/vm.c +3 -3
@@ -30,7 +30,7 @@ void *alloc_page()if (!free)return 0 ; - + p = free; free = *(void **)free;
@@ -184,7 +184,7 @@ void *vmalloc(unsigned long size)unsigned pages; size +=sizeof (unsigned long ); - + size = (size +PAGE_SIZE -1 ) & ~(PAGE_SIZE -1 ); vfree_top -= size; mem = p = vfree_top;
@@ -201,7 +201,7 @@ void *vmalloc(unsigned long size)void vfree (void *mem) {unsigned long size = ((unsigned long *)mem)[-1 ]; - +while (size) {free_page (phys_to_virt (get_pte (phys_to_virt (read_cr3 ()), mem) &PTE_ADDR )); mem +=PAGE_SIZE ;
PATCH 3/10 Makefile cleanup
In reply to Jason WangRemove the obsoleted target and directories.
--- Makefile | 9 +-------- 1 files changed, 1 insertions(+), 8 deletions(-)
Makefile +1 -8
@@ -30,10 +30,6 @@ CFLAGS += -O1 CFLAGS += $(autodepend-flags) -g -fomit-frame-pointer -Wall CFLAGS += $(call cc-option, -fno-stack-protector, "") CFLAGS += $(call cc-option, -fno-stack-protector-all, "") -CFLAGS += -I../include -CFLAGS += -I ../libkvm - -LDFLAGS += $(CFLAGS) -L ../libkvm CXXFLAGS = $(autodepend-flags)
@@ -43,9 +39,6 @@ LDFLAGS += -pthread -lrt kvmtrace_objs= kvmtrace.o -kvmctl: $(kvmctl_objs) - $(CC) $(LDFLAGS) $^ -o $@ - kvmtrace: $(kvmtrace_objs) $(CC) $(LDFLAGS) $^ -o $@
@@ -62,4 +55,4 @@ install: install $(tests_and_config) $(DESTDIR) clean: arch_clean - $(RM) kvmctl kvmtrace *.o *.a .*.d $(libcflat) $(cflatobjs) + $(RM) kvmtrace *.o *.a .*.d $(libcflat) $(cflatobjs)
PATCH 4/10 Correct the path in README
In reply to Jason Wang--- README | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
README +5 -5
@@ -7,17 +7,17 @@ Tests uses a qemu's virtual test device, named testdev, for services like printi See file testdev.txt for more details. To create the tests' images just type 'make' in this directory. -Tests' images created in ./test/<ARCH>/*.flat +Tests' images created in ./<ARCH>/*.flat An example of a test invocation: -qemu-system-x86_64 -device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out -kernel ./test/x86/msr.flat +qemu-system-x86_64 -device testdev,chardev=testlog -chardev file,id=testlog,path=msr.out -kernel ./x86/msr.flat This invocation runs the msr test case. The test output is in file msr.out. Directory structure: .: Makefile and config files for the tests -./test/lib: general services for the tests -./test/lib/<ARCH>: architecture dependent services for the tests -./test/<ARCH>: the sources of the tests and the created objects/images +./lib: general services for the tests +./lib/<ARCH>: architecture dependent services for the tests +./<ARCH>: the sources of the tests and the created objects/images
PATCH 5/10 Drop print.S
In reply to Jason WangWe've already had lib/printf.c.
--- config-x86-common.mak | 9 ++++----- x86/print.S | 31 ------------------------------- 2 files changed, 4 insertions(+), 36 deletions(-) delete mode 100644 x86/print.S
config-x86-common.mak +4 -5
@@ -33,7 +33,7 @@ test_cases: $(tests-common) $(tests) $(TEST_DIR)/%.o: CFLAGS += -std=gnu99 -ffreestanding -I lib -I lib/x86 -$(TEST_DIR)/access.flat: $(cstart.o) $(TEST_DIR)/access.o $(TEST_DIR)/print.o +$(TEST_DIR)/access.flat: $(cstart.o) $(TEST_DIR)/access.o $(TEST_DIR)/hypercall.flat: $(cstart.o) $(TEST_DIR)/hypercall.o
@@ -45,14 +45,13 @@ $(TEST_DIR)/vmexit.flat: $(cstart.o) $(TEST_DIR)/vmexit.o $(TEST_DIR)/smptest.flat: $(cstart.o) $(TEST_DIR)/smptest.o $(TEST_DIR)/emulator.flat: $(cstart.o) $(TEST_DIR)/emulator.o \ - $(TEST_DIR)/vm.o $(TEST_DIR)/print.o + $(TEST_DIR)/vm.o $(TEST_DIR)/port80.flat: $(cstart.o) $(TEST_DIR)/port80.o $(TEST_DIR)/tsc.flat: $(cstart.o) $(TEST_DIR)/tsc.o -$(TEST_DIR)/apic.flat: $(cstart.o) $(TEST_DIR)/apic.o $(TEST_DIR)/vm.o \ - $(TEST_DIR)/print.o +$(TEST_DIR)/apic.flat: $(cstart.o) $(TEST_DIR)/apic.o $(TEST_DIR)/vm.o $(TEST_DIR)/realmode.flat: $(TEST_DIR)/realmode.o $(CC) -m32 -nostdlib -o $@ -Wl,-T,$(TEST_DIR)/realmode.lds $^
@@ -66,7 +65,7 @@ $(TEST_DIR)/idt_test.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/idt_test.o $(TEST_DIR)/xsave.flat: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/xsave.o $(TEST_DIR)/rmap_chain.flat: $(cstart.o) $(TEST_DIR)/rmap_chain.o \ - $(TEST_DIR)/print.o $(TEST_DIR)/vm.o + $(TEST_DIR)/vm.o $(TEST_DIR)/svm.flat: $(cstart.o) $(TEST_DIR)/vm.o
x86/print.S deleted +0 -31
@@ -1,31 +0,0 @@ - -#include "print.h" - -#define PSEUDO_SERIAL_PORT 0xf1 - - -.text - PRINT "boo" - hlt -1: jmp 1b - -.globl print -print: - push %rax - push %rsi - push %rdx - - mov %rdi, %rsi - mov $(PSEUDO_SERIAL_PORT), %edx - -putchar: - cmpb $0, (%rsi) - jz done - outsb - jmp putchar -done: - - pop %rdx - pop %rsi - pop %rax - ret
PATCH 6/10 Remove the duplicated rdmsr/wrmsr
In reply to Jason WangThey have been implemented in lib/x86/processor.h. Also rename the cpuid to cpuid_test because cpuid have been defined.
--- x86/msr.c | 16 +--------------- x86/vmexit.c | 20 +++----------------- 2 files changed, 4 insertions(+), 32 deletions(-)
x86/msr.c +1 -15
@@ -1,6 +1,7 @@/* msr tests */ #include "libcflat.h" +#include "processor.h" struct msr_info {int index;
@@ -87,21 +88,6 @@ static void report(const char *name, int passed)printf ("%s: %s\n" , name, passed ?"PASS" :"FAIL" ); } -static void wrmsr (unsigned index,unsigned long long value) -{ -unsigned a = value, d = value >>32 ; - - asmvolatile ("wrmsr" : :"a" (a),"d" (d),"c" (index)); -} - -static unsigned long long rdmsr (unsigned index) -{ -unsigned a, d; - - asmvolatile ("rdmsr" :"=a" (a),"=d" (d) :"c" (index)); -return ((unsigned long long )d <<32 ) | a; -} -static void test_msr_rw (int msr_index,unsigned long long input,unsigned long long expected) {unsigned long long r =0 ;
x86/vmexit.c +3 -17
@@ -1,6 +1,7 @@#include "libcflat.h" #include "smp.h" +#include "processor.h" static inline unsigned long long rdtsc () {
@@ -32,7 +33,7 @@ static unsigned int inl(unsigned short port)# define R "e"#endif -static void cpuid (void ) +static void cpuid_test (void ) { asmvolatile ("push %%" R "bx; cpuid; pop %%" R "bx" : : :"eax" ,"ecx" ,"edx" );
@@ -48,21 +49,6 @@ static void vmcall(void)#define MSR_EFER 0xc0000080#define EFER_NX_MASK (1ull << 11) -unsigned long long rdmsr (unsigned index) -{ -unsigned a, d; - - asmvolatile ("rdmsr" :"=a" (a),"=d" (d) :"c" (index)); -return ((unsigned long long )d <<32 ) | a; -} - -void wrmsr (unsigned index,unsigned long long val) -{ -unsigned a = val, d = val >>32 ; - - asmvolatile ("wrmsr" : :"a" (a),"d" (d),"c" (index)); -} -static void mov_from_cr8 (void ) {unsigned long cr8;
@@ -112,7 +98,7 @@ static struct test {int (*valid)(void );int parallel; } tests[] = { - { cpuid, "cpuid", .parallel = 1, }, + { cpuid_test, "cpuid", .parallel = 1, }, { vmcall, "vmcall", .parallel = 1, }, { mov_from_cr8, "mov_from_cr8", .parallel = 1, }, { mov_to_cr8, "mov_to_cr8" , .parallel = 1, },
PATCH 7/10 Correct the tss size
In reply to Jason WangTSS size should be 104 byte.
--- x86/cstart64.S | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
x86/cstart64.S +1 -1
@@ -69,7 +69,7 @@ tss: .long 0 .quad ring0stacktop - i * 4096 .quad 0, 0, 0 - .quad 0, 0, 0, 0, 0, 0, 0, 0 + .quad 0, 0, 0, 0, 0, 0, 0 .long 0, 0, 0 i = i + 1 .endr
Re: [PATCH kvm-unit-tests 07/10] Correct the tss size
Quoted 12 lines · Jason Wang
TSS size should be 104 byte.
Signed-off-by Jason Wang<[email protected]>--- x86/cstart64.S | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)x86/cstart64.S +0
-0
x86/cstart64.S tss: · line 70
Quoted 2 lines
x86/cstart64.S +0
-0@@ -69,7 +69,7 @@ tss: .long 0 .quad ring0stacktop - i * 4096
ring 0 stack
x86/cstart64.S tss: · line 71
Quoted 1 line
x86/cstart64.S +0
-0.quad 0, 0, 0
rings 1, 2, 3 stack
x86/cstart64.S tss: · line 72
Quoted 1 line
x86/cstart64.S +0
-1- .quad 0, 0, 0, 0, 0, 0, 0, 0
1 qword reserved, 7 qwords IST
x86/cstart64.S tss: · line 73
Quoted 2 lines
x86/cstart64.S +1
-0+ .quad 0, 0, 0, 0, 0, 0, 0 .long 0, 0, 0
3 dwords reserved + I/O map base address - so this looks correct?
Quoted 3 lines
x86/cstart64.S +0
-0i = i + 1 .endr
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH 8/10 Check whether in long mode before testing vmexit caused by cr8 access
In reply to Jason WangCR8 is only availabe when in long mode.
--- x86/vmexit.c | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-)
x86/vmexit.c +12 -2
@@ -48,6 +48,7 @@ static void vmcall(void)#define MSR_EFER 0xc0000080#define EFER_NX_MASK (1ull << 11) +#define EFER_LMA_MASK (1ull << 10)static void mov_from_cr8 (void ) {
@@ -68,6 +69,15 @@ static int is_smp(void)return cpu_count () >1 ; } +static int is_long_mode (void ) +{ +#ifdef __i386__ +return 0 ; +#else +return rdmsr (MSR_EFER ) |EFER_LMA_MASK ; +#endif +} +static void nop (void *junk) { }
@@ -100,8 +110,8 @@ static struct test { } tests[] = { { cpuid_test, "cpuid", .parallel = 1, }, { vmcall, "vmcall", .parallel = 1, }, - { mov_from_cr8, "mov_from_cr8", .parallel = 1, }, - { mov_to_cr8, "mov_to_cr8" , .parallel = 1, }, + { mov_from_cr8, "mov_from_cr8", is_long_mode, .parallel = 1, }, + { mov_to_cr8, "mov_to_cr8" , is_long_mode, .parallel = 1, }, { inl_pmtimer, "inl_from_pmtimer", .parallel = 1, }, { ipi, "ipi", is_smp, .parallel = 0, }, { ipi_halt, "ipi+halt", is_smp, .parallel = 0, },
Re: [PATCH kvm-unit-tests 08/10] Check whether in long mode before testing vmexit caused by cr8 access
Quoted 36 lines · Jason Wang
CR8 is only availabe when in long mode.
Signed-off-by Jason Wang<[email protected]>--- x86/vmexit.c | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-)x86/vmexit.c +10
-0@@ -48,6 +48,7 @@ static void vmcall(void)#define MSR_EFER 0xc0000080#define EFER_NX_MASK (1ull<< 11) +#define EFER_LMA_MASK (1ull<< 10)static void mov_from_cr8 (void ) {@@ -68,6 +69,15 @@ static int is_smp(void)return cpu_count ()>1 ; } +static int is_long_mode (void ) +{ +#ifdef __i386__ +return 0 ; +#else +return rdmsr (MSR_EFER ) |EFER_LMA_MASK ; +#endif +} +static void nop (void *junk) { }
x86/vmexit.c static struct test { · line 117
Quoted 10 lines
x86/vmexit.c +2
-2@@ -100,8 +110,8 @@ static struct test { } tests[] = { { cpuid_test, "cpuid", .parallel = 1, }, { vmcall, "vmcall", .parallel = 1, }, - { mov_from_cr8, "mov_from_cr8", .parallel = 1, }, - { mov_to_cr8, "mov_to_cr8" , .parallel = 1, }, + { mov_from_cr8, "mov_from_cr8", is_long_mode, .parallel = 1, }, + { mov_to_cr8, "mov_to_cr8" , is_long_mode, .parallel = 1, }, { inl_pmtimer, "inl_from_pmtimer", .parallel = 1, }, { ipi, "ipi", is_smp, .parallel = 0, }, { ipi_halt, "ipi+halt", is_smp, .parallel = 0, },
Enough to #ifdef __x86_64__. If it's defined we're in long mode.
Signature · 1 line
error compiling committee.c: too many arguments to function
PATCH 9/10 Do not test IA32_EFER in 32bit mode.
In reply to Jason Wang--- x86/msr.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
x86/msr.c +2 -0
@@ -49,9 +49,11 @@ struct msr_info msr_info[] = { .index = 0xc0000102, .name = "MSR_KERNEL_GS_BASE", .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}} }, +#ifdef __x86_64__ { .index = 0xc0000080, .name = "MSR_EFER", .val_pairs = {{ .valid = 1, .value = 0xD00, .expected = 0xD00}} }, +#endif { .index = 0xc0000082, .name = "MSR_LSTAR", .val_pairs = {{ .valid = 1, .value = addr_64, .expected = addr_64}} },
PATCH 10/10 Add the 32bit smp initialization code
In reply to Jason WangAdd the smp initlaization codes for 32bit. This would make the 32bit smp tests available.
--- x86/cstart.S | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 173 insertions(+), 6 deletions(-)
x86/cstart.S +173 -6
@@ -1,9 +1,65 @@ +#include "apic-defs.h" + +.globl boot_idt +boot_idt = 0 + +ipi_vector = 0x20 + +max_cpus = 4 .bss + . = . + 4096 * max_cpus + .align 16 +stacktop: + + . = . + 4096 + .align 16 +ring0stacktop: + +.data + +.align 4096 +pt: +i = 0 + .rept 1024 + .long 0x1e7 | (i << 22) + i = i + 1 + .endr + +gdt32: + .quad 0 + .quad 0x00cf9b000000ffff // flat 32-bit code segment + .quad 0x00cf93000000ffff // flat 32-bit data segment + +tss_descr: + .rept max_cpus + .quad 0x000089000000ffff // 32-bit avail tss + .endr +gdt32_end: + +i = 0 +tss: + .rept max_cpus + .long 0 + .long ring0stacktop - i * 4096 + .long 0 + .quad 0, 0, 0 + .quad 0, 0, 0, 0, 0, 0, 0 + .long 0, 0, 0 + i = i + 1 + .endr +tss_end: + +idt_descr: + .word 16 * 256 - 1 + .long boot_idt + .section .init +.code32 + mb_magic = 0x1BADB002 mb_flags = 0x0
@@ -11,15 +67,126 @@ mb_flags = 0x0 .long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) mb_cmdline = 16 +MSR_GS_BASE = 0xc0000101 + +.macro setup_percpu_area + lea -4096(%esp), %eax + mov $0, %edx + mov $MSR_GS_BASE, %ecx + wrmsr +.endm + .globl start start: - mov mb_cmdline(%ebx), %eax - mov %eax, __args - call __setup_args - pushl $__argv - pushl __argc - call main + mov mb_cmdline(%ebx), %eax + mov %eax, __args + call __setup_args + mov $stacktop, %esp + setup_percpu_area + call prepare_32 + jmpl $8, $start32 + +prepare_32: + lgdtl gdt32_descr + + mov %cr4, %eax + bts $4, %eax // pse + mov %eax, %cr4 + + mov $pt, %eax + mov %eax, %cr3 + + mov %cr0, %eax + bts $0, %eax + bts $31, %eax + mov %eax, %cr0 + ret + +smp_stacktop: .long 0xa0000 + +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 + setup_percpu_area + call prepare_32 + call load_tss + call enable_apic + call enable_x2apic + sti + nop + lock incw cpu_online_count + +1: hlt + jmp 1b + +start32: + call load_tss + call mask_pic_interrupts + call enable_apic + call smp_init + call enable_x2apic + push $__argv + push __argc + call main push %eax call exit +load_tss: + lidt idt_descr + mov $16, %eax + mov %ax, %ss + mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax + mov (%eax), %eax + shr $24, %eax + mov %eax, %ebx + shl $3, %ebx + mov $((tss_end - tss) / max_cpus), %edx + imul %edx + add $tss, %eax + mov %ax, tss_descr+2(%ebx) + shr $16, %eax + mov %al, tss_descr+4(%ebx) + shr $8, %eax + mov %al, tss_descr+7(%ebx) + lea tss_descr-gdt32(%ebx), %eax + ltr %ax + ret + +smp_init: + cld + lea sipi_entry, %esi + xor %edi, %edi + mov $(sipi_end - sipi_entry), %ecx + rep/movsb + mov $APIC_DEFAULT_PHYS_BASE, %eax + movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT | APIC_INT_ASSERT), APIC_ICR(%eax) + movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_INIT), APIC_ICR(%eax) + movl $(APIC_DEST_ALLBUT | APIC_DEST_PHYSICAL | APIC_DM_STARTUP), APIC_ICR(%eax) + call fwcfg_get_nb_cpus +1: pause + cmpw %ax, cpu_online_count + jne 1b +smp_init_done: + ret + +cpu_online_count: .word 1 + +.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: