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 "monitor/qdev.h"
18 #include "qapi/error.h"
19 #include "qapi/visitor.h"
20 #include "qemu/config-file.h"
21 #include "qemu/error-report.h"
22 #include "qemu/option.h"
23 #include "qemu/units.h"
24 #include "target/i386/cpu.h"
25 #include "exec/address-spaces.h"
27 static Property sgx_epc_properties
[] = {
28 DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP
, SGXEPCDevice
, addr
, 0),
29 DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP
, SGXEPCDevice
, hostmem
,
30 TYPE_MEMORY_BACKEND_EPC
, HostMemoryBackendEpc
*),
31 DEFINE_PROP_END_OF_LIST(),
34 static void sgx_epc_get_size(Object
*obj
, Visitor
*v
, const char *name
,
35 void *opaque
, Error
**errp
)
37 Error
*local_err
= NULL
;
40 value
= memory_device_get_region_size(MEMORY_DEVICE(obj
), &local_err
);
42 error_propagate(errp
, local_err
);
46 visit_type_uint64(v
, name
, &value
, errp
);
49 static void sgx_epc_init(Object
*obj
)
51 object_property_add(obj
, SGX_EPC_SIZE_PROP
, "uint64", sgx_epc_get_size
,
55 static void sgx_epc_realize(DeviceState
*dev
, Error
**errp
)
57 PCMachineState
*pcms
= PC_MACHINE(qdev_get_machine());
58 X86MachineState
*x86ms
= X86_MACHINE(pcms
);
59 SGXEPCDevice
*epc
= SGX_EPC(dev
);
60 HostMemoryBackend
*hostmem
;
63 if (x86ms
->boot_cpus
!= 0) {
64 error_setg(errp
, "'" TYPE_SGX_EPC
"' can't be created after vCPUs,"
70 error_setg(errp
, "'" SGX_EPC_MEMDEV_PROP
"' property is not set");
73 hostmem
= MEMORY_BACKEND(epc
->hostmem
);
74 if (host_memory_backend_is_mapped(hostmem
)) {
75 path
= object_get_canonical_path_component(OBJECT(hostmem
));
76 error_setg(errp
, "can't use already busy memdev: %s", path
);
80 error_setg(errp
, "'" TYPE_SGX_EPC
"' not supported");
83 static void sgx_epc_unrealize(DeviceState
*dev
)
85 SGXEPCDevice
*epc
= SGX_EPC(dev
);
86 HostMemoryBackend
*hostmem
= MEMORY_BACKEND(epc
->hostmem
);
88 host_memory_backend_set_mapped(hostmem
, false);
91 static uint64_t sgx_epc_md_get_addr(const MemoryDeviceState
*md
)
93 const SGXEPCDevice
*epc
= SGX_EPC(md
);
98 static void sgx_epc_md_set_addr(MemoryDeviceState
*md
, uint64_t addr
,
101 object_property_set_uint(OBJECT(md
), SGX_EPC_ADDR_PROP
, addr
, errp
);
104 static uint64_t sgx_epc_md_get_plugged_size(const MemoryDeviceState
*md
,
110 static MemoryRegion
*sgx_epc_md_get_memory_region(MemoryDeviceState
*md
,
113 SGXEPCDevice
*epc
= SGX_EPC(md
);
114 HostMemoryBackend
*hostmem
;
117 error_setg(errp
, "'" SGX_EPC_MEMDEV_PROP
"' property must be set");
121 hostmem
= MEMORY_BACKEND(epc
->hostmem
);
122 return host_memory_backend_get_memory(hostmem
);
125 static void sgx_epc_md_fill_device_info(const MemoryDeviceState
*md
,
126 MemoryDeviceInfo
*info
)
131 static void sgx_epc_class_init(ObjectClass
*oc
, void *data
)
133 DeviceClass
*dc
= DEVICE_CLASS(oc
);
134 MemoryDeviceClass
*mdc
= MEMORY_DEVICE_CLASS(oc
);
136 dc
->hotpluggable
= false;
137 dc
->realize
= sgx_epc_realize
;
138 dc
->unrealize
= sgx_epc_unrealize
;
139 dc
->desc
= "SGX EPC section";
140 device_class_set_props(dc
, sgx_epc_properties
);
142 mdc
->get_addr
= sgx_epc_md_get_addr
;
143 mdc
->set_addr
= sgx_epc_md_set_addr
;
144 mdc
->get_plugged_size
= sgx_epc_md_get_plugged_size
;
145 mdc
->get_memory_region
= sgx_epc_md_get_memory_region
;
146 mdc
->fill_device_info
= sgx_epc_md_fill_device_info
;
149 static TypeInfo sgx_epc_info
= {
150 .name
= TYPE_SGX_EPC
,
151 .parent
= TYPE_DEVICE
,
152 .instance_size
= sizeof(SGXEPCDevice
),
153 .instance_init
= sgx_epc_init
,
154 .class_init
= sgx_epc_class_init
,
155 .class_size
= sizeof(DeviceClass
),
156 .interfaces
= (InterfaceInfo
[]) {
157 { TYPE_MEMORY_DEVICE
},
162 static void sgx_epc_register_types(void)
164 type_register_static(&sgx_epc_info
);
167 type_init(sgx_epc_register_types
)