hvm.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (c) 2008, 2013 Citrix Systems, Inc.
  5. * Copyright (c) 2012 Spectra Logic Corporation
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. #include <sys/cdefs.h>
  30. __FBSDID("$FreeBSD$");
  31. #include <sys/param.h>
  32. #include <sys/bus.h>
  33. #include <sys/kernel.h>
  34. #include <sys/malloc.h>
  35. #include <sys/proc.h>
  36. #include <sys/smp.h>
  37. #include <sys/systm.h>
  38. #include <vm/vm.h>
  39. #include <vm/pmap.h>
  40. #include <vm/vm_param.h>
  41. #include <dev/pci/pcivar.h>
  42. #include <machine/cpufunc.h>
  43. #include <machine/cpu.h>
  44. #include <machine/smp.h>
  45. #include <x86/apicreg.h>
  46. #include <xen/xen-os.h>
  47. #include <xen/error.h>
  48. #include <xen/features.h>
  49. #include <xen/gnttab.h>
  50. #include <xen/hypervisor.h>
  51. #include <xen/hvm.h>
  52. #include <xen/xen_intr.h>
  53. #include <xen/interface/arch-x86/cpuid.h>
  54. #include <xen/interface/hvm/params.h>
  55. #include <xen/interface/vcpu.h>
  56. /*--------------------------- Forward Declarations ---------------------------*/
  57. static void xen_hvm_cpu_init(void);
  58. /*-------------------------------- Global Data -------------------------------*/
  59. enum xen_domain_type xen_domain_type = XEN_NATIVE;
  60. #ifdef SMP
  61. struct cpu_ops xen_hvm_cpu_ops = {
  62. .cpu_init = xen_hvm_cpu_init,
  63. .cpu_resume = xen_hvm_cpu_init
  64. };
  65. #endif
  66. static MALLOC_DEFINE(M_XENHVM, "xen_hvm", "Xen HVM PV Support");
  67. /**
  68. * If non-zero, the hypervisor has been configured to use a direct
  69. * IDT event callback for interrupt injection.
  70. */
  71. int xen_vector_callback_enabled;
  72. /**
  73. * Start info flags. ATM this only used to store the initial domain flag for
  74. * PVHv2, and it's always empty for HVM guests.
  75. */
  76. uint32_t hvm_start_flags;
  77. /**
  78. * Signal whether the vector injected for the event channel upcall requires to
  79. * be EOI'ed on the local APIC.
  80. */
  81. bool xen_evtchn_needs_ack;
  82. /*------------------------------- Per-CPU Data -------------------------------*/
  83. DPCPU_DEFINE(struct vcpu_info, vcpu_local_info);
  84. DPCPU_DEFINE(struct vcpu_info *, vcpu_info);
  85. /*------------------ Hypervisor Access Shared Memory Regions -----------------*/
  86. shared_info_t *HYPERVISOR_shared_info;
  87. /*------------------------------ Sysctl tunables -----------------------------*/
  88. int xen_disable_pv_disks = 0;
  89. int xen_disable_pv_nics = 0;
  90. TUNABLE_INT("hw.xen.disable_pv_disks", &xen_disable_pv_disks);
  91. TUNABLE_INT("hw.xen.disable_pv_nics", &xen_disable_pv_nics);
  92. /*---------------------- XEN Hypervisor Probe and Setup ----------------------*/
  93. static uint32_t cpuid_base;
  94. static uint32_t
  95. xen_hvm_cpuid_base(void)
  96. {
  97. uint32_t base, regs[4];
  98. for (base = 0x40000000; base < 0x40010000; base += 0x100) {
  99. do_cpuid(base, regs);
  100. if (!memcmp("XenVMMXenVMM", &regs[1], 12)
  101. && (regs[0] - base) >= 2)
  102. return (base);
  103. }
  104. return (0);
  105. }
  106. static void
  107. hypervisor_quirks(unsigned int major, unsigned int minor)
  108. {
  109. #ifdef SMP
  110. if (((major < 4) || (major == 4 && minor <= 5)) &&
  111. msix_disable_migration == -1) {
  112. /*
  113. * Xen hypervisors prior to 4.6.0 do not properly
  114. * handle updates to enabled MSI-X table entries,
  115. * so disable MSI-X interrupt migration in that
  116. * case.
  117. */
  118. if (bootverbose)
  119. printf(
  120. "Disabling MSI-X interrupt migration due to Xen hypervisor bug.\n"
  121. "Set machdep.msix_disable_migration=0 to forcefully enable it.\n");
  122. msix_disable_migration = 1;
  123. }
  124. #endif
  125. }
  126. static void
  127. hypervisor_version(void)
  128. {
  129. uint32_t regs[4];
  130. int major, minor;
  131. do_cpuid(cpuid_base + 1, regs);
  132. major = regs[0] >> 16;
  133. minor = regs[0] & 0xffff;
  134. printf("XEN: Hypervisor version %d.%d detected.\n", major, minor);
  135. hypervisor_quirks(major, minor);
  136. }
  137. /*
  138. * Allocate and fill in the hypcall page.
  139. */
  140. int
  141. xen_hvm_init_hypercall_stubs(enum xen_hvm_init_type init_type)
  142. {
  143. uint32_t regs[4];
  144. /* Legacy PVH will get here without the cpuid leaf being set. */
  145. if (cpuid_base == 0)
  146. cpuid_base = xen_hvm_cpuid_base();
  147. if (cpuid_base == 0)
  148. return (ENXIO);
  149. if (xen_domain() && init_type == XEN_HVM_INIT_LATE) {
  150. /*
  151. * If the domain type is already set we can assume that the
  152. * hypercall page has been populated too, so just print the
  153. * version (and apply any quirks) and exit.
  154. */
  155. hypervisor_version();
  156. return 0;
  157. }
  158. if (init_type == XEN_HVM_INIT_LATE)
  159. hypervisor_version();
  160. /*
  161. * Find the hypercall pages.
  162. */
  163. do_cpuid(cpuid_base + 2, regs);
  164. if (regs[0] != 1)
  165. return (EINVAL);
  166. wrmsr(regs[1], (init_type == XEN_HVM_INIT_EARLY)
  167. ? ((vm_paddr_t)&hypercall_page - KERNBASE)
  168. : vtophys(&hypercall_page));
  169. return (0);
  170. }
  171. static void
  172. xen_hvm_init_shared_info_page(void)
  173. {
  174. struct xen_add_to_physmap xatp;
  175. if (xen_pv_domain()) {
  176. /*
  177. * Already setup in the PV case, shared_info is passed inside
  178. * of the start_info struct at start of day.
  179. */
  180. return;
  181. }
  182. if (HYPERVISOR_shared_info == NULL) {
  183. HYPERVISOR_shared_info = malloc(PAGE_SIZE, M_XENHVM, M_NOWAIT);
  184. if (HYPERVISOR_shared_info == NULL)
  185. panic("Unable to allocate Xen shared info page");
  186. }
  187. xatp.domid = DOMID_SELF;
  188. xatp.idx = 0;
  189. xatp.space = XENMAPSPACE_shared_info;
  190. xatp.gpfn = vtophys(HYPERVISOR_shared_info) >> PAGE_SHIFT;
  191. if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
  192. panic("HYPERVISOR_memory_op failed");
  193. }
  194. static int
  195. set_percpu_callback(unsigned int vcpu)
  196. {
  197. struct xen_hvm_evtchn_upcall_vector vec;
  198. int error;
  199. vec.vcpu = vcpu;
  200. vec.vector = IDT_EVTCHN;
  201. error = HYPERVISOR_hvm_op(HVMOP_set_evtchn_upcall_vector, &vec);
  202. return (error != 0 ? xen_translate_error(error) : 0);
  203. }
  204. /*
  205. * Tell the hypervisor how to contact us for event channel callbacks.
  206. */
  207. void
  208. xen_hvm_set_callback(device_t dev)
  209. {
  210. struct xen_hvm_param xhp;
  211. int irq;
  212. if (xen_vector_callback_enabled)
  213. return;
  214. xhp.domid = DOMID_SELF;
  215. xhp.index = HVM_PARAM_CALLBACK_IRQ;
  216. if (xen_feature(XENFEAT_hvm_callback_vector) != 0) {
  217. int error;
  218. error = set_percpu_callback(0);
  219. if (error == 0) {
  220. xen_evtchn_needs_ack = true;
  221. /* Trick toolstack to think we are enlightened */
  222. xhp.value = 1;
  223. } else
  224. xhp.value = HVM_CALLBACK_VECTOR(IDT_EVTCHN);
  225. error = HYPERVISOR_hvm_op(HVMOP_set_param, &xhp);
  226. if (error == 0) {
  227. xen_vector_callback_enabled = 1;
  228. return;
  229. } else if (xen_evtchn_needs_ack)
  230. panic("Unable to setup fake HVM param: %d", error);
  231. printf("Xen HVM callback vector registration failed (%d). "
  232. "Falling back to emulated device interrupt\n", error);
  233. }
  234. xen_vector_callback_enabled = 0;
  235. if (dev == NULL) {
  236. /*
  237. * Called from early boot or resume.
  238. * xenpci will invoke us again later.
  239. */
  240. return;
  241. }
  242. irq = pci_get_irq(dev);
  243. if (irq < 16) {
  244. xhp.value = HVM_CALLBACK_GSI(irq);
  245. } else {
  246. u_int slot;
  247. u_int pin;
  248. slot = pci_get_slot(dev);
  249. pin = pci_get_intpin(dev) - 1;
  250. xhp.value = HVM_CALLBACK_PCI_INTX(slot, pin);
  251. }
  252. if (HYPERVISOR_hvm_op(HVMOP_set_param, &xhp) != 0)
  253. panic("Can't set evtchn callback");
  254. }
  255. #define XEN_MAGIC_IOPORT 0x10
  256. enum {
  257. XMI_MAGIC = 0x49d2,
  258. XMI_UNPLUG_IDE_DISKS = 0x01,
  259. XMI_UNPLUG_NICS = 0x02,
  260. XMI_UNPLUG_IDE_EXCEPT_PRI_MASTER = 0x04
  261. };
  262. static void
  263. xen_hvm_disable_emulated_devices(void)
  264. {
  265. u_short disable_devs = 0;
  266. if (xen_pv_domain()) {
  267. /*
  268. * No emulated devices in the PV case, so no need to unplug
  269. * anything.
  270. */
  271. if (xen_disable_pv_disks != 0 || xen_disable_pv_nics != 0)
  272. printf("PV devices cannot be disabled in PV guests\n");
  273. return;
  274. }
  275. if (inw(XEN_MAGIC_IOPORT) != XMI_MAGIC)
  276. return;
  277. if (xen_disable_pv_disks == 0) {
  278. if (bootverbose)
  279. printf("XEN: disabling emulated disks\n");
  280. disable_devs |= XMI_UNPLUG_IDE_DISKS;
  281. }
  282. if (xen_disable_pv_nics == 0) {
  283. if (bootverbose)
  284. printf("XEN: disabling emulated nics\n");
  285. disable_devs |= XMI_UNPLUG_NICS;
  286. }
  287. if (disable_devs != 0)
  288. outw(XEN_MAGIC_IOPORT, disable_devs);
  289. }
  290. static void
  291. xen_hvm_init(enum xen_hvm_init_type init_type)
  292. {
  293. int error;
  294. int i;
  295. if (init_type == XEN_HVM_INIT_CANCELLED_SUSPEND)
  296. return;
  297. error = xen_hvm_init_hypercall_stubs(init_type);
  298. switch (init_type) {
  299. case XEN_HVM_INIT_LATE:
  300. if (error != 0)
  301. return;
  302. /*
  303. * If xen_domain_type is not set at this point
  304. * it means we are inside a (PV)HVM guest, because
  305. * for PVH the guest type is set much earlier
  306. * (see hammer_time_xen).
  307. */
  308. if (!xen_domain()) {
  309. xen_domain_type = XEN_HVM_DOMAIN;
  310. vm_guest = VM_GUEST_XEN;
  311. }
  312. setup_xen_features();
  313. #ifdef SMP
  314. cpu_ops = xen_hvm_cpu_ops;
  315. #endif
  316. break;
  317. case XEN_HVM_INIT_RESUME:
  318. if (error != 0)
  319. panic("Unable to init Xen hypercall stubs on resume");
  320. /* Clear stale vcpu_info. */
  321. CPU_FOREACH(i)
  322. DPCPU_ID_SET(i, vcpu_info, NULL);
  323. break;
  324. default:
  325. panic("Unsupported HVM initialization type");
  326. }
  327. xen_vector_callback_enabled = 0;
  328. xen_evtchn_needs_ack = false;
  329. xen_hvm_set_callback(NULL);
  330. /*
  331. * On (PV)HVM domains we need to request the hypervisor to
  332. * fill the shared info page, for PVH guest the shared_info page
  333. * is passed inside the start_info struct and is already set, so this
  334. * functions are no-ops.
  335. */
  336. xen_hvm_init_shared_info_page();
  337. xen_hvm_disable_emulated_devices();
  338. }
  339. void
  340. xen_hvm_suspend(void)
  341. {
  342. }
  343. void
  344. xen_hvm_resume(bool suspend_cancelled)
  345. {
  346. xen_hvm_init(suspend_cancelled ?
  347. XEN_HVM_INIT_CANCELLED_SUSPEND : XEN_HVM_INIT_RESUME);
  348. /* Register vcpu_info area for CPU#0. */
  349. xen_hvm_cpu_init();
  350. }
  351. static void
  352. xen_hvm_sysinit(void *arg __unused)
  353. {
  354. xen_hvm_init(XEN_HVM_INIT_LATE);
  355. }
  356. SYSINIT(xen_hvm_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, xen_hvm_sysinit, NULL);
  357. static void
  358. xen_hvm_cpu_init(void)
  359. {
  360. struct vcpu_register_vcpu_info info;
  361. struct vcpu_info *vcpu_info;
  362. uint32_t regs[4];
  363. int cpu, rc;
  364. if (!xen_domain())
  365. return;
  366. if (DPCPU_GET(vcpu_info) != NULL) {
  367. /*
  368. * vcpu_info is already set. We're resuming
  369. * from a failed migration and our pre-suspend
  370. * configuration is still valid.
  371. */
  372. return;
  373. }
  374. /*
  375. * Set vCPU ID. If available fetch the ID from CPUID, if not just use
  376. * the ACPI ID.
  377. */
  378. KASSERT(cpuid_base != 0, ("Invalid base Xen CPUID leaf"));
  379. cpuid_count(cpuid_base + 4, 0, regs);
  380. KASSERT((regs[0] & XEN_HVM_CPUID_VCPU_ID_PRESENT) ||
  381. !xen_pv_domain(),
  382. ("Xen PV domain without vcpu_id in cpuid"));
  383. PCPU_SET(vcpu_id, (regs[0] & XEN_HVM_CPUID_VCPU_ID_PRESENT) ?
  384. regs[1] : PCPU_GET(acpi_id));
  385. if (xen_evtchn_needs_ack && !IS_BSP()) {
  386. /*
  387. * Setup the per-vpcu event channel upcall vector. This is only
  388. * required when using the new HVMOP_set_evtchn_upcall_vector
  389. * hypercall, which allows using a different vector for each
  390. * vCPU. Note that FreeBSD uses the same vector for all vCPUs
  391. * because it's not dynamically allocated.
  392. */
  393. rc = set_percpu_callback(PCPU_GET(vcpu_id));
  394. if (rc != 0)
  395. panic("Event channel upcall vector setup failed: %d",
  396. rc);
  397. }
  398. /*
  399. * Set the vCPU info.
  400. *
  401. * NB: the vCPU info for vCPUs < 32 can be fetched from the shared info
  402. * page, but in order to make sure the mapping code is correct always
  403. * attempt to map the vCPU info at a custom place.
  404. */
  405. vcpu_info = DPCPU_PTR(vcpu_local_info);
  406. cpu = PCPU_GET(vcpu_id);
  407. info.mfn = vtophys(vcpu_info) >> PAGE_SHIFT;
  408. info.offset = vtophys(vcpu_info) - trunc_page(vtophys(vcpu_info));
  409. rc = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info);
  410. if (rc != 0)
  411. DPCPU_SET(vcpu_info, &HYPERVISOR_shared_info->vcpu_info[cpu]);
  412. else
  413. DPCPU_SET(vcpu_info, vcpu_info);
  414. }
  415. SYSINIT(xen_hvm_cpu_init, SI_SUB_INTR, SI_ORDER_FIRST, xen_hvm_cpu_init, NULL);
  416. /* HVM/PVH start_info accessors */
  417. static vm_paddr_t
  418. hvm_get_xenstore_mfn(void)
  419. {
  420. return (hvm_get_parameter(HVM_PARAM_STORE_PFN));
  421. }
  422. static evtchn_port_t
  423. hvm_get_xenstore_evtchn(void)
  424. {
  425. return (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN));
  426. }
  427. static vm_paddr_t
  428. hvm_get_console_mfn(void)
  429. {
  430. return (hvm_get_parameter(HVM_PARAM_CONSOLE_PFN));
  431. }
  432. static evtchn_port_t
  433. hvm_get_console_evtchn(void)
  434. {
  435. return (hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN));
  436. }
  437. static uint32_t
  438. hvm_get_start_flags(void)
  439. {
  440. return (hvm_start_flags);
  441. }
  442. struct hypervisor_info hypervisor_info = {
  443. .get_xenstore_mfn = hvm_get_xenstore_mfn,
  444. .get_xenstore_evtchn = hvm_get_xenstore_evtchn,
  445. .get_console_mfn = hvm_get_console_mfn,
  446. .get_console_evtchn = hvm_get_console_evtchn,
  447. .get_start_flags = hvm_get_start_flags,
  448. };