Hello,

Damien Zammit via Bug reports for the GNU Hurd, le ven. 02 janv. 2026 04:16:17 
+0000, a ecrit:
> This hardcodes the AP boot address to 0x11000

We should really avoid that, that'll be a headache long-term.

> so that we do not need to patch the ljmp absolute address in the code
> segment at runtime when flushing the gdt.

We don't actually need that, see how I have now fixed it in the 32b
version.

> Also becomes easier to write 64 bit AP bringup.

Making some code easy is not really an argument for introducing more
technical debt somewhere else.

Samuel

> ---
>  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