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
)
139 static void sgx_epc_class_init(ObjectClass
*oc
, void *data
)
141 DeviceClass
*dc
= DEVICE_CLASS(oc
);
142 MemoryDeviceClass
*mdc
= MEMORY_DEVICE_CLASS(oc
);
144 dc
->hotpluggable
= false;
145 dc
->realize
= sgx_epc_realize
;
146 dc
->unrealize
= sgx_epc_unrealize
;
147 dc
->desc
= "SGX EPC section";
148 device_class_set_props(dc
, sgx_epc_properties
);
150 mdc
->get_addr
= sgx_epc_md_get_addr
;
151 mdc
->set_addr
= sgx_epc_md_set_addr
;
152 mdc
->get_plugged_size
= sgx_epc_md_get_plugged_size
;
153 mdc
->get_memory_region
= sgx_epc_md_get_memory_region
;
154 mdc
->fill_device_info
= sgx_epc_md_fill_device_info
;
157 static TypeInfo sgx_epc_info
= {
158 .name
= TYPE_SGX_EPC
,
159 .parent
= TYPE_DEVICE
,
160 .instance_size
= sizeof(SGXEPCDevice
),
161 .instance_init
= sgx_epc_init
,
162 .class_init
= sgx_epc_class_init
,
163 .class_size
= sizeof(DeviceClass
),
164 .interfaces
= (InterfaceInfo
[]) {
165 { TYPE_MEMORY_DEVICE
},
170 static void sgx_epc_register_types(void)
172 type_register_static(&sgx_epc_info
);
175 type_init(sgx_epc_register_types
)