diff options
| author | Roger Pau Monné <royger@FreeBSD.org> | 2018-04-05 14:39:51 +0000 |
|---|---|---|
| committer | Roger Pau Monné <royger@FreeBSD.org> | 2018-04-05 14:39:51 +0000 |
| commit | 9dba82a4422a50722d40bf5318e6de204c1e372a (patch) | |
| tree | 375b46e497b395cbac9a906ebf91d7db7414a2b8 /sys/amd64 | |
| parent | 319cc4a70059e20e5c43e6704485139a3398ebf0 (diff) | |
Notes
Diffstat (limited to 'sys/amd64')
| -rw-r--r-- | sys/amd64/amd64/machdep.c | 10 | ||||
| -rw-r--r-- | sys/amd64/amd64/mp_machdep.c | 45 | ||||
| -rw-r--r-- | sys/amd64/amd64/mpboot.S | 8 | ||||
| -rw-r--r-- | sys/amd64/include/smp.h | 2 |
4 files changed, 44 insertions, 21 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index a24546df23178..22cdb3fe6c22e 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1246,14 +1246,10 @@ getmemsize(caddr_t kmdp, u_int64_t first) * Make hole for "AP -> long mode" bootstrap code. The * mp_bootaddress vector is only available when the kernel * is configured to support APs and APs for the system start - * in 32bit mode (e.g. SMP bare metal). + * in real mode mode (e.g. SMP bare metal). */ - if (init_ops.mp_bootaddress) { - if (physmap[1] >= 0x100000000) - panic( - "Basemem segment is not suitable for AP bootstrap code!"); - physmap[1] = init_ops.mp_bootaddress(physmap[1] / 1024); - } + if (init_ops.mp_bootaddress) + init_ops.mp_bootaddress(physmap, &physmap_idx); /* * Maxmem isn't the "maximum memory", it's one larger than the diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 34012d2b4f968..7ef2c241e042a 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -96,24 +96,45 @@ char *nmi_stack; static int start_ap(int apic_id); -static u_int bootMP_size; -static u_int boot_address; - /* * Calculate usable address in base memory for AP trampoline code. */ -u_int -mp_bootaddress(u_int basemem) +void +mp_bootaddress(vm_paddr_t *physmap, unsigned int *physmap_idx) { + unsigned int i; + bool allocated; + + alloc_ap_trampoline(physmap, physmap_idx); - bootMP_size = mptramp_end - mptramp_start; - boot_address = trunc_page(basemem * 1024); /* round down to 4k boundary */ - if (((basemem * 1024) - boot_address) < bootMP_size) - boot_address -= PAGE_SIZE; /* not enough, lower by 4k */ - /* 3 levels of page table pages */ - mptramp_pagetables = boot_address - (PAGE_SIZE * 3); + allocated = false; + for (i = *physmap_idx; i <= *physmap_idx; i -= 2) { + /* + * Find a memory region big enough below the 4GB boundary to + * store the initial page tables. Note that it needs to be + * aligned to a page boundary. + */ + if (physmap[i] >= GiB(4) || + (physmap[i + 1] - round_page(physmap[i])) < (PAGE_SIZE * 3)) + continue; - return mptramp_pagetables; + allocated = true; + mptramp_pagetables = round_page(physmap[i]); + physmap[i] = round_page(physmap[i]) + (PAGE_SIZE * 3); + if (physmap[i] == physmap[i + 1] && *physmap_idx != 0) { + memmove(&physmap[i], &physmap[i + 2], + sizeof(*physmap) * (*physmap_idx - i + 2)); + *physmap_idx -= 2; + } + } + + if (!allocated) { + mptramp_pagetables = trunc_page(boot_address) - (PAGE_SIZE * 3); + if (bootverbose) + printf( +"Cannot find enough space for the initial AP page tables, placing them at %#x", + mptramp_pagetables); + } } /* diff --git a/sys/amd64/amd64/mpboot.S b/sys/amd64/amd64/mpboot.S index 8af5a7898c9a2..5545fe9290d14 100644 --- a/sys/amd64/amd64/mpboot.S +++ b/sys/amd64/amd64/mpboot.S @@ -216,8 +216,14 @@ lgdt_desc: .word gdtend-gdt /* Length */ .long gdt-mptramp_start /* Offset plus %ds << 4 */ - .globl mptramp_end mptramp_end: + /* + * The size of the trampoline code that needs to be relocated + * below the 1MiB boundary. + */ + .globl bootMP_size +bootMP_size: + .long mptramp_end - mptramp_start /* * From here on down is executed in the kernel .text section. diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h index 64135bc36f580..2ecfe62cf9fbf 100644 --- a/sys/amd64/include/smp.h +++ b/sys/amd64/include/smp.h @@ -23,7 +23,6 @@ /* global symbols in mpboot.S */ extern char mptramp_start[]; -extern char mptramp_end[]; extern u_int32_t mptramp_pagetables; /* IPI handlers */ @@ -59,6 +58,7 @@ void invlpg_pcid_handler(void); void invlrng_invpcid_handler(void); void invlrng_pcid_handler(void); int native_start_all_aps(void); +void mp_bootaddress(vm_paddr_t *, unsigned int *); #endif /* !LOCORE */ #endif /* SMP */ |
