aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2016-10-28 22:06:21 +1100
committerDavid Gibson <david@gibson.dropbear.id.au>2017-01-31 10:10:13 +1100
commit1d1be34d26b66069e20cbbcd798ea57763a0f152 (patch)
tree1299adce01019ee3e3b757edb3a5e38e27a662c4 /hw
parent5b120785e70a9a48b43e3f1f156a10a015334a28 (diff)
ppc: Clean up and QOMify hypercall emulation
The pseries machine type is a bit unusual in that it runs a paravirtualized guest. The guest expects to interact with a hypervisor, and qemu emulates the functions of that hypervisor directly, rather than executing hypervisor code within the emulated system. To implement this in TCG, we need to intercept hypercall instructions and direct them to the machine's hypercall handlers, rather than attempting to perform a privilege change within TCG. This is controlled by a global hook - cpu_ppc_hypercall. This cleanup makes the handling a little cleaner and more extensible than a single global variable. Instead, each CPU to have hypercalls intercepted has a pointer set to a QOM object implementing a new virtual hypervisor interface. A method in that interface is called by TCG when it sees a hypercall instruction. It's possible we may want to add other methods in future. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Reviewed-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'hw')
-rw-r--r--hw/ppc/spapr.c8
-rw-r--r--hw/ppc/spapr_cpu_core.c1
2 files changed, 6 insertions, 3 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index ca78e314a5..a4774fb185 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1005,7 +1005,8 @@ static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
}
-static void emulate_spapr_hypercall(PowerPCCPU *cpu)
+static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp,
+ PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
@@ -1843,8 +1844,6 @@ static void ppc_spapr_init(MachineState *machine)
QLIST_INIT(&spapr->phbs);
- cpu_ppc_hypercall = emulate_spapr_hypercall;
-
/* Allocate RMA if necessary */
rma_alloc_size = kvmppc_alloc_rma(&rma);
@@ -2680,6 +2679,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
NMIClass *nc = NMI_CLASS(oc);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
+ PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc);
mc->desc = "pSeries Logical Partition (PAPR compliant)";
@@ -2711,6 +2711,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
fwc->get_dev_path = spapr_get_fw_dev_path;
nc->nmi_monitor_handler = spapr_nmi;
smc->phb_placement = spapr_phb_placement;
+ vhc->hypercall = emulate_spapr_hypercall;
}
static const TypeInfo spapr_machine_info = {
@@ -2726,6 +2727,7 @@ static const TypeInfo spapr_machine_info = {
{ TYPE_FW_PATH_PROVIDER },
{ TYPE_NMI },
{ TYPE_HOTPLUG_HANDLER },
+ { TYPE_PPC_VIRTUAL_HYPERVISOR },
{ }
},
};
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index f532689354..9dddaeb3fa 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -57,6 +57,7 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
/* Enable PAPR mode in TCG or KVM */
+ cpu_ppc_set_vhyp(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
cpu_ppc_set_papr(cpu);
if (cpu->max_compat) {