qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

sgx-epc.c (5730B)


      1 /*
      2  * SGX EPC device
      3  *
      4  * Copyright (C) 2019 Intel Corporation
      5  *
      6  * Authors:
      7  *   Sean Christopherson <sean.j.christopherson@intel.com>
      8  *
      9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
     10  * See the COPYING file in the top-level directory.
     11  */
     12 #include "qemu/osdep.h"
     13 #include "hw/i386/pc.h"
     14 #include "hw/i386/sgx-epc.h"
     15 #include "hw/mem/memory-device.h"
     16 #include "hw/qdev-properties.h"
     17 #include "qapi/error.h"
     18 #include "qapi/visitor.h"
     19 #include "target/i386/cpu.h"
     20 #include "exec/address-spaces.h"
     21 
     22 static Property sgx_epc_properties[] = {
     23     DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP, SGXEPCDevice, addr, 0),
     24     DEFINE_PROP_UINT32(SGX_EPC_NUMA_NODE_PROP, SGXEPCDevice, node, 0),
     25     DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP, SGXEPCDevice, hostmem,
     26                      TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *),
     27     DEFINE_PROP_END_OF_LIST(),
     28 };
     29 
     30 static void sgx_epc_get_size(Object *obj, Visitor *v, const char *name,
     31                              void *opaque, Error **errp)
     32 {
     33     Error *local_err = NULL;
     34     uint64_t value;
     35 
     36     value = memory_device_get_region_size(MEMORY_DEVICE(obj), &local_err);
     37     if (local_err) {
     38         error_propagate(errp, local_err);
     39         return;
     40     }
     41 
     42     visit_type_uint64(v, name, &value, errp);
     43 }
     44 
     45 static void sgx_epc_init(Object *obj)
     46 {
     47     object_property_add(obj, SGX_EPC_SIZE_PROP, "uint64", sgx_epc_get_size,
     48                         NULL, NULL, NULL);
     49 }
     50 
     51 static void sgx_epc_realize(DeviceState *dev, Error **errp)
     52 {
     53     PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
     54     X86MachineState *x86ms = X86_MACHINE(pcms);
     55     MemoryDeviceState *md = MEMORY_DEVICE(dev);
     56     SGXEPCState *sgx_epc = &pcms->sgx_epc;
     57     SGXEPCDevice *epc = SGX_EPC(dev);
     58     HostMemoryBackend *hostmem;
     59     const char *path;
     60 
     61     if (x86ms->boot_cpus != 0) {
     62         error_setg(errp, "'" TYPE_SGX_EPC "' can't be created after vCPUs,"
     63                          "e.g. via -device");
     64         return;
     65     }
     66 
     67     if (!epc->hostmem) {
     68         error_setg(errp, "'" SGX_EPC_MEMDEV_PROP "' property is not set");
     69         return;
     70     }
     71     hostmem = MEMORY_BACKEND(epc->hostmem);
     72     if (host_memory_backend_is_mapped(hostmem)) {
     73         path = object_get_canonical_path_component(OBJECT(hostmem));
     74         error_setg(errp, "can't use already busy memdev: %s", path);
     75         return;
     76     }
     77 
     78     epc->addr = sgx_epc->base + sgx_epc->size;
     79 
     80     memory_region_add_subregion(&sgx_epc->mr, epc->addr - sgx_epc->base,
     81                                 host_memory_backend_get_memory(hostmem));
     82 
     83     host_memory_backend_set_mapped(hostmem, true);
     84 
     85     sgx_epc->sections = g_renew(SGXEPCDevice *, sgx_epc->sections,
     86                                 sgx_epc->nr_sections + 1);
     87     sgx_epc->sections[sgx_epc->nr_sections++] = epc;
     88 
     89     sgx_epc->size += memory_device_get_region_size(md, errp);
     90 }
     91 
     92 static void sgx_epc_unrealize(DeviceState *dev)
     93 {
     94     SGXEPCDevice *epc = SGX_EPC(dev);
     95     HostMemoryBackend *hostmem = MEMORY_BACKEND(epc->hostmem);
     96 
     97     host_memory_backend_set_mapped(hostmem, false);
     98 }
     99 
    100 static uint64_t sgx_epc_md_get_addr(const MemoryDeviceState *md)
    101 {
    102     const SGXEPCDevice *epc = SGX_EPC(md);
    103 
    104     return epc->addr;
    105 }
    106 
    107 static void sgx_epc_md_set_addr(MemoryDeviceState *md, uint64_t addr,
    108                                 Error **errp)
    109 {
    110     object_property_set_uint(OBJECT(md), SGX_EPC_ADDR_PROP, addr, errp);
    111 }
    112 
    113 static uint64_t sgx_epc_md_get_plugged_size(const MemoryDeviceState *md,
    114                                             Error **errp)
    115 {
    116     return 0;
    117 }
    118 
    119 static MemoryRegion *sgx_epc_md_get_memory_region(MemoryDeviceState *md,
    120                                                   Error **errp)
    121 {
    122     SGXEPCDevice *epc = SGX_EPC(md);
    123     HostMemoryBackend *hostmem;
    124 
    125     if (!epc->hostmem) {
    126         error_setg(errp, "'" SGX_EPC_MEMDEV_PROP "' property must be set");
    127         return NULL;
    128     }
    129 
    130     hostmem = MEMORY_BACKEND(epc->hostmem);
    131     return host_memory_backend_get_memory(hostmem);
    132 }
    133 
    134 static void sgx_epc_md_fill_device_info(const MemoryDeviceState *md,
    135                                         MemoryDeviceInfo *info)
    136 {
    137     SgxEPCDeviceInfo *se = g_new0(SgxEPCDeviceInfo, 1);
    138     SGXEPCDevice *epc = SGX_EPC(md);
    139 
    140     se->memaddr = epc->addr;
    141     se->size = object_property_get_uint(OBJECT(epc), SGX_EPC_SIZE_PROP,
    142                                         NULL);
    143     se->node = object_property_get_uint(OBJECT(epc), SGX_EPC_NUMA_NODE_PROP,
    144                                         NULL);
    145     se->memdev = object_get_canonical_path(OBJECT(epc->hostmem));
    146 
    147     info->u.sgx_epc.data = se;
    148     info->type = MEMORY_DEVICE_INFO_KIND_SGX_EPC;
    149 }
    150 
    151 static void sgx_epc_class_init(ObjectClass *oc, void *data)
    152 {
    153     DeviceClass *dc = DEVICE_CLASS(oc);
    154     MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(oc);
    155 
    156     dc->hotpluggable = false;
    157     dc->realize = sgx_epc_realize;
    158     dc->unrealize = sgx_epc_unrealize;
    159     dc->desc = "SGX EPC section";
    160     dc->user_creatable = false;
    161     device_class_set_props(dc, sgx_epc_properties);
    162 
    163     mdc->get_addr = sgx_epc_md_get_addr;
    164     mdc->set_addr = sgx_epc_md_set_addr;
    165     mdc->get_plugged_size = sgx_epc_md_get_plugged_size;
    166     mdc->get_memory_region = sgx_epc_md_get_memory_region;
    167     mdc->fill_device_info = sgx_epc_md_fill_device_info;
    168 }
    169 
    170 static const TypeInfo sgx_epc_info = {
    171     .name          = TYPE_SGX_EPC,
    172     .parent        = TYPE_DEVICE,
    173     .instance_size = sizeof(SGXEPCDevice),
    174     .instance_init = sgx_epc_init,
    175     .class_init    = sgx_epc_class_init,
    176     .class_size    = sizeof(DeviceClass),
    177     .interfaces = (InterfaceInfo[]) {
    178         { TYPE_MEMORY_DEVICE },
    179         { }
    180     },
    181 };
    182 
    183 static void sgx_epc_register_types(void)
    184 {
    185     type_register_static(&sgx_epc_info);
    186 }
    187 
    188 type_init(sgx_epc_register_types)