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