summaryrefslogtreecommitdiffstats
path: root/hw/arm/virt.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/arm/virt.c')
-rw-r--r--hw/arm/virt.c124
1 files changed, 116 insertions, 8 deletions
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index caceb1e4a0..af3050bc4b 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -217,11 +217,9 @@ static bool cpu_type_valid(const char *cpu)
static void create_kaslr_seed(VirtMachineState *vms, const char *node)
{
- Error *err = NULL;
uint64_t seed;
- if (qemu_guest_getrandom(&seed, sizeof(seed), &err)) {
- error_free(err);
+ if (qemu_guest_getrandom(&seed, sizeof(seed), NULL)) {
return;
}
qemu_fdt_setprop_u64(vms->fdt, node, "kaslr-seed", seed);
@@ -1390,8 +1388,19 @@ static void create_platform_bus(VirtMachineState *vms)
sysbus_mmio_get_region(s, 0));
}
+static void create_tag_ram(MemoryRegion *tag_sysmem,
+ hwaddr base, hwaddr size,
+ const char *name)
+{
+ MemoryRegion *tagram = g_new(MemoryRegion, 1);
+
+ memory_region_init_ram(tagram, NULL, name, size / 32, &error_fatal);
+ memory_region_add_subregion(tag_sysmem, base / 32, tagram);
+}
+
static void create_secure_ram(VirtMachineState *vms,
- MemoryRegion *secure_sysmem)
+ MemoryRegion *secure_sysmem,
+ MemoryRegion *secure_tag_sysmem)
{
MemoryRegion *secram = g_new(MemoryRegion, 1);
char *nodename;
@@ -1409,6 +1418,10 @@ static void create_secure_ram(VirtMachineState *vms,
qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled");
qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay");
+ if (secure_tag_sysmem) {
+ create_tag_ram(secure_tag_sysmem, base, size, "mach-virt.secure-tag");
+ }
+
g_free(nodename);
}
@@ -1665,6 +1678,8 @@ static void machvirt_init(MachineState *machine)
const CPUArchIdList *possible_cpus;
MemoryRegion *sysmem = get_system_memory();
MemoryRegion *secure_sysmem = NULL;
+ MemoryRegion *tag_sysmem = NULL;
+ MemoryRegion *secure_tag_sysmem = NULL;
int n, virt_max_cpus;
bool firmware_loaded;
bool aarch64 = true;
@@ -1819,6 +1834,35 @@ static void machvirt_init(MachineState *machine)
"secure-memory", &error_abort);
}
+ /*
+ * The cpu adds the property if and only if MemTag is supported.
+ * If it is, we must allocate the ram to back that up.
+ */
+ if (object_property_find(cpuobj, "tag-memory", NULL)) {
+ if (!tag_sysmem) {
+ tag_sysmem = g_new(MemoryRegion, 1);
+ memory_region_init(tag_sysmem, OBJECT(machine),
+ "tag-memory", UINT64_MAX / 32);
+
+ if (vms->secure) {
+ secure_tag_sysmem = g_new(MemoryRegion, 1);
+ memory_region_init(secure_tag_sysmem, OBJECT(machine),
+ "secure-tag-memory", UINT64_MAX / 32);
+
+ /* As with ram, secure-tag takes precedence over tag. */
+ memory_region_add_subregion_overlap(secure_tag_sysmem, 0,
+ tag_sysmem, -1);
+ }
+ }
+
+ object_property_set_link(cpuobj, OBJECT(tag_sysmem),
+ "tag-memory", &error_abort);
+ if (vms->secure) {
+ object_property_set_link(cpuobj, OBJECT(secure_tag_sysmem),
+ "secure-tag-memory", &error_abort);
+ }
+ }
+
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
object_unref(cpuobj);
}
@@ -1857,10 +1901,15 @@ static void machvirt_init(MachineState *machine)
create_uart(vms, VIRT_UART, sysmem, serial_hd(0));
if (vms->secure) {
- create_secure_ram(vms, secure_sysmem);
+ create_secure_ram(vms, secure_sysmem, secure_tag_sysmem);
create_uart(vms, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
}
+ if (tag_sysmem) {
+ create_tag_ram(tag_sysmem, vms->memmap[VIRT_MEM].base,
+ machine->ram_size, "mach-virt.tag");
+ }
+
vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64);
create_rtc(vms);
@@ -2177,11 +2226,68 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
}
}
+static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
+ Error *local_err = NULL;
+
+ if (!vms->acpi_dev) {
+ error_setg(&local_err,
+ "memory hotplug is not enabled: missing acpi-ged device");
+ goto out;
+ }
+
+ if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
+ error_setg(&local_err,
+ "nvdimm device hot unplug is not supported yet.");
+ goto out;
+ }
+
+ hotplug_handler_unplug_request(HOTPLUG_HANDLER(vms->acpi_dev), dev,
+ &local_err);
+out:
+ error_propagate(errp, local_err);
+}
+
+static void virt_dimm_unplug(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
+ Error *local_err = NULL;
+
+ hotplug_handler_unplug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err);
+ if (local_err) {
+ goto out;
+ }
+
+ pc_dimm_unplug(PC_DIMM(dev), MACHINE(vms));
+ qdev_unrealize(dev);
+
+out:
+ error_propagate(errp, local_err);
+}
+
static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
- error_setg(errp, "device unplug request for unsupported device"
- " type: %s", object_get_typename(OBJECT(dev)));
+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+ virt_dimm_unplug_request(hotplug_dev, dev, errp);
+ } else {
+ error_setg(errp, "device unplug request for unsupported device"
+ " type: %s", object_get_typename(OBJECT(dev)));
+ }
+}
+
+static void virt_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
+{
+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
+ virt_dimm_unplug(hotplug_dev, dev, errp);
+ } else {
+ error_setg(errp, "virt: device unplug for unsupported device"
+ " type: %s", object_get_typename(OBJECT(dev)));
+ }
}
static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
@@ -2262,7 +2368,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
hc->pre_plug = virt_machine_device_pre_plug_cb;
hc->plug = virt_machine_device_plug_cb;
hc->unplug_request = virt_machine_device_unplug_request_cb;
- mc->numa_mem_supported = true;
+ hc->unplug = virt_machine_device_unplug_cb;
mc->nvdimm_supported = true;
mc->auto_enable_numa_with_memhp = true;
mc->default_ram_id = "mach-virt.ram";
@@ -2375,6 +2481,8 @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 1)
static void virt_machine_5_0_options(MachineClass *mc)
{
virt_machine_5_1_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len);
+ mc->numa_mem_supported = true;
}
DEFINE_VIRT_MACHINE(5, 0)