diff options
Diffstat (limited to 'hw/ppc/spapr.c')
-rw-r--r-- | hw/ppc/spapr.c | 115 |
1 files changed, 108 insertions, 7 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index e09c67e..64fc225 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -79,6 +79,7 @@ #include "qemu/cutils.h" #include "hw/ppc/spapr_cpu_core.h" #include "hw/mem/memory-device.h" +#include "hw/ppc/spapr_tpm_proxy.h" #include <libfdt.h> @@ -1070,6 +1071,7 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt) add_str(hypertas, "hcall-tce"); add_str(hypertas, "hcall-vio"); add_str(hypertas, "hcall-splpar"); + add_str(hypertas, "hcall-join"); add_str(hypertas, "hcall-bulk"); add_str(hypertas, "hcall-set-mode"); add_str(hypertas, "hcall-sprg0"); @@ -1753,10 +1755,6 @@ static void spapr_machine_reset(MachineState *machine) ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal); } - if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { - spapr_irq_msi_reset(spapr); - } - /* * This is fixing some of the default configuration of the XIVE * devices. To be called after the reset of the machine devices. @@ -3081,6 +3079,13 @@ static void spapr_machine_init(MachineState *machine) qemu_register_boot_set(spapr_boot_set, spapr); + /* + * Nothing needs to be done to resume a suspended guest because + * suspending does not change the machine state, so no need for + * a ->wakeup method. + */ + qemu_register_wakeup_support(); + if (kvm_enabled()) { /* to stop and start vmclock */ qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, @@ -4035,6 +4040,29 @@ static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, } } +static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); + SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); + + if (spapr->tpm_proxy != NULL) { + error_setg(errp, "Only one TPM proxy can be specified for this machine"); + return; + } + + spapr->tpm_proxy = tpm_proxy; +} + +static void spapr_tpm_proxy_unplug(HotplugHandler *hotplug_dev, DeviceState *dev) +{ + SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); + + object_property_set_bool(OBJECT(dev), false, "realized", NULL); + object_unparent(OBJECT(dev)); + spapr->tpm_proxy = NULL; +} + static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -4044,6 +4072,8 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, spapr_core_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { spapr_phb_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { + spapr_tpm_proxy_plug(hotplug_dev, dev, errp); } } @@ -4056,6 +4086,8 @@ static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, spapr_core_unplug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { spapr_phb_unplug(hotplug_dev, dev); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { + spapr_tpm_proxy_unplug(hotplug_dev, dev); } } @@ -4090,6 +4122,8 @@ static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, return; } spapr_phb_unplug_request(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { + spapr_tpm_proxy_unplug(hotplug_dev, dev); } } @@ -4110,7 +4144,8 @@ static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE) || - object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { + object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE) || + object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { return HOTPLUG_HANDLER(machine); } if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { @@ -4306,6 +4341,53 @@ PowerPCCPU *spapr_find_cpu(int vcpu_id) return NULL; } +static void spapr_cpu_exec_enter(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) +{ + SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); + + /* These are only called by TCG, KVM maintains dispatch state */ + + spapr_cpu->prod = false; + if (spapr_cpu->vpa_addr) { + CPUState *cs = CPU(cpu); + uint32_t dispatch; + + dispatch = ldl_be_phys(cs->as, + spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); + dispatch++; + if ((dispatch & 1) != 0) { + qemu_log_mask(LOG_GUEST_ERROR, + "VPA: incorrect dispatch counter value for " + "dispatched partition %u, correcting.\n", dispatch); + dispatch++; + } + stl_be_phys(cs->as, + spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); + } +} + +static void spapr_cpu_exec_exit(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu) +{ + SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu); + + if (spapr_cpu->vpa_addr) { + CPUState *cs = CPU(cpu); + uint32_t dispatch; + + dispatch = ldl_be_phys(cs->as, + spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER); + dispatch++; + if ((dispatch & 1) != 1) { + qemu_log_mask(LOG_GUEST_ERROR, + "VPA: incorrect dispatch counter value for " + "preempted partition %u, correcting.\n", dispatch); + dispatch++; + } + stl_be_phys(cs->as, + spapr_cpu->vpa_addr + VPA_DISPATCH_COUNTER, dispatch); + } +} + static void spapr_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -4362,6 +4444,8 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) vhc->hpte_set_r = spapr_hpte_set_r; vhc->get_pate = spapr_get_pate; vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; + vhc->cpu_exec_enter = spapr_cpu_exec_enter; + vhc->cpu_exec_exit = spapr_cpu_exec_exit; xic->ics_get = spapr_ics_get; xic->ics_resend = spapr_ics_resend; xic->icp_get = spapr_icp_get; @@ -4431,14 +4515,31 @@ static const TypeInfo spapr_machine_info = { type_init(spapr_machine_register_##suffix) /* + * pseries-4.2 + */ +static void spapr_machine_4_2_class_options(MachineClass *mc) +{ + /* Defaults for the latest behaviour inherited from the base class */ +} + +DEFINE_SPAPR_MACHINE(4_2, "4.2", true); + +/* * pseries-4.1 */ static void spapr_machine_4_1_class_options(MachineClass *mc) { - /* Defaults for the latest behaviour inherited from the base class */ + static GlobalProperty compat[] = { + /* Only allow 4kiB and 64kiB IOMMU pagesizes */ + { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" }, + }; + + spapr_machine_4_2_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len); + compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); } -DEFINE_SPAPR_MACHINE(4_1, "4.1", true); +DEFINE_SPAPR_MACHINE(4_1, "4.1", false); /* * pseries-4.0 |