target-arm queue:

* hw/ssi/npcm7xx_fiu: Fix handling of unsigned integer
  * hw/arm/fsl-imx25: Fix a typo
  * hw/arm/sbsa-ref : Fix SMMUv3 Initialisation
  * hw/arm/sbsa-ref : allocate IRQs for SMMUv3
  * hw/char/bcm2835_aux: Allow less than 32-bit accesses
  * hw/arm/virt: Implement kvm-steal-time
  * target/arm: Make '-cpu max' have a 48-bit PA
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAl9/eT8ZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3kvPD/wOBv0XR1VZ/MBRqa36gZuI
 oGB3GTrD9xLvUoPx107lNecXmGQY3rzQoo9f11+0RTfnd289yLtI8u1zp83zupnc
 kltbSVmmGtO8j6Zr603U/piBCWFxn3DwEBz0ZmSU3xHVLcpGfgK7896be6pzRLa8
 Kk4TUsOBQFYFfdApB2E5qoYnUzDpLjz1AcPhBMuAlJUmn7YZiSS+uuHFBQ9gOwIU
 2R3TurUx5M65xQJPVh/ejOVSDxwsgDZ74VlWdvmuXJ2OSpyZzv4xOXp9ckHr9tk4
 jz0C7GHhCkiHciJ9V0UTzp9dwTxr2ShA5ikT/FLdx8k4ahzxsbo9T6C2kXi4NJ2X
 xt651GG5gOskkEhKonoDBZieY9xhTQoAjl6u5A529kMVw1gZxJ/0mET3qlMWGHoq
 8DjFouDboqXC2I6qWiHmwN2HNqoDtScMZcO/kMkaspUAGvfpK85AT9PUogUr/1NV
 sSSmQlQRclGTEgFQL/J6RuGZHoUB/S1nUYEepz7ragYCVbORs2k/3Ouq7z/fE18W
 cUitLWqSWHfkoUKRkJ4+JTo0SlVNnA+2/MfbBfWTvWAHdjomNxQQQCHyJpLIViZj
 W0QQXJqcJL1TL7CmHYoNe2AOYu+/KXJU7dGppyupf0JAzoRNj8JSLSCFDFtCFPIk
 kN8WngucPR6+W0vL1woQiw==
 =B2p0
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20201008-1' into staging

target-arm queue:
 * hw/ssi/npcm7xx_fiu: Fix handling of unsigned integer
 * hw/arm/fsl-imx25: Fix a typo
 * hw/arm/sbsa-ref : Fix SMMUv3 Initialisation
 * hw/arm/sbsa-ref : allocate IRQs for SMMUv3
 * hw/char/bcm2835_aux: Allow less than 32-bit accesses
 * hw/arm/virt: Implement kvm-steal-time
 * target/arm: Make '-cpu max' have a 48-bit PA

# gpg: Signature made Thu 08 Oct 2020 21:40:31 BST
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20201008-1:
  target/arm: Make '-cpu max' have a 48-bit PA
  hw/arm/virt: Implement kvm-steal-time
  tests/qtest: Restore aarch64 arm-cpu-features test
  hw/arm/virt: Move kvm pmu setup to virt_cpu_post_init
  hw/arm/virt: Move post cpu realize check into its own function
  target/arm/kvm: Make uncalled stubs explicitly unreachable
  linux headers: sync to 5.9-rc7
  hw/char/bcm2835_aux: Allow less than 32-bit accesses
  hw/arm/sbsa-ref : allocate IRQs for SMMUv3
  hw/arm/sbsa-ref : Fix SMMUv3 Initialisation
  hw/arm/fsl-imx25: Fix a typo
  hw/ssi/npcm7xx_fiu: Fix handling of unsigned integer

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-10-08 21:41:20 +01:00
commit 497d415d76
18 changed files with 304 additions and 72 deletions

View File

