mirror of https://github.com/xemu-project/xemu.git
target-arm queue:
* arm/kvm: drop the split between "common KVM support" and "64-bit KVM support", since 32-bit Arm KVM no longer exists * arm/kvm: clean up APIs to be consistent about CPU arguments * Don't implement *32_EL2 registers when EL1 is AArch64 only * Restrict DC CVAP & DC CVADP instructions to TCG accel * Restrict TCG specific helpers * Propagate MDCR_EL2.HPMN into PMCR_EL0.N * Include missing 'exec/exec-all.h' header * fsl-imx: add simple RTC emulation for i.MX6 and i.MX7 boards -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmWB6o0ZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3mxMEACRpRxJ81pLs8fFYC5BgRhU BCxr+ZqarBygzsH9YWUN2TFFKlEZi7mLu6lzFsfN/qEmYCg8VslPbulQHqcGkx51 kVxXFp/KuGlKt4zGRagZUJxgYAwwU5mnK6dTZT5/ZF6yWX67dXn8V7MP9lqqEPw5 5gut7Mu4f7MiAQbwZY1CWP+iu5uZmdsBuKxA6zkxOWJh/A1SfaqQRO6xVQttLAxS DPMTpQGmwPS4I+3gGNnqlSu6etp2tdy2K0cW3fhMp6hx70uNMHmFNzRhT/6TaKka 9AqXQsFHQiFXDGAm6PmCvfQI6KpLljDyNL/TuUkQWi72bGEHjUsJAdG0aXVOa30W uC7vuJkdZrP/t5P1AkZhWQUrlawDRV2YHNDD+gY4fxJL/STkGyU6M8R1nm1J+InN n0SeK0VHRC6DRPXCMQhC5QwKUH6ZjFZRs/r2opTu9p+ThQAQRmZBiVfdISCDMYnN DCiSb78gIFaUkwtiP44qq8MJQjsHnXtTD1Akqyo2fXSKs66jDK9Gnc8gENYdpghe 7V36bOp6scROHOB2a/r8gT42RKzSN6uh6xByaaToza63/bPgvHnn8vvQQbB01AgX zJC1xs3dwY8JMyqDefda0K0NDPS8TzNsXYmgxxxcQJpUvB4VVjet9VIMF3T+d8HO Pas41Z1gsQY+rcaRk/9mPA== =GWIA -----END PGP SIGNATURE----- Merge tag 'pull-target-arm-20231219' of https://git.linaro.org/people/pmaydell/qemu-arm into staging target-arm queue: * arm/kvm: drop the split between "common KVM support" and "64-bit KVM support", since 32-bit Arm KVM no longer exists * arm/kvm: clean up APIs to be consistent about CPU arguments * Don't implement *32_EL2 registers when EL1 is AArch64 only * Restrict DC CVAP & DC CVADP instructions to TCG accel * Restrict TCG specific helpers * Propagate MDCR_EL2.HPMN into PMCR_EL0.N * Include missing 'exec/exec-all.h' header * fsl-imx: add simple RTC emulation for i.MX6 and i.MX7 boards # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmWB6o0ZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3mxMEACRpRxJ81pLs8fFYC5BgRhU # BCxr+ZqarBygzsH9YWUN2TFFKlEZi7mLu6lzFsfN/qEmYCg8VslPbulQHqcGkx51 # kVxXFp/KuGlKt4zGRagZUJxgYAwwU5mnK6dTZT5/ZF6yWX67dXn8V7MP9lqqEPw5 # 5gut7Mu4f7MiAQbwZY1CWP+iu5uZmdsBuKxA6zkxOWJh/A1SfaqQRO6xVQttLAxS # DPMTpQGmwPS4I+3gGNnqlSu6etp2tdy2K0cW3fhMp6hx70uNMHmFNzRhT/6TaKka # 9AqXQsFHQiFXDGAm6PmCvfQI6KpLljDyNL/TuUkQWi72bGEHjUsJAdG0aXVOa30W # uC7vuJkdZrP/t5P1AkZhWQUrlawDRV2YHNDD+gY4fxJL/STkGyU6M8R1nm1J+InN # n0SeK0VHRC6DRPXCMQhC5QwKUH6ZjFZRs/r2opTu9p+ThQAQRmZBiVfdISCDMYnN # DCiSb78gIFaUkwtiP44qq8MJQjsHnXtTD1Akqyo2fXSKs66jDK9Gnc8gENYdpghe # 7V36bOp6scROHOB2a/r8gT42RKzSN6uh6xByaaToza63/bPgvHnn8vvQQbB01AgX # zJC1xs3dwY8JMyqDefda0K0NDPS8TzNsXYmgxxxcQJpUvB4VVjet9VIMF3T+d8HO # Pas41Z1gsQY+rcaRk/9mPA== # =GWIA # -----END PGP SIGNATURE----- # gpg: Signature made Tue 19 Dec 2023 14:10:05 EST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [unknown] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20231219' of https://git.linaro.org/people/pmaydell/qemu-arm: (43 commits) fsl-imx: add simple RTC emulation for i.MX6 and i.MX7 boards target/arm/helper: Propagate MDCR_EL2.HPMN into PMCR_EL0.N target/arm/tcg: Including missing 'exec/exec-all.h' header target/arm: Restrict DC CVAP & DC CVADP instructions to TCG accel target/arm: Restrict TCG specific helpers target/arm: Don't implement *32_EL2 registers when EL1 is AArch64 only target/arm/kvm: Have kvm_arm_hw_debug_active take a ARMCPU argument target/arm/kvm: Have kvm_arm_handle_debug take a ARMCPU argument target/arm/kvm: Have kvm_arm_handle_dabt_nisv take a ARMCPU argument target/arm/kvm: Have kvm_arm_verify_ext_dabt_pending take a ARMCPU arg target/arm/kvm: Have kvm_arm_[get|put]_virtual_time take ARMCPU argument target/arm/kvm: Have kvm_arm_vcpu_finalize take a ARMCPU argument target/arm/kvm: Have kvm_arm_vcpu_init take a ARMCPU argument target/arm/kvm: Have kvm_arm_pmu_set_irq take a ARMCPU argument target/arm/kvm: Have kvm_arm_pmu_init take a ARMCPU argument target/arm/kvm: Have kvm_arm_pvtime_init take a ARMCPU argument target/arm/kvm: Have kvm_arm_set_device_attr take a ARMCPU argument target/arm/kvm: Have kvm_arm_sve_get_vls take a ARMCPU argument target/arm/kvm: Have kvm_arm_sve_set_vls take a ARMCPU argument target/arm/kvm: Have kvm_arm_add_vcpu_properties take a ARMCPU argument ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
63d6632512
|
@ -98,7 +98,7 @@ bool kvm_allowed;
|
||||||
bool kvm_readonly_mem_allowed;
|
bool kvm_readonly_mem_allowed;
|
||||||
bool kvm_vm_attributes_allowed;
|
bool kvm_vm_attributes_allowed;
|
||||||
bool kvm_msi_use_devid;
|
bool kvm_msi_use_devid;
|
||||||
bool kvm_has_guest_debug;
|
static bool kvm_has_guest_debug;
|
||||||
static int kvm_sstep_flags;
|
static int kvm_sstep_flags;
|
||||||
static bool kvm_immediate_exit;
|
static bool kvm_immediate_exit;
|
||||||
static hwaddr kvm_max_slot_size = ~0;
|
static hwaddr kvm_max_slot_size = ~0;
|
||||||
|
|
|
@ -1998,13 +1998,14 @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
|
||||||
if (pmu) {
|
if (pmu) {
|
||||||
assert(arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_PMU));
|
assert(arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_PMU));
|
||||||
if (kvm_irqchip_in_kernel()) {
|
if (kvm_irqchip_in_kernel()) {
|
||||||
kvm_arm_pmu_set_irq(cpu, VIRTUAL_PMU_IRQ);
|
kvm_arm_pmu_set_irq(ARM_CPU(cpu), VIRTUAL_PMU_IRQ);
|
||||||
}
|
}
|
||||||
kvm_arm_pmu_init(cpu);
|
kvm_arm_pmu_init(ARM_CPU(cpu));
|
||||||
}
|
}
|
||||||
if (steal_time) {
|
if (steal_time) {
|
||||||
kvm_arm_pvtime_init(cpu, pvtime_reg_base +
|
kvm_arm_pvtime_init(ARM_CPU(cpu), pvtime_reg_base
|
||||||
cpu->cpu_index * PVTIME_SIZE_PER_CPU);
|
+ cpu->cpu_index
|
||||||
|
* PVTIME_SIZE_PER_CPU);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "hw/intc/arm_gicv3_its_common.h"
|
#include "hw/intc/arm_gicv3_its_common.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
#include "sysemu/runstate.h"
|
#include "sysemu/runstate.h"
|
||||||
|
|
|
@ -13,28 +13,100 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/bitops.h"
|
||||||
|
#include "qemu/timer.h"
|
||||||
|
#include "migration/vmstate.h"
|
||||||
#include "hw/misc/imx7_snvs.h"
|
#include "hw/misc/imx7_snvs.h"
|
||||||
|
#include "qemu/cutils.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "sysemu/rtc.h"
|
||||||
#include "sysemu/runstate.h"
|
#include "sysemu/runstate.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
|
#define RTC_FREQ 32768ULL
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_imx7_snvs = {
|
||||||
|
.name = TYPE_IMX7_SNVS,
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_UINT64(tick_offset, IMX7SNVSState),
|
||||||
|
VMSTATE_UINT64(lpcr, IMX7SNVSState),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint64_t imx7_snvs_get_count(IMX7SNVSState *s)
|
||||||
|
{
|
||||||
|
uint64_t ticks = muldiv64(qemu_clock_get_ns(rtc_clock), RTC_FREQ,
|
||||||
|
NANOSECONDS_PER_SECOND);
|
||||||
|
return s->tick_offset + ticks;
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size)
|
static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
{
|
{
|
||||||
trace_imx7_snvs_read(offset, 0);
|
IMX7SNVSState *s = IMX7_SNVS(opaque);
|
||||||
|
uint64_t ret = 0;
|
||||||
|
|
||||||
return 0;
|
switch (offset) {
|
||||||
|
case SNVS_LPSRTCMR:
|
||||||
|
ret = extract64(imx7_snvs_get_count(s), 32, 15);
|
||||||
|
break;
|
||||||
|
case SNVS_LPSRTCLR:
|
||||||
|
ret = extract64(imx7_snvs_get_count(s), 0, 32);
|
||||||
|
break;
|
||||||
|
case SNVS_LPCR:
|
||||||
|
ret = s->lpcr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_imx7_snvs_read(offset, ret, size);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void imx7_snvs_reset(DeviceState *dev)
|
||||||
|
{
|
||||||
|
IMX7SNVSState *s = IMX7_SNVS(dev);
|
||||||
|
|
||||||
|
s->lpcr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void imx7_snvs_write(void *opaque, hwaddr offset,
|
static void imx7_snvs_write(void *opaque, hwaddr offset,
|
||||||
uint64_t v, unsigned size)
|
uint64_t v, unsigned size)
|
||||||
{
|
{
|
||||||
const uint32_t value = v;
|
trace_imx7_snvs_write(offset, v, size);
|
||||||
const uint32_t mask = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
|
|
||||||
|
|
||||||
trace_imx7_snvs_write(offset, value);
|
IMX7SNVSState *s = IMX7_SNVS(opaque);
|
||||||
|
|
||||||
if (offset == SNVS_LPCR && ((value & mask) == mask)) {
|
uint64_t new_value = 0, snvs_count = 0;
|
||||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
|
||||||
|
if (offset == SNVS_LPSRTCMR || offset == SNVS_LPSRTCLR) {
|
||||||
|
snvs_count = imx7_snvs_get_count(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (offset) {
|
||||||
|
case SNVS_LPSRTCMR:
|
||||||
|
new_value = deposit64(snvs_count, 32, 32, v);
|
||||||
|
break;
|
||||||
|
case SNVS_LPSRTCLR:
|
||||||
|
new_value = deposit64(snvs_count, 0, 32, v);
|
||||||
|
break;
|
||||||
|
case SNVS_LPCR: {
|
||||||
|
s->lpcr = v;
|
||||||
|
|
||||||
|
const uint32_t mask = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
|
||||||
|
|
||||||
|
if ((v & mask) == mask) {
|
||||||
|
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == SNVS_LPSRTCMR || offset == SNVS_LPSRTCLR) {
|
||||||
|
s->tick_offset += new_value - snvs_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,17 +131,24 @@ static void imx7_snvs_init(Object *obj)
|
||||||
{
|
{
|
||||||
SysBusDevice *sd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sd = SYS_BUS_DEVICE(obj);
|
||||||
IMX7SNVSState *s = IMX7_SNVS(obj);
|
IMX7SNVSState *s = IMX7_SNVS(obj);
|
||||||
|
struct tm tm;
|
||||||
|
|
||||||
memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s,
|
memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s,
|
||||||
TYPE_IMX7_SNVS, 0x1000);
|
TYPE_IMX7_SNVS, 0x1000);
|
||||||
|
|
||||||
sysbus_init_mmio(sd, &s->mmio);
|
sysbus_init_mmio(sd, &s->mmio);
|
||||||
|
|
||||||
|
qemu_get_timedate(&tm, 0);
|
||||||
|
s->tick_offset = mktimegm(&tm) -
|
||||||
|
qemu_clock_get_ns(rtc_clock) / NANOSECONDS_PER_SECOND;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void imx7_snvs_class_init(ObjectClass *klass, void *data)
|
static void imx7_snvs_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
|
dc->reset = imx7_snvs_reset;
|
||||||
|
dc->vmsd = &vmstate_imx7_snvs;
|
||||||
dc->desc = "i.MX7 Secure Non-Volatile Storage Module";
|
dc->desc = "i.MX7 Secure Non-Volatile Storage Module";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,8 +116,8 @@ imx7_gpr_read(uint64_t offset) "addr 0x%08" PRIx64
|
||||||
imx7_gpr_write(uint64_t offset, uint64_t value) "addr 0x%08" PRIx64 "value 0x%08" PRIx64
|
imx7_gpr_write(uint64_t offset, uint64_t value) "addr 0x%08" PRIx64 "value 0x%08" PRIx64
|
||||||
|
|
||||||
# imx7_snvs.c
|
# imx7_snvs.c
|
||||||
imx7_snvs_read(uint64_t offset, uint32_t value) "addr 0x%08" PRIx64 "value 0x%08" PRIx32
|
imx7_snvs_read(uint64_t offset, uint64_t value, unsigned size) "i.MX SNVS read: offset 0x%08" PRIx64 " value 0x%08" PRIx64 " size %u"
|
||||||
imx7_snvs_write(uint64_t offset, uint32_t value) "addr 0x%08" PRIx64 "value 0x%08" PRIx32
|
imx7_snvs_write(uint64_t offset, uint64_t value, unsigned size) "i.MX SNVS write: offset 0x%08" PRIx64 " value 0x%08" PRIx64 " size %u"
|
||||||
|
|
||||||
# mos6522.c
|
# mos6522.c
|
||||||
mos6522_set_counter(int index, unsigned int val) "T%d.counter=%d"
|
mos6522_set_counter(int index, unsigned int val) "T%d.counter=%d"
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
enum IMX7SNVSRegisters {
|
enum IMX7SNVSRegisters {
|
||||||
SNVS_LPCR = 0x38,
|
SNVS_LPCR = 0x38,
|
||||||
SNVS_LPCR_TOP = BIT(6),
|
SNVS_LPCR_TOP = BIT(6),
|
||||||
SNVS_LPCR_DP_EN = BIT(5)
|
SNVS_LPCR_DP_EN = BIT(5),
|
||||||
|
SNVS_LPSRTCMR = 0x050, /* Secure Real Time Counter MSB Register */
|
||||||
|
SNVS_LPSRTCLR = 0x054, /* Secure Real Time Counter LSB Register */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TYPE_IMX7_SNVS "imx7.snvs"
|
#define TYPE_IMX7_SNVS "imx7.snvs"
|
||||||
|
@ -31,6 +33,9 @@ struct IMX7SNVSState {
|
||||||
SysBusDevice parent_obj;
|
SysBusDevice parent_obj;
|
||||||
|
|
||||||
MemoryRegion mmio;
|
MemoryRegion mmio;
|
||||||
|
|
||||||
|
uint64_t tick_offset;
|
||||||
|
uint64_t lpcr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* IMX7_SNVS_H */
|
#endif /* IMX7_SNVS_H */
|
||||||
|
|
|
@ -1686,7 +1686,7 @@ void arm_cpu_post_init(Object *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
kvm_arm_add_vcpu_properties(obj);
|
kvm_arm_add_vcpu_properties(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
|
|
@ -66,7 +66,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
|
||||||
*/
|
*/
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
if (kvm_arm_sve_supported()) {
|
if (kvm_arm_sve_supported()) {
|
||||||
cpu->sve_vq.supported = kvm_arm_sve_get_vls(CPU(cpu));
|
cpu->sve_vq.supported = kvm_arm_sve_get_vls(cpu);
|
||||||
vq_supported = cpu->sve_vq.supported;
|
vq_supported = cpu->sve_vq.supported;
|
||||||
} else {
|
} else {
|
||||||
assert(!cpu_isar_feature(aa64_sve, cpu));
|
assert(!cpu_isar_feature(aa64_sve, cpu));
|
||||||
|
|
|
@ -1026,14 +1026,6 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
|
||||||
.cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
|
.cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
|
||||||
.access = PL1_RW, .accessfn = access_tda,
|
.access = PL1_RW, .accessfn = access_tda,
|
||||||
.type = ARM_CP_NOP },
|
.type = ARM_CP_NOP },
|
||||||
/*
|
|
||||||
* Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor
|
|
||||||
* to save and restore a 32-bit guest's DBGVCR)
|
|
||||||
*/
|
|
||||||
{ .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
|
|
||||||
.opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
|
|
||||||
.access = PL2_RW, .accessfn = access_tda,
|
|
||||||
.type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
|
|
||||||
/*
|
/*
|
||||||
* Dummy MDCCINT_EL1, since we don't implement the Debug Communications
|
* Dummy MDCCINT_EL1, since we don't implement the Debug Communications
|
||||||
* Channel but Linux may try to access this register. The 32-bit
|
* Channel but Linux may try to access this register. The 32-bit
|
||||||
|
@ -1062,6 +1054,18 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
|
||||||
.fieldoffset = offsetof(CPUARMState, cp15.dbgclaim) },
|
.fieldoffset = offsetof(CPUARMState, cp15.dbgclaim) },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* These are present only when EL1 supports AArch32 */
|
||||||
|
static const ARMCPRegInfo debug_aa32_el1_reginfo[] = {
|
||||||
|
/*
|
||||||
|
* Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor
|
||||||
|
* to save and restore a 32-bit guest's DBGVCR)
|
||||||
|
*/
|
||||||
|
{ .name = "DBGVCR32_EL2", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 2, .opc1 = 4, .crn = 0, .crm = 7, .opc2 = 0,
|
||||||
|
.access = PL2_RW, .accessfn = access_tda,
|
||||||
|
.type = ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP },
|
||||||
|
};
|
||||||
|
|
||||||
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
|
static const ARMCPRegInfo debug_lpae_cp_reginfo[] = {
|
||||||
/* 64 bit access versions of the (dummy) debug registers */
|
/* 64 bit access versions of the (dummy) debug registers */
|
||||||
{ .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0,
|
{ .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0,
|
||||||
|
@ -1207,6 +1211,9 @@ void define_debug_regs(ARMCPU *cpu)
|
||||||
assert(ctx_cmps <= brps);
|
assert(ctx_cmps <= brps);
|
||||||
|
|
||||||
define_arm_cp_regs(cpu, debug_cp_reginfo);
|
define_arm_cp_regs(cpu, debug_cp_reginfo);
|
||||||
|
if (cpu_isar_feature(aa64_aa32_el1, cpu)) {
|
||||||
|
define_arm_cp_regs(cpu, debug_aa32_el1_reginfo);
|
||||||
|
}
|
||||||
|
|
||||||
if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
|
if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) {
|
||||||
define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);
|
define_arm_cp_regs(cpu, debug_lpae_cp_reginfo);
|
||||||
|
|
|
@ -1475,6 +1475,22 @@ static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
pmu_op_finish(env);
|
pmu_op_finish(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t pmcr_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||||
|
{
|
||||||
|
uint64_t pmcr = env->cp15.c9_pmcr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If EL2 is implemented and enabled for the current security state, reads
|
||||||
|
* of PMCR.N from EL1 or EL0 return the value of MDCR_EL2.HPMN or HDCR.HPMN.
|
||||||
|
*/
|
||||||
|
if (arm_current_el(env) <= 1 && arm_is_el2_enabled(env)) {
|
||||||
|
pmcr &= ~PMCRN_MASK;
|
||||||
|
pmcr |= (env->cp15.mdcr_el2 & MDCR_HPMN) << PMCRN_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pmcr;
|
||||||
|
}
|
||||||
|
|
||||||
static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
uint64_t value)
|
uint64_t value)
|
||||||
{
|
{
|
||||||
|
@ -5698,20 +5714,6 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
|
||||||
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 0,
|
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 0,
|
||||||
.type = ARM_CP_NO_RAW,
|
.type = ARM_CP_NO_RAW,
|
||||||
.access = PL1_RW, .readfn = spsel_read, .writefn = spsel_write },
|
.access = PL1_RW, .readfn = spsel_read, .writefn = spsel_write },
|
||||||
{ .name = "FPEXC32_EL2", .state = ARM_CP_STATE_AA64,
|
|
||||||
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 3, .opc2 = 0,
|
|
||||||
.access = PL2_RW,
|
|
||||||
.type = ARM_CP_ALIAS | ARM_CP_FPU | ARM_CP_EL3_NO_EL2_KEEP,
|
|
||||||
.fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) },
|
|
||||||
{ .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64,
|
|
||||||
.opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0,
|
|
||||||
.access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
|
|
||||||
.writefn = dacr_write, .raw_writefn = raw_write,
|
|
||||||
.fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) },
|
|
||||||
{ .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64,
|
|
||||||
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1,
|
|
||||||
.access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
|
|
||||||
.fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) },
|
|
||||||
{ .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64,
|
{ .name = "SPSR_IRQ", .state = ARM_CP_STATE_AA64,
|
||||||
.type = ARM_CP_ALIAS,
|
.type = ARM_CP_ALIAS,
|
||||||
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0,
|
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 3, .opc2 = 0,
|
||||||
|
@ -5746,6 +5748,24 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
|
||||||
.fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
|
.fieldoffset = offsetoflow32(CPUARMState, cp15.mdcr_el3) },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* These are present only when EL1 supports AArch32 */
|
||||||
|
static const ARMCPRegInfo v8_aa32_el1_reginfo[] = {
|
||||||
|
{ .name = "FPEXC32_EL2", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 3, .opc2 = 0,
|
||||||
|
.access = PL2_RW,
|
||||||
|
.type = ARM_CP_ALIAS | ARM_CP_FPU | ARM_CP_EL3_NO_EL2_KEEP,
|
||||||
|
.fieldoffset = offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) },
|
||||||
|
{ .name = "DACR32_EL2", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 3, .opc1 = 4, .crn = 3, .crm = 0, .opc2 = 0,
|
||||||
|
.access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
|
||||||
|
.writefn = dacr_write, .raw_writefn = raw_write,
|
||||||
|
.fieldoffset = offsetof(CPUARMState, cp15.dacr32_el2) },
|
||||||
|
{ .name = "IFSR32_EL2", .state = ARM_CP_STATE_AA64,
|
||||||
|
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 0, .opc2 = 1,
|
||||||
|
.access = PL2_RW, .resetvalue = 0, .type = ARM_CP_EL3_NO_EL2_KEEP,
|
||||||
|
.fieldoffset = offsetof(CPUARMState, cp15.ifsr32_el2) },
|
||||||
|
};
|
||||||
|
|
||||||
static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
|
static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_mask)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
@ -7154,8 +7174,9 @@ static void define_pmu_regs(ARMCPU *cpu)
|
||||||
.fgt = FGT_PMCR_EL0,
|
.fgt = FGT_PMCR_EL0,
|
||||||
.type = ARM_CP_IO | ARM_CP_ALIAS,
|
.type = ARM_CP_IO | ARM_CP_ALIAS,
|
||||||
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
|
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
|
||||||
.accessfn = pmreg_access, .writefn = pmcr_write,
|
.accessfn = pmreg_access,
|
||||||
.raw_writefn = raw_write,
|
.readfn = pmcr_read, .raw_readfn = raw_read,
|
||||||
|
.writefn = pmcr_write, .raw_writefn = raw_write,
|
||||||
};
|
};
|
||||||
ARMCPRegInfo pmcr64 = {
|
ARMCPRegInfo pmcr64 = {
|
||||||
.name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
|
.name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
|
||||||
|
@ -7165,6 +7186,7 @@ static void define_pmu_regs(ARMCPU *cpu)
|
||||||
.type = ARM_CP_IO,
|
.type = ARM_CP_IO,
|
||||||
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
|
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
|
||||||
.resetvalue = cpu->isar.reset_pmcr_el0,
|
.resetvalue = cpu->isar.reset_pmcr_el0,
|
||||||
|
.readfn = pmcr_read, .raw_readfn = raw_read,
|
||||||
.writefn = pmcr_write, .raw_writefn = raw_write,
|
.writefn = pmcr_write, .raw_writefn = raw_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7645,6 +7667,7 @@ static const ARMCPRegInfo rndr_reginfo[] = {
|
||||||
static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
|
static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
|
||||||
uint64_t value)
|
uint64_t value)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_TCG
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
/* CTR_EL0 System register -> DminLine, bits [19:16] */
|
/* CTR_EL0 System register -> DminLine, bits [19:16] */
|
||||||
uint64_t dline_size = 4 << ((cpu->ctr >> 16) & 0xF);
|
uint64_t dline_size = 4 << ((cpu->ctr >> 16) & 0xF);
|
||||||
|
@ -7669,6 +7692,10 @@ static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque,
|
||||||
}
|
}
|
||||||
#endif /*CONFIG_USER_ONLY*/
|
#endif /*CONFIG_USER_ONLY*/
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
/* Handled by hardware accelerator. */
|
||||||
|
g_assert_not_reached();
|
||||||
|
#endif /* CONFIG_TCG */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ARMCPRegInfo dcpop_reg[] = {
|
static const ARMCPRegInfo dcpop_reg[] = {
|
||||||
|
@ -8716,6 +8743,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
|
||||||
}
|
}
|
||||||
define_arm_cp_regs(cpu, v8_idregs);
|
define_arm_cp_regs(cpu, v8_idregs);
|
||||||
define_arm_cp_regs(cpu, v8_cp_reginfo);
|
define_arm_cp_regs(cpu, v8_cp_reginfo);
|
||||||
|
if (cpu_isar_feature(aa64_aa32_el1, cpu)) {
|
||||||
|
define_arm_cp_regs(cpu, v8_aa32_el1_reginfo);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 4; i < 16; i++) {
|
for (i = 4; i < 16; i++) {
|
||||||
/*
|
/*
|
||||||
|
@ -10135,61 +10165,6 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sign/zero extend */
|
|
||||||
uint32_t HELPER(sxtb16)(uint32_t x)
|
|
||||||
{
|
|
||||||
uint32_t res;
|
|
||||||
res = (uint16_t)(int8_t)x;
|
|
||||||
res |= (uint32_t)(int8_t)(x >> 16) << 16;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_possible_div0_trap(CPUARMState *env, uintptr_t ra)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Take a division-by-zero exception if necessary; otherwise return
|
|
||||||
* to get the usual non-trapping division behaviour (result of 0)
|
|
||||||
*/
|
|
||||||
if (arm_feature(env, ARM_FEATURE_M)
|
|
||||||
&& (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_DIV_0_TRP_MASK)) {
|
|
||||||
raise_exception_ra(env, EXCP_DIVBYZERO, 0, 1, ra);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t HELPER(uxtb16)(uint32_t x)
|
|
||||||
{
|
|
||||||
uint32_t res;
|
|
||||||
res = (uint16_t)(uint8_t)x;
|
|
||||||
res |= (uint32_t)(uint8_t)(x >> 16) << 16;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t HELPER(sdiv)(CPUARMState *env, int32_t num, int32_t den)
|
|
||||||
{
|
|
||||||
if (den == 0) {
|
|
||||||
handle_possible_div0_trap(env, GETPC());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (num == INT_MIN && den == -1) {
|
|
||||||
return INT_MIN;
|
|
||||||
}
|
|
||||||
return num / den;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t HELPER(udiv)(CPUARMState *env, uint32_t num, uint32_t den)
|
|
||||||
{
|
|
||||||
if (den == 0) {
|
|
||||||
handle_possible_div0_trap(env, GETPC());
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return num / den;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t HELPER(rbit)(uint32_t x)
|
|
||||||
{
|
|
||||||
return revbit32(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
|
||||||
static void switch_mode(CPUARMState *env, int mode)
|
static void switch_mode(CPUARMState *env, int mode)
|
||||||
|
|
1409
target/arm/kvm.c
1409
target/arm/kvm.c
File diff suppressed because it is too large
Load Diff
1290
target/arm/kvm64.c
1290
target/arm/kvm64.c
File diff suppressed because it is too large
Load Diff
|
@ -12,46 +12,10 @@
|
||||||
#define QEMU_KVM_ARM_H
|
#define QEMU_KVM_ARM_H
|
||||||
|
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "exec/memory.h"
|
|
||||||
#include "qemu/error-report.h"
|
|
||||||
|
|
||||||
#define KVM_ARM_VGIC_V2 (1 << 0)
|
#define KVM_ARM_VGIC_V2 (1 << 0)
|
||||||
#define KVM_ARM_VGIC_V3 (1 << 1)
|
#define KVM_ARM_VGIC_V3 (1 << 1)
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_arm_init_debug() - initialize guest debug capabilities
|
|
||||||
* @s: KVMState
|
|
||||||
*
|
|
||||||
* Should be called only once before using guest debug capabilities.
|
|
||||||
*/
|
|
||||||
void kvm_arm_init_debug(KVMState *s);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_arm_vcpu_init:
|
|
||||||
* @cs: CPUState
|
|
||||||
*
|
|
||||||
* Initialize (or reinitialize) the VCPU by invoking the
|
|
||||||
* KVM_ARM_VCPU_INIT ioctl with the CPU type and feature
|
|
||||||
* bitmask specified in the CPUState.
|
|
||||||
*
|
|
||||||
* Returns: 0 if success else < 0 error code
|
|
||||||
*/
|
|
||||||
int kvm_arm_vcpu_init(CPUState *cs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_arm_vcpu_finalize:
|
|
||||||
* @cs: CPUState
|
|
||||||
* @feature: feature to finalize
|
|
||||||
*
|
|
||||||
* Finalizes the configuration of the specified VCPU feature by
|
|
||||||
* invoking the KVM_ARM_VCPU_FINALIZE ioctl. Features requiring
|
|
||||||
* this are documented in the "KVM_ARM_VCPU_FINALIZE" section of
|
|
||||||
* KVM's API documentation.
|
|
||||||
*
|
|
||||||
* Returns: 0 if success else < 0 error code
|
|
||||||
*/
|
|
||||||
int kvm_arm_vcpu_finalize(CPUState *cs, int feature);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kvm_arm_register_device:
|
* kvm_arm_register_device:
|
||||||
* @mr: memory region for this device
|
* @mr: memory region for this device
|
||||||
|
@ -73,37 +37,6 @@ int kvm_arm_vcpu_finalize(CPUState *cs, int feature);
|
||||||
void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
|
void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
|
||||||
uint64_t attr, int dev_fd, uint64_t addr_ormask);
|
uint64_t attr, int dev_fd, uint64_t addr_ormask);
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_arm_init_cpreg_list:
|
|
||||||
* @cpu: ARMCPU
|
|
||||||
*
|
|
||||||
* 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).
|
|
||||||
*
|
|
||||||
* Returns: 0 if success, else < 0 error code
|
|
||||||
*/
|
|
||||||
int kvm_arm_init_cpreg_list(ARMCPU *cpu);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
* by hand using code in kvm_arch_get/put_registers().
|
|
||||||
*/
|
|
||||||
bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
int kvm_arm_cpreg_level(uint64_t regidx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write_list_to_kvmstate:
|
* write_list_to_kvmstate:
|
||||||
* @cpu: ARMCPU
|
* @cpu: ARMCPU
|
||||||
|
@ -163,34 +96,6 @@ void kvm_arm_cpu_post_load(ARMCPU *cpu);
|
||||||
*/
|
*/
|
||||||
void kvm_arm_reset_vcpu(ARMCPU *cpu);
|
void kvm_arm_reset_vcpu(ARMCPU *cpu);
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_arm_init_serror_injection:
|
|
||||||
* @cs: CPUState
|
|
||||||
*
|
|
||||||
* Check whether KVM can set guest SError syndrome.
|
|
||||||
*/
|
|
||||||
void kvm_arm_init_serror_injection(CPUState *cs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_get_vcpu_events:
|
|
||||||
* @cpu: ARMCPU
|
|
||||||
*
|
|
||||||
* Get VCPU related state from kvm.
|
|
||||||
*
|
|
||||||
* Returns: 0 if success else < 0 error code
|
|
||||||
*/
|
|
||||||
int kvm_get_vcpu_events(ARMCPU *cpu);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_put_vcpu_events:
|
|
||||||
* @cpu: ARMCPU
|
|
||||||
*
|
|
||||||
* Put VCPU related state to kvm.
|
|
||||||
*
|
|
||||||
* Returns: 0 if success else < 0 error code
|
|
||||||
*/
|
|
||||||
int kvm_put_vcpu_events(ARMCPU *cpu);
|
|
||||||
|
|
||||||
#ifdef CONFIG_KVM
|
#ifdef CONFIG_KVM
|
||||||
/**
|
/**
|
||||||
* kvm_arm_create_scratch_host_vcpu:
|
* kvm_arm_create_scratch_host_vcpu:
|
||||||
|
@ -222,37 +127,15 @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
|
||||||
*/
|
*/
|
||||||
void kvm_arm_destroy_scratch_host_vcpu(int *fdarray);
|
void kvm_arm_destroy_scratch_host_vcpu(int *fdarray);
|
||||||
|
|
||||||
/**
|
|
||||||
* ARMHostCPUFeatures: information about the host CPU (identified
|
|
||||||
* by asking the host kernel)
|
|
||||||
*/
|
|
||||||
typedef struct ARMHostCPUFeatures {
|
|
||||||
ARMISARegisters isar;
|
|
||||||
uint64_t features;
|
|
||||||
uint32_t target;
|
|
||||||
const char *dtb_compatible;
|
|
||||||
} ARMHostCPUFeatures;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_arm_get_host_cpu_features:
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kvm_arm_sve_get_vls:
|
* kvm_arm_sve_get_vls:
|
||||||
* @cs: CPUState
|
* @cpu: ARMCPU
|
||||||
*
|
*
|
||||||
* Get all the SVE vector lengths supported by the KVM host, setting
|
* Get all the SVE vector lengths supported by the KVM host, setting
|
||||||
* the bits corresponding to their length in quadwords minus one
|
* the bits corresponding to their length in quadwords minus one
|
||||||
* (vq - 1) up to ARM_MAX_VQ. Return the resulting map.
|
* (vq - 1) up to ARM_MAX_VQ. Return the resulting map.
|
||||||
*/
|
*/
|
||||||
uint32_t kvm_arm_sve_get_vls(CPUState *cs);
|
uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kvm_arm_set_cpu_features_from_host:
|
* kvm_arm_set_cpu_features_from_host:
|
||||||
|
@ -265,12 +148,12 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kvm_arm_add_vcpu_properties:
|
* kvm_arm_add_vcpu_properties:
|
||||||
* @obj: The CPU object to add the properties to
|
* @cpu: The CPU object to add the properties to
|
||||||
*
|
*
|
||||||
* Add all KVM specific CPU properties to the CPU object. These
|
* Add all KVM specific CPU properties to the CPU object. These
|
||||||
* are the CPU properties with "kvm-" prefixed names.
|
* are the CPU properties with "kvm-" prefixed names.
|
||||||
*/
|
*/
|
||||||
void kvm_arm_add_vcpu_properties(Object *obj);
|
void kvm_arm_add_vcpu_properties(ARMCPU *cpu);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kvm_arm_steal_time_finalize:
|
* kvm_arm_steal_time_finalize:
|
||||||
|
@ -282,14 +165,6 @@ void kvm_arm_add_vcpu_properties(Object *obj);
|
||||||
*/
|
*/
|
||||||
void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp);
|
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:
|
||||||
*
|
*
|
||||||
|
@ -323,57 +198,19 @@ bool kvm_arm_sve_supported(void);
|
||||||
*/
|
*/
|
||||||
int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa);
|
int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa);
|
||||||
|
|
||||||
/**
|
|
||||||
* 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:
|
|
||||||
* @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, bool running, RunState state);
|
|
||||||
|
|
||||||
int kvm_arm_vgic_probe(void);
|
int kvm_arm_vgic_probe(void);
|
||||||
|
|
||||||
void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
|
void kvm_arm_pmu_init(ARMCPU *cpu);
|
||||||
void kvm_arm_pmu_init(CPUState *cs);
|
void kvm_arm_pmu_set_irq(ARMCPU *cpu, int irq);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kvm_arm_pvtime_init:
|
* kvm_arm_pvtime_init:
|
||||||
* @cs: CPUState
|
* @cpu: ARMCPU
|
||||||
* @ipa: Per-vcpu guest physical base address of the pvtime structures
|
* @ipa: Per-vcpu guest physical base address of the pvtime structures
|
||||||
*
|
*
|
||||||
* Initializes PVTIME for the VCPU, setting the PVTIME IPA to @ipa.
|
* Initializes PVTIME for the VCPU, setting the PVTIME IPA to @ipa.
|
||||||
*/
|
*/
|
||||||
void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa);
|
void kvm_arm_pvtime_init(ARMCPU *cpu, 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);
|
||||||
|
|
||||||
|
@ -398,11 +235,6 @@ 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.
|
* These functions should never actually be called without KVM support.
|
||||||
*/
|
*/
|
||||||
|
@ -411,7 +243,7 @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void kvm_arm_add_vcpu_properties(Object *obj)
|
static inline void kvm_arm_add_vcpu_properties(ARMCPU *cpu)
|
||||||
{
|
{
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -426,17 +258,17 @@ static inline int kvm_arm_vgic_probe(void)
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void kvm_arm_pmu_set_irq(CPUState *cs, int irq)
|
static inline void kvm_arm_pmu_set_irq(ARMCPU *cpu, int irq)
|
||||||
{
|
{
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void kvm_arm_pmu_init(CPUState *cs)
|
static inline void kvm_arm_pmu_init(ARMCPU *cpu)
|
||||||
{
|
{
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void kvm_arm_pvtime_init(CPUState *cs, uint64_t ipa)
|
static inline void kvm_arm_pvtime_init(ARMCPU *cpu, uint64_t ipa)
|
||||||
{
|
{
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
@ -446,48 +278,11 @@ static inline void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp)
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t kvm_arm_sve_get_vls(CPUState *cs)
|
static inline uint32_t kvm_arm_sve_get_vls(ARMCPU *cpu)
|
||||||
{
|
{
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_arm_handle_debug:
|
|
||||||
* @cs: CPUState
|
|
||||||
* @debug_exit: debug part of the KVM exit structure
|
|
||||||
*
|
|
||||||
* Returns: TRUE if the debug exception was handled.
|
|
||||||
*/
|
|
||||||
bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_arm_hw_debug_active:
|
|
||||||
* @cs: CPU State
|
|
||||||
*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* kvm_arm_verify_ext_dabt_pending:
|
|
||||||
* @cs: CPUState
|
|
||||||
*
|
|
||||||
* Verify the fault status code wrt the Ext DABT injection
|
|
||||||
*
|
|
||||||
* Returns: true if the fault status code is as expected, false otherwise
|
|
||||||
*/
|
|
||||||
bool kvm_arm_verify_ext_dabt_pending(CPUState *cs);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,7 @@ arm_ss.add(files(
|
||||||
))
|
))
|
||||||
arm_ss.add(zlib)
|
arm_ss.add(zlib)
|
||||||
|
|
||||||
arm_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
|
arm_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c'), if_false: files('kvm-stub.c'))
|
||||||
arm_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
|
arm_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
|
||||||
|
|
||||||
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
|
arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
|
||||||
|
|
|
@ -121,6 +121,61 @@ void HELPER(v8m_stackcheck)(CPUARMState *env, uint32_t newvalue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sign/zero extend */
|
||||||
|
uint32_t HELPER(sxtb16)(uint32_t x)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
res = (uint16_t)(int8_t)x;
|
||||||
|
res |= (uint32_t)(int8_t)(x >> 16) << 16;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_possible_div0_trap(CPUARMState *env, uintptr_t ra)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Take a division-by-zero exception if necessary; otherwise return
|
||||||
|
* to get the usual non-trapping division behaviour (result of 0)
|
||||||
|
*/
|
||||||
|
if (arm_feature(env, ARM_FEATURE_M)
|
||||||
|
&& (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_DIV_0_TRP_MASK)) {
|
||||||
|
raise_exception_ra(env, EXCP_DIVBYZERO, 0, 1, ra);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t HELPER(uxtb16)(uint32_t x)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
res = (uint16_t)(uint8_t)x;
|
||||||
|
res |= (uint32_t)(uint8_t)(x >> 16) << 16;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t HELPER(sdiv)(CPUARMState *env, int32_t num, int32_t den)
|
||||||
|
{
|
||||||
|
if (den == 0) {
|
||||||
|
handle_possible_div0_trap(env, GETPC());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (num == INT_MIN && den == -1) {
|
||||||
|
return INT_MIN;
|
||||||
|
}
|
||||||
|
return num / den;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t HELPER(udiv)(CPUARMState *env, uint32_t num, uint32_t den)
|
||||||
|
{
|
||||||
|
if (den == 0) {
|
||||||
|
handle_possible_div0_trap(env, GETPC());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return num / den;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t HELPER(rbit)(uint32_t x)
|
||||||
|
{
|
||||||
|
return revbit32(x);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
|
uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b)
|
||||||
{
|
{
|
||||||
uint32_t res = a + b;
|
uint32_t res = a + b;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
|
#include "exec/exec-all.h"
|
||||||
#include "translate.h"
|
#include "translate.h"
|
||||||
#include "translate-a64.h"
|
#include "translate-a64.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
|
Loading…
Reference in New Issue