[PULL 05/33] i386: Add 'sgx-epc' device to expose EPC sections to guest

Paolo Bonzini posted 33 patches 4 years, 4 months ago
Maintainers: Eduardo Habkost <ehabkost@redhat.com>, Greg Kurz <groug@kaod.org>, Colin Xu <colin.xu@intel.com>, Roman Bolshakov <r.bolshakov@yadro.com>, Paolo Bonzini <pbonzini@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, John G Johnson <john.g.johnson@oracle.com>, Reinoud Zandijk <reinoud@netbsd.org>, "Daniel P. Berrangé" <berrange@redhat.com>, David Gibson <david@gibson.dropbear.id.au>, Cameron Esfahani <dirty@apple.com>, David Hildenbrand <david@redhat.com>, Peter Xu <peterx@redhat.com>, Ani Sinha <ani@anisinha.ca>, Markus Armbruster <armbru@redhat.com>, Sunil Muthuswamy <sunilmut@microsoft.com>, Igor Mammedov <imammedo@redhat.com>, Paul Durrant <paul@xen.org>, Anthony Perard <anthony.perard@citrix.com>, "Michael S. Tsirkin" <mst@redhat.com>, Wenchao Wang <wenchao.wang@intel.com>, Laurent Vivier <lvivier@redhat.com>, Jagannathan Raman <jag.raman@oracle.com>, Eric Blake <eblake@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, Elena Ufimtseva <elena.ufimtseva@oracle.com>, Peter Maydell <peter.maydell@linaro.org>, Thomas Huth <thuth@redhat.com>, Marcelo Tosatti <mtosatti@redhat.com>, Stefano Stabellini <sstabellini@kernel.org>, "Dr. David Alan Gilbert" <dgilbert@redhat.com>, Alex Williamson <alex.williamson@redhat.com>, Kamil Rytarowski <kamil@netbsd.org>
There is a newer version of this series
[PULL 05/33] i386: Add 'sgx-epc' device to expose EPC sections to guest
Posted by Paolo Bonzini 4 years, 4 months ago
From: Sean Christopherson <sean.j.christopherson@intel.com>

SGX EPC is enumerated through CPUID, i.e. EPC "devices" need to be
realized prior to realizing the vCPUs themselves, which occurs long
before generic devices are parsed and realized.  Because of this,
do not allow 'sgx-epc' devices to be instantiated after vCPUS have
been created.

The 'sgx-epc' device is essentially a placholder at this time, it will
be fully implemented in a future patch along with a dedicated command
to create 'sgx-epc' devices.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Yang Zhong <yang.zhong@intel.com>
Message-Id: <20210719112136.57018-5-yang.zhong@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/i386/meson.build       |   1 +
 hw/i386/sgx-epc.c         | 167 ++++++++++++++++++++++++++++++++++++++
 include/hw/i386/sgx-epc.h |  44 ++++++++++
 3 files changed, 212 insertions(+)
 create mode 100644 hw/i386/sgx-epc.c
 create mode 100644 include/hw/i386/sgx-epc.h

diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 80dad29f2b..b1862c83d4 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -16,6 +16,7 @@ i386_ss.add(when: 'CONFIG_Q35', if_true: files('pc_q35.c'))
 i386_ss.add(when: 'CONFIG_VMMOUSE', if_true: files('vmmouse.c'))
 i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c'))
 i386_ss.add(when: 'CONFIG_VTD', if_true: files('intel_iommu.c'))
+i386_ss.add(when: 'CONFIG_SGX', if_true: files('sgx-epc.c'))
 
 i386_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c'))
 i386_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device_x86.c'))
diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c
new file mode 100644
index 0000000000..c584acc17b
--- /dev/null
+++ b/hw/i386/sgx-epc.c
@@ -0,0 +1,167 @@
+/*
+ * SGX EPC device
+ *
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * Authors:
+ *   Sean Christopherson <sean.j.christopherson@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "hw/i386/pc.h"
+#include "hw/i386/sgx-epc.h"
+#include "hw/mem/memory-device.h"
+#include "hw/qdev-properties.h"
+#include "monitor/qdev.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qemu/config-file.h"
+#include "qemu/error-report.h"
+#include "qemu/option.h"
+#include "qemu/units.h"
+#include "target/i386/cpu.h"
+#include "exec/address-spaces.h"
+
+static Property sgx_epc_properties[] = {
+    DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP, SGXEPCDevice, addr, 0),
+    DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP, SGXEPCDevice, hostmem,
+                     TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sgx_epc_get_size(Object *obj, Visitor *v, const char *name,
+                             void *opaque, Error **errp)
+{
+    Error *local_err = NULL;
+    uint64_t value;
+
+    value = memory_device_get_region_size(MEMORY_DEVICE(obj), &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    visit_type_uint64(v, name, &value, errp);
+}
+
+static void sgx_epc_init(Object *obj)
+{
+    object_property_add(obj, SGX_EPC_SIZE_PROP, "uint64", sgx_epc_get_size,
+                        NULL, NULL, NULL);
+}
+
+static void sgx_epc_realize(DeviceState *dev, Error **errp)
+{
+    PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+    X86MachineState *x86ms = X86_MACHINE(pcms);
+    SGXEPCDevice *epc = SGX_EPC(dev);
+    HostMemoryBackend *hostmem;
+    const char *path;
+
+    if (x86ms->boot_cpus != 0) {
+        error_setg(errp, "'" TYPE_SGX_EPC "' can't be created after vCPUs,"
+                         "e.g. via -device");
+        return;
+    }
+
+    if (!epc->hostmem) {
+        error_setg(errp, "'" SGX_EPC_MEMDEV_PROP "' property is not set");
+        return;
+    }
+    hostmem = MEMORY_BACKEND(epc->hostmem);
+    if (host_memory_backend_is_mapped(hostmem)) {
+        path = object_get_canonical_path_component(OBJECT(hostmem));
+        error_setg(errp, "can't use already busy memdev: %s", path);
+        return;
+    }
+
+    error_setg(errp, "'" TYPE_SGX_EPC "' not supported");
+}
+
+static void sgx_epc_unrealize(DeviceState *dev)
+{
+    SGXEPCDevice *epc = SGX_EPC(dev);
+    HostMemoryBackend *hostmem = MEMORY_BACKEND(epc->hostmem);
+
+    host_memory_backend_set_mapped(hostmem, false);
+}
+
+static uint64_t sgx_epc_md_get_addr(const MemoryDeviceState *md)
+{
+    const SGXEPCDevice *epc = SGX_EPC(md);
+
+    return epc->addr;
+}
+
+static void sgx_epc_md_set_addr(MemoryDeviceState *md, uint64_t addr,
+                                Error **errp)
+{
+    object_property_set_uint(OBJECT(md), SGX_EPC_ADDR_PROP, addr, errp);
+}
+
+static uint64_t sgx_epc_md_get_plugged_size(const MemoryDeviceState *md,
+                                            Error **errp)
+{
+    return 0;
+}
+
+static MemoryRegion *sgx_epc_md_get_memory_region(MemoryDeviceState *md,
+                                                  Error **errp)
+{
+    SGXEPCDevice *epc = SGX_EPC(md);
+    HostMemoryBackend *hostmem;
+
+    if (!epc->hostmem) {
+        error_setg(errp, "'" SGX_EPC_MEMDEV_PROP "' property must be set");
+        return NULL;
+    }
+
+    hostmem = MEMORY_BACKEND(epc->hostmem);
+    return host_memory_backend_get_memory(hostmem);
+}
+
+static void sgx_epc_md_fill_device_info(const MemoryDeviceState *md,
+                                        MemoryDeviceInfo *info)
+{
+    /* TODO */
+}
+
+static void sgx_epc_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(oc);
+
+    dc->hotpluggable = false;
+    dc->realize = sgx_epc_realize;
+    dc->unrealize = sgx_epc_unrealize;
+    dc->desc = "SGX EPC section";
+    device_class_set_props(dc, sgx_epc_properties);
+
+    mdc->get_addr = sgx_epc_md_get_addr;
+    mdc->set_addr = sgx_epc_md_set_addr;
+    mdc->get_plugged_size = sgx_epc_md_get_plugged_size;
+    mdc->get_memory_region = sgx_epc_md_get_memory_region;
+    mdc->fill_device_info = sgx_epc_md_fill_device_info;
+}
+
+static TypeInfo sgx_epc_info = {
+    .name          = TYPE_SGX_EPC,
+    .parent        = TYPE_DEVICE,
+    .instance_size = sizeof(SGXEPCDevice),
+    .instance_init = sgx_epc_init,
+    .class_init    = sgx_epc_class_init,
+    .class_size    = sizeof(DeviceClass),
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_MEMORY_DEVICE },
+        { }
+    },
+};
+
+static void sgx_epc_register_types(void)
+{
+    type_register_static(&sgx_epc_info);
+}
+
+type_init(sgx_epc_register_types)
diff --git a/include/hw/i386/sgx-epc.h b/include/hw/i386/sgx-epc.h
new file mode 100644
index 0000000000..cf3ed5c0cd
--- /dev/null
+++ b/include/hw/i386/sgx-epc.h
@@ -0,0 +1,44 @@
+/*
+ * SGX EPC device
+ *
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * Authors:
+ *   Sean Christopherson <sean.j.christopherson@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#ifndef QEMU_SGX_EPC_H
+#define QEMU_SGX_EPC_H
+
+#include "hw/i386/hostmem-epc.h"
+
+#define TYPE_SGX_EPC "sgx-epc"
+#define SGX_EPC(obj) \
+    OBJECT_CHECK(SGXEPCDevice, (obj), TYPE_SGX_EPC)
+#define SGX_EPC_CLASS(oc) \
+    OBJECT_CLASS_CHECK(SGXEPCDeviceClass, (oc), TYPE_SGX_EPC)
+#define SGX_EPC_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(SGXEPCDeviceClass, (obj), TYPE_SGX_EPC)
+
+#define SGX_EPC_ADDR_PROP "addr"
+#define SGX_EPC_SIZE_PROP "size"
+#define SGX_EPC_MEMDEV_PROP "memdev"
+
+/**
+ * SGXEPCDevice:
+ * @addr: starting guest physical address, where @SGXEPCDevice is mapped.
+ *         Default value: 0, means that address is auto-allocated.
+ * @hostmem: host memory backend providing memory for @SGXEPCDevice
+ */
+typedef struct SGXEPCDevice {
+    /* private */
+    DeviceState parent_obj;
+
+    /* public */
+    uint64_t addr;
+    HostMemoryBackendEpc *hostmem;
+} SGXEPCDevice;
+
+#endif
-- 
2.31.1



