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.
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to