@ -200,6 +200,17 @@ the list of KVM VCPU features and their descriptions.
adjustment, also restoring the legacy (pre-5.0) adjustment, also restoring the legacy (pre-5.0)
behavior. behavior.
kvm-steal-time Since v5.2, kvm-steal-time is enabled by
default when KVM is enabled, the feature is
supported, and the guest is 64-bit.
When kvm-steal-time is enabled a 64-bit guest
can account for time its CPUs were not running
due to the host not scheduling the corresponding
VCPU threads. The accounting statistics may
influence the guest scheduler behavior and/or be
exposed to the guest userspace.
SVE CPU Properties SVE CPU Properties
================== ==================

View File

@ -133,6 +133,7 @@ static const int sbsa_ref_irqmap[] = {
[SBSA_SECURE_UART_MM] = 9, [SBSA_SECURE_UART_MM] = 9,
[SBSA_AHCI] = 10, [SBSA_AHCI] = 10,
[SBSA_EHCI] = 11, [SBSA_EHCI] = 11,
[SBSA_SMMU] = 12, /* ... to 15 */
}; };
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx) static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
@ -525,7 +526,7 @@ static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
for (i = 0; i < NUM_SMMU_IRQS; i++) { for (i = 0; i < NUM_SMMU_IRQS; i++) {
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
qdev_get_gpio_in(sms->gic, irq + 1)); qdev_get_gpio_in(sms->gic, irq + i));
} }
} }

View File

