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_LINK(SGX_EPC_MEMDEV_PROP
, SGXEPCDevice
, hostmem
,
25 TYPE_MEMORY_BACKEND_EPC
, HostMemoryBackendEpc
*),
26 DEFINE_PROP_END_OF_LIST(),
29 static void sgx_epc_get_size(Object
*obj
, Visitor
*v
, const char *name
,
30 void *opaque
, Error
**errp
)
32 Error
*local_err
= NULL
;
35 value
= memory_device_get_region_size(MEMORY_DEVICE(obj
), &local_err
);
37 error_propagate(errp
, local_err
);
41 visit_type_uint64(v
, name
, &value
, errp
);
44 static void sgx_epc_init(Object
*obj
)
46 object_property_add(obj
, SGX_EPC_SIZE_PROP
, "uint64", sgx_epc_get_size
,
50 static void sgx_epc_realize(DeviceState
*dev
, Error
**errp
)
52 PCMachineState
*pcms
= PC_MACHINE(qdev_get_machine());
53 X86MachineState
*x86ms
= X86_MACHINE(pcms
);
54 MemoryDeviceState
*md
= MEMORY_DEVICE(dev
);
55 SGXEPCState
*sgx_epc
= &pcms
->sgx_epc
;
56 SGXEPCDevice
*epc
= SGX_EPC(dev
);
57 HostMemoryBackend
*hostmem
;
60 if (x86ms
->boot_cpus
!= 0) {
61 error_setg(errp
, "'" TYPE_SGX_EPC
"' can't be created after vCPUs,"
67 error_setg(errp
, "'" SGX_EPC_MEMDEV_PROP
"' property is not set");
70 hostmem
= MEMORY_BACKEND(epc
->hostmem
);
71 if (host_memory_backend_is_mapped(hostmem
)) {
72 path
= object_get_canonical_path_component(OBJECT(hostmem
));
73 error_setg(errp
, "can't use already busy memdev: %s", path
);
77 epc
->addr
= sgx_epc
->base
+ sgx_epc
->size
;
79 memory_region_add_subregion(&sgx_epc
->mr
, epc
->addr
- sgx_epc
->base
,
80 host_memory_backend_get_memory(hostmem
));
82 host_memory_backend_set_mapped(hostmem
, true);
84 sgx_epc
->sections
= g_renew(SGXEPCDevice
*, sgx_epc
->sections
,
85 sgx_epc
->nr_sections
+ 1);
86 sgx_epc
->sections
[sgx_epc
->nr_sections
++] = epc
;
88 sgx_epc
->size
+= memory_device_get_region_size(md
, errp
);
91 static void sgx_epc_unrealize(DeviceState
*dev
)
93 SGXEPCDevice
*epc
= SGX_EPC(dev
);
94 HostMemoryBackend
*hostmem
= MEMORY_BACKEND(epc
->hostmem
);
96 host_memory_backend_set_mapped(hostmem
, false);
99 static uint64_t sgx_epc_md_get_addr(const MemoryDeviceState
*md
)
101 const SGXEPCDevice
*epc
= SGX_EPC(md
);
106 static void sgx_epc_md_set_addr(MemoryDeviceState
*md
, uint64_t addr
,
109 object_property_set_uint(OBJECT(md
), SGX_EPC_ADDR_PROP
, addr
, errp
);
112 static uint64_t sgx_epc_md_get_plugged_size(const MemoryDeviceState
*md
,
118 static MemoryRegion
*sgx_epc_md_get_memory_region(MemoryDeviceState
*md
,
121 SGXEPCDevice
*epc
= SGX_EPC(md
);
122 HostMemoryBackend
*hostmem
;
125 error_setg(errp
, "'" SGX_EPC_MEMDEV_PROP
"' property must be set");
129 hostmem
= MEMORY_BACKEND(epc
->hostmem
);
130 return host_memory_backend_get_memory(hostmem
);
133 static void sgx_epc_md_fill_device_info(const MemoryDeviceState
*md
,
134 MemoryDeviceInfo
*info
)
136 SgxEPCDeviceInfo
*se
= g_new0(SgxEPCDeviceInfo
, 1);
137 SGXEPCDevice
*epc
= SGX_EPC(md
);
139 se
->memaddr
= epc
->addr
;
140 se
->size
= object_property_get_uint(OBJECT(epc
), SGX_EPC_SIZE_PROP
,
142 se
->memdev
= object_get_canonical_path(OBJECT(epc
->hostmem
));
144 info
->u
.sgx_epc
.data
= se
;
145 info
->type
= MEMORY_DEVICE_INFO_KIND_SGX_EPC
;
148 static void sgx_epc_class_init(ObjectClass
*oc
, void *data
)
150 DeviceClass
*dc
= DEVICE_CLASS(oc
);
151 MemoryDeviceClass
*mdc
= MEMORY_DEVICE_CLASS(oc
);
153 dc
->hotpluggable
= false;
154 dc
->realize
= sgx_epc_realize
;
155 dc
->unrealize
= sgx_epc_unrealize
;
156 dc
->desc
= "SGX EPC section";
157 device_class_set_props(dc
, sgx_epc_properties
);
159 mdc
->get_addr
= sgx_epc_md_get_addr
;
160 mdc
->set_addr
= sgx_epc_md_set_addr
;
161 mdc
->get_plugged_size
= sgx_epc_md_get_plugged_size
;
162 mdc
->get_memory_region
= sgx_epc_md_get_memory_region
;
163 mdc
->fill_device_info
= sgx_epc_md_fill_device_info
;
166 static TypeInfo sgx_epc_info
= {
167 .name
= TYPE_SGX_EPC
,
168 .parent
= TYPE_DEVICE
,
169 .instance_size
= sizeof(SGXEPCDevice
),
170 .instance_init
= sgx_epc_init
,
171 .class_init
= sgx_epc_class_init
,
172 .class_size
= sizeof(DeviceClass
),
173 .interfaces
= (InterfaceInfo
[]) {
174 { TYPE_MEMORY_DEVICE
},
179 static void sgx_epc_register_types(void)
181 type_register_static(&sgx_epc_info
);
184 type_init(sgx_epc_register_types
)