Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F156772923
D14878.id40834.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D14878.id40834.diff
View Options
Index: sys/amd64/amd64/machdep.c
===================================================================
--- sys/amd64/amd64/machdep.c
+++ sys/amd64/amd64/machdep.c
@@ -1245,14 +1245,10 @@
* 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
Index: sys/amd64/amd64/mp_machdep.c
===================================================================
--- sys/amd64/amd64/mp_machdep.c
+++ sys/amd64/amd64/mp_machdep.c
@@ -102,18 +102,82 @@
/*
* 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;
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 and below the 1MB boundary
+ * for the trampoline code.
+ * NB: needs to be page aligned.
+ */
+ if (physmap[i] >= MiB(1) ||
+ (trunc_page(physmap[i + 1]) - round_page(physmap[i])) <
+ round_page(bootMP_size))
+ continue;
+
+ allocated = true;
+ /*
+ * Try to steal from the end of the region to mimic previous
+ * behaviour, else fallback to steal from the start.
+ */
+ if (physmap[i + 1] < MiB(1)) {
+ boot_address = trunc_page(physmap[i + 1]);
+ if ((physmap[i + 1] - boot_address) < bootMP_size)
+ boot_address -= round_page(bootMP_size);
+ physmap[i + 1] = boot_address;
+ } else {
+ boot_address = round_page(physmap[i]);
+ physmap[i] = boot_address + round_page(bootMP_size);
+ }
+ 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) {
+ boot_address = basemem * 1024 - bootMP_size;
+ if (bootverbose)
+ printf(
+"Cannot find enough space for the boot trampoline, placing it at %#x",
+ boot_address);
+ }
- return mptramp_pagetables;
+ 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;
+
+ 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);
+ }
}
/*
Index: sys/i386/i386/machdep.c
===================================================================
--- sys/i386/i386/machdep.c
+++ sys/i386/i386/machdep.c
@@ -1902,7 +1902,7 @@
#ifdef SMP
/* make hole for AP bootstrap code */
- physmap[1] = mp_bootaddress(physmap[1]);
+ mp_bootaddress(physmap, &physmap_idx);
#endif
/*
Index: sys/i386/i386/mp_machdep.c
===================================================================
--- sys/i386/i386/mp_machdep.c
+++ sys/i386/i386/mp_machdep.c
@@ -144,15 +144,52 @@
/*
* 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;
+
+ allocated = false;
+ for (i = *physmap_idx; i <= *physmap_idx; i -= 2) {
+ /*
+ * Find a memory region big enough and below the 1MB boundary
+ * for the trampoline code.
+ * NB: needs to be page aligned.
+ */
+ if (physmap[i] >= MiB(1) ||
+ (trunc_page(physmap[i + 1]) - round_page(physmap[i])) <
+ round_page(bootMP_size))
+ continue;
+
+ allocated = true;
+ /*
+ * Try to steal from the end of the region to mimic previous
+ * behaviour, else fallback to steal from the start.
+ */
+ if (physmap[i + 1] < MiB(1)) {
+ boot_address = trunc_page(physmap[i + 1]);
+ if ((physmap[i + 1] - boot_address) < bootMP_size)
+ boot_address -= round_page(bootMP_size);
+ physmap[i + 1] = boot_address;
+ } else {
+ boot_address = round_page(physmap[i]);
+ physmap[i] = boot_address + round_page(bootMP_size);
+ }
+ if (physmap[i] == physmap[i + 1] && *physmap_idx != 0) {
+ memmove(&physmap[i], &physmap[i + 2],
+ sizeof(*physmap) * (*physmap_idx - i + 2));
+ *physmap_idx -= 2;
+ }
+ }
- boot_address = trunc_page(basemem); /* round down to 4k boundary */
- if ((basemem - boot_address) < bootMP_size)
- boot_address -= PAGE_SIZE; /* not enough, lower by 4k */
-
- return boot_address;
+ if (!allocated) {
+ boot_address = basemem * 1024 - bootMP_size;
+ if (bootverbose)
+ printf(
+"Cannot find enough space for the boot trampoline, placing it at %#x",
+ boot_address);
+ }
}
/*
Index: sys/sys/param.h
===================================================================
--- sys/sys/param.h
+++ sys/sys/param.h
@@ -362,4 +362,8 @@
*/
#define __PAST_END(array, offset) (((__typeof__(*(array)) *)(array))[offset])
+/* Unit conversion macros. */
+#define GiB(v) (v ## ULL << 30)
+#define MiB(v) (v ## ULL << 20)
+
#endif /* _SYS_PARAM_H_ */
Index: sys/x86/include/init.h
===================================================================
--- sys/x86/include/init.h
+++ sys/x86/include/init.h
@@ -41,7 +41,7 @@
void (*early_clock_source_init)(void);
void (*early_delay)(int);
void (*parse_memmap)(caddr_t, vm_paddr_t *, int *);
- u_int (*mp_bootaddress)(u_int);
+ void (*mp_bootaddress)(vm_paddr_t *, unsigned int *);
int (*start_all_aps)(void);
void (*msi_init)(void);
};
Index: sys/x86/include/x86_smp.h
===================================================================
--- sys/x86/include/x86_smp.h
+++ sys/x86/include/x86_smp.h
@@ -95,7 +95,7 @@
void ipi_cpu(int cpu, u_int ipi);
int ipi_nmi_handler(void);
void ipi_selected(cpuset_t cpus, u_int ipi);
-u_int mp_bootaddress(u_int);
+void mp_bootaddress(vm_paddr_t *, unsigned int *);
void set_interrupt_apic_ids(void);
void smp_cache_flush(void);
void smp_masked_invlpg(cpuset_t mask, vm_offset_t addr, struct pmap *pmap);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, May 17, 6:22 AM (16 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33179579
Default Alt Text
D14878.id40834.diff (7 KB)
Attached To
Mode
D14878: x86: improve reservation of AP trampoline memory
Attached
Detach File
Event Timeline
Log In to Comment