git: a8d453eec1e3 - stable/13 - amd64: stop doing special allocation for the AP startup trampoline

Konstantin Belousov kib at FreeBSD.org
Mon Aug 23 23:22:21 UTC 2021


The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=a8d453eec1e3ea7c62e82a8e591035876da2580e

commit a8d453eec1e3ea7c62e82a8e591035876da2580e
Author:     Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-07-29 00:22:35 +0000
Commit:     Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-08-23 23:21:13 +0000

    amd64: stop doing special allocation for the AP startup trampoline
    
    (cherry picked from commit b27fe1c3ba2a1302c2866751e0c618b5a697bf30)
---
 sys/amd64/amd64/machdep.c    |  8 -------
 sys/amd64/amd64/mp_machdep.c | 19 +++++++++++----
 sys/i386/i386/mp_machdep.c   | 55 ++++++++++++++++++++++++++++++++++++++++++++
 sys/x86/include/x86_smp.h    | 10 ++++++--
 sys/x86/x86/mp_x86.c         | 54 -------------------------------------------
 5 files changed, 77 insertions(+), 69 deletions(-)

diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 840570be534a..63f933ad535c 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1281,14 +1281,6 @@ getmemsize(caddr_t kmdp, u_int64_t first)
 	    (boothowto & RB_VERBOSE))
 		printf("Physical memory use set to %ldK\n", Maxmem * 4);
 
-	/*
-	 * 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 real mode mode (e.g. SMP bare metal).
-	 */
-	alloc_ap_trampoline(physmap, &physmap_idx);
-
 	/* call pmap initialization to make new kernel address space */
 	pmap_bootstrap(&first);
 
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index 082a58ada48f..383226b96d10 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -112,7 +112,7 @@ extern u_int mptramp_nx;
  * Local data and functions.
  */
 
-static int	start_ap(int apic_id);
+static int start_ap(int apic_id, vm_paddr_t boot_address);
 
 /*
  * Initialize the IPI handlers and start up the AP's.
@@ -322,17 +322,25 @@ mp_realloc_pcpu(int cpuid, int domain)
 int
 native_start_all_aps(void)
 {
-	vm_page_t m_pml4, m_pdp, m_pd[4];
+	vm_page_t m_boottramp, m_pml4, m_pdp, m_pd[4];
 	pml5_entry_t old_pml45;
 	pml4_entry_t *v_pml4;
 	pdp_entry_t *v_pdp;
 	pd_entry_t *v_pd;
+	vm_paddr_t boot_address;
 	u_int32_t mpbioswarmvec;
 	int apic_id, cpu, domain, i;
 	u_char mpbiosreason;
 
 	mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
 
+	MPASS(bootMP_size <= PAGE_SIZE);
+	m_boottramp = vm_page_alloc_contig(NULL, 0, VM_ALLOC_NORMAL |
+	    VM_ALLOC_NOBUSY | VM_ALLOC_NOOBJ, 1, 0,
+	    (1ULL << 20), /* Trampoline should be below 1M for real mode */
+	    PAGE_SIZE, 0, VM_MEMATTR_DEFAULT);
+	boot_address = VM_PAGE_TO_PHYS(m_boottramp);
+
 	/* Create a transient 1:1 mapping of low 4G */
 	if (la57) {
 		m_pml4 = pmap_page_alloc_below_4g(true);
@@ -382,7 +390,7 @@ native_start_all_aps(void)
 	/* copy the AP 1st level boot code */
 	bcopy(mptramp_start, (void *)PHYS_TO_DMAP(boot_address), bootMP_size);
 	if (bootverbose)
-		printf("AP boot address %#x\n", boot_address);
+		printf("AP boot address %#lx\n", boot_address);
 
 	/* save the current value of the warm-start vector */
 	if (!efi_boot)
@@ -436,7 +444,7 @@ native_start_all_aps(void)
 		bootAP = cpu;
 
 		/* attempt to start the Application Processor */
-		if (!start_ap(apic_id)) {
+		if (!start_ap(apic_id, boot_address)) {
 			/* restore the warmstart vector */
 			if (!efi_boot)
 				*(u_int32_t *)WARMBOOT_OFF = mpbioswarmvec;
@@ -463,6 +471,7 @@ native_start_all_aps(void)
 	vm_page_free(m_pd[1]);
 	vm_page_free(m_pd[0]);
 	vm_page_free(m_pdp);
+	vm_page_free(m_boottramp);
 
 	/* number of APs actually started */
 	return (mp_naps);
@@ -476,7 +485,7 @@ native_start_all_aps(void)
  * but it seems to work.
  */
 static int
-start_ap(int apic_id)
+start_ap(int apic_id, vm_paddr_t boot_address)
 {
 	int vector, ms;
 	int cpus;
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index 91ca6945f1ae..156702118c45 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -147,6 +147,61 @@ static int	start_ap(int apic_id);
 
 static char *ap_copyout_buf;
 static char *ap_tramp_stack_base;
+
+unsigned int boot_address;
+
+#define MiB(v)	(v ## ULL << 20)
+
+/* Allocate memory for the AP trampoline. */
+void
+alloc_ap_trampoline(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;
+		}
+		break;
+	}
+
+	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);
+	}
+}
+
 /*
  * Initialize the IPI handlers and start up the AP's.
  */
