4 * Copyright (C) 2019 Intel Corporation
7 * Sean Christopherson <sean.j.christopherson@intel.com>
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.
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"
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(),
30 static void sgx_epc_get_size(Object
*obj
, Visitor
*v
, const char *name
,
31 void *opaque
, Error
**errp
)
33 Error
*local_err
= NULL
;
36 value
= memory_device_get_region_size(MEMORY_DEVICE(obj
), &local_err
);
38 error_propagate(errp
, local_err
);
42 visit_type_uint64(v
, name
, &value
, errp
);
45 static void sgx_epc_init(Object
*obj
)
47 object_property_add(obj
, SGX_EPC_SIZE_PROP
, "uint64", sgx_epc_get_size
,
51 static void sgx_epc_realize(DeviceState
*dev
, Error
**errp
)
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
;
61 if (x86ms
->boot_cpus
!= 0) {
62 error_setg(errp
, "'" TYPE_SGX_EPC
"' can't be created after vCPUs,"
68 error_setg(errp
, "'" SGX_EPC_MEMDEV_PROP
"' property is not set");
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
);
78 epc
->addr
= sgx_epc
->base
+ sgx_epc
->size
;
80 memory_region_add_subregion(&sgx_epc
->mr
, epc
->addr
- sgx_epc
->base
,
81 host_memory_backend_get_memory(hostmem
));
83 host_memory_backend_set_mapped(hostmem
, true);
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
;
89 sgx_epc
->size
+= memory_device_get_region_size(md
, errp
);
92 static void sgx_epc_unrealize(DeviceState
*dev
)
94 SGXEPCDevice
*epc
= SGX_EPC(dev
);
95 HostMemoryBackend
*hostmem
= MEMORY_BACKEND(epc
->hostmem
);
97 host_memory_backend_set_mapped(hostmem
, false);
100 static uint64_t sgx_epc_md_get_addr(const MemoryDeviceState
*md
)
102 const SGXEPCDevice
*epc
= SGX_EPC(md
);
107 static void sgx_epc_md_set_addr(MemoryDeviceState
*md
, uint64_t addr
,
110 object_property_set_uint(OBJECT(md
), SGX_EPC_ADDR_PROP
, addr
, errp
);
113 static uint64_t sgx_epc_md_get_plugged_size(const MemoryDeviceState
*md
,
119 static MemoryRegion
*sgx_epc_md_get_memory_region(MemoryDeviceState
*md
,
122 SGXEPCDevice
*epc
= SGX_EPC(md
);
123 HostMemoryBackend
*hostmem
;
126 error_setg(errp
, "'" SGX_EPC_MEMDEV_PROP
"' property must be set");
130 hostmem
= MEMORY_BACKEND(epc
->hostmem
);
131 return host_memory_backend_get_memory(hostmem
);
134 static void sgx_epc_md_fill_device_info(const MemoryDeviceState
*md
,
135 MemoryDeviceInfo
*info
)
137 SgxEPCDeviceInfo
*se
= g_new0(SgxEPCDeviceInfo
, 1);
138 SGXEPCDevice
*epc
= SGX_EPC(md
);
140 se
->memaddr
= epc
->addr
;
141 se
->size
= object_property_get_uint(OBJECT(epc
), SGX_EPC_SIZE_PROP
,
143 se
->node
= object_property_get_uint(OBJECT(epc
), SGX_EPC_NUMA_NODE_PROP
,
145 se
->memdev
= object_get_canonical_path(OBJECT(epc
->hostmem
));
147 info
->u
.sgx_epc
.data
= se
;
148 info
->type
= MEMORY_DEVICE_INFO_KIND_SGX_EPC
;
151 static void sgx_epc_class_init(ObjectClass
*oc
, void *data
)
153 DeviceClass
*dc
= DEVICE_CLASS(oc
);
154 MemoryDeviceClass
*mdc
= MEMORY_DEVICE_CLASS(oc
);
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
);
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
;
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
},
183 static void sgx_epc_register_types(void)
185 type_register_static(&sgx_epc_info
);
188 type_init(sgx_epc_register_types
)