diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-01-30 16:19:04 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-01-30 16:19:04 +0000 |
commit | 928173659d6e5dc368284f73f90ea1d129e1f57d (patch) | |
tree | a7c20f44a7f47478a8b475fb42609af5d2977f64 /target | |
parent | 204aa60b37c23a89e690d418f49787d274303ca7 (diff) | |
parent | dea101a1ae9968c9fec6ab0291489dad7c49f36f (diff) | |
download | qemu-928173659d6e5dc368284f73f90ea1d129e1f57d.zip qemu-928173659d6e5dc368284f73f90ea1d129e1f57d.tar.gz qemu-928173659d6e5dc368284f73f90ea1d129e1f57d.tar.bz2 |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200130' into staging
target-arm queue:
* hw/core/or-irq: Fix incorrect assert forbidding num-lines == MAX_OR_LINES
* target/arm/arm-semi: Don't let the guest close stdin/stdout/stderr
* aspeed: some minor bugfixes
* aspeed: add eMMC controller model for AST2600 SoC
* hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
* New 3-phase reset API for device models
* hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
* Arm KVM: stop/restart the guest counter when the VM is stopped and started
# gpg: Signature made Thu 30 Jan 2020 16:14:45 GMT
# 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-20200130: (26 commits)
target/arm/cpu: Add the kvm-no-adjvtime CPU property
target/arm/kvm: Implement virtual time adjustment
tests/arm-cpu-features: Check feature default values
target/arm/kvm64: kvm64 cpus have timer registers
hw/arm/virt: Add missing 5.0 options call to 4.2 options
target/arm/kvm: trivial: Clean up header documentation
hw/intc/arm_gicv3_kvm: Stop wrongly programming GICR_PENDBASER.PTZ bit
hw/s390x/ipl: replace deprecated qdev_reset_all registration
vl: replace deprecated qbus_reset_all registration
docs/devel/reset.rst: add doc about Resettable interface
hw/core: deprecate old reset functions and introduce new ones
hw/core/qdev: update hotplug reset regarding resettable
hw/core/qdev: handle parent bus change regarding resettable
hw/core/resettable: add support for changing parent
hw/core: add Resettable support to BusClass and DeviceClass
hw/core: create Resettable QOM interface
hw/core/qdev: add trace events to help with resettable transition
add device_legacy_reset function to prepare for reset api change
hw/arm/raspi: Remove obsolete use of -smp to set the soc 'enabled-cpus'
misc/pca9552: Add qom set and get
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/arm-semi.c | 9 | ||||
-rw-r--r-- | target/arm/cpu.c | 2 | ||||
-rw-r--r-- | target/arm/cpu.h | 7 | ||||
-rw-r--r-- | target/arm/cpu64.c | 1 | ||||
-rw-r--r-- | target/arm/kvm.c | 120 | ||||
-rw-r--r-- | target/arm/kvm32.c | 3 | ||||
-rw-r--r-- | target/arm/kvm64.c | 4 | ||||
-rw-r--r-- | target/arm/kvm_arm.h | 95 | ||||
-rw-r--r-- | target/arm/machine.c | 7 | ||||
-rw-r--r-- | target/arm/monitor.c | 1 |
10 files changed, 230 insertions, 19 deletions
diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c index 788fe61..8718fd0 100644 --- a/target/arm/arm-semi.c +++ b/target/arm/arm-semi.c @@ -403,6 +403,15 @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf) { CPUARMState *env = &cpu->env; + /* + * Only close the underlying host fd if it's one we opened on behalf + * of the guest in SYS_OPEN. + */ + if (gf->hostfd == STDIN_FILENO || + gf->hostfd == STDOUT_FILENO || + gf->hostfd == STDERR_FILENO) { + return 0; + } return set_swi_errno(env, close(gf->hostfd)); } diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 06907b3..f86e71a 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -2551,6 +2551,7 @@ static void arm_max_initfn(Object *obj) if (kvm_enabled()) { kvm_arm_set_cpu_features_from_host(cpu); + kvm_arm_add_vcpu_properties(obj); } else { cortex_a15_initfn(obj); @@ -2743,6 +2744,7 @@ static void arm_host_initfn(Object *obj) if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { aarch64_add_sve_properties(obj); } + kvm_arm_add_vcpu_properties(obj); arm_cpu_post_init(obj); } diff --git a/target/arm/cpu.h b/target/arm/cpu.h index c1aedbe..608fcbd 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -821,6 +821,13 @@ struct ARMCPU { /* KVM init features for this CPU */ uint32_t kvm_init_features[7]; + /* KVM CPU state */ + + /* KVM virtual time adjustment */ + bool kvm_adjvtime; + bool kvm_vtime_dirty; + uint64_t kvm_vtime; + /* Uniprocessor system with MP extensions */ bool mp_is_up; diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 61fd0ad..2d97bf4 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -605,6 +605,7 @@ static void aarch64_max_initfn(Object *obj) if (kvm_enabled()) { kvm_arm_set_cpu_features_from_host(cpu); + kvm_arm_add_vcpu_properties(obj); } else { uint64_t t; uint32_t u; diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 8d82889..85860e6 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -17,6 +17,8 @@ #include "qemu/timer.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" +#include "qom/object.h" +#include "qapi/error.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "sysemu/kvm_int.h" @@ -179,6 +181,32 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) env->features = arm_host_cpu_features.features; } +static bool kvm_no_adjvtime_get(Object *obj, Error **errp) +{ + return !ARM_CPU(obj)->kvm_adjvtime; +} + +static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp) +{ + ARM_CPU(obj)->kvm_adjvtime = !value; +} + +/* KVM VCPU properties should be prefixed with "kvm-". */ +void kvm_arm_add_vcpu_properties(Object *obj) +{ + if (!kvm_enabled()) { + return; + } + + ARM_CPU(obj)->kvm_adjvtime = true; + object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get, + kvm_no_adjvtime_set, &error_abort); + object_property_set_description(obj, "kvm-no-adjvtime", + "Set on to disable the adjustment of " + "the virtual counter. VM stopped time " + "will be counted.", &error_abort); +} + bool kvm_arm_pmu_supported(CPUState *cpu) { return kvm_check_extension(cpu->kvm_state, KVM_CAP_ARM_PMU_V3); @@ -357,6 +385,22 @@ static int compare_u64(const void *a, const void *b) return 0; } +/* + * cpreg_values are sorted in ascending order by KVM register ID + * (see kvm_arm_init_cpreg_list). This allows us to cheaply find + * the storage for a KVM register by ID with a binary search. + */ +static uint64_t *kvm_arm_get_cpreg_ptr(ARMCPU *cpu, uint64_t regidx) +{ + uint64_t *res; + + res = bsearch(®idx, cpu->cpreg_indexes, cpu->cpreg_array_len, + sizeof(uint64_t), compare_u64); + assert(res); + + return &cpu->cpreg_values[res - cpu->cpreg_indexes]; +} + /* Initialize the ARMCPU cpreg list according to the kernel's * definition of what CPU registers it knows about (and throw away * the previous TCG-created cpreg list). @@ -510,6 +554,23 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level) return ok; } +void kvm_arm_cpu_pre_save(ARMCPU *cpu) +{ + /* KVM virtual time adjustment */ + if (cpu->kvm_vtime_dirty) { + *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT) = cpu->kvm_vtime; + } +} + +void kvm_arm_cpu_post_load(ARMCPU *cpu) +{ + /* KVM virtual time adjustment */ + if (cpu->kvm_adjvtime) { + cpu->kvm_vtime = *kvm_arm_get_cpreg_ptr(cpu, KVM_REG_ARM_TIMER_CNT); + cpu->kvm_vtime_dirty = true; + } +} + void kvm_arm_reset_vcpu(ARMCPU *cpu) { int ret; @@ -577,6 +638,50 @@ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu) return 0; } +void kvm_arm_get_virtual_time(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + struct kvm_one_reg reg = { + .id = KVM_REG_ARM_TIMER_CNT, + .addr = (uintptr_t)&cpu->kvm_vtime, + }; + int ret; + + if (cpu->kvm_vtime_dirty) { + return; + } + + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + error_report("Failed to get KVM_REG_ARM_TIMER_CNT"); + abort(); + } + + cpu->kvm_vtime_dirty = true; +} + +void kvm_arm_put_virtual_time(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + struct kvm_one_reg reg = { + .id = KVM_REG_ARM_TIMER_CNT, + .addr = (uintptr_t)&cpu->kvm_vtime, + }; + int ret; + + if (!cpu->kvm_vtime_dirty) { + return; + } + + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + error_report("Failed to set KVM_REG_ARM_TIMER_CNT"); + abort(); + } + + cpu->kvm_vtime_dirty = false; +} + int kvm_put_vcpu_events(ARMCPU *cpu) { CPUARMState *env = &cpu->env; @@ -688,6 +793,21 @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) return MEMTXATTRS_UNSPECIFIED; } +void kvm_arm_vm_state_change(void *opaque, int running, RunState state) +{ + CPUState *cs = opaque; + ARMCPU *cpu = ARM_CPU(cs); + + if (running) { + if (cpu->kvm_adjvtime) { + kvm_arm_put_virtual_time(cs); + } + } else { + if (cpu->kvm_adjvtime) { + kvm_arm_get_virtual_time(cs); + } + } +} int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c index 32bf8d6..3a8b437 100644 --- a/target/arm/kvm32.c +++ b/target/arm/kvm32.c @@ -16,6 +16,7 @@ #include "qemu-common.h" #include "cpu.h" #include "qemu/timer.h" +#include "sysemu/runstate.h" #include "sysemu/kvm.h" #include "kvm_arm.h" #include "internals.h" @@ -198,6 +199,8 @@ int kvm_arch_init_vcpu(CPUState *cs) return -EINVAL; } + qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs); + /* Determine init features for this CPU */ memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features)); if (cpu->start_powered_off) { diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 6344113..fb21ab9 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -23,6 +23,7 @@ #include "qemu/host-utils.h" #include "qemu/main-loop.h" #include "exec/gdbstub.h" +#include "sysemu/runstate.h" #include "sysemu/kvm.h" #include "sysemu/kvm_int.h" #include "kvm_arm.h" @@ -604,6 +605,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) set_feature(&features, ARM_FEATURE_NEON); set_feature(&features, ARM_FEATURE_AARCH64); set_feature(&features, ARM_FEATURE_PMU); + set_feature(&features, ARM_FEATURE_GENERIC_TIMER); ahcf->features = features; @@ -733,6 +735,8 @@ int kvm_arch_init_vcpu(CPUState *cs) return -EINVAL; } + qemu_add_vm_change_state_handler(kvm_arm_vm_state_change, cs); + /* Determine init features for this CPU */ memset(cpu->kvm_init_features, 0, sizeof(cpu->kvm_init_features)); if (cpu->start_powered_off) { diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 8e14d40..ae9e075 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -28,9 +28,9 @@ int kvm_arm_vcpu_init(CPUState *cs); /** - * kvm_arm_vcpu_finalize + * kvm_arm_vcpu_finalize: * @cs: CPUState - * @feature: int + * @feature: feature to finalize * * Finalizes the configuration of the specified VCPU feature by * invoking the KVM_ARM_VCPU_FINALIZE ioctl. Features requiring @@ -75,8 +75,8 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group, int kvm_arm_init_cpreg_list(ARMCPU *cpu); /** - * kvm_arm_reg_syncs_via_cpreg_list - * regidx: KVM register index + * kvm_arm_reg_syncs_via_cpreg_list: + * @regidx: KVM register index * * Return true if this KVM register should be synchronized via the * cpreg list of arbitrary system registers, false if it is synchronized @@ -85,8 +85,8 @@ int kvm_arm_init_cpreg_list(ARMCPU *cpu); bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx); /** - * kvm_arm_cpreg_level - * regidx: KVM register index + * kvm_arm_cpreg_level: + * @regidx: KVM register index * * Return the level of this coprocessor/system register. Return value is * either KVM_PUT_RUNTIME_STATE, KVM_PUT_RESET_STATE, or KVM_PUT_FULL_STATE. @@ -128,6 +128,23 @@ bool write_list_to_kvmstate(ARMCPU *cpu, int level); bool write_kvmstate_to_list(ARMCPU *cpu); /** + * kvm_arm_cpu_pre_save: + * @cpu: ARMCPU + * + * Called after write_kvmstate_to_list() from cpu_pre_save() to update + * the cpreg list with KVM CPU state. + */ +void kvm_arm_cpu_pre_save(ARMCPU *cpu); + +/** + * kvm_arm_cpu_post_load: + * @cpu: ARMCPU + * + * Called from cpu_post_load() to update KVM CPU state from the cpreg list. + */ +void kvm_arm_cpu_post_load(ARMCPU *cpu); + +/** * kvm_arm_reset_vcpu: * @cpu: ARMCPU * @@ -148,6 +165,8 @@ void kvm_arm_init_serror_injection(CPUState *cs); * @cpu: ARMCPU * * Get VCPU related state from kvm. + * + * Returns: 0 if success else < 0 error code */ int kvm_get_vcpu_events(ARMCPU *cpu); @@ -156,6 +175,8 @@ int kvm_get_vcpu_events(ARMCPU *cpu); * @cpu: ARMCPU * * Put VCPU related state to kvm. + * + * Returns: 0 if success else < 0 error code */ int kvm_put_vcpu_events(ARMCPU *cpu); @@ -205,10 +226,12 @@ typedef struct ARMHostCPUFeatures { /** * kvm_arm_get_host_cpu_features: - * @ahcc: ARMHostCPUClass to fill in + * @ahcf: ARMHostCPUClass to fill in * * Probe the capabilities of the host kernel's preferred CPU and fill * in the ARMHostCPUClass struct accordingly. + * + * Returns true on success and false otherwise. */ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf); @@ -233,6 +256,15 @@ void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map); void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); /** + * kvm_arm_add_vcpu_properties: + * @obj: The CPU object to add the properties to + * + * Add all KVM specific CPU properties to the CPU object. These + * are the CPU properties with "kvm-" prefixed names. + */ +void kvm_arm_add_vcpu_properties(Object *obj); + +/** * kvm_arm_aarch32_supported: * @cs: CPUState * @@ -242,7 +274,7 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu); bool kvm_arm_aarch32_supported(CPUState *cs); /** - * bool kvm_arm_pmu_supported: + * kvm_arm_pmu_supported: * @cs: CPUState * * Returns: true if the KVM VCPU can enable its PMU @@ -251,7 +283,7 @@ bool kvm_arm_aarch32_supported(CPUState *cs); bool kvm_arm_pmu_supported(CPUState *cs); /** - * bool kvm_arm_sve_supported: + * kvm_arm_sve_supported: * @cs: CPUState * * Returns true if the KVM VCPU can enable SVE and false otherwise. @@ -259,29 +291,51 @@ bool kvm_arm_pmu_supported(CPUState *cs); bool kvm_arm_sve_supported(CPUState *cs); /** - * kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the - * IPA address space supported by KVM - * + * kvm_arm_get_max_vm_ipa_size: * @ms: Machine state handle + * + * Returns the number of bits in the IPA address space supported by KVM */ int kvm_arm_get_max_vm_ipa_size(MachineState *ms); /** - * kvm_arm_sync_mpstate_to_kvm + * kvm_arm_sync_mpstate_to_kvm: * @cpu: ARMCPU * * If supported set the KVM MP_STATE based on QEMU's model. + * + * Returns 0 on success and -1 on failure. */ int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu); /** - * kvm_arm_sync_mpstate_to_qemu + * kvm_arm_sync_mpstate_to_qemu: * @cpu: ARMCPU * * If supported get the MP_STATE from KVM and store in QEMU's model. + * + * Returns 0 on success and aborts on failure. */ int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu); +/** + * kvm_arm_get_virtual_time: + * @cs: CPUState + * + * Gets the VCPU's virtual counter and stores it in the KVM CPU state. + */ +void kvm_arm_get_virtual_time(CPUState *cs); + +/** + * kvm_arm_put_virtual_time: + * @cs: CPUState + * + * Sets the VCPU's virtual counter to the value stored in the KVM CPU state. + */ +void kvm_arm_put_virtual_time(CPUState *cs); + +void kvm_arm_vm_state_change(void *opaque, int running, RunState state); + int kvm_arm_vgic_probe(void); void kvm_arm_pmu_set_irq(CPUState *cs, int irq); @@ -292,13 +346,16 @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu) { - /* This should never actually be called in the "not KVM" case, + /* + * 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(CPUState *cs) { return false; @@ -328,6 +385,9 @@ static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq) {} static inline void kvm_arm_pmu_init(CPUState *cs) {} static inline void kvm_arm_sve_get_vls(CPUState *cs, unsigned long *map) {} + +static inline void kvm_arm_get_virtual_time(CPUState *cs) {} +static inline void kvm_arm_put_virtual_time(CPUState *cs) {} #endif static inline const char *gic_class_name(void) @@ -377,23 +437,20 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit); * * Return: TRUE if any hardware breakpoints in use. */ - bool kvm_arm_hw_debug_active(CPUState *cs); /** * kvm_arm_copy_hw_debug_data: - * * @ptr: kvm_guest_debug_arch structure * * Copy the architecture specific debug registers into the * kvm_guest_debug ioctl structure. */ struct kvm_guest_debug_arch; - void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr); /** - * its_class_name + * its_class_name: * * Return the ITS class name to use depending on whether KVM acceleration * and KVM CAP_SIGNAL_MSI are supported diff --git a/target/arm/machine.c b/target/arm/machine.c index eb28b23..241890a 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -642,6 +642,12 @@ static int cpu_pre_save(void *opaque) /* This should never fail */ abort(); } + + /* + * kvm_arm_cpu_pre_save() must be called after + * write_kvmstate_to_list() + */ + kvm_arm_cpu_pre_save(cpu); } else { if (!write_cpustate_to_list(cpu, false)) { /* This should never fail. */ @@ -744,6 +750,7 @@ static int cpu_post_load(void *opaque, int version_id) * we're using it. */ write_list_to_cpustate(cpu); + kvm_arm_cpu_post_load(cpu); } else { if (!write_list_to_cpustate(cpu)) { return -1; diff --git a/target/arm/monitor.c b/target/arm/monitor.c index fa054f8..9725dff 100644 --- a/target/arm/monitor.c +++ b/target/arm/monitor.c @@ -103,6 +103,7 @@ static const char *cpu_model_advertised_features[] = { "sve128", "sve256", "sve384", "sve512", "sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280", "sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048", + "kvm-no-adjvtime", NULL }; |