This hardcodes the AP boot address to 0x11000 so that we do not need
to patch the ljmp absolute address in the code segment at runtime when flushing 
the gdt.
This is safer so code segment remains read-only.
Also becomes easier to write 64 bit AP bringup.

---
 i386/Makefrag.am        |  3 +++
 i386/i386/cpuboot.S     | 41 +++++++++++++++++++----------------------
 i386/i386/i386asm.sym   |  3 +++
 i386/i386/model_dep.h   |  7 +++----
 i386/i386/mp_desc.c     | 13 ++++++-------
 i386/i386at/biosmem.c   |  7 +++----
 i386/i386at/boothdr.S   | 23 +++++++++--------------
 i386/i386at/model_dep.c | 19 ++++---------------
 i386/ldscript           | 15 +++++++++++++++
 x86_64/Makefrag.am      |  2 ++
 x86_64/boothdr.S        | 22 +++++++++-------------
 x86_64/ldscript         | 15 +++++++++++++++
 12 files changed, 91 insertions(+), 79 deletions(-)

diff --git a/i386/Makefrag.am b/i386/Makefrag.am
index 906ccc2d..f8792030 100644
--- a/i386/Makefrag.am
+++ b/i386/Makefrag.am
@@ -165,10 +165,13 @@ nodist_libkernel_a_SOURCES += \
 # Architecture specialities.
 #
 
+SIPI_AP_ADDR=0x11000
+
 if PLATFORM_at
 gnumach_LINKFLAGS += \
        --defsym _START_MAP=$(_START_MAP) \
        --defsym _START=_START_MAP+0xC0000000 \
+       --defsym SIPI_AP_ADDR=$(SIPI_AP_ADDR) \
        -T '$(srcdir)'/i386/ldscript
 endif
 
diff --git a/i386/i386/cpuboot.S b/i386/i386/cpuboot.S
index 76de8714..94280de6 100644
--- a/i386/i386/cpuboot.S
+++ b/i386/i386/cpuboot.S
@@ -34,7 +34,7 @@
 #define GDT_DESCR_M32  4
 #define GDT_TABLE_M32  (14*2)
 
-.data
+.section .data
 
 .align 16
 apboot_idt_ptr:
@@ -98,20 +98,24 @@ apboot_gdt:
        /* boot GS = 0x68 */
        .word 0xffff
 apboot_percpu_low:
-       .word 0
+       .word (-KERNELBASE) & 0xffff
 apboot_percpu_med:
-       .byte 0
+       .byte ((-KERNELBASE) >> 16) & 0xff
        .byte ACC_PL_K | ACC_DATA_W | ACC_P
        .byte ((SZ_32 | SZ_G) << 4) | 0xf
 apboot_percpu_high:
-       .byte 0
+       .byte ((-KERNELBASE) >> 24) & 0xff
 
 /* Empty space for per-cpu gdt descriptor and gdt */
 .space (NCPUS-1) * (GDT_DESCR_M32 + GDT_TABLE_M32) * 4, 0x0
 
-.globl apboot, apbootend, gdt_descr_tmp, apboot_jmp_offset
-.align 16
-.code16
+/* NOTE: apboot16 section is auto-loaded at runtime to just above 64k
+ * so it can be called as a SIPI vector.  Relocations are thus computed simply.
+ */
+.section .apboot16.text,"ax",@progbits
+.globl apboot, apbootend
+.align 4096
+       .code16
 
 apboot:
 _apboot:
@@ -137,15 +141,14 @@ _apboot:
        orl     $CR0_SET_FLAGS, %eax
        movl    %eax, %cr0
 
-       /* ljmpl with relocation from machine_init */
+       /* ljmpl with no relocation */
        .byte 0x66
        .byte 0xea
-apboot_jmp_offset:
-       .long M(0f)
+       .long 0f
        .word BOOT_CS
 
-0:
        .code32
+0:
        /* Protected mode! */
        movw    $BOOT_DS, %ax
        movw    %ax, %ds
@@ -153,13 +156,8 @@ apboot_jmp_offset:
        movw    %ax, %ss
 
        lgdtl   apboot_gdt_descr - KERNELBASE
-       ljmpl   $KERNEL_CS, $1f
+       ljmpl   $KERNEL_CS, $(1f + KERNELBASE)
 1:
