aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc/spapr.c
diff options
context:
space:
mode:
authorMichael Roth <mdroth@linux.vnet.ibm.com>2019-07-17 15:58:42 -0500
committerDavid Gibson <david@gibson.dropbear.id.au>2019-08-21 17:17:12 +1000
commit0fb6bd07323019dc8d3f2c124323f71e2ddfc9f4 (patch)
treeb58f56e89db22e181cbb27194767ffdd59fb3fb8 /hw/ppc/spapr.c
parent1daba4d1b296d23907b73735615b12588da670fb (diff)
spapr: initial implementation for H_TPM_COMM/spapr-tpm-proxy
This implements the H_TPM_COMM hypercall, which is used by an Ultravisor to pass TPM commands directly to the host's TPM device, or a TPM Resource Manager associated with the device. This also introduces a new virtual device, spapr-tpm-proxy, which is used to configure the host TPM path to be used to service requests sent by H_TPM_COMM hcalls, for example: -device spapr-tpm-proxy,id=tpmp0,host-path=/dev/tpmrm0 By default, no spapr-tpm-proxy will be created, and hcalls will return H_FUNCTION. The full specification for this hypercall can be found in docs/specs/ppc-spapr-uv-hcalls.txt Since SVM-related hcalls like H_TPM_COMM use a reserved range of 0xEF00-0xEF80, we introduce a separate hcall table here to handle them. Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com Message-Id: <20190717205842.17827-3-mdroth@linux.vnet.ibm.com> [dwg: Corrected #include for upstream change] Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/ppc/spapr.c')
-rw-r--r--hw/ppc/spapr.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 15e27d9a10..56b33571c5 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>
@@ -4036,6 +4037,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)
{
@@ -4045,6 +4069,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);
}
}
@@ -4057,6 +4083,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);
}
}
@@ -4091,6 +4119,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);
}
}
@@ -4111,7 +4141,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)) {