@ -151,6 +151,7 @@ static const MemMapEntry base_memmap[] = {
[VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN }, [VIRT_PCDIMM_ACPI] = { 0x09070000, MEMORY_HOTPLUG_IO_LEN },
[VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN }, [VIRT_ACPI_GED] = { 0x09080000, ACPI_GED_EVT_SEL_LEN },
[VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN},
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
[VIRT_MMIO] = { 0x0a000000, 0x00000200 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 },
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
@ -521,21 +522,12 @@ static void fdt_add_gic_node(VirtMachineState *vms)
static void fdt_add_pmu_nodes(const VirtMachineState *vms) static void fdt_add_pmu_nodes(const VirtMachineState *vms)
{ {
CPUState *cpu; ARMCPU *armcpu = ARM_CPU(first_cpu);
ARMCPU *armcpu;
uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI; uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI;
CPU_FOREACH(cpu) { if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
armcpu = ARM_CPU(cpu); assert(!object_property_get_bool(OBJECT(armcpu), "pmu", NULL));
if (!arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { return;
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 (vms->gic_version == VIRT_GIC_VERSION_2) { if (vms->gic_version == VIRT_GIC_VERSION_2) {
@ -544,7 +536,6 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms)
(1 << vms->smp_cpus) - 1); (1 << vms->smp_cpus) - 1);
} }
armcpu = ARM_CPU(qemu_get_cpu(0));
qemu_fdt_add_subnode(vms->fdt, "/pmu"); qemu_fdt_add_subnode(vms->fdt, "/pmu");
if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) { if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) {
const char compat[] = "arm,armv8-pmuv3"; const char compat[] = "arm,armv8-pmuv3";
@ -1672,6 +1663,72 @@ 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, int max_cpus,
MemoryRegion *sysmem)
{
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));
if (kvm_irqchip_in_kernel()) {
kvm_arm_pmu_set_irq(cpu, PPI(VIRTUAL_PMU_IRQ));
}
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) {
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) static void machvirt_init(MachineState *machine)
{ {
VirtMachineState *vms = VIRT_MACHINE(machine); VirtMachineState *vms = VIRT_MACHINE(machine);
@ -1826,6 +1883,11 @@ static void machvirt_init(MachineState *machine)
object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL); 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")) { if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) {
object_property_set_bool(cpuobj, "pmu", false, NULL); object_property_set_bool(cpuobj, "pmu", false, NULL);
} }
@ -1886,22 +1948,6 @@ static void machvirt_init(MachineState *machine)
fdt_add_timer_nodes(vms); fdt_add_timer_nodes(vms);
fdt_add_cpu_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, memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base,
machine->ram); machine->ram);
if (machine->device_memory) { if (machine->device_memory) {
@ -1913,6 +1959,8 @@ static void machvirt_init(MachineState *machine)
create_gic(vms); create_gic(vms);
virt_cpu_post_init(vms, possible_cpus->len, sysmem);
fdt_add_pmu_nodes(vms); fdt_add_pmu_nodes(vms);
create_uart(vms, VIRT_UART, sysmem, serial_hd(0)); create_uart(vms, VIRT_UART, sysmem, serial_hd(0));
@ -2553,8 +2601,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 2)
static void virt_machine_5_1_options(MachineClass *mc) static void virt_machine_5_1_options(MachineClass *mc)
{ {
VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
virt_machine_5_2_options(mc); virt_machine_5_2_options(mc);
compat_props_add(mc->compat_props, hw_compat_5_1, hw_compat_5_1_len); 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) DEFINE_VIRT_MACHINE(5, 1)

View File

@ -249,7 +249,9 @@ static const MemoryRegionOps bcm2835_aux_ops = {
.read = bcm2835_aux_read, .read = bcm2835_aux_read,
.write = bcm2835_aux_write, .write = bcm2835_aux_write,
.endianness = DEVICE_NATIVE_ENDIAN, .endianness = DEVICE_NATIVE_ENDIAN,
.valid.min_access_size = 4, .impl.min_access_size = 4,
.impl.max_access_size = 4,
.valid.min_access_size = 1,
.valid.max_access_size = 4, .valid.max_access_size = 4,
}; };

View File

@ -103,7 +103,8 @@ enum NPCM7xxFIURegister {
* Returns the index of flash in the fiu->flash array. This corresponds to the * Returns the index of flash in the fiu->flash array. This corresponds to the
* chip select ID of the flash. * chip select ID of the flash.
*/ */
static int npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, NPCM7xxFIUFlash *flash) static unsigned npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu,
NPCM7xxFIUFlash *flash)
{ {
int index = flash - fiu->flash; int index = flash - fiu->flash;
@ -113,20 +114,19 @@ static int npcm7xx_fiu_cs_index(NPCM7xxFIUState *fiu, NPCM7xxFIUFlash *flash)
} }
/* Assert the chip select specified in the UMA Control/Status Register. */ /* Assert the chip select specified in the UMA Control/Status Register. */
static void npcm7xx_fiu_select(NPCM7xxFIUState *s, int cs_id) static void npcm7xx_fiu_select(NPCM7xxFIUState *s, unsigned cs_id)
{ {
trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id); trace_npcm7xx_fiu_select(DEVICE(s)->canonical_path, cs_id);
if (cs_id < s->cs_count) { if (cs_id < s->cs_count) {
qemu_irq_lower(s->cs_lines[cs_id]); qemu_irq_lower(s->cs_lines[cs_id]);
s->active_cs = cs_id;
} else { } else {
qemu_log_mask(LOG_GUEST_ERROR, qemu_log_mask(LOG_GUEST_ERROR,
"%s: UMA to CS%d; this module has only %d chip selects", "%s: UMA to CS%d; this module has only %d chip selects",
DEVICE(s)->canonical_path, cs_id, s->cs_count); DEVICE(s)->canonical_path, cs_id, s->cs_count);
cs_id = -1; s->active_cs = -1;
} }
s->active_cs = cs_id;
} }
/* Deassert the currently active chip select. */ /* Deassert the currently active chip select. */
@ -206,7 +206,7 @@ static void npcm7xx_fiu_flash_write(void *opaque, hwaddr addr, uint64_t v,
NPCM7xxFIUFlash *f = opaque; NPCM7xxFIUFlash *f = opaque;
NPCM7xxFIUState *fiu = f->fiu; NPCM7xxFIUState *fiu = f->fiu;
uint32_t dwr_cfg; uint32_t dwr_cfg;
int cs_id; unsigned cs_id;
int i; int i;
if (fiu->active_cs != -1) { if (fiu->active_cs != -1) {

View File

@ -19,4 +19,4 @@ npcm7xx_fiu_deselect(const char *id, int cs) "%s deselect CS%d"
npcm7xx_fiu_ctrl_read(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 npcm7xx_fiu_ctrl_read(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32 npcm7xx_fiu_ctrl_write(const char *id, uint64_t addr, uint32_t data) "%s offset: 0x%04" PRIx64 " value: 0x%08" PRIx32
npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64 npcm7xx_fiu_flash_read(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64
npcm7xx_fiu_flash_write(const char *id, int cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64 npcm7xx_fiu_flash_write(const char *id, unsigned cs, uint64_t addr, unsigned int size, uint64_t value) "%s[%d] offset: 0x%08" PRIx64 " size: %u value: 0x%" PRIx64

View File

@ -179,7 +179,7 @@ struct FslIMX25State {
* 0xBB00_0000 0xBB00_0FFF 4 Kbytes NAND flash main area buffer * 0xBB00_0000 0xBB00_0FFF 4 Kbytes NAND flash main area buffer
* 0xBB00_1000 0xBB00_11FF 512 B NAND flash spare area buffer * 0xBB00_1000 0xBB00_11FF 512 B NAND flash spare area buffer
* 0xBB00_1200 0xBB00_1DFF 3 Kbytes Reserved * 0xBB00_1200 0xBB00_1DFF 3 Kbytes Reserved
* 0xBB00_1E00 0xBB00_1FFF 512 B NAND flash control regisers * 0xBB00_1E00 0xBB00_1FFF 512 B NAND flash control registers
* 0xBB01_2000 0xBFFF_FFFF 96 Mbytes (minus 8 Kbytes) Reserved * 0xBB01_2000 0xBFFF_FFFF 96 Mbytes (minus 8 Kbytes) Reserved
* 0xC000_0000 0xFFFF_FFFF 1024 Mbytes Reserved * 0xC000_0000 0xFFFF_FFFF 1024 Mbytes Reserved
*/ */

View File

@ -54,6 +54,9 @@
#define PPI(irq) ((irq) + 16) #define PPI(irq) ((irq) + 16)
/* See Linux kernel arch/arm64/include/asm/pvclock-abi.h */
#define PVTIME_SIZE_PER_CPU 64
enum { enum {
VIRT_FLASH, VIRT_FLASH,
VIRT_MEM, VIRT_MEM,
@ -81,6 +84,7 @@ enum {
VIRT_PCDIMM_ACPI, VIRT_PCDIMM_ACPI,
VIRT_ACPI_GED, VIRT_ACPI_GED,
VIRT_NVDIMM_ACPI, VIRT_NVDIMM_ACPI,
VIRT_PVTIME,
VIRT_LOWMEMMAP_LAST, VIRT_LOWMEMMAP_LAST,
}; };
@ -121,6 +125,7 @@ struct VirtMachineClass {
bool no_highmem_ecam; bool no_highmem_ecam;
bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */ bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */
bool kvm_no_adjvtime; bool kvm_no_adjvtime;
bool no_kvm_steal_time;
bool acpi_expose_flash; bool acpi_expose_flash;
}; };

View File

@ -790,9 +790,10 @@ struct kvm_ppc_resize_hpt {
#define KVM_VM_PPC_HV 1 #define KVM_VM_PPC_HV 1
#define KVM_VM_PPC_PR 2 #define KVM_VM_PPC_PR 2
/* on MIPS, 0 forces trap & emulate, 1 forces VZ ASE */ /* on MIPS, 0 indicates auto, 1 forces VZ ASE, 2 forces trap & emulate */
#define KVM_VM_MIPS_TE 0 #define KVM_VM_MIPS_AUTO 0
#define KVM_VM_MIPS_VZ 1 #define KVM_VM_MIPS_VZ 1
#define KVM_VM_MIPS_TE 2
#define KVM_S390_SIE_PAGE_OFFSET 1 #define KVM_S390_SIE_PAGE_OFFSET 1
@ -1035,6 +1036,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_LAST_CPU 184 #define KVM_CAP_LAST_CPU 184
#define KVM_CAP_SMALLER_MAXPHYADDR 185 #define KVM_CAP_SMALLER_MAXPHYADDR 185
#define KVM_CAP_S390_DIAG318 186 #define KVM_CAP_S390_DIAG318 186
#define KVM_CAP_STEAL_TIME 187
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING

View File

@ -1310,6 +1310,14 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
return; return;
} }
} }
if (kvm_enabled()) {
kvm_arm_steal_time_finalize(cpu, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
return;
}
}
} }
static void arm_cpu_realizefn(DeviceState *dev, Error **errp) static void arm_cpu_realizefn(DeviceState *dev, Error **errp)

View File

@ -24,6 +24,7 @@
#include "hw/registerfields.h" #include "hw/registerfields.h"
#include "cpu-qom.h" #include "cpu-qom.h"
#include "exec/cpu-defs.h" #include "exec/cpu-defs.h"
#include "qapi/qapi-types-common.h"
/* ARM processors have a weak memory model */ /* ARM processors have a weak memory model */
#define TCG_GUEST_DEFAULT_MO (0) #define TCG_GUEST_DEFAULT_MO (0)
@ -863,6 +864,9 @@ struct ARMCPU {
bool kvm_vtime_dirty; bool kvm_vtime_dirty;
uint64_t kvm_vtime; uint64_t kvm_vtime;
/* KVM steal time */
OnOffAuto kvm_steal_time;
/* Uniprocessor system with MP extensions */ /* Uniprocessor system with MP extensions */
bool mp_is_up; bool mp_is_up;

View File

@ -653,6 +653,10 @@ static void aarch64_max_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64PFR1, MTE, 2); t = FIELD_DP64(t, ID_AA64PFR1, MTE, 2);
cpu->isar.id_aa64pfr1 = t; cpu->isar.id_aa64pfr1 = t;
t = cpu->isar.id_aa64mmfr0;
t = FIELD_DP64(t, ID_AA64MMFR0, PARANGE, 5); /* PARange: 48 bits */
cpu->isar.id_aa64mmfr0 = t;
t = cpu->isar.id_aa64mmfr1; t = cpu->isar.id_aa64mmfr1;
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */ t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);

View File

@ -192,6 +192,16 @@ static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp)
ARM_CPU(obj)->kvm_adjvtime = !value; ARM_CPU(obj)->kvm_adjvtime = !value;
} }
static bool kvm_steal_time_get(Object *obj, Error **errp)
{
return ARM_CPU(obj)->kvm_steal_time != ON_OFF_AUTO_OFF;
}
static void kvm_steal_time_set(Object *obj, bool value, Error **errp)
{
ARM_CPU(obj)->kvm_steal_time = value ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
/* KVM VCPU properties should be prefixed with "kvm-". */ /* KVM VCPU properties should be prefixed with "kvm-". */
void kvm_arm_add_vcpu_properties(Object *obj) void kvm_arm_add_vcpu_properties(Object *obj)
{ {
@ -207,6 +217,12 @@ void kvm_arm_add_vcpu_properties(Object *obj)
"the virtual counter. VM stopped time " "the virtual counter. VM stopped time "
"will be counted."); "will be counted.");
} }
cpu->kvm_steal_time = ON_OFF_AUTO_AUTO;
object_property_add_bool(obj, "kvm-steal-time", kvm_steal_time_get,
kvm_steal_time_set);
object_property_set_description(obj, "kvm-steal-time",
"Set off to disable KVM steal time.");
} }
bool kvm_arm_pmu_supported(void) bool kvm_arm_pmu_supported(void)