-       xorl    %eax, %eax
-       movw    %ax, %ds
-       movw    %ax, %es
-       movw    %ax, %fs
-       movw    %ax, %gs
        movw    $KERNEL_DS, %ax
        movw    %ax, %ds
        movw    %ax, %es
@@ -213,14 +211,13 @@ apboot_jmp_offset:
 
        /* Reload our copy of gdt */
        lgdtl   apboot_gdt_descr(%eax)
-       ljmpl   $KERNEL_CS, $2f
+       ljmpl   $KERNEL_CS, $(2f + KERNELBASE)
 2:
-
        movw    $PERCPU_DS, %ax
        movw    %ax, %gs
 
        /* Load null Interrupt descriptor table */
-       mov     apboot_idt_ptr, %ebx
+       movl    $apboot_idt_ptr, %ebx
        lidt    (%ebx)
 
        /* Enable local apic in xAPIC mode */
@@ -245,7 +242,7 @@ apboot_jmp_offset:
        popfl
 
        /* Finish the cpu configuration */
-       call EXT(cpu_ap_main)
+       call EXT(cpu_ap_main) - KERNELBASE
 
 3:
        /* NOT REACHED */
@@ -256,7 +253,7 @@ apboot_jmp_offset:
     .word 0
 gdt_descr_tmp:
     .short 3*8-1
-    .long M(gdt_tmp)
+    .long gdt_tmp
 
 .align 16
 gdt_tmp:
diff --git a/i386/i386/i386asm.sym b/i386/i386/i386asm.sym
index e1f5c6bb..d9c51f04 100644
--- a/i386/i386/i386asm.sym
+++ b/i386/i386/i386asm.sym
@@ -45,6 +45,7 @@
 #include <i386/gdt.h>
 #include <i386/ldt.h>
 #include <i386/mp_desc.h>
+#include <i386/model_dep.h>
 #include <i386/apic.h>
 #include <i386/xen.h>
 
@@ -132,6 +133,8 @@ offset      i386_tss                tss     ss0
 
 offset machine_slot            sub_type        cpu_type
 
+expr   SIPI_AP_ADDR
+expr   SIPI_AP_LENGTH
 expr   I386_PGBYTES                                    NBPG
 expr   VM_MIN_ADDRESS
 expr   VM_MAX_ADDRESS
diff --git a/i386/i386/model_dep.h b/i386/i386/model_dep.h
index 5369e288..62532215 100644
--- a/i386/i386/model_dep.h
+++ b/i386/i386/model_dep.h
@@ -28,10 +28,9 @@
 
 #include <mach/std_types.h>
 
-/*
- * Address to hold AP boot code, held in ASM
- */
-extern phys_addr_t apboot_addr;
+/* Hardcoded AP boot code address */
+#define SIPI_AP_ADDR   0x11000
+#define SIPI_AP_LENGTH (0x20000 - SIPI_AP_ADDR)
 
 /*
  * Find devices.  The system is alive.
diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c
index e67aa767..b6778531 100644
--- a/i386/i386/mp_desc.c
+++ b/i386/i386/mp_desc.c
@@ -45,6 +45,7 @@
 #include <i386at/int_init.h>
 #include <i386/cpu.h>
 #include <i386/smp.h>
+#include <i386/model_dep.h>
 
 #include <i386at/model_dep.h>
 #include <machine/ktss.h>
@@ -95,10 +96,11 @@ interrupt_stack_alloc(void)
 }
 
 #if    NCPUS > 1
-phys_addr_t apboot_addr;
-extern void *apboot, *apbootend;
 extern volatile ApicLocalUnit* lapic;
 
+/* This is needed to stop the linker dropping the .apboot16 section. */
+extern uint32_t *apboot;
+
 /*
  * Multiprocessor i386/i486 systems use a separate copy of the
  * GDT, IDT, LDT, and kernel TSS per processor.  The first three
@@ -282,13 +284,10 @@ start_other_cpus(void)
        if (ncpus == 1)
          return;
 
-       //Copy cpu initialization assembly routine
-       memcpy((void*) phystokv(apboot_addr), (void*) &apboot,
-              (uint32_t)&apbootend - (uint32_t)&apboot);
-
        unsigned cpu = cpu_number_slow();
 
        assert (cpu == 0);
+       assert (phystokv(&apboot) != 0);
 
        splhigh();
 
@@ -310,7 +309,7 @@ start_other_cpus(void)
                machine_slot[cpu].running = FALSE;
        }
 
-       smp_startup_cpus(apic_get_current_cpu(), apboot_addr);
+       smp_startup_cpus(apic_get_current_cpu(), SIPI_AP_ADDR);
 
        for (cpu = 1; cpu < ncpus; cpu++) {
                printf("Waiting for AP %d\n", cpu);
diff --git a/i386/i386at/biosmem.c b/i386/i386at/biosmem.c
index 7cf7e171..e117a359 100644
--- a/i386/i386at/biosmem.c
+++ b/i386/i386at/biosmem.c
@@ -690,12 +690,11 @@ biosmem_bootstrap_common(void)
         boot_panic(biosmem_panic_noseg_msg);
 
 #if !defined(MACH_HYP) && NCPUS > 1
-    /*
-     * Grab an early page for AP boot code which needs to be below 1MB.
-     */
     assert (phys_start < 0x100000);
