gibbs a9c07a6f67 Add support for suspend/resume/migration operations when running as a
Xen PVHVM guest.

Submitted by:	Roger Pau Monné
Sponsored by:	Citrix Systems R&D
Reviewed by:	gibbs
Approved by:	re (blanket Xen)
MFC after:	2 weeks

sys/amd64/amd64/mp_machdep.c:
sys/i386/i386/mp_machdep.c:
	- Make sure that are no MMU related IPIs pending on migration.
	- Reset pending IPI_BITMAP on resume.
	- Init vcpu_info on resume.

sys/amd64/include/intr_machdep.h:
sys/i386/include/intr_machdep.h:
sys/x86/acpica/acpi_wakeup.c:
sys/x86/x86/intr_machdep.c:
sys/x86/isa/atpic.c:
sys/x86/x86/io_apic.c:
sys/x86/x86/local_apic.c:
	- Add a "suspend_cancelled" parameter to pic_resume().  For the
	  Xen PIC, restoration of interrupt services differs between
	  the aborted suspend and normal resume cases, so we must provide
	  this information.

sys/dev/acpica/acpi_timer.c:
sys/dev/xen/timer/timer.c:
sys/timetc.h:
	- Don't swap out "suspend safe" timers across a suspend/resume
	  cycle.  This includes the Xen PV and ACPI timers.

sys/dev/xen/control/control.c:
	- Perform proper suspend/resume process for PVHVM:
		- Suspend all APs before going into suspension, this allows us
		  to reset the vcpu_info on resume for each AP.
		- Reset shared info page and callback on resume.

sys/dev/xen/timer/timer.c:
	- Implement suspend/resume support for the PV timer. Since FreeBSD
	  doesn't perform a per-cpu resume of the timer, we need to call
	  smp_rendezvous in order to correctly resume the timer on each CPU.

sys/dev/xen/xenpci/xenpci.c:
	- Don't reset the PCI interrupt on each suspend/resume.

sys/kern/subr_smp.c:
	- When suspending a PVHVM domain make sure there are no MMU IPIs
	  in-flight, or we will get a lockup on resume due to the fact that
	  pending event channels are not carried over on migration.
	- Implement a generic version of restart_cpus that can be used by
	  suspended and stopped cpus.

sys/x86/xen/hvm.c:
	- Implement resume support for the hypercall page and shared info.
	- Clear vcpu_info so it can be reset by APs when resuming from
	  suspension.

sys/dev/xen/xenpci/xenpci.c:
sys/x86/xen/hvm.c:
sys/x86/xen/xen_intr.c:
	- Support UP kernel configurations.

sys/x86/xen/xen_intr.c:
	- Properly rebind per-cpus VIRQs and IPIs on resume.
2013-09-20 05:06:03 +00:00

99 lines
3.1 KiB
C

/*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* $FreeBSD$
*/
#ifndef __XEN_HVM_H__
#define __XEN_HVM_H__
#include <xen/xen-os.h>
#include <xen/hypervisor.h>
#include <xen/interface/hvm/params.h>
/**
* \brief Wrapper function to obtain a HVM parameter value.
*
* \param index HVM parameter index; see <xen/interface/hvm/params.h>.
*
* \returns 0 on failure; the value of the parameter otherwise.
*/
static inline unsigned long
hvm_get_parameter(int index)
{
struct xen_hvm_param xhv;
int error;
xhv.domid = DOMID_SELF;
xhv.index = index;
error = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
if (error) {
printf("%s: error %d trying to get %d\n", __func__,
error, index);
return (0);
}
return (xhv.value);
}
/** The callback method types for Hypervisor event delivery to our domain. */
enum {
HVM_CB_TYPE_GSI,
HVM_CB_TYPE_PCI_INTX,
HVM_CB_TYPE_VECTOR,
HVM_CB_TYPE_MASK = 0xFF,
HVM_CB_TYPE_SHIFT = 56
};
/** Format for specifying a GSI type callback. */
enum {
HVM_CB_GSI_GSI_MASK = 0xFFFFFFFF,
HVM_CB_GSI_GSI_SHIFT = 0
};
#define HVM_CALLBACK_GSI(gsi) \
(((uint64_t)HVM_CB_TYPE_GSI << HVM_CB_TYPE_SHIFT) \
| ((gsi) & HVM_CB_GSI_GSI_MASK) << HVM_CB_GSI_GSI_SHIFT)
/** Format for specifying a virtual PCI interrupt line GSI style callback. */
enum {
HVM_CB_PCI_INTX_INTPIN_MASK = 0x3,
HVM_CB_PCI_INTX_INTPIN_SHIFT = 0,
HVM_CB_PCI_INTX_SLOT_MASK = 0x1F,
HVM_CB_PCI_INTX_SLOT_SHIFT = 11,
};
#define HVM_CALLBACK_PCI_INTX(slot, pin) \
(((uint64_t)HVM_CB_TYPE_PCI_INTX << HVM_CB_TYPE_SHIFT) \
| (((slot) & HVM_CB_PCI_INTX_SLOT_MASK) << HVM_CB_PCI_INTX_SLOT_SHIFT) \
| (((pin) & HVM_CB_PCI_INTX_INTPIN_MASK) << HVM_CB_PCI_INTX_INTPIN_SHIFT))
/** Format for specifying a direct IDT vector injection style callback. */
enum {
HVM_CB_VECTOR_VECTOR_MASK = 0xFFFFFFFF,
HVM_CB_VECTOR_VECTOR_SHIFT = 0
};
#define HVM_CALLBACK_VECTOR(vector) \
(((uint64_t)HVM_CB_TYPE_VECTOR << HVM_CB_TYPE_SHIFT) \
| (((vector) & HVM_CB_GSI_GSI_MASK) << HVM_CB_GSI_GSI_SHIFT))
void xen_hvm_set_callback(device_t);
void xen_hvm_suspend(void);
void xen_hvm_resume(bool suspend_cancelled);
void xen_hvm_init_cpu(void);
#endif /* __XEN_HVM_H__ */