Re: [PULL 05/33] i386: Add 'sgx-epc' device to expose EPC sections to guest
Posted by Thomas Huth 4 years, 3 months ago
On 28/09/2021 14.50, Paolo Bonzini wrote:
> From: Sean Christopherson <sean.j.christopherson@intel.com>
> 
> SGX EPC is enumerated through CPUID, i.e. EPC "devices" need to be
> realized prior to realizing the vCPUs themselves, which occurs long
> before generic devices are parsed and realized.  Because of this,
> do not allow 'sgx-epc' devices to be instantiated after vCPUS have
> been created.
> 
> The 'sgx-epc' device is essentially a placholder at this time, it will
> be fully implemented in a future patch along with a dedicated command
> to create 'sgx-epc' devices.
> 
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Signed-off-by: Yang Zhong <yang.zhong@intel.com>
> Message-Id: <20210719112136.57018-5-yang.zhong@intel.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>   hw/i386/meson.build       |   1 +
>   hw/i386/sgx-epc.c         | 167 ++++++++++++++++++++++++++++++++++++++
>   include/hw/i386/sgx-epc.h |  44 ++++++++++
>   3 files changed, 212 insertions(+)
>   create mode 100644 hw/i386/sgx-epc.c
>   create mode 100644 include/hw/i386/sgx-epc.h
...
> +static void sgx_epc_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(oc);
> +
> +    dc->hotpluggable = false;
> +    dc->realize = sgx_epc_realize;
> +    dc->unrealize = sgx_epc_unrealize;
> +    dc->desc = "SGX EPC section";
> +    device_class_set_props(dc, sgx_epc_properties);
> +
> +    mdc->get_addr = sgx_epc_md_get_addr;
> +    mdc->set_addr = sgx_epc_md_set_addr;
> +    mdc->get_plugged_size = sgx_epc_md_get_plugged_size;
> +    mdc->get_memory_region = sgx_epc_md_get_memory_region;
> +    mdc->fill_device_info = sgx_epc_md_fill_device_info;
> +}

  Hi!