-    apboot_addr = phys_start;
+    /* Grab an early page for multiboot header. */
     phys_start += PAGE_SIZE;
+    /* Skip over AP boot code. */
+    phys_start += SIPI_AP_LENGTH;
 #endif
 
     biosmem_set_segment(VM_PAGE_SEG_DMA, phys_start, phys_end);
diff --git a/i386/i386at/boothdr.S b/i386/i386at/boothdr.S
index ff055746..69efdbdc 100644
--- a/i386/i386at/boothdr.S
+++ b/i386/i386at/boothdr.S
@@ -12,20 +12,10 @@
 #endif /* __ELF__ */
 #define MULTIBOOT_FLAGS        MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | 
MULTIBOOT_VIDEO_MODE | AOUT_KLUDGE
 
-       /*
-        * This section will be put first into .text.  See also i386/ldscript.
-        */
-       .section .text.start,"ax"
-       
-       /* We should never be entered this way.  */
-       .globl  start,_start
-start:
-_start:
-       jmp     boot_entry
-
-       /* MultiBoot header - see multiboot.h.  */
-       P2ALIGN(2)
+       .section .multiboot,"ax",@progbits
+       .align 8
 boot_hdr:
+       /* MultiBoot header - see multiboot.h.  */
        .long   MULTIBOOT_MAGIC
        .long   MULTIBOOT_FLAGS
                /*
@@ -51,7 +41,12 @@ boot_hdr:
         .long  25
         .long  MULTIBOOT_VIDEO_PARAM_NO_PREFERENCE
 
-boot_entry:
+       .section .text,"ax",@progbits
+       .globl boot_start
+       .global _start
+boot_start:
+_start:
+       .code32
        movl    $percpu_array - KERNELBASE, %eax
        movw    %ax, boot_percpu_low - KERNELBASE
        shr     $16, %eax
diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c
index e713cc8a..14518e3e 100644
--- a/i386/i386at/model_dep.c
+++ b/i386/i386at/model_dep.c
@@ -127,12 +127,6 @@ char *kernel_cmdline = "";
 
 extern char    version[];
 
-/* Realmode temporary GDT */
-extern struct pseudo_descriptor gdt_descr_tmp;
-
-/* Realmode relocated jmp */
-extern uint32_t apboot_jmp_offset;
-
 /* If set, reboot the system on ctrl-alt-delete.  */
 boolean_t      rebootflag = FALSE;     /* exported to kdintr */
 
@@ -217,15 +211,6 @@ void machine_init(void)
        pmap_unmap_page_zero();
 #endif
 
-#if NCPUS > 1
-       /*
-        * Patch the realmode gdt with the correct offset and the first jmp to
-        * protected mode with the correct target.
-        */
-       gdt_descr_tmp.linear_base += apboot_addr;
-       apboot_jmp_offset += apboot_addr;
-#endif
-
 #ifdef APIC
        /*
         * Initialize the HPET
@@ -390,6 +375,10 @@ i386at_init(void)
 #ifdef MACH_HYP
        biosmem_xen_bootstrap();
 #else /* MACH_HYP */
+#if NCPUS > 1
+       /* Register one page for multiboot header plus the rest for AP boot 
code */
+       biosmem_register_boot_data(SIPI_AP_ADDR - PAGE_SIZE, SIPI_AP_ADDR + 
SIPI_AP_LENGTH, FALSE);
+#endif
        register_boot_data((struct multiboot_raw_info *) &boot_info);
        biosmem_bootstrap((struct multiboot_raw_info *) &boot_info);
 #endif /* MACH_HYP */