diff --git a/sys/x86/include/x86_smp.h b/sys/x86/include/x86_smp.h
index e01f869a58f6..b9a1febb70f2 100644
--- a/sys/x86/include/x86_smp.h
+++ b/sys/x86/include/x86_smp.h
@@ -23,6 +23,10 @@
 
 struct pmap;
 
+#ifdef __i386__
+extern unsigned int boot_address;
+#endif
+
 /* global data in mp_x86.c */
 extern int mp_naps;
 extern int boot_cpu_id;
@@ -32,7 +36,6 @@ extern int bootAP;
 extern void *dpcpu;
 extern char *bootSTK;
 extern void *bootstacks[];
-extern unsigned int boot_address;
 extern unsigned int bootMP_size;
 extern volatile int aps_ready;
 extern struct mtx ap_boot_mtx;
@@ -84,12 +87,15 @@ inthand_t
 typedef void (*smp_invl_cb_t)(struct pmap *, vm_offset_t addr1,
     vm_offset_t addr2);
 
+#ifdef __i386__
+void	alloc_ap_trampoline(vm_paddr_t *physmap, unsigned int *physmap_idx);
+#endif
+
 /* functions in x86_mp.c */
 void	assign_cpu_ids(void);
 void	cpu_add(u_int apic_id, char boot_cpu);
 void	cpustop_handler(void);
 void	cpususpend_handler(void);
-void	alloc_ap_trampoline(vm_paddr_t *physmap, unsigned int *physmap_idx);
 void	init_secondary_tail(void);
 void	init_secondary(void);
 void	ipi_startup(int apic_id, int vector);
diff --git a/sys/x86/x86/mp_x86.c b/sys/x86/x86/mp_x86.c
index 441a766f87fb..db40aab28ad5 100644
--- a/sys/x86/x86/mp_x86.c
+++ b/sys/x86/x86/mp_x86.c
@@ -167,14 +167,10 @@ struct cache_info {
 	int	present;
 } static caches[MAX_CACHE_LEVELS];
 
-unsigned int boot_address;
-
 static bool stop_mwait = false;
 SYSCTL_BOOL(_machdep, OID_AUTO, stop_mwait, CTLFLAG_RWTUN, &stop_mwait, 0,
     "Use MONITOR/MWAIT when stopping CPU, if available");
 
-#define MiB(v)	(v ## ULL << 20)
-
 void
 mem_range_AP_init(void)
 {
@@ -938,56 +934,6 @@ cpu_mp_probe(void)
 	return (mp_ncpus > 1);
 }
 
-/* Allocate memory for the AP trampoline. */
-void
-alloc_ap_trampoline(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;
-		}
-		break;
-	}
-
-	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);
-	}
-}
-
 /*
  * AP CPU's call this to initialize themselves.
  */


More information about the dev-commits-src-branches mailing list