Our device-crash-test script reports that this new device can be used to 
crash QEMU:

$ ./qemu-system-x86_64 -M none -device sgx-epc
/home/thuth/devel/qemu/include/hw/i386/pc.h:128:PC_MACHINE: Object 
0x55c80d332290 is not an instance of type generic-pc-machine

Should it be marked with:

     dc->user_creatable = false

?

   Thomas


Re: [PULL 05/33] i386: Add 'sgx-epc' device to expose EPC sections to guest
Posted by Paolo Bonzini 4 years, 3 months ago
On 11/9/21 15:25, Thomas Huth wrote:
> Our device-crash-test script reports that this new device can be used to 
> crash QEMU:
> 
> $ ./qemu-system-x86_64 -M none -device sgx-epc
> /home/thuth/devel/qemu/include/hw/i386/pc.h:128:PC_MACHINE: Object 
> 0x55c80d332290 is not an instance of type generic-pc-machine
> 
> Should it be marked with:
> 
>      dc->user_creatable = false
> 
> ?

Yes, it should.  Thanks for the report!

Paolo


Re: [PULL 05/33] i386: Add 'sgx-epc' device to expose EPC sections to guest
Posted by Yang Zhong 4 years, 3 months ago
On Tue, Nov 09, 2021 at 06:48:59PM +0100, Paolo Bonzini wrote:
> On 11/9/21 15:25, Thomas Huth wrote:
> >Our device-crash-test script reports that this new device can be
> >used to crash QEMU:
> >
> >$ ./qemu-system-x86_64 -M none -device sgx-epc
> >/home/thuth/devel/qemu/include/hw/i386/pc.h:128:PC_MACHINE: Object
> >0x55c80d332290 is not an instance of type generic-pc-machine
> >
> >Should it be marked with:
> >
> >     dc->user_creatable = false
> >
> >?
> 
> Yes, it should.  Thanks for the report!
>

  Thanks Thomas reported this issue!

  I did not know we need do this test before. this test is not
  covered into Qemu Gitlab CI build system? or what's kind of tests we
  need do before we send the patches to Qemu community? If there is one
  guide or CI build including this, which is much better. Thanks!

  Yang

 
> Paolo

Re: [PULL 05/33] i386: Add 'sgx-epc' device to expose EPC sections to guest
Posted by Thomas Huth 4 years, 3 months ago
On 10/11/2021 07.41, Yang Zhong wrote:
> On Tue, Nov 09, 2021 at 06:48:59PM +0100, Paolo Bonzini wrote:
>> On 11/9/21 15:25, Thomas Huth wrote:
>>> Our device-crash-test script reports that this new device can be
>>> used to crash QEMU:
>>>
>>> $ ./qemu-system-x86_64 -M none -device sgx-epc
>>> /home/thuth/devel/qemu/include/hw/i386/pc.h:128:PC_MACHINE: Object
>>> 0x55c80d332290 is not an instance of type generic-pc-machine
>>>
>>> Should it be marked with:
>>>
>>>      dc->user_creatable = false
>>>
>>> ?
>>
>> Yes, it should.  Thanks for the report!
>>
> 
>    Thanks Thomas reported this issue!
> 
>    I did not know we need do this test before. this test is not
>    covered into Qemu Gitlab CI build system? or what's kind of tests we
>    need do before we send the patches to Qemu community? If there is one
>    guide or CI build including this, which is much better. Thanks!

No worry, device-crash-test is not mandatory, I just have the habit to run 
it and report the new problems when QEMU enters the freeze period for the 
next release.

But you're right, we should ultimatively try to get this included in the CI, 
too, so that the script does not bit-rot so easily anymore...

  Thomas