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_vm_attributes_allowed;
|
||||
bool kvm_msi_use_devid;
|
||||
bool kvm_has_guest_debug;
|
||||
static bool kvm_has_guest_debug;
|
||||
static int kvm_sstep_flags;
|
||||
static bool kvm_immediate_exit;
|
||||
static hwaddr kvm_max_slot_size = ~0;
|
||||
|
|
|
@ -1998,13 +1998,14 @@ static void virt_cpu_post_init(VirtMachineState *vms, MemoryRegion *sysmem)
|
|||
if (pmu) {
|
||||
assert(arm_feature(&ARM_CPU(cpu)->env, ARM_FEATURE_PMU));
|
||||
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) {
|
||||
kvm_arm_pvtime_init(cpu, pvtime_reg_base +
|
||||
cpu->cpu_index * PVTIME_SIZE_PER_CPU);
|
||||
kvm_arm_pvtime_init(ARM_CPU(cpu), pvtime_reg_base
|
||||
+ cpu->cpu_index
|
||||
* PVTIME_SIZE_PER_CPU);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/intc/arm_gicv3_its_common.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "sysemu/runstate.h"
|
||||
|
|
|
@ -13,28 +13,100 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/misc/imx7_snvs.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/module.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/rtc.h"
|
||||
#include "sysemu/runstate.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)
|
||||
{
|
||||
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,
|
||||
uint64_t v, unsigned size)
|
||||
{
|
||||
const uint32_t value = v;
|
||||
const uint32_t mask = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
|
||||
trace_imx7_snvs_write(offset, v, size);
|
||||
|
||||
trace_imx7_snvs_write(offset, value);
|
||||
IMX7SNVSState *s = IMX7_SNVS(opaque);
|
||||
|
||||
if (offset == SNVS_LPCR && ((value & mask) == mask)) {
|
||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
||||
uint64_t new_value = 0, snvs_count = 0;
|
||||
|
||||
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);
|
||||
IMX7SNVSState *s = IMX7_SNVS(obj);
|
||||
struct tm tm;
|
||||
|
||||
memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s,
|
||||
TYPE_IMX7_SNVS, 0x1000);
|
||||
|
||||
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)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->reset = imx7_snvs_reset;
|
||||
dc->vmsd = &vmstate_imx7_snvs;
|
||||
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_snvs.c
|
||||
imx7_snvs_read(uint64_t offset, uint32_t value) "addr 0x%08" PRIx64 "value 0x%08" PRIx32
|
||||
imx7_snvs_write(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, uint64_t value, unsigned size) "i.MX SNVS write: offset 0x%08" PRIx64 " value 0x%08" PRIx64 " size %u"
|
||||
|
||||
# mos6522.c
|
||||
mos6522_set_counter(int index, unsigned int val) "T%d.counter=%d"
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
enum IMX7SNVSRegisters {
|
||||
SNVS_LPCR = 0x38,
|
||||
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"
|
||||
|
@ -31,6 +33,9 @@ struct IMX7SNVSState {
|
|||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion mmio;
|
||||
|
||||
uint64_t tick_offset;
|
||||
uint64_t lpcr;
|
||||
};
|
||||
|
||||
#endif /* IMX7_SNVS_H */
|
||||
|
|
|
@ -1686,7 +1686,7 @@ void arm_cpu_post_init(Object *obj)
|
|||
}
|
||||
|
||||
if (kvm_enabled()) {
|
||||
kvm_arm_add_vcpu_properties(obj);
|
||||
kvm_arm_add_vcpu_properties(cpu);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
|
|
@ -66,7 +66,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
|
|||
*/
|
||||
if (kvm_enabled()) {
|
||||
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;
|
||||
} else {
|
||||
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,
|
||||
.access = PL1_RW, .accessfn = access_tda,
|
||||
.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
|
||||
* 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) },
|
||||
};
|
||||
|
||||
/* 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[] = {
|
||||
/* 64 bit access versions of the (dummy) debug registers */
|
||||
{ .name = "DBGDRAR", .cp = 14, .crm = 1, .opc1 = 0,
|
||||
|
@ -1207,6 +1211,9 @@ void define_debug_regs(ARMCPU *cpu)
|
|||
assert(ctx_cmps <= brps);
|
||||
|
||||
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)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
uint64_t value)
|
||||
{
|
||||
|
@ -5698,20 +5714,6 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
|
|||
.opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 0,
|
||||
.type = ARM_CP_NO_RAW,
|
||||
.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,
|
||||
.type = ARM_CP_ALIAS,
|
||||
.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) },
|
||||
};
|
||||
|
||||
/* 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)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
@ -7154,8 +7174,9 @@ static void define_pmu_regs(ARMCPU *cpu)
|
|||
.fgt = FGT_PMCR_EL0,
|
||||
.type = ARM_CP_IO | ARM_CP_ALIAS,
|
||||
.fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcr),
|
||||
.accessfn = pmreg_access, .writefn = pmcr_write,
|
||||
.raw_writefn = raw_write,
|
||||
.accessfn = pmreg_access,
|
||||
.readfn = pmcr_read, .raw_readfn = raw_read,
|
||||
.writefn = pmcr_write, .raw_writefn = raw_write,
|
||||
};
|
||||
ARMCPRegInfo pmcr64 = {
|
||||
.name = "PMCR_EL0", .state = ARM_CP_STATE_AA64,
|
||||
|
@ -7165,6 +7186,7 @@ static void define_pmu_regs(ARMCPU *cpu)
|
|||
.type = ARM_CP_IO,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.c9_pmcr),
|
||||
.resetvalue = cpu->isar.reset_pmcr_el0,
|
||||
.readfn = pmcr_read, .raw_readfn = raw_read,
|
||||
.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,
|
||||
uint64_t value)
|
||||
{
|
||||
#ifdef CONFIG_TCG
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
/* CTR_EL0 System register -> DminLine, bits [19:16] */
|
||||
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*/
|
||||
}
|
||||
#else
|
||||
/* Handled by hardware accelerator. */
|
||||
g_assert_not_reached();
|
||||
#endif /* CONFIG_TCG */
|
||||
}
|
||||
|
||||
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_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++) {
|
||||
/*
|
||||
|
@ -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
|
||||
|
||||
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
|
||||
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/memory.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define KVM_ARM_VGIC_V2 (1 << 0)
|
||||
#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:
|
||||
* @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,
|
||||
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:
|
||||
* @cpu: ARMCPU
|
||||
|
@ -163,34 +96,6 @@ void kvm_arm_cpu_post_load(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
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* @cs: CPUState
|
||||
* @cpu: ARMCPU
|
||||
*
|
||||
* Get all the SVE vector lengths supported by the KVM host, setting
|
||||
* the bits corresponding to their length in quadwords minus one
|
||||
* (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:
|
||||
|
@ -265,12 +148,12 @@ void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu);
|
|||
|
||||
/**
|
||||
* 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
|
||||
* 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:
|
||||
|
@ -282,14 +165,6 @@ void kvm_arm_add_vcpu_properties(Object *obj);
|
|||
*/
|
||||
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:
|
||||
*
|
||||
|
@ -323,57 +198,19 @@ bool kvm_arm_sve_supported(void);
|
|||
*/
|
||||
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);
|
||||
|
||||
void kvm_arm_pmu_set_irq(CPUState *cs, int irq);
|
||||
void kvm_arm_pmu_init(CPUState *cs);
|
||||
void kvm_arm_pmu_init(ARMCPU *cpu);
|
||||
void kvm_arm_pmu_set_irq(ARMCPU *cpu, int irq);
|
||||
|
||||
/**
|
||||
* kvm_arm_pvtime_init:
|
||||
* @cs: CPUState
|
||||
* @cpu: ARMCPU
|
||||
* @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);
|
||||
void kvm_arm_pvtime_init(ARMCPU *cpu, uint64_t ipa);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static inline bool kvm_arm_steal_time_supported(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
static inline void kvm_arm_add_vcpu_properties(Object *obj)
|
||||
static inline void kvm_arm_add_vcpu_properties(ARMCPU *cpu)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
@ -426,17 +258,17 @@ static inline int kvm_arm_vgic_probe(void)
|
|||
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();
|
||||
}
|
||||
|
||||
static inline void kvm_arm_pmu_init(CPUState *cs)
|
||||
static inline void kvm_arm_pmu_init(ARMCPU *cpu)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
@ -446,48 +278,11 @@ static inline void kvm_arm_steal_time_finalize(ARMCPU *cpu, Error **errp)
|
|||
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();
|
||||
}
|
||||
|
||||
#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
|
||||
|
|
|
@ -8,7 +8,7 @@ arm_ss.add(files(
|
|||
))
|
||||
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: '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 res = a + b;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "exec/exec-all.h"
|
||||
#include "translate.h"
|
||||
#include "translate-a64.h"
|
||||
#include "qemu/log.h"
|
||||
|
|
Loading…
Reference in New Issue