diff --git a/i386/ldscript b/i386/ldscript
index ddbbf910..1335653a 100644
--- a/i386/ldscript
+++ b/i386/ldscript
@@ -11,6 +11,21 @@ SECTIONS
    * be first in there.  See also `i386/i386at/boothdr.S' and
    * `gnumach_LINKFLAGS' in `i386/Makefrag.am'.
    */
+  . = SIPI_AP_ADDR - 1024;
+  .multiboot      : AT(SIPI_AP_ADDR - 1024)
+  {
+    /* The MultiBoot header section */
+    KEEP (*(.multiboot))
+  }
+
+  . = SIPI_AP_ADDR;
+  .apboot16       : AT(SIPI_AP_ADDR)
+  {
+    /* A realmode section for starting APs */
+    KEEP (*(.apboot16.text))
+    KEEP (*(.apboot16.data))
+  } =0x90909090
+
   . = _START;
   .text           :
   AT (_START_MAP)
diff --git a/x86_64/Makefrag.am b/x86_64/Makefrag.am
index e0d4d2f9..1fc3bcfd 100644
--- a/x86_64/Makefrag.am
+++ b/x86_64/Makefrag.am
@@ -207,6 +207,7 @@ endif
 #
 
 KERNEL_MAP_BASE=0xffffffff80000000
+SIPI_AP_ADDR=0x11000
 
 if PLATFORM_at
 # For now simply keep all the kernel virtual space in the last 2G.
@@ -218,6 +219,7 @@ gnumach_LINKFLAGS += \
        --defsym _START_MAP=$(_START_MAP) \
        --defsym _START=$(_START_MAP) \
        --defsym KERNEL_MAP_SHIFT=$(KERNEL_MAP_BASE) \
+       --defsym SIPI_AP_ADDR=$(SIPI_AP_ADDR) \
        -z max-page-size=0x1000 \
        -T '$(srcdir)'/x86_64/ldscript
 
diff --git a/x86_64/boothdr.S b/x86_64/boothdr.S
index abccec9a..88a77315 100644
--- a/x86_64/boothdr.S
+++ b/x86_64/boothdr.S
@@ -24,22 +24,14 @@
 #include <i386/i386/msr.h>
 #include <i386/i386/seg.h>
 #include <i386/apic.h>
-       /*
-        * This section will be put first into .boot.  See also x86_64/ldscript.
-        */
-       .section .boot.text,"ax"
-       /* We should never be entered this way.  */
-       .globl  boot_start
-boot_start:
 
-       .code32
-       jmp     boot_entry
-
-       /* MultiBoot header - see multiboot.h.  */
 #define        MULTIBOOT_MAGIC         0x1BADB002
 #define MULTIBOOT_FLAGS                0x00000003
-       P2ALIGN(2)
+
+       .section .multiboot,"ax"
+       .align 8
 boot_hdr:
+       /* MultiBoot header - see multiboot.h.  */
        .long   MULTIBOOT_MAGIC
        .long   MULTIBOOT_FLAGS
        /*
@@ -48,9 +40,13 @@ boot_hdr:
        */
        .long   - (MULTIBOOT_MAGIC+MULTIBOOT_FLAGS)
 
+       .section .boot.text,"ax"
+       .globl boot_start
        .global _start
+boot_start:
 _start:
-boot_entry:
+       .code32
+
        /* Enable local apic in xAPIC mode */
        xorl    %eax, %eax
        xorl    %edx, %edx
diff --git a/x86_64/ldscript b/x86_64/ldscript
index 67703b4d..2e371cd0 100644
--- a/x86_64/ldscript
+++ b/x86_64/ldscript
@@ -12,6 +12,21 @@ SECTIONS
    * `gnumach_LINKFLAGS' in `i386/Makefrag.am'.
    */
 
+  . = SIPI_AP_ADDR - 1024;
+  .multiboot      : AT(SIPI_AP_ADDR - 1024)
+  {
+    /* The MultiBoot header section */
+    KEEP (*(.multiboot))
+  }
+
+  . = SIPI_AP_ADDR;
+  .apboot16       : AT(SIPI_AP_ADDR)
+  {
+    /* A realmode section for starting APs */
+    KEEP (*(.apboot16.text))
+    KEEP (*(.apboot16.data))
+  } =0x90909090
+
   . = _START;
   .boot           : AT(_START_MAP)
   {
-- 
2.45.2



Reply via email to