Module Name: src Committed By: bouyer Date: Sat Apr 18 15:06:18 UTC 2020
Modified Files: src/sys/arch/x86/include [bouyer-xenpvh]: cpu.h cpuvar.h src/sys/arch/x86/x86 [bouyer-xenpvh]: cpu.c mainbus.c src/sys/arch/xen/include [bouyer-xenpvh]: hypervisor.h xen.h src/sys/arch/xen/x86 [bouyer-xenpvh]: cpu.c hypervisor_machdep.c xen_ipi.c xen_mainbus.c src/sys/arch/xen/xen [bouyer-xenpvh]: evtchn.c hypervisor.c xen_clock.c Log Message: Add PVHVM multiprocessor support: We need the hypervisor to be set up before cpus attaches. Move hypervisor setup to a new function xen_hvm_init(), called at the beggining of mainbus_attach(). This function searches the cfdata[] array to see if the hypervisor device is enabled (so you can disable PV support with disable hypervisor from userconf). For HVM, ci_cpuid doens't match the virtual CPU index needed by Xen. Introduce ci_vcpuid to cpu_info. Introduce xen_hvm_init_cpu(), to be called for each CPU in in its context, which initialize ci_vcpuid and ci_vcpu, and setup the event callback. Change Xen code to use ci_vcpuid. Do not call lapic_calibrate_timer() for VM_GUEST_XENPVHVM, we will use Xen timers. Don't call lapic_initclocks() from cpu_hatch(); instead set x86_cpu_initclock_func to lapic_initclocks() in lapic_calibrate_timer(), and call *(x86_cpu_initclock_func)() from cpu_hatch(). Also call x86_cpu_initclock_func from cpu_attach() for the boot CPU. As x86_cpu_initclock_func is called for all CPUs, x86_initclock_func can be a NOP for lapic timer. Reorganize Xen code for x86_initclock_func/x86_cpu_initclock_func. Move x86_cpu_idle_xen() to hypervisor_machdep.c To generate a diff of this commit: cvs rdiff -u -r1.117.4.5 -r1.117.4.6 src/sys/arch/x86/include/cpu.h cvs rdiff -u -r1.51 -r1.51.10.1 src/sys/arch/x86/include/cpuvar.h cvs rdiff -u -r1.181.4.2 -r1.181.4.3 src/sys/arch/x86/x86/cpu.c cvs rdiff -u -r1.3.12.2 -r1.3.12.3 src/sys/arch/x86/x86/mainbus.c cvs rdiff -u -r1.49.10.2 -r1.49.10.3 src/sys/arch/xen/include/hypervisor.h cvs rdiff -u -r1.44 -r1.44.8.1 src/sys/arch/xen/include/xen.h cvs rdiff -u -r1.133 -r1.133.4.1 src/sys/arch/xen/x86/cpu.c cvs rdiff -u -r1.36.8.3 -r1.36.8.4 src/sys/arch/xen/x86/hypervisor_machdep.c cvs rdiff -u -r1.35.6.3 -r1.35.6.4 src/sys/arch/xen/x86/xen_ipi.c cvs rdiff -u -r1.6.12.2 -r1.6.12.3 src/sys/arch/xen/x86/xen_mainbus.c cvs rdiff -u -r1.88.2.4 -r1.88.2.5 src/sys/arch/xen/xen/evtchn.c cvs rdiff -u -r1.73.2.5 -r1.73.2.6 src/sys/arch/xen/xen/hypervisor.c cvs rdiff -u -r1.1.2.2 -r1.1.2.3 src/sys/arch/xen/xen/xen_clock.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/include/cpu.h diff -u src/sys/arch/x86/include/cpu.h:1.117.4.5 src/sys/arch/x86/include/cpu.h:1.117.4.6 --- src/sys/arch/x86/include/cpu.h:1.117.4.5 Thu Apr 16 17:44:54 2020 +++ src/sys/arch/x86/include/cpu.h Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.117.4.5 2020/04/16 17:44:54 bouyer Exp $ */ +/* $NetBSD: cpu.h,v 1.117.4.6 2020/04/18 15:06:18 bouyer Exp $ */ /* * Copyright (c) 1990 The Regents of the University of California. @@ -223,6 +223,7 @@ struct cpu_info { uint32_t ci_flags __aligned(64);/* general flags */ uint32_t ci_acpiid; /* our ACPI/MADT ID */ uint32_t ci_initapicid; /* our initial APIC ID */ + uint32_t ci_vcpuid; /* our CPU id for hypervisor */ cpuid_t ci_cpuid; /* our CPU ID */ struct cpu_info *ci_next; /* next cpu */ @@ -530,6 +531,7 @@ void lwp_trampoline(void); void xen_startrtclock(void); void xen_delay(unsigned int); void xen_initclocks(void); +void xen_cpu_initclocks(void); void xen_suspendclocks(struct cpu_info *); void xen_resumeclocks(struct cpu_info *); #endif /* XEN */ Index: src/sys/arch/x86/include/cpuvar.h diff -u src/sys/arch/x86/include/cpuvar.h:1.51 src/sys/arch/x86/include/cpuvar.h:1.51.10.1 --- src/sys/arch/x86/include/cpuvar.h:1.51 Mon Feb 11 14:59:32 2019 +++ src/sys/arch/x86/include/cpuvar.h Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cpuvar.h,v 1.51 2019/02/11 14:59:32 cherry Exp $ */ +/* $NetBSD: cpuvar.h,v 1.51.10.1 2020/04/18 15:06:18 bouyer Exp $ */ /*- * Copyright (c) 2000, 2007 The NetBSD Foundation, Inc. @@ -99,6 +99,7 @@ struct cpufeature_attach_args { #include <sys/kcpuset.h> #if defined(_KERNEL_OPT) #include "opt_multiprocessor.h" +#include "opt_xen.h" #endif /* defined(_KERNEL_OPT) */ extern int (*x86_ipi)(int, int, int); @@ -115,7 +116,7 @@ void cpu_init_first(void); void x86_cpu_idle_init(void); void x86_cpu_idle_halt(void); void x86_cpu_idle_mwait(void); -#ifdef XENPV +#ifdef XEN void x86_cpu_idle_xen(void); #endif Index: src/sys/arch/x86/x86/cpu.c diff -u src/sys/arch/x86/x86/cpu.c:1.181.4.2 src/sys/arch/x86/x86/cpu.c:1.181.4.3 --- src/sys/arch/x86/x86/cpu.c:1.181.4.2 Thu Apr 16 09:45:56 2020 +++ src/sys/arch/x86/x86/cpu.c Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.181.4.2 2020/04/16 09:45:56 bouyer Exp $ */ +/* $NetBSD: cpu.c,v 1.181.4.3 2020/04/18 15:06:18 bouyer Exp $ */ /* * Copyright (c) 2000-2012 NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.181.4.2 2020/04/16 09:45:56 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.181.4.3 2020/04/18 15:06:18 bouyer Exp $"); #include "opt_ddb.h" #include "opt_mpbios.h" /* for MPDEBUG */ @@ -89,6 +89,7 @@ __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.18 #include "acpica.h" /* for NACPICA, for mp_verbose */ +#include <x86/machdep.h> #include <machine/cpufunc.h> #include <machine/cpuvar.h> #include <machine/pmap.h> @@ -130,6 +131,10 @@ __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.18 #endif #endif +#ifdef XEN +#include <xen/hypervisor.h> +#endif + static int cpu_match(device_t, cfdata_t, void *); static void cpu_attach(device_t, device_t, void *); static void cpu_defer(device_t); @@ -442,7 +447,8 @@ cpu_attach(device_t parent, device_t sel /* Enable lapic. */ lapic_enable(); lapic_set_lvt(); - lapic_calibrate_timer(ci); + if (vm_guest != VM_GUEST_XENPVHVM) + lapic_calibrate_timer(ci); } #endif /* Make sure DELAY() is initialized. */ @@ -459,6 +465,10 @@ cpu_attach(device_t parent, device_t sel cpu_identify(ci); x86_errata(); x86_cpu_idle_init(); + (*x86_cpu_initclock_func)(); +#ifdef XENPVHVM + xen_hvm_init_cpu(ci); +#endif break; case CPU_ROLE_BP: @@ -466,6 +476,10 @@ cpu_attach(device_t parent, device_t sel cpu_identify(ci); x86_errata(); x86_cpu_idle_init(); +#ifdef XENPVHVM + xen_hvm_init_cpu(ci); +#endif + (*x86_cpu_initclock_func)(); break; #ifdef MULTIPROCESSOR @@ -971,7 +985,6 @@ cpu_hatch(void *v) #if NLAPIC > 0 lapic_enable(); lapic_set_lvt(); - lapic_initclocks(); #endif fpuinit(ci); @@ -984,6 +997,10 @@ cpu_hatch(void *v) * above. */ cpu_init(ci); +#ifdef XENPVHVM + xen_hvm_init_cpu(ci); +#endif + (*x86_cpu_initclock_func)(); cpu_get_tsc_freq(ci); s = splhigh(); Index: src/sys/arch/x86/x86/mainbus.c diff -u src/sys/arch/x86/x86/mainbus.c:1.3.12.2 src/sys/arch/x86/x86/mainbus.c:1.3.12.3 --- src/sys/arch/x86/x86/mainbus.c:1.3.12.2 Thu Apr 16 08:46:35 2020 +++ src/sys/arch/x86/x86/mainbus.c Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: mainbus.c,v 1.3.12.2 2020/04/16 08:46:35 bouyer Exp $ */ +/* $NetBSD: mainbus.c,v 1.3.12.3 2020/04/18 15:06:18 bouyer Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.3.12.2 2020/04/16 08:46:35 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mainbus.c,v 1.3.12.3 2020/04/18 15:06:18 bouyer Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -217,6 +217,10 @@ mainbus_attach(device_t parent, device_t aprint_naive("\n"); aprint_normal("\n"); +#if defined(XENPVHVM) + xen_hvm_init(); /* before attaching CPUs */ +#endif + #if defined(XENPV) if (xendomain_is_dom0()) { #endif /* XENPV */ @@ -226,6 +230,10 @@ mainbus_attach(device_t parent, device_t } #endif /* XENPV */ #if defined(XEN) + /* + * before isa/pci probe, so that PV devices are not probed again + * as emulated + */ xen_mainbus_attach(parent, self, aux); #endif #if defined(__i386__) && !defined(XENPV) Index: src/sys/arch/xen/include/hypervisor.h diff -u src/sys/arch/xen/include/hypervisor.h:1.49.10.2 src/sys/arch/xen/include/hypervisor.h:1.49.10.3 --- src/sys/arch/xen/include/hypervisor.h:1.49.10.2 Thu Apr 16 08:46:35 2020 +++ src/sys/arch/xen/include/hypervisor.h Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: hypervisor.h,v 1.49.10.2 2020/04/16 08:46:35 bouyer Exp $ */ +/* $NetBSD: hypervisor.h,v 1.49.10.3 2020/04/18 15:06:18 bouyer Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -58,6 +58,10 @@ #include "isa.h" #include "pci.h" +struct cpu_info; + +int xen_hvm_init(void); +int xen_hvm_init_cpu(struct cpu_info *); void xen_mainbus_attach(device_t, device_t, void *); struct hypervisor_attach_args { Index: src/sys/arch/xen/include/xen.h diff -u src/sys/arch/xen/include/xen.h:1.44 src/sys/arch/xen/include/xen.h:1.44.8.1 --- src/sys/arch/xen/include/xen.h:1.44 Thu May 9 17:09:50 2019 +++ src/sys/arch/xen/include/xen.h Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: xen.h,v 1.44 2019/05/09 17:09:50 bouyer Exp $ */ +/* $NetBSD: xen.h,v 1.44.8.1 2020/04/18 15:06:18 bouyer Exp $ */ /* * @@ -70,8 +70,6 @@ void xenevt_event(int); void xenevt_setipending(int, int); void xenevt_notify(void); -void idle_block(void); - /* xen_machdep.c */ void sysctl_xen_suspend_setup(void); Index: src/sys/arch/xen/x86/cpu.c diff -u src/sys/arch/xen/x86/cpu.c:1.133 src/sys/arch/xen/x86/cpu.c:1.133.4.1 --- src/sys/arch/xen/x86/cpu.c:1.133 Mon Feb 24 12:20:29 2020 +++ src/sys/arch/xen/x86/cpu.c Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.133 2020/02/24 12:20:29 rin Exp $ */ +/* $NetBSD: cpu.c,v 1.133.4.1 2020/04/18 15:06:18 bouyer Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.133 2020/02/24 12:20:29 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.133.4.1 2020/04/18 15:06:18 bouyer Exp $"); #include "opt_ddb.h" #include "opt_multiprocessor.h" @@ -317,7 +317,7 @@ static int vcpu_is_up(struct cpu_info *ci) { KASSERT(ci != NULL); - return HYPERVISOR_vcpu_op(VCPUOP_is_up, ci->ci_cpuid, NULL); + return HYPERVISOR_vcpu_op(VCPUOP_is_up, ci->ci_vcpuid, NULL); } static void @@ -390,6 +390,7 @@ cpu_attach_common(device_t parent, devic sc->sc_info = ci; ci->ci_dev = self; ci->ci_cpuid = cpunum; + ci->ci_vcpuid = cpunum; KASSERT(HYPERVISOR_shared_info != NULL); KASSERT(cpunum < XEN_LEGACY_MAX_VCPUS); @@ -455,12 +456,14 @@ cpu_attach_common(device_t parent, devic atomic_or_32(&ci->ci_flags, CPUF_SP); cpu_identify(ci); x86_cpu_idle_init(); + xen_cpu_initclocks(); break; case CPU_ROLE_BP: atomic_or_32(&ci->ci_flags, CPUF_BSP); cpu_identify(ci); x86_cpu_idle_init(); + xen_cpu_initclocks(); break; case CPU_ROLE_AP: @@ -723,7 +726,7 @@ cpu_hatch(void *v) xen_ipi_init(); - xen_initclocks(); + xen_cpu_initclocks(); #ifdef __x86_64__ fpuinit(ci); @@ -764,7 +767,7 @@ cpu_debug_dump(void) db_printf("%p %s %ld %x %x %10p\n", ci, ci->ci_dev == NULL ? "BOOT" : device_xname(ci->ci_dev), - (long)ci->ci_cpuid, + (long)ci->ci_vcpuid, ci->ci_flags, ci->ci_ipis, ci->ci_curlwp); } @@ -1011,7 +1014,7 @@ mp_cpu_start(struct cpu_info *ci, vaddr_ #endif /* Initialise the given vcpu to execute cpu_hatch(ci); */ - if ((hyperror = HYPERVISOR_vcpu_op(VCPUOP_initialise, ci->ci_cpuid, &vcpuctx))) { + if ((hyperror = HYPERVISOR_vcpu_op(VCPUOP_initialise, ci->ci_vcpuid, &vcpuctx))) { aprint_error(": context initialisation failed. errno = %d\n", hyperror); return hyperror; } @@ -1019,12 +1022,12 @@ mp_cpu_start(struct cpu_info *ci, vaddr_ /* Start it up */ /* First bring it down */ - if ((hyperror = HYPERVISOR_vcpu_op(VCPUOP_down, ci->ci_cpuid, NULL))) { + if ((hyperror = HYPERVISOR_vcpu_op(VCPUOP_down, ci->ci_vcpuid, NULL))) { aprint_error(": VCPUOP_down hypervisor command failed. errno = %d\n", hyperror); return hyperror; } - if ((hyperror = HYPERVISOR_vcpu_op(VCPUOP_up, ci->ci_cpuid, NULL))) { + if ((hyperror = HYPERVISOR_vcpu_op(VCPUOP_up, ci->ci_vcpuid, NULL))) { aprint_error(": VCPUOP_up hypervisor command failed. errno = %d\n", hyperror); return hyperror; } @@ -1086,21 +1089,6 @@ cpu_get_tsc_freq(struct cpu_info *ci) ci->ci_data.cpu_cc_freq = freq; } -void -x86_cpu_idle_xen(void) -{ - struct cpu_info *ci = curcpu(); - - KASSERT(ci->ci_ilevel == IPL_NONE); - - x86_disable_intr(); - if (!__predict_false(ci->ci_want_resched)) { - idle_block(); - } else { - x86_enable_intr(); - } -} - /* * Loads pmap for the current CPU. */ Index: src/sys/arch/xen/x86/hypervisor_machdep.c diff -u src/sys/arch/xen/x86/hypervisor_machdep.c:1.36.8.3 src/sys/arch/xen/x86/hypervisor_machdep.c:1.36.8.4 --- src/sys/arch/xen/x86/hypervisor_machdep.c:1.36.8.3 Thu Apr 16 17:50:52 2020 +++ src/sys/arch/xen/x86/hypervisor_machdep.c Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: hypervisor_machdep.c,v 1.36.8.3 2020/04/16 17:50:52 bouyer Exp $ */ +/* $NetBSD: hypervisor_machdep.c,v 1.36.8.4 2020/04/18 15:06:18 bouyer Exp $ */ /* * @@ -54,7 +54,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.36.8.3 2020/04/16 17:50:52 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.36.8.4 2020/04/18 15:06:18 bouyer Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -66,6 +66,9 @@ __KERNEL_RCSID(0, "$NetBSD: hypervisor_m #include <machine/vmparam.h> #include <machine/pmap.h> +#include <x86/machdep.h> +#include <x86/cpuvar.h> + #include <xen/xen.h> #include <xen/intr.h> #include <xen/hypervisor.h> @@ -315,8 +318,8 @@ hypervisor_send_event(struct cpu_info *c hypervisor_force_callback(); } else { if (__predict_false(xen_send_ipi(ci, XEN_IPI_HVCB))) { - panic("xen_send_ipi(cpu%d, XEN_IPI_HVCB) failed\n", - (int) ci->ci_cpuid); + panic("xen_send_ipi(cpu%d id %d, XEN_IPI_HVCB) failed\n", + (int) ci->ci_cpuid, ci->ci_vcpuid); } } } @@ -422,8 +425,8 @@ hypervisor_set_ipending(uint32_t imask, if (__predict_false(ci != curcpu())) { if (xen_send_ipi(ci, XEN_IPI_HVCB)) { panic("hypervisor_set_ipending: " - "xen_send_ipi(cpu%d, XEN_IPI_HVCB) failed\n", - (int) ci->ci_cpuid); + "xen_send_ipi(cpu%d id %d, XEN_IPI_HVCB) failed\n", + (int) ci->ci_cpuid, ci->ci_vcpuid); } } } @@ -450,6 +453,35 @@ hypervisor_machdep_resume(void) #endif } +/* + * idle_block() + * + * Called from the idle loop when we have nothing to do but wait + * for an interrupt. + */ +static void +idle_block(void) +{ + KASSERT(curcpu()->ci_ipending == 0); + HYPERVISOR_block(); + KASSERT(curcpu()->ci_ipending == 0); +} + +void +x86_cpu_idle_xen(void) +{ + struct cpu_info *ci = curcpu(); + + KASSERT(ci->ci_ilevel == IPL_NONE); + + x86_disable_intr(); + if (!__predict_false(ci->ci_want_resched)) { + idle_block(); + } else { + x86_enable_intr(); + } +} + #ifdef XENPV /* * Generate the p2m_frame_list_list table, Index: src/sys/arch/xen/x86/xen_ipi.c diff -u src/sys/arch/xen/x86/xen_ipi.c:1.35.6.3 src/sys/arch/xen/x86/xen_ipi.c:1.35.6.4 --- src/sys/arch/xen/x86/xen_ipi.c:1.35.6.3 Thu Apr 16 08:46:35 2020 +++ src/sys/arch/xen/x86/xen_ipi.c Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: xen_ipi.c,v 1.35.6.3 2020/04/16 08:46:35 bouyer Exp $ */ +/* $NetBSD: xen_ipi.c,v 1.35.6.4 2020/04/18 15:06:18 bouyer Exp $ */ /*- * Copyright (c) 2011, 2019 The NetBSD Foundation, Inc. @@ -33,10 +33,10 @@ /* * Based on: x86/ipi.c - * __KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.35.6.3 2020/04/16 08:46:35 bouyer Exp $"); + * __KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.35.6.4 2020/04/18 15:06:18 bouyer Exp $"); */ -__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.35.6.3 2020/04/16 08:46:35 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.35.6.4 2020/04/18 15:06:18 bouyer Exp $"); #include "opt_ddb.h" @@ -132,7 +132,7 @@ xen_ipi_init(void) ci = curcpu(); - vcpu = ci->ci_cpuid; + vcpu = ci->ci_vcpuid; KASSERT(vcpu < XEN_LEGACY_MAX_VCPUS); evtchn = bind_vcpu_to_evtch(vcpu); @@ -231,7 +231,7 @@ xen_ipi_halt(struct cpu_info *ci, struct { KASSERT(ci == curcpu()); KASSERT(ci != NULL); - if (HYPERVISOR_vcpu_op(VCPUOP_down, ci->ci_cpuid, NULL)) { + if (HYPERVISOR_vcpu_op(VCPUOP_down, ci->ci_vcpuid, NULL)) { panic("%s shutdown failed.\n", device_xname(ci->ci_dev)); } Index: src/sys/arch/xen/x86/xen_mainbus.c diff -u src/sys/arch/xen/x86/xen_mainbus.c:1.6.12.2 src/sys/arch/xen/x86/xen_mainbus.c:1.6.12.3 --- src/sys/arch/xen/x86/xen_mainbus.c:1.6.12.2 Thu Apr 16 17:46:44 2020 +++ src/sys/arch/xen/x86/xen_mainbus.c Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: xen_mainbus.c,v 1.6.12.2 2020/04/16 17:46:44 bouyer Exp $ */ +/* $NetBSD: xen_mainbus.c,v 1.6.12.3 2020/04/18 15:06:18 bouyer Exp $ */ /* NetBSD: mainbus.c,v 1.19 2017/05/23 08:54:39 nonaka Exp */ /* NetBSD: mainbus.c,v 1.53 2003/10/27 14:11:47 junyoung Exp */ @@ -33,7 +33,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xen_mainbus.c,v 1.6.12.2 2020/04/16 17:46:44 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xen_mainbus.c,v 1.6.12.3 2020/04/18 15:06:18 bouyer Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -131,7 +131,7 @@ xen_mainbus_attach(device_t parent, devi config_found_ia(self, "ipmibus", &mba.mba_ipmi, 0); #endif /* FALLTHROUGH */ - case VM_GUEST_XENHVM: + case VM_GUEST_XENPVHVM: mba.mba_haa.haa_busname = "hypervisor"; config_found_ia(self, "hypervisorbus", &mba.mba_haa, xen_mainbus_print); Index: src/sys/arch/xen/xen/evtchn.c diff -u src/sys/arch/xen/xen/evtchn.c:1.88.2.4 src/sys/arch/xen/xen/evtchn.c:1.88.2.5 --- src/sys/arch/xen/xen/evtchn.c:1.88.2.4 Thu Apr 16 08:46:36 2020 +++ src/sys/arch/xen/xen/evtchn.c Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: evtchn.c,v 1.88.2.4 2020/04/16 08:46:36 bouyer Exp $ */ +/* $NetBSD: evtchn.c,v 1.88.2.5 2020/04/18 15:06:18 bouyer Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -54,7 +54,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.88.2.4 2020/04/16 08:46:36 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: evtchn.c,v 1.88.2.5 2020/04/18 15:06:18 bouyer Exp $"); #include "opt_xen.h" #include "isa.h" @@ -564,7 +564,7 @@ bind_virq_to_evtch(int virq) } if (virq == VIRQ_TIMER) { - evtchn = virq_timer_to_evtch[ci->ci_cpuid]; + evtchn = virq_timer_to_evtch[ci->ci_vcpuid]; } else { evtchn = virq_to_evtch[virq]; } @@ -573,7 +573,7 @@ bind_virq_to_evtch(int virq) if (evtchn == -1) { op.cmd = EVTCHNOP_bind_virq; op.u.bind_virq.virq = virq; - op.u.bind_virq.vcpu = ci->ci_cpuid; + op.u.bind_virq.vcpu = ci->ci_vcpuid; if (HYPERVISOR_event_channel_op(&op) != 0) panic("Failed to bind virtual IRQ %d\n", virq); evtchn = op.u.bind_virq.port; @@ -581,7 +581,7 @@ bind_virq_to_evtch(int virq) /* Set event channel */ if (virq == VIRQ_TIMER) { - virq_timer_to_evtch[ci->ci_cpuid] = evtchn; + virq_timer_to_evtch[ci->ci_vcpuid] = evtchn; } else { virq_to_evtch[virq] = evtchn; } @@ -603,7 +603,7 @@ unbind_virq_from_evtch(int virq) struct cpu_info *ci = curcpu(); if (virq == VIRQ_TIMER) { - evtchn = virq_timer_to_evtch[ci->ci_cpuid]; + evtchn = virq_timer_to_evtch[ci->ci_vcpuid]; } else { evtchn = virq_to_evtch[virq]; @@ -623,7 +623,7 @@ unbind_virq_from_evtch(int virq) panic("Failed to unbind virtual IRQ %d\n", virq); if (virq == VIRQ_TIMER) { - virq_timer_to_evtch[ci->ci_cpuid] = -1; + virq_timer_to_evtch[ci->ci_vcpuid] = -1; } else { virq_to_evtch[virq] = -1; } Index: src/sys/arch/xen/xen/hypervisor.c diff -u src/sys/arch/xen/xen/hypervisor.c:1.73.2.5 src/sys/arch/xen/xen/hypervisor.c:1.73.2.6 --- src/sys/arch/xen/xen/hypervisor.c:1.73.2.5 Thu Apr 16 20:21:04 2020 +++ src/sys/arch/xen/xen/hypervisor.c Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: hypervisor.c,v 1.73.2.5 2020/04/16 20:21:04 bouyer Exp $ */ +/* $NetBSD: hypervisor.c,v 1.73.2.6 2020/04/18 15:06:18 bouyer Exp $ */ /* * Copyright (c) 2005 Manuel Bouyer. @@ -53,7 +53,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: hypervisor.c,v 1.73.2.5 2020/04/16 20:21:04 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hypervisor.c,v 1.73.2.6 2020/04/18 15:06:18 bouyer Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -73,7 +73,8 @@ __KERNEL_RCSID(0, "$NetBSD: hypervisor.c #include <xen/hypervisor.h> #include <xen/evtchn.h> #include <xen/include/public/version.h> -#include <x86//pio.h> +#include <x86/pio.h> +#include <x86/machdep.h> #include <sys/cpu.h> #include <sys/dirent.h> @@ -184,11 +185,9 @@ extern struct xenstore_domain_interface volatile shared_info_t *HYPERVISOR_shared_info __read_mostly; paddr_t HYPERVISOR_shared_info_pa; union start_info_union start_info_union __aligned(PAGE_SIZE); -#endif - -extern void (*delay_func)(unsigned int); -extern void (*initclock_func)(void); +static int xen_hvm_vec = 0; +#endif int xen_version; @@ -205,60 +204,70 @@ enum { XMI_UNPLUG_IDE_EXCEPT_PRI_MASTER = 0x04 }; -/* - * Probe for the hypervisor; always succeeds. - */ + +#ifdef XENPVHVM + +static bool +xen_check_hypervisordev(void) +{ + extern struct cfdata cfdata[]; + for (int i = 0; cfdata[i].cf_name != NULL; i++) { + if (strcasecmp("hypervisor", cfdata[i].cf_name) == 0) { + switch(cfdata[i].cf_fstate) { + case FSTATE_NOTFOUND: + case FSTATE_FOUND: + case FSTATE_STAR: + printf("xen_check_hypervisordev: enabled\n"); + return true; + default: + printf("xen_check_hypervisordev: disabled\n"); + return false; + } + } + } + printf("xen_check_hypervisordev: notfound\n"); + return 0; +} int -hypervisor_match(device_t parent, cfdata_t match, void *aux) +xen_hvm_init(void) { - struct hypervisor_attach_args *haa = aux; - - /* Attach path sanity check */ - if (strncmp(haa->haa_busname, "hypervisor", sizeof("hypervisor")) != 0) - return 0; + extern vaddr_t hypercall_page; + u_int descs[4]; -#if defined(XENPVHVM) /* - * The strategy here is to setup hypercall and all PVHVM - * interfaces on match, or fail to match. - * Ideally this should happen under attach, but it's too late - * then and there's no way to bailout. + * We need to setup the HVM interfaces early, so that we can + * properly setup the CPUs later (especially, all CPUs needs to + * run x86_cpuid() locally to get their vcpuid. * - * If match fails, hypervisor does not attach, and the domain - * can boot with the minimal PC AT ISA configuration just - * enough to attach wd(4) and mount the rootfs. + * if everything goes fine, we switch vm_guest to VM_GUEST_XENPVHVM */ - int vec; - extern vaddr_t hypercall_page; - if (vm_guest == VM_GUEST_XENHVM) { - aprint_normal("%s: Identified Guest XEN in HVM mode.\n", - haa->haa_busname); - - u_int descs[4]; - x86_cpuid(XEN_CPUID_LEAF(2), descs); - - /* - * Given 32 bytes per hypercall stub, and an optimistic number - * of 100 hypercalls ( the current max is 55), there shouldn't - * be any reason to spill over the arbitrary number of 1 - * hypercall page. This is what we allocate in locore.S - * anyway. Make sure the allocation matches the registration. - */ + if (vm_guest != VM_GUEST_XENHVM) + return 0; - KASSERT(descs[0] == 1); + /* check if hypervisor was disabled with userconf */ + if (!xen_check_hypervisordev()) + return 0; - /* XXX: vtophys(&hypercall_page) */ - wrmsr(descs[1], (uintptr_t)&hypercall_page - KERNBASE); + aprint_normal("Identified Guest XEN in HVM mode.\n"); - } else { - return 0; - } + x86_cpuid(XEN_CPUID_LEAF(2), descs); - if (-1 != HYPERVISOR_xen_version(XENVER_version, NULL)) { - printf("%s: detected functional hypercall page.\n", - haa->haa_busname); + /* + * Given 32 bytes per hypercall stub, and an optimistic number + * of 100 hypercalls ( the current max is 55), there shouldn't + * be any reason to spill over the arbitrary number of 1 + * hypercall page. This is what we allocate in locore.S + * anyway. Make sure the allocation matches the registration. + */ + + KASSERT(descs[0] == 1); + /* XXX: vtophys(&hypercall_page) */ + wrmsr(descs[1], (uintptr_t)&hypercall_page - KERNBASE); + + if (-1 != HYPERVISOR_xen_version(XENVER_version, NULL)) { + printf("Xen HVM: detected functional hypercall page.\n"); xen_init_features(); } @@ -271,8 +280,8 @@ hypervisor_match(device_t parent, cfdata xen_hvm_param.index = HVM_PARAM_STORE_PFN; if ( HYPERVISOR_hvm_op(HVMOP_get_param, &xen_hvm_param) < 0) { - aprint_error("%s: Unable to obtain xenstore page address\n", - haa->haa_busname); + aprint_error( + "Xen HVM: Unable to obtain xenstore page address\n"); return 0; } @@ -286,8 +295,8 @@ hypervisor_match(device_t parent, cfdata xen_hvm_param.index = HVM_PARAM_STORE_EVTCHN; if ( HYPERVISOR_hvm_op(HVMOP_get_param, &xen_hvm_param) < 0) { - aprint_error("%s: Unable to obtain xenstore event channel\n", - haa->haa_busname); + aprint_error( + "Xen HVM: Unable to obtain xenstore event channel\n"); return 0; } @@ -297,8 +306,8 @@ hypervisor_match(device_t parent, cfdata xen_hvm_param.index = HVM_PARAM_CONSOLE_PFN; if ( HYPERVISOR_hvm_op(HVMOP_get_param, &xen_hvm_param) < 0) { - aprint_error("%s: Unable to obtain xencons page address\n", - haa->haa_busname); + aprint_error( + "Xen HVM: Unable to obtain xencons page address\n"); return 0; } @@ -312,8 +321,8 @@ hypervisor_match(device_t parent, cfdata xen_hvm_param.index = HVM_PARAM_CONSOLE_EVTCHN; if ( HYPERVISOR_hvm_op(HVMOP_get_param, &xen_hvm_param) < 0) { - aprint_error("%s: Unable to obtain xencons event channel\n", - haa->haa_busname); + aprint_error( + "Xen HVM: Unable to obtain xencons event channel\n"); return 0; } @@ -328,8 +337,8 @@ hypervisor_match(device_t parent, cfdata }; if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xmap) < 0) { - aprint_error("%s: Unable to register HYPERVISOR_shared_info\n", - haa->haa_busname); + aprint_error( + "Xen HVM: Unable to register HYPERVISOR_shared_info\n"); return 0; } @@ -337,8 +346,6 @@ hypervisor_match(device_t parent, cfdata pmap_kenter_pa((vaddr_t) HYPERVISOR_shared_info, HYPERVISOR_shared_info_pa, VM_PROT_READ|VM_PROT_WRITE, 0); - cpu_info_primary.ci_vcpu = &HYPERVISOR_shared_info->vcpu_info[0]; - /* * First register callback: here's why * http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=7b5b8ca7dffde866d851f0b87b994e0b13e5b867 @@ -349,65 +356,121 @@ hypervisor_match(device_t parent, cfdata * without it. */ if (!xen_feature(XENFEAT_hvm_callback_vector)) { - aprint_error("%s: XENFEAT_hvm_callback_vector" - "not available, cannot proceed", haa->haa_busname); - + aprint_error("Xen HVM: XENFEAT_hvm_callback_vector" + "not available, cannot proceed"); return 0; } - /* Register event callback handler. */ + /* + * prepare vector. + * We don't really care where it is, as long as it's free + */ + xen_hvm_vec = idt_vec_alloc(129, 255); + idt_vec_set(xen_hvm_vec, &IDTVEC(hypervisor_pvhvm_callback)); - /* We don't really care where it is, as long as it's free */ - vec = idt_vec_alloc(129, 255); + events_default_setup(); - idt_vec_set(vec, &IDTVEC(hypervisor_pvhvm_callback)); + delay_func = xen_delay; + x86_initclock_func = xen_initclocks; + x86_cpu_initclock_func = xen_cpu_initclocks; + x86_cpu_idle_set(x86_cpu_idle_xen, "xen", true); + vm_guest = VM_GUEST_XENPVHVM; /* Be more specific */ + return 1; +} - cpu_init_idt(); /* XXX remove and use only native one below ? */ +int +xen_hvm_init_cpu(struct cpu_info *ci) +{ + u_int32_t descs[4]; + struct xen_hvm_param xen_hvm_param; - xen_hvm_param.domid = DOMID_SELF; - xen_hvm_param.index = HVM_PARAM_CALLBACK_IRQ; + if (vm_guest != VM_GUEST_XENPVHVM) + return 0; - /* val[63:56] = 2, val[7:0] = vec */ - xen_hvm_param.value = ((int64_t)0x2 << 56) | vec; + KASSERT(ci == curcpu()); - if (HYPERVISOR_hvm_op(HVMOP_set_param, &xen_hvm_param) < 0) { - aprint_error("%s: Unable to register event callback vector\n", - haa->haa_busname); + descs[0] = 0; + x86_cpuid(XEN_CPUID_LEAF(4), descs); + if (!(descs[0] & XEN_HVM_CPUID_VCPU_ID_PRESENT)) { + aprint_error_dev(ci->ci_dev, "Xen HVM: can't get VCPU id\n"); + vm_guest = VM_GUEST_XENHVM; return 0; } + printf("cpu %s ci_acpiid %d vcpuid %d domid %d\n", + device_xname(ci->ci_dev), ci->ci_acpiid, descs[1], descs[2]); + + ci->ci_vcpuid = descs[1]; + ci->ci_vcpu = &HYPERVISOR_shared_info->vcpu_info[ci->ci_vcpuid]; + + /* Register event callback handler. */ - /* Print out value. */ xen_hvm_param.domid = DOMID_SELF; xen_hvm_param.index = HVM_PARAM_CALLBACK_IRQ; - xen_hvm_param.value = 0; - if (HYPERVISOR_hvm_op(HVMOP_get_param, &xen_hvm_param) < 0) { - printf("%s: Unable to get event callback vector\n", - haa->haa_busname); + /* val[63:56] = 2, val[7:0] = vec */ + xen_hvm_param.value = ((int64_t)0x2 << 56) | xen_hvm_vec; + + if (HYPERVISOR_hvm_op(HVMOP_set_param, &xen_hvm_param) < 0) { + aprint_error_dev(ci->ci_dev, + "Xen HVM: Unable to register event callback vector\n"); + vm_guest = VM_GUEST_XENHVM; return 0; } - /* - * Afterwards vector callback is done, register VCPU info - * page. Here's why: - * http://xenbits.xen.org/gitweb/?p=xen.git;a=commit;h=7b5b8ca7dffde866d851f0b87b994e0b13e5b867 - * XXX: Ideally this should happen at vcpu attach. - */ - struct vcpu_register_vcpu_info vrvi; + return 1; +} - paddr_t vcpu_info_pa = HYPERVISOR_shared_info_pa + - offsetof(struct shared_info, vcpu_info); - - vrvi.mfn = atop(vcpu_info_pa); - vrvi.offset = vcpu_info_pa - trunc_page(vcpu_info_pa); +#endif /* XENPVHVM */ + +/* + * Probe for the hypervisor; always succeeds. + */ +int +hypervisor_match(device_t parent, cfdata_t match, void *aux) +{ + struct hypervisor_attach_args *haa = aux; - if (HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, curcpu()->ci_cpuid /* VCPU0 */, - &vrvi) < 0) { - aprint_error("%s: Unable to register vcpu info page\n", - haa->haa_busname); + /* Attach path sanity check */ + if (strncmp(haa->haa_busname, "hypervisor", sizeof("hypervisor")) != 0) return 0; - } + +#ifdef XENPVHVM + if (vm_guest != VM_GUEST_XENPVHVM) + return 0; +#endif + /* If we got here, it must mean we matched */ + return 1; +} + +#ifdef MULTIPROCESSOR +static int +hypervisor_vcpu_print(void *aux, const char *parent) +{ + /* Unconfigured cpus are ignored quietly. */ + return (QUIET); +} +#endif /* MULTIPROCESSOR */ + +/* + * Attach the hypervisor. + */ +void +hypervisor_attach(device_t parent, device_t self, void *aux) +{ + +#if NPCI >0 +#ifdef PCI_BUS_FIXUP + int pci_maxbus = 0; +#endif +#endif /* NPCI */ + union hypervisor_attach_cookie hac; + char xen_extra_version[XEN_EXTRAVERSION_LEN]; + static char xen_version_string[20]; + int rc; + const struct sysctlnode *node = NULL; + +#ifdef XENPVHVM /* * Set the boot device to xbd0a. * We claim this is a reasonable default which is picked up @@ -425,7 +488,7 @@ hypervisor_match(device_t parent, cfdata bi.common.len = sizeof(struct btinfo_rootdevice); /* From i386/multiboot.c */ - /* $NetBSD: hypervisor.c,v 1.73.2.5 2020/04/16 20:21:04 bouyer Exp $ */ + /* $NetBSD: hypervisor.c,v 1.73.2.6 2020/04/18 15:06:18 bouyer Exp $ */ int i, len; vaddr_t data; extern struct bootinfo bootinfo; @@ -448,47 +511,9 @@ hypervisor_match(device_t parent, cfdata if (inw(XEN_MAGIC_IOPORT) == XMI_MAGIC) { outw(XEN_MAGIC_IOPORT, XMI_UNPLUG_IDE_DISKS | XMI_UNPLUG_NICS); } else { - aprint_error("%s: Unable to disable emulated devices\n", - haa->haa_busname); + aprint_error_dev(self, "Unable to disable emulated devices\n"); } - events_default_setup(); - delay_func = xen_delay; - initclock_func = xen_initclocks; - vm_guest = VM_GUEST_XENPVHVM; /* Be more specific */ - #endif /* XENPVHVM */ - - /* If we got here, it must mean we matched */ - return 1; -} - -#ifdef MULTIPROCESSOR -static int -hypervisor_vcpu_print(void *aux, const char *parent) -{ - /* Unconfigured cpus are ignored quietly. */ - return (QUIET); -} -#endif /* MULTIPROCESSOR */ - -/* - * Attach the hypervisor. - */ -void -hypervisor_attach(device_t parent, device_t self, void *aux) -{ - -#if NPCI >0 -#ifdef PCI_BUS_FIXUP - int pci_maxbus = 0; -#endif -#endif /* NPCI */ - union hypervisor_attach_cookie hac; - char xen_extra_version[XEN_EXTRAVERSION_LEN]; - static char xen_version_string[20]; - int rc; - const struct sysctlnode *node = NULL; - xenkernfs_init(); xen_version = HYPERVISOR_xen_version(XENVER_version, NULL); Index: src/sys/arch/xen/xen/xen_clock.c diff -u src/sys/arch/xen/xen/xen_clock.c:1.1.2.2 src/sys/arch/xen/xen/xen_clock.c:1.1.2.3 --- src/sys/arch/xen/xen/xen_clock.c:1.1.2.2 Thu Apr 16 20:21:44 2020 +++ src/sys/arch/xen/xen/xen_clock.c Sat Apr 18 15:06:18 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: xen_clock.c,v 1.1.2.2 2020/04/16 20:21:44 bouyer Exp $ */ +/* $NetBSD: xen_clock.c,v 1.1.2.3 2020/04/18 15:06:18 bouyer Exp $ */ /*- * Copyright (c) 2017, 2018 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xen_clock.c,v 1.1.2.2 2020/04/16 20:21:44 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xen_clock.c,v 1.1.2.3 2020/04/18 15:06:18 bouyer Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -115,20 +115,6 @@ static int sysctl_xen_timepush(SYSCTLFN_ #endif /* - * idle_block() - * - * Called from the idle loop when we have nothing to do but wait - * for an interrupt. - */ -void -idle_block(void) -{ - KASSERT(curcpu()->ci_ipending == 0); - HYPERVISOR_block(); - KASSERT(curcpu()->ci_ipending == 0); -} - -/* * xen_rdtsc() * * Read the local pCPU's tsc. @@ -521,6 +507,11 @@ xen_delay(unsigned n) /* Bind to the CPU so we don't compare tsc on different CPUs. */ bound = curlwp_bind(); + if (curcpu()->ci_vcpu == NULL) { + curlwp_bindx(bound); + return; + } + /* Short wait (<500us) or long wait? */ if (n < 500000) { /* @@ -655,7 +646,7 @@ xen_resumeclocks(struct cpu_info *ci) /* Disarm the periodic timer on Xen>=3.1 which is allegedly buggy. */ if (XEN_MAJOR(xen_version) > 3 || XEN_MINOR(xen_version) > 0) { error = HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, - ci->ci_cpuid, NULL); + ci->ci_vcpuid, NULL); KASSERT(error == 0); } @@ -738,12 +729,12 @@ again: } /* - * xen_initclocks() + * xen_cpu_initclocks() * * Initialize the Xen clocks on the current CPU. */ void -xen_initclocks(void) +xen_cpu_initclocks(void) { struct cpu_info *ci = curcpu(); @@ -751,15 +742,6 @@ xen_initclocks(void) if (ci == &cpu_info_primary) { /* Initialize the systemwide Xen timecounter. */ tc_init(&xen_timecounter); - -#ifdef DOM0OPS - /* - * If this is a privileged dom0, start pushing the wall - * clock time back to the Xen hypervisor. - */ - if (xendomain_is_privileged()) - xen_timepush_init(); -#endif } /* Attach the event counters. */ @@ -786,6 +768,24 @@ xen_initclocks(void) xen_resumeclocks(ci); } +/* + * xen_initclocks() + * + * Initialize the Xen global clock + */ +void +xen_initclocks(void) +{ +#ifdef DOM0OPS + /* + * If this is a privileged dom0, start pushing the wall + * clock time back to the Xen hypervisor. + */ + if (xendomain_is_privileged()) + xen_timepush_init(); +#endif +} + #ifdef DOM0OPS /*