From fe11f058c5fda70360f810e7bddd4b6d69f76230 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 1 Oct 2020 08:17:15 +0200 Subject: hw/arm/virt: Move post cpu realize check into its own function We'll add more to this new function in coming patches so we also state the gic must be created and call it below create_gic(). No functional change intended. Reviewed-by: Eric Auger Reviewed-by: Peter Maydell Signed-off-by: Andrew Jones Message-id: 20201001061718.101915-4-drjones@redhat.com Signed-off-by: Peter Maydell --- hw/arm/virt.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'hw/arm/virt.c') diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 1231a197c8..524eafe22d 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1672,6 +1672,31 @@ static void finalize_gic_version(VirtMachineState *vms) } } +/* + * virt_cpu_post_init() must be called after the CPUs have + * been realized and the GIC has been created. + */ +static void virt_cpu_post_init(VirtMachineState *vms) +{ + bool aarch64; + + aarch64 = object_property_get_bool(OBJECT(first_cpu), "aarch64", NULL); + + if (!kvm_enabled()) { + if (aarch64 && vms->highmem) { + int requested_pa_size = 64 - clz64(vms->highest_gpa); + int pamax = arm_pamax(ARM_CPU(first_cpu)); + + if (pamax < requested_pa_size) { + error_report("VCPU supports less PA bits (%d) than " + "requested by the memory map (%d)", + pamax, requested_pa_size); + exit(1); + } + } + } +} + static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); @@ -1886,22 +1911,6 @@ static void machvirt_init(MachineState *machine) fdt_add_timer_nodes(vms); fdt_add_cpu_nodes(vms); - if (!kvm_enabled()) { - ARMCPU *cpu = ARM_CPU(first_cpu); - bool aarch64 = object_property_get_bool(OBJECT(cpu), "aarch64", NULL); - - if (aarch64 && vms->highmem) { - int requested_pa_size, pamax = arm_pamax(cpu); - - requested_pa_size = 64 - clz64(vms->highest_gpa); - if (pamax < requested_pa_size) { - error_report("VCPU supports less PA bits (%d) than requested " - "by the memory map (%d)", pamax, requested_pa_size); - exit(1); - } - } - } - memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, machine->ram); if (machine->device_memory) { @@ -1913,6 +1922,8 @@ static void machvirt_init(MachineState *machine) create_gic(vms); + virt_cpu_post_init(vms); + fdt_add_pmu_nodes(vms); create_uart(vms, VIRT_UART, sysmem, serial_hd(0)); -- cgit v1.2.3 From 946f1bb18c342fa548f9c0f52f64836ff49d99c8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 1 Oct 2020 08:17:16 +0200 Subject: hw/arm/virt: Move kvm pmu setup to virt_cpu_post_init Move the KVM PMU setup part of fdt_add_pmu_nodes() to virt_cpu_post_init(), which is a more appropriate location. Now fdt_add_pmu_nodes() is also named more appropriately, because it no longer does anything but fdt node creation. No functional change intended. Reviewed-by: Peter Maydell Reviewed-by: Eric Auger Signed-off-by: Andrew Jones Message-id: 20201001061718.101915-5-drjones@redhat.com Signed-off-by: Peter Maydell --- hw/arm/virt.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'hw/arm/virt.c') diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 524eafe22d..92ab0fd094 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -521,21 +521,12 @@ static void fdt_add_gic_node(VirtMachineState *vms) static void fdt_add_pmu_nodes(const VirtMachineState *vms) { - CPUState *cpu; - ARMCPU *armcpu; + ARMCPU *armcpu = ARM_CPU(first_cpu); uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI; - CPU_FOREACH(cpu) { - armcpu = ARM_CPU(cpu); - if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { - return; - } - if (kvm_enabled()) { - if (kvm_irqchip_in_kernel()) { - kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ)); - } - kvm_arm_pmu_init(cpu); - } + if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { + assert(!object_property_get_bool(OBJECT(armcpu), "pmu", NULL)); + return; } if (vms->gic_version == VIRT_GIC_VERSION_2) { @@ -544,7 +535,6 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms) (1 << vms->smp_cpus) - 1); } - armcpu = ARM_CPU(qemu_get_cpu(0)); qemu_fdt_add_subnode(vms->fdt, "/pmu"); if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) { const char compat[] = "arm,armv8-pmuv3"; @@ -1678,11 +1668,23 @@ static void finalize_gic_version(VirtMachineState *vms) */ static void virt_cpu_post_init(VirtMachineState *vms) { - bool aarch64; + bool aarch64, pmu; + CPUState *cpu; aarch64 = object_property_get_bool(OBJECT(first_cpu), "aarch64", NULL); + pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL); - if (!kvm_enabled()) { + if (kvm_enabled()) { + CPU_FOREACH(cpu) { + if (pmu) { + assert(arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_PMU)); + if (kvm_irqchip_in_kernel()) { + kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ)); + } + kvm_arm_pmu_init(cpu); + } + } + } else { if (aarch64 && vms->highmem) { int requested_pa_size = 64 - clz64(vms->highest_gpa); int pamax = arm_pamax(ARM_CPU(first_cpu)); -- cgit v1.2.3 From 68970d1e0d07e3a266141bbd9038fd9890ca88f2 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 1 Oct 2020 08:17:18 +0200 Subject: hw/arm/virt: Implement kvm-steal-time We add the kvm-steal-time CPU property and implement it for machvirt. A tiny bit of refactoring was also done to allow pmu and pvtime to use the same vcpu device helper functions. Reviewed-by: Eric Auger Signed-off-by: Andrew Jones Message-id: 20201001061718.101915-7-drjones@redhat.com Signed-off-by: Peter Maydell --- hw/arm/virt.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) (limited to 'hw/arm/virt.c') diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 92ab0fd094..e465a988d6 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -151,6 +151,7 @@ static const MemMapEntry base_memmap[] = { [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, + [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, @@ -1666,15 +1667,40 @@ static void finalize_gic_version(VirtMachineState *vms) * virt_cpu_post_init() must be called after the CPUs have * been realized and the GIC has been created. */ -static void virt_cpu_post_init(VirtMachineState *vms) +static void virt_cpu_post_init(VirtMachineState *vms, int max_cpus, + MemoryRegion *sysmem) { - bool aarch64, pmu; + bool aarch64, pmu, steal_time; CPUState *cpu; aarch64 = object_property_get_bool(OBJECT(first_cpu), "aarch64", NULL); pmu = object_property_get_bool(OBJECT(first_cpu), "pmu", NULL); + steal_time = object_property_get_bool(OBJECT(first_cpu), + "kvm-steal-time", NULL); if (kvm_enabled()) { + hwaddr pvtime_reg_base = vms->memmap[VIRT_PVTIME].base; + hwaddr pvtime_reg_size = vms->memmap[VIRT_PVTIME].size; + + if (steal_time) { + MemoryRegion *pvtime = g_new(MemoryRegion, 1); + hwaddr pvtime_size = max_cpus * PVTIME_SIZE_PER_CPU; + + /* The memory region size must be a multiple of host page size. */ + pvtime_size = REAL_HOST_PAGE_ALIGN(pvtime_size); + + if (pvtime_size > pvtime_reg_size) { + error_report("pvtime requires a %" HWADDR_PRId + " byte memory region for %d CPUs," + " but only %" HWADDR_PRId " has been reserved", + pvtime_size, max_cpus, pvtime_reg_size); + exit(1); + } + + memory_region_init_ram(pvtime, NULL, "pvtime", pvtime_size, NULL); + memory_region_add_subregion(sysmem, pvtime_reg_base, pvtime); + } + CPU_FOREACH(cpu) { if (pmu) { assert(arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_PMU)); @@ -1683,6 +1709,10 @@ static void virt_cpu_post_init(VirtMachineState *vms) } kvm_arm_pmu_init(cpu); } + if (steal_time) { + kvm_arm_pvtime_init(cpu, pvtime_reg_base + + cpu->cpu_index * PVTIME_SIZE_PER_CPU); + } } } else { if (aarch64 && vms->highmem) { @@ -1853,6 +1883,11 @@ static void machvirt_init(MachineState *machine) object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL); } + if (vmc->no_kvm_steal_time && + object_property_find(cpuobj, "kvm-steal-time")) { + object_property_set_bool(cpuobj, "kvm-steal-time", false, NULL); + } + if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) { object_property_set_bool(cpuobj, "pmu", false, NULL); } @@ -1924,7 +1959,7 @@ static void machvirt_init(MachineState *machine) create_gic(vms); - virt_cpu_post_init(vms); + virt_cpu_post_init(vms, possible_cpus->len, sysmem); fdt_add_pmu_nodes(vms); @@ -2566,8 +2601,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 2) static void virt_machine_5_1_options(MachineClass *mc) { + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + virt_machine_5_2_options(mc); compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len); + vmc->no_kvm_steal_time = true; } DEFINE_VIRT_MACHINE(5, 1) -- cgit v1.2.3