Add smp initlaization codes for 32bit. This would make the 32bit
smp tests available.

Signed-off-by: Jason Wang <jasow...@redhat.com>
---
 x86/cstart.S |  179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 173 insertions(+), 6 deletions(-)

diff --git a/x86/cstart.S b/x86/cstart.S
index 1bdf789..ae1fdbb 100644
--- a/x86/cstart.S
+++ b/x86/cstart.S
@@ -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 16
+        .quad 0, 0
+        .quad 0, 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:

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to