aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2018-04-05 14:39:51 +0000
committerRoger Pau Monné <royger@FreeBSD.org>2018-04-05 14:39:51 +0000
commit9dba82a4422a50722d40bf5318e6de204c1e372a (patch)
tree375b46e497b395cbac9a906ebf91d7db7414a2b8 /sys/amd64
parent319cc4a70059e20e5c43e6704485139a3398ebf0 (diff)
Notes
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/machdep.c10
-rw-r--r--sys/amd64/amd64/mp_machdep.c45
-rw-r--r--sys/amd64/amd64/mpboot.S8
-rw-r--r--sys/amd64/include/smp.h2
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 */