hvm.c (ef90af83a58199ef3980d8c9a7dad07ec9b4bea3) hvm.c (428b7ca290208e6b15d46440cd8d6309dc92dd2d)
1/*
2 * Copyright (c) 2008, 2013 Citrix Systems, Inc.
3 * Copyright (c) 2012 Spectra Logic Corporation
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 44 unchanged lines hidden (view full) ---

53#include <xen/hypervisor.h>
54#include <xen/hvm.h>
55#include <xen/xen_intr.h>
56
57#include <xen/interface/hvm/params.h>
58#include <xen/interface/vcpu.h>
59
60/*--------------------------- Forward Declarations ---------------------------*/
1/*
2 * Copyright (c) 2008, 2013 Citrix Systems, Inc.
3 * Copyright (c) 2012 Spectra Logic Corporation
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 44 unchanged lines hidden (view full) ---

53#include <xen/hypervisor.h>
54#include <xen/hvm.h>
55#include <xen/xen_intr.h>
56
57#include <xen/interface/hvm/params.h>
58#include <xen/interface/vcpu.h>
59
60/*--------------------------- Forward Declarations ---------------------------*/
61#ifdef SMP
61static driver_filter_t xen_smp_rendezvous_action;
62static driver_filter_t xen_invltlb;
63static driver_filter_t xen_invlpg;
64static driver_filter_t xen_invlrng;
65static driver_filter_t xen_invlcache;
66#ifdef __i386__
67static driver_filter_t xen_lazypmap;
68#endif
69static driver_filter_t xen_ipi_bitmap_handler;
70static driver_filter_t xen_cpustop_handler;
71static driver_filter_t xen_cpususpend_handler;
72static driver_filter_t xen_cpustophard_handler;
62static driver_filter_t xen_smp_rendezvous_action;
63static driver_filter_t xen_invltlb;
64static driver_filter_t xen_invlpg;
65static driver_filter_t xen_invlrng;
66static driver_filter_t xen_invlcache;
67#ifdef __i386__
68static driver_filter_t xen_lazypmap;
69#endif
70static driver_filter_t xen_ipi_bitmap_handler;
71static driver_filter_t xen_cpustop_handler;
72static driver_filter_t xen_cpususpend_handler;
73static driver_filter_t xen_cpustophard_handler;
74#endif
73
74/*---------------------------- Extern Declarations ---------------------------*/
75/* Variables used by mp_machdep to perform the MMU related IPIs */
76extern volatile int smp_tlb_wait;
77extern vm_offset_t smp_tlb_addr2;
78#ifdef __i386__
79extern vm_offset_t smp_tlb_addr1;
80#else

--- 7 unchanged lines hidden (view full) ---

88#ifdef __i386__
89extern void pmap_lazyfix_action(void);
90#endif
91
92/*---------------------------------- Macros ----------------------------------*/
93#define IPI_TO_IDX(ipi) ((ipi) - APIC_IPI_INTS)
94
95/*-------------------------------- Local Types -------------------------------*/
75
76/*---------------------------- Extern Declarations ---------------------------*/
77/* Variables used by mp_machdep to perform the MMU related IPIs */
78extern volatile int smp_tlb_wait;
79extern vm_offset_t smp_tlb_addr2;
80#ifdef __i386__
81extern vm_offset_t smp_tlb_addr1;
82#else

--- 7 unchanged lines hidden (view full) ---

90#ifdef __i386__
91extern void pmap_lazyfix_action(void);
92#endif
93
94/*---------------------------------- Macros ----------------------------------*/
95#define IPI_TO_IDX(ipi) ((ipi) - APIC_IPI_INTS)
96
97/*-------------------------------- Local Types -------------------------------*/
98enum xen_hvm_init_type {
99 XEN_HVM_INIT_COLD,
100 XEN_HVM_INIT_CANCELLED_SUSPEND,
101 XEN_HVM_INIT_RESUME
102};
103
96struct xen_ipi_handler
97{
98 driver_filter_t *filter;
99 const char *description;
100};
101
102/*-------------------------------- Global Data -------------------------------*/
103enum xen_domain_type xen_domain_type = XEN_NATIVE;
104
105static MALLOC_DEFINE(M_XENHVM, "xen_hvm", "Xen HVM PV Support");
106
104struct xen_ipi_handler
105{
106 driver_filter_t *filter;
107 const char *description;
108};
109
110/*-------------------------------- Global Data -------------------------------*/
111enum xen_domain_type xen_domain_type = XEN_NATIVE;
112
113static MALLOC_DEFINE(M_XENHVM, "xen_hvm", "Xen HVM PV Support");
114
115#ifdef SMP
107static struct xen_ipi_handler xen_ipis[] =
108{
109 [IPI_TO_IDX(IPI_RENDEZVOUS)] = { xen_smp_rendezvous_action, "r" },
110 [IPI_TO_IDX(IPI_INVLTLB)] = { xen_invltlb, "itlb"},
111 [IPI_TO_IDX(IPI_INVLPG)] = { xen_invlpg, "ipg" },
112 [IPI_TO_IDX(IPI_INVLRNG)] = { xen_invlrng, "irg" },
113 [IPI_TO_IDX(IPI_INVLCACHE)] = { xen_invlcache, "ic" },
114#ifdef __i386__
115 [IPI_TO_IDX(IPI_LAZYPMAP)] = { xen_lazypmap, "lp" },
116#endif
117 [IPI_TO_IDX(IPI_BITMAP_VECTOR)] = { xen_ipi_bitmap_handler, "b" },
118 [IPI_TO_IDX(IPI_STOP)] = { xen_cpustop_handler, "st" },
119 [IPI_TO_IDX(IPI_SUSPEND)] = { xen_cpususpend_handler, "sp" },
120 [IPI_TO_IDX(IPI_STOP_HARD)] = { xen_cpustophard_handler, "sth" },
121};
116static struct xen_ipi_handler xen_ipis[] =
117{
118 [IPI_TO_IDX(IPI_RENDEZVOUS)] = { xen_smp_rendezvous_action, "r" },
119 [IPI_TO_IDX(IPI_INVLTLB)] = { xen_invltlb, "itlb"},
120 [IPI_TO_IDX(IPI_INVLPG)] = { xen_invlpg, "ipg" },
121 [IPI_TO_IDX(IPI_INVLRNG)] = { xen_invlrng, "irg" },
122 [IPI_TO_IDX(IPI_INVLCACHE)] = { xen_invlcache, "ic" },
123#ifdef __i386__
124 [IPI_TO_IDX(IPI_LAZYPMAP)] = { xen_lazypmap, "lp" },
125#endif
126 [IPI_TO_IDX(IPI_BITMAP_VECTOR)] = { xen_ipi_bitmap_handler, "b" },
127 [IPI_TO_IDX(IPI_STOP)] = { xen_cpustop_handler, "st" },
128 [IPI_TO_IDX(IPI_SUSPEND)] = { xen_cpususpend_handler, "sp" },
129 [IPI_TO_IDX(IPI_STOP_HARD)] = { xen_cpustophard_handler, "sth" },
130};
131#endif
122
123/**
124 * If non-zero, the hypervisor has been configured to use a direct
125 * IDT event callback for interrupt injection.
126 */
127int xen_vector_callback_enabled;
128
129/*------------------------------- Per-CPU Data -------------------------------*/
130DPCPU_DEFINE(struct vcpu_info, vcpu_local_info);
131DPCPU_DEFINE(struct vcpu_info *, vcpu_info);
132
133/**
134 * If non-zero, the hypervisor has been configured to use a direct
135 * IDT event callback for interrupt injection.
136 */
137int xen_vector_callback_enabled;
138
139/*------------------------------- Per-CPU Data -------------------------------*/
140DPCPU_DEFINE(struct vcpu_info, vcpu_local_info);
141DPCPU_DEFINE(struct vcpu_info *, vcpu_info);
142#ifdef SMP
132DPCPU_DEFINE(xen_intr_handle_t, ipi_handle[nitems(xen_ipis)]);
143DPCPU_DEFINE(xen_intr_handle_t, ipi_handle[nitems(xen_ipis)]);
144#endif
133
134/*------------------ Hypervisor Access Shared Memory Regions -----------------*/
135/** Hypercall table accessed via HYPERVISOR_*_op() methods. */
136char *hypercall_stubs;
137shared_info_t *HYPERVISOR_shared_info;
138
145
146/*------------------ Hypervisor Access Shared Memory Regions -----------------*/
147/** Hypercall table accessed via HYPERVISOR_*_op() methods. */
148char *hypercall_stubs;
149shared_info_t *HYPERVISOR_shared_info;
150
151#ifdef SMP
139/*---------------------------- XEN PV IPI Handlers ---------------------------*/
140/*
141 * This are C clones of the ASM functions found in apic_vector.s
142 */
143static int
144xen_ipi_bitmap_handler(void *arg)
145{
146 struct trapframe *frame;

--- 344 unchanged lines hidden (view full) ---

491 }
492#endif
493 CPU_FOREACH(i)
494 xen_cpu_ipi_init(i);
495
496 /* Set the xen pv ipi ops to replace the native ones */
497 cpu_ops.ipi_vectored = xen_ipi_vectored;
498}
152/*---------------------------- XEN PV IPI Handlers ---------------------------*/
153/*
154 * This are C clones of the ASM functions found in apic_vector.s
155 */
156static int
157xen_ipi_bitmap_handler(void *arg)
158{
159 struct trapframe *frame;

--- 344 unchanged lines hidden (view full) ---

504 }
505#endif
506 CPU_FOREACH(i)
507 xen_cpu_ipi_init(i);
508
509 /* Set the xen pv ipi ops to replace the native ones */
510 cpu_ops.ipi_vectored = xen_ipi_vectored;
511}
512#endif
499
500/*---------------------- XEN Hypervisor Probe and Setup ----------------------*/
501static uint32_t
502xen_hvm_cpuid_base(void)
503{
504 uint32_t base, regs[4];
505
506 for (base = 0x40000000; base < 0x40010000; base += 0x100) {

--- 67 unchanged lines hidden (view full) ---

574 * Tell the hypervisor how to contact us for event channel callbacks.
575 */
576void
577xen_hvm_set_callback(device_t dev)
578{
579 struct xen_hvm_param xhp;
580 int irq;
581
513
514/*---------------------- XEN Hypervisor Probe and Setup ----------------------*/
515static uint32_t
516xen_hvm_cpuid_base(void)
517{
518 uint32_t base, regs[4];
519
520 for (base = 0x40000000; base < 0x40010000; base += 0x100) {

--- 67 unchanged lines hidden (view full) ---

588 * Tell the hypervisor how to contact us for event channel callbacks.
589 */
590void
591xen_hvm_set_callback(device_t dev)
592{
593 struct xen_hvm_param xhp;
594 int irq;
595
596 if (xen_vector_callback_enabled)
597 return;
598
582 xhp.domid = DOMID_SELF;
583 xhp.index = HVM_PARAM_CALLBACK_IRQ;
584 if (xen_feature(XENFEAT_hvm_callback_vector) != 0) {
585 int error;
586
587 xhp.value = HVM_CALLBACK_VECTOR(IDT_EVTCHN);
588 error = HYPERVISOR_hvm_op(HVMOP_set_param, &xhp);
589 if (error == 0) {

--- 42 unchanged lines hidden (view full) ---

632 if (inw(XEN_MAGIC_IOPORT) != XMI_MAGIC)
633 return;
634
635 if (bootverbose)
636 printf("XEN: Disabling emulated block and network devices\n");
637 outw(XEN_MAGIC_IOPORT, XMI_UNPLUG_IDE_DISKS|XMI_UNPLUG_NICS);
638}
639
599 xhp.domid = DOMID_SELF;
600 xhp.index = HVM_PARAM_CALLBACK_IRQ;
601 if (xen_feature(XENFEAT_hvm_callback_vector) != 0) {
602 int error;
603
604 xhp.value = HVM_CALLBACK_VECTOR(IDT_EVTCHN);
605 error = HYPERVISOR_hvm_op(HVMOP_set_param, &xhp);
606 if (error == 0) {

--- 42 unchanged lines hidden (view full) ---

649 if (inw(XEN_MAGIC_IOPORT) != XMI_MAGIC)
650 return;
651
652 if (bootverbose)
653 printf("XEN: Disabling emulated block and network devices\n");
654 outw(XEN_MAGIC_IOPORT, XMI_UNPLUG_IDE_DISKS|XMI_UNPLUG_NICS);
655}
656
657static void
658xen_hvm_init(enum xen_hvm_init_type init_type)
659{
660 int error;
661 int i;
662
663 if (init_type == XEN_HVM_INIT_CANCELLED_SUSPEND)
664 return;
665
666 error = xen_hvm_init_hypercall_stubs();
667
668 switch (init_type) {
669 case XEN_HVM_INIT_COLD:
670 if (error != 0)
671 return;
672
673 setup_xen_features();
674 break;
675 case XEN_HVM_INIT_RESUME:
676 if (error != 0)
677 panic("Unable to init Xen hypercall stubs on resume");
678 break;
679 default:
680 panic("Unsupported HVM initialization type");
681 }
682
683 /* Clear any stale vcpu_info. */
684 CPU_FOREACH(i)
685 DPCPU_ID_SET(i, vcpu_info, NULL);
686
687 xen_vector_callback_enabled = 0;
688 xen_domain_type = XEN_HVM_DOMAIN;
689 xen_hvm_init_shared_info_page();
690 xen_hvm_set_callback(NULL);
691 xen_hvm_disable_emulated_devices();
692}
693
640void
641xen_hvm_suspend(void)
642{
643}
644
645void
694void
695xen_hvm_suspend(void)
696{
697}
698
699void
646xen_hvm_resume(void)
700xen_hvm_resume(bool suspend_cancelled)
647{
648
701{
702
649 xen_hvm_init_hypercall_stubs();
650 xen_hvm_init_shared_info_page();
703 xen_hvm_init(suspend_cancelled ?
704 XEN_HVM_INIT_CANCELLED_SUSPEND : XEN_HVM_INIT_RESUME);
705
706 /* Register vcpu_info area for CPU#0. */
707 xen_hvm_init_cpu();
651}
652
653static void
708}
709
710static void
654xen_hvm_init(void *dummy __unused)
711xen_hvm_sysinit(void *arg __unused)
655{
712{
713 xen_hvm_init(XEN_HVM_INIT_COLD);
714}
656
715
657 if (xen_hvm_init_hypercall_stubs() != 0)
658 return;
659
660 xen_domain_type = XEN_HVM_DOMAIN;
661 setup_xen_features();
662 xen_hvm_init_shared_info_page();
663 xen_hvm_set_callback(NULL);
664 xen_hvm_disable_emulated_devices();
665}
666
667void xen_hvm_init_cpu(void)
716void
717xen_hvm_init_cpu(void)
668{
669 struct vcpu_register_vcpu_info info;
670 struct vcpu_info *vcpu_info;
671 int cpu, rc;
672
718{
719 struct vcpu_register_vcpu_info info;
720 struct vcpu_info *vcpu_info;
721 int cpu, rc;
722
673 cpu = PCPU_GET(acpi_id);
723 if (DPCPU_GET(vcpu_info) != NULL) {
724 /*
725 * vcpu_info is already set. We're resuming
726 * from a failed migration and our pre-suspend
727 * configuration is still valid.
728 */
729 return;
730 }
731
674 vcpu_info = DPCPU_PTR(vcpu_local_info);
732 vcpu_info = DPCPU_PTR(vcpu_local_info);
733 cpu = PCPU_GET(acpi_id);
675 info.mfn = vtophys(vcpu_info) >> PAGE_SHIFT;
676 info.offset = vtophys(vcpu_info) - trunc_page(vtophys(vcpu_info));
677
678 rc = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info);
679 if (rc != 0)
680 DPCPU_SET(vcpu_info, &HYPERVISOR_shared_info->vcpu_info[cpu]);
681 else
682 DPCPU_SET(vcpu_info, vcpu_info);
683}
684
734 info.mfn = vtophys(vcpu_info) >> PAGE_SHIFT;
735 info.offset = vtophys(vcpu_info) - trunc_page(vtophys(vcpu_info));
736
737 rc = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info);
738 if (rc != 0)
739 DPCPU_SET(vcpu_info, &HYPERVISOR_shared_info->vcpu_info[cpu]);
740 else
741 DPCPU_SET(vcpu_info, vcpu_info);
742}
743
685SYSINIT(xen_hvm_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, xen_hvm_init, NULL);
744SYSINIT(xen_hvm_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, xen_hvm_sysinit, NULL);
745#ifdef SMP
686SYSINIT(xen_init_ipis, SI_SUB_SMP, SI_ORDER_FIRST, xen_init_ipis, NULL);
746SYSINIT(xen_init_ipis, SI_SUB_SMP, SI_ORDER_FIRST, xen_init_ipis, NULL);
747#endif
687SYSINIT(xen_hvm_init_cpu, SI_SUB_INTR, SI_ORDER_FIRST, xen_hvm_init_cpu, NULL);
748SYSINIT(xen_hvm_init_cpu, SI_SUB_INTR, SI_ORDER_FIRST, xen_hvm_init_cpu, NULL);