View File

@ -17,6 +17,7 @@
#include <linux/kvm.h> #include <linux/kvm.h>
#include "qemu-common.h" #include "qemu-common.h"
#include "qapi/error.h"
#include "cpu.h" #include "cpu.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
@ -397,19 +398,20 @@ static CPUWatchpoint *find_hw_watchpoint(CPUState *cpu, target_ulong addr)
return NULL; return NULL;
} }
static bool kvm_arm_pmu_set_attr(CPUState *cs, struct kvm_device_attr *attr) static bool kvm_arm_set_device_attr(CPUState *cs, struct kvm_device_attr *attr,
const char *name)
{ {
int err; int err;
err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr); err = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, attr);
if (err != 0) { if (err != 0) {
error_report("PMU: KVM_HAS_DEVICE_ATTR: %s", strerror(-err)); error_report("%s: KVM_HAS_DEVICE_ATTR: %s", name, strerror(-err));
return false; return false;
} }
err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr); err = kvm_vcpu_ioctl(cs, KVM_SET_DEVICE_ATTR, attr);
if (err != 0) { if (err != 0) {
error_report("PMU: KVM_SET_DEVICE_ATTR: %s", strerror(-err)); error_report("%s: KVM_SET_DEVICE_ATTR: %s", name, strerror(-err));
return false; return false;
} }
@ -426,7 +428,7 @@ void kvm_arm_pmu_init(CPUState *cs)
if (!ARM_CPU(cs)->has_pmu) { if (!ARM_CPU(cs)->has_pmu) {
return; return;
} }
if (!kvm_arm_pmu_set_attr(cs, &attr)) { if (!kvm_arm_set_device_attr(cs, &attr, "PMU")) {
error_report("failed to init PMU"); error_report("failed to init PMU");
abort(); abort();
} }
@ -443,12 +445,29 @@ void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
if (!ARM_CPU(cs)->has_pmu) { if (!ARM_CPU(cs)->has_pmu) {
return; return;
} }
if (!kvm_arm_pmu_set_attr(cs, &attr)) { if (!kvm_arm_set_device_attr(cs, &attr, "PMU")) {
error_report("failed to set irq for PMU"); error_report("failed to set irq for PMU");
abort(); abort();
} }
} }
void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa)
{
struct kvm_device_attr attr = {
.group = KVM_ARM_VCPU_PVTIME_CTRL,
.attr = KVM_ARM_VCPU_PVTIME_IPA,
.addr = (uint64_t)&ipa,
};
if (ARM_CPU(cs)->kvm_steal_time == ON_OFF_AUTO_OFF) {
return;
}
if (!kvm_arm_set_device_attr(cs, &attr, "PVTIME IPA")) {
error_report("failed to init PVTIME IPA");
abort();
}
}
static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id)
{ {
uint64_t ret; uint64_t ret;
@ -655,6 +674,36 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
return true; return true;
} }
void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp)
{
bool has_steal_time = kvm_arm_steal_time_supported();
if (cpu->kvm_steal_time == ON_OFF_AUTO_AUTO) {
if (!has_steal_time || !arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
cpu->kvm_steal_time = ON_OFF_AUTO_OFF;
} else {
cpu->kvm_steal_time = ON_OFF_AUTO_ON;
}
} else if (cpu->kvm_steal_time == ON_OFF_AUTO_ON) {
if (!has_steal_time) {
error_setg(errp, "'kvm-steal-time' cannot be enabled "
"on this host");
return;
} else if (!arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
/*
* DEN0057A chapter 2 says "This specification only covers
* systems in which the Execution state of the hypervisor
* as well as EL1 of virtual machines is AArch64.". And,
* to ensure that, the smc/hvc calls are only specified as
* smc64/hvc64.
*/
error_setg(errp, "'kvm-steal-time' cannot be enabled "
"for AArch32 guests");
return;
}
}
}
bool kvm_arm_aarch32_supported(void) bool kvm_arm_aarch32_supported(void)
{ {
return kvm_check_extension(kvm_state, KVM_CAP_ARM_EL1_32BIT); return kvm_check_extension(kvm_state, KVM_CAP_ARM_EL1_32BIT);
@ -665,6 +714,11 @@ bool kvm_arm_sve_supported(void)
return kvm_check_extension(kvm_state, KVM_CAP_ARM_SVE); return kvm_check_extension(kvm_state, KVM_CAP_ARM_SVE);
} }
bool kvm_arm_steal_time_supported(void)
{
return kvm_check_extension(kvm_state, KVM_CAP_STEAL_TIME);
}
QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1); QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map)

View File

@ -267,6 +267,24 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
*/ */
void kvm_arm_add_vcpu_properties(Object *obj); void kvm_arm_add_vcpu_properties(Object *obj);
/**
* kvm_arm_steal_time_finalize:
* @cpu: ARMCPU for which to finalize kvm-steal-time
* @errp: Pointer to Error* for error propagation
*
* Validate the kvm-steal-time property selection and set its default
* based on KVM support and guest configuration.
*/
void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp);
/**
* kvm_arm_steal_time_supported:
*
* Returns: true if KVM can enable steal time reporting
* and false otherwise.
*/
bool kvm_arm_steal_time_supported(void);
/** /**
* kvm_arm_aarch32_supported: * kvm_arm_aarch32_supported:
* *
@ -340,22 +358,24 @@ int kvm_arm_vgic_probe(void);
void kvm_arm_pmu_set_irq(CPUState *cs, int irq); void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
void kvm_arm_pmu_init(CPUState *cs); void kvm_arm_pmu_init(CPUState *cs);
/**
* kvm_arm_pvtime_init:
* @cs: CPUState
* @ipa: Per-vcpu guest physical base address of the pvtime structures
*
* Initializes PVTIME for the VCPU, setting the PVTIME IPA to @ipa.
*/
void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa);
int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
#else #else
static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) /*
{ * It's safe to call these functions without KVM support.
/* * They should either do nothing or return "not supported".
* This should never actually be called in the "not KVM" case, */
* but set up the fields to indicate an error anyway.
*/
cpu->kvm_target = QEMU_KVM_ARM_TARGET_NONE;
cpu->host_cpu_probe_failed = true;
}
static inline void kvm_arm_add_vcpu_properties(Object *obj) {}
static inline bool kvm_arm_aarch32_supported(void) static inline bool kvm_arm_aarch32_supported(void)
{ {
return false; return false;
@ -371,23 +391,59 @@ static inline bool kvm_arm_sve_supported(void)
return false; return false;
} }
static inline bool kvm_arm_steal_time_supported(void)
{
return false;
}
/*
* These functions should never actually be called without KVM support.
*/
static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
{
g_assert_not_reached();
}
static inline void kvm_arm_add_vcpu_properties(Object *obj)
{
g_assert_not_reached();
}
static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms) static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
{ {
return -ENOENT; g_assert_not_reached();
} }
static inline int kvm_arm_vgic_probe(void) static inline int kvm_arm_vgic_probe(void)
{ {
return 0; g_assert_not_reached();
} }
static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {} static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
static inline void kvm_arm_pmu_init(CPUState *cs) {} {
g_assert_not_reached();
}
static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) {} static inline void kvm_arm_pmu_init(CPUState *cs)
{
g_assert_not_reached();
}
static inline void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa)
{
g_assert_not_reached();
}
static inline void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp)
{
g_assert_not_reached();
}
static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map)
{
g_assert_not_reached();
}
static inline void kvm_arm_get_virtual_time(CPUState *cs) {}
static inline void kvm_arm_put_virtual_time(CPUState *cs) {}
#endif #endif
static inline const char *gic_class_name(void) static inline const char *gic_class_name(void)

View File

@ -103,7 +103,7 @@ static const char *cpu_model_advertised_features[] = {
"sve128", "sve256", "sve384", "sve512", "sve128", "sve256", "sve384", "sve512",
"sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280", "sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
"sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048", "sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
"kvm-no-adjvtime", "kvm-no-adjvtime", "kvm-steal-time",
NULL NULL
}; };

View File

@ -452,6 +452,7 @@ static void test_query_cpu_model_expansion(const void *data)
assert_set_feature(qts, "max", "pmu", true); assert_set_feature(qts, "max", "pmu", true);
assert_has_not_feature(qts, "max", "kvm-no-adjvtime"); assert_has_not_feature(qts, "max", "kvm-no-adjvtime");
assert_has_not_feature(qts, "max", "kvm-steal-time");
if (g_str_equal(qtest_get_arch(), "aarch64")) { if (g_str_equal(qtest_get_arch(), "aarch64")) {
assert_has_feature_enabled(qts, "max", "aarch64"); assert_has_feature_enabled(qts, "max", "aarch64");
@ -493,6 +494,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
assert_set_feature(qts, "host", "kvm-no-adjvtime", false); assert_set_feature(qts, "host", "kvm-no-adjvtime", false);
if (g_str_equal(qtest_get_arch(), "aarch64")) { if (g_str_equal(qtest_get_arch(), "aarch64")) {
bool kvm_supports_steal_time;
bool kvm_supports_sve; bool kvm_supports_sve;
char max_name[8], name[8]; char max_name[8], name[8];
uint32_t max_vq, vq; uint32_t max_vq, vq;
@ -500,6 +502,10 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
QDict *resp; QDict *resp;
char *error; char *error;
assert_error(qts, "cortex-a15",
"We cannot guarantee the CPU type 'cortex-a15' works "
"with KVM on this host", NULL);
assert_has_feature_enabled(qts, "host", "aarch64"); assert_has_feature_enabled(qts, "host", "aarch64");
/* Enabling and disabling pmu should always work. */ /* Enabling and disabling pmu should always work. */
@ -507,16 +513,26 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
assert_set_feature(qts, "host", "pmu", false); assert_set_feature(qts, "host", "pmu", false);
assert_set_feature(qts, "host", "pmu", true); assert_set_feature(qts, "host", "pmu", true);
assert_error(qts, "cortex-a15", /*
"We cannot guarantee the CPU type 'cortex-a15' works " * Some features would be enabled by default, but they're disabled
"with KVM on this host", NULL); * because this instance of KVM doesn't support them. Test that the
* features are present, and, when enabled, issue further tests.
*/
assert_has_feature(qts, "host", "kvm-steal-time");
assert_has_feature(qts, "host", "sve"); assert_has_feature(qts, "host", "sve");
resp = do_query_no_props(qts, "host"); resp = do_query_no_props(qts, "host");
kvm_supports_steal_time = resp_get_feature(resp, "kvm-steal-time");
kvm_supports_sve = resp_get_feature(resp, "sve"); kvm_supports_sve = resp_get_feature(resp, "sve");
vls = resp_get_sve_vls(resp); vls = resp_get_sve_vls(resp);
qobject_unref(resp); qobject_unref(resp);
if (kvm_supports_steal_time) {
/* If we have steal-time then we should be able to toggle it. */
assert_set_feature(qts, "host", "kvm-steal-time", false);
assert_set_feature(qts, "host", "kvm-steal-time", true);
}
if (kvm_supports_sve) { if (kvm_supports_sve) {
g_assert(vls != 0); g_assert(vls != 0);
max_vq = 64 - __builtin_clzll(vls); max_vq = 64 - __builtin_clzll(vls);
@ -577,6 +593,7 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
assert_has_not_feature(qts, "host", "aarch64"); assert_has_not_feature(qts, "host", "aarch64");
assert_has_not_feature(qts, "host", "pmu"); assert_has_not_feature(qts, "host", "pmu");
assert_has_not_feature(qts, "host", "sve"); assert_has_not_feature(qts, "host", "sve");
assert_has_not_feature(qts, "host", "kvm-steal-time");
} }
qtest_quit(qts); qtest_quit(qts);

View File

@ -146,7 +146,8 @@ qtests_aarch64 = \
(cpu != 'arm' ? ['bios-tables-test'] : []) + \ (cpu != 'arm' ? ['bios-tables-test'] : []) + \
(config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-test'] : []) + \ (config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-test'] : []) + \
(config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-swtpm-test'] : []) + \ (config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ? ['tpm-tis-device-swtpm-test'] : []) + \
['numa-test', ['arm-cpu-features',
'numa-test',
'boot-serial-test', 'boot-serial-test',
'migration-test'] 'migration-test']