Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Mar 2014 10:27:57 +0000 (UTC)
From:      Roger Pau Monné <royger@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r263014 - in head/sys: amd64/amd64 amd64/include x86/include x86/xen
Message-ID:  <201403111027.s2BARvoC023640@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: royger
Date: Tue Mar 11 10:27:57 2014
New Revision: 263014
URL: http://svnweb.freebsd.org/changeset/base/263014

Log:
  xen: add a hook to perform AP startup
  
  AP startup on PVH follows the PV method, so we need to add a hook in
  order to diverge from bare metal.
  
  Approved by: gibbs
  Sponsored by: Citrix Systems R&D
  
  amd64/amd64/machdep.c:
   - Add hook for start_all_aps on native (using native_start_all_aps
     defined in mp_machdep).
  
  amd64/amd64/mp_machdep.c:
   - Make some variables global because they will also be used by the
     Xen PVH AP startup code.
   - Use the start_all_aps hook to start APs.
   - Rename start_all_aps to native_start_all_aps.
  
  amd64/include/smp.h:
   - Add declaration for native_start_all_aps.
  
  x86/include/init.h:
   - Declare start_all_aps hook in init_ops.
  
  x86/xen/pv.c:
   - Pick external declarations from mp_machdep.
   - Introduce Xen PV code to start APs on PVH.
   - Set start_all_aps init hook to use the Xen PVH implementation.

Modified:
  head/sys/amd64/amd64/machdep.c
  head/sys/amd64/amd64/mp_machdep.c
  head/sys/amd64/include/smp.h
  head/sys/x86/include/init.h
  head/sys/x86/xen/pv.c

Modified: head/sys/amd64/amd64/machdep.c
==============================================================================
--- head/sys/amd64/amd64/machdep.c	Tue Mar 11 10:26:53 2014	(r263013)
+++ head/sys/amd64/amd64/machdep.c	Tue Mar 11 10:27:57 2014	(r263014)
@@ -180,6 +180,7 @@ struct init_ops init_ops = {
 	.parse_memmap =			native_parse_memmap,
 #ifdef SMP
 	.mp_bootaddress =		mp_bootaddress,
+	.start_all_aps =		native_start_all_aps,
 #endif
 };
 

Modified: head/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- head/sys/amd64/amd64/mp_machdep.c	Tue Mar 11 10:26:53 2014	(r263013)
+++ head/sys/amd64/amd64/mp_machdep.c	Tue Mar 11 10:27:57 2014	(r263014)
@@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/specialreg.h>
 #include <machine/tss.h>
 #include <machine/cpu.h>
+#include <x86/init.h>
 
 #define WARMBOOT_TARGET		0
 #define WARMBOOT_OFF		(KERNBASE + 0x0467)
@@ -90,7 +91,7 @@ extern  struct pcpu __pcpu[];
 
 /* AP uses this during bootstrap.  Do not staticize.  */
 char *bootSTK;
-static int bootAP;
+int bootAP;
 
 /* Free these after use */
 void *bootstacks[MAXCPU];
@@ -139,7 +140,7 @@ extern int pmap_pcid_enabled;
 static volatile cpuset_t ipi_nmi_pending;
 
 /* used to hold the AP's until we are ready to release them */
-static struct mtx ap_boot_mtx;
+struct mtx ap_boot_mtx;
 
 /* Set to 1 once we're ready to let the APs out of the pen. */
 static volatile int aps_ready = 0;
@@ -166,7 +167,6 @@ static int cpu_cores;			/* cores per pac
 
 static void	assign_cpu_ids(void);
 static void	set_interrupt_apic_ids(void);
-static int	start_all_aps(void);
 static int	start_ap(int apic_id);
 static void	release_aps(void *dummy);
 
@@ -570,7 +570,7 @@ cpu_mp_start(void)
 	assign_cpu_ids();
 
 	/* Start each Application Processor */
-	start_all_aps();
+	init_ops.start_all_aps();
 
 	set_interrupt_apic_ids();
 }
@@ -909,8 +909,8 @@ assign_cpu_ids(void)
 /*
  * start each AP in our list
  */
-static int
-start_all_aps(void)
+int
+native_start_all_aps(void)
 {
 	vm_offset_t va = boot_address + KERNBASE;
 	u_int64_t *pt4, *pt3, *pt2;

Modified: head/sys/amd64/include/smp.h
==============================================================================
--- head/sys/amd64/include/smp.h	Tue Mar 11 10:26:53 2014	(r263013)
+++ head/sys/amd64/include/smp.h	Tue Mar 11 10:27:57 2014	(r263014)
@@ -85,6 +85,7 @@ void	smp_masked_invlpg_range(cpuset_t ma
 	    vm_offset_t startva, vm_offset_t endva);
 void	smp_invltlb(struct pmap *pmap);
 void	smp_masked_invltlb(cpuset_t mask, struct pmap *pmap);
+int	native_start_all_aps(void);
 
 #endif /* !LOCORE */
 #endif /* SMP */

Modified: head/sys/x86/include/init.h
==============================================================================
--- head/sys/x86/include/init.h	Tue Mar 11 10:26:53 2014	(r263013)
+++ head/sys/x86/include/init.h	Tue Mar 11 10:27:57 2014	(r263014)
@@ -40,6 +40,7 @@ struct init_ops {
 	void	(*early_delay)(int);
 	void	(*parse_memmap)(caddr_t, vm_paddr_t *, int *);
 	u_int	(*mp_bootaddress)(u_int);
+	int	(*start_all_aps)(void);
 };
 
 extern struct init_ops init_ops;

Modified: head/sys/x86/xen/pv.c
==============================================================================
--- head/sys/x86/xen/pv.c	Tue Mar 11 10:26:53 2014	(r263013)
+++ head/sys/x86/xen/pv.c	Tue Mar 11 10:27:57 2014	(r263014)
@@ -34,10 +34,13 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/reboot.h>
 #include <sys/systm.h>
+#include <sys/malloc.h>
 #include <sys/lock.h>
 #include <sys/rwlock.h>
 #include <sys/boot.h>
 #include <sys/ctype.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
 
 #include <vm/vm.h>
 #include <vm/vm_extern.h>
@@ -50,10 +53,13 @@ __FBSDID("$FreeBSD$");
 
 #include <x86/init.h>
 #include <machine/pc/bios.h>
+#include <machine/smp.h>
 
 #include <xen/xen-os.h>
 #include <xen/hypervisor.h>
 
+#include <xen/interface/vcpu.h>
+
 #include <dev/xen/timer/timer.h>
 
 /* Native initial function */
@@ -67,6 +73,22 @@ uint64_t hammer_time_xen(start_info_t *,
 static caddr_t xen_pv_parse_preload_data(u_int64_t);
 static void xen_pv_parse_memmap(caddr_t, vm_paddr_t *, int *);
 
+#ifdef SMP
+static int xen_pv_start_all_aps(void);
+#endif
+
+/*---------------------------- Extern Declarations ---------------------------*/
+#ifdef SMP
+/* Variables used by amd64 mp_machdep to start APs */
+extern struct mtx ap_boot_mtx;
+extern void *bootstacks[];
+extern char *doublefault_stack;
+extern char *nmi_stack;
+extern void *dpcpu;
+extern int bootAP;
+extern char *bootSTK;
+#endif
+
 /*-------------------------------- Global Data -------------------------------*/
 /* Xen init_ops implementation. */
 struct init_ops xen_init_ops = {
@@ -74,6 +96,9 @@ struct init_ops xen_init_ops = {
 	.early_clock_source_init =	xen_clock_init,
 	.early_delay =			xen_delay,
 	.parse_memmap =			xen_pv_parse_memmap,
+#ifdef SMP
+	.start_all_aps =		xen_pv_start_all_aps,
+#endif
 };
 
 static struct bios_smap xen_smap[MAX_E820_ENTRIES];
@@ -151,6 +176,77 @@ hammer_time_xen(start_info_t *si, uint64
 }
 
 /*-------------------------------- PV specific -------------------------------*/
+#ifdef SMP
+static bool
+start_xen_ap(int cpu)
+{
+	struct vcpu_guest_context *ctxt;
+	int ms, cpus = mp_naps;
+	const size_t stacksize = KSTACK_PAGES * PAGE_SIZE;
+
+	/* allocate and set up an idle stack data page */
+	bootstacks[cpu] =
+	    (void *)kmem_malloc(kernel_arena, stacksize, M_WAITOK | M_ZERO);
+	doublefault_stack =
+	    (char *)kmem_malloc(kernel_arena, PAGE_SIZE, M_WAITOK | M_ZERO);
+	nmi_stack =
+	    (char *)kmem_malloc(kernel_arena, PAGE_SIZE, M_WAITOK | M_ZERO);
+	dpcpu =
+	    (void *)kmem_malloc(kernel_arena, DPCPU_SIZE, M_WAITOK | M_ZERO);
+
+	bootSTK = (char *)bootstacks[cpu] + KSTACK_PAGES * PAGE_SIZE - 8;
+	bootAP = cpu;
+
+	ctxt = malloc(sizeof(*ctxt), M_TEMP, M_WAITOK | M_ZERO);
+	if (ctxt == NULL)
+		panic("unable to allocate memory");
+
+	ctxt->flags = VGCF_IN_KERNEL;
+	ctxt->user_regs.rip = (unsigned long) init_secondary;
+	ctxt->user_regs.rsp = (unsigned long) bootSTK;
+
+	/* Set the AP to use the same page tables */
+	ctxt->ctrlreg[3] = KPML4phys;
+
+	if (HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, ctxt))
+		panic("unable to initialize AP#%d", cpu);
+
+	free(ctxt, M_TEMP);
+
+	/* Launch the vCPU */
+	if (HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL))
+		panic("unable to start AP#%d", cpu);
+
+	/* Wait up to 5 seconds for it to start. */
+	for (ms = 0; ms < 5000; ms++) {
+		if (mp_naps > cpus)
+			return (true);
+		DELAY(1000);
+	}
+
+	return (false);
+}
+
+static int
+xen_pv_start_all_aps(void)
+{
+	int cpu;
+
+	mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
+
+	for (cpu = 1; cpu < mp_ncpus; cpu++) {
+
+		/* attempt to start the Application Processor */
+		if (!start_xen_ap(cpu))
+			panic("AP #%d failed to start!", cpu);
+
+		CPU_SET(cpu, &all_cpus);	/* record AP in CPU map */
+	}
+
+	return (mp_naps);
+}
+#endif /* SMP */
+
 /*
  * Functions to convert the "extra" parameters passed by Xen
  * into FreeBSD boot options.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201403111027.s2BARvoC023640>