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>