* [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites
@ 2014-02-15 16:06 Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 01/31] target-arm: Fix raw read and write functions on AArch64 registers Peter Maydell
` (31 more replies)
0 siblings, 32 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Here's the latest patchset aimed towards implementing AArch64
system emulation.
Patch 1 is an actually working version of a fix for a problem
I tried to deal with incorrectly in the previous series.
Following patches are implementations of AArch64 views of various
system registers -- these generally got review last time around but
I resend them as they depend on patch 1.
Then we start to get into new stuff:
* implementation of WFI (very simple)
* moving the exception-mask DAIF bits out of pstate and uncached_cpsr
so they're in env->daif in all situations. This allows us to have
simple code in places like cpu-exec.c that doesn't need to consider
what kind of core it's running on. I thought about keeping these
in pstate but that seemed a bit odd for 32 bit cores and the ARM ARM
seems to want to encourage thinking about all these bits of PSTATE as
being genuinely separate.
* handling of exception syndrome information: generally we have to
update everywhere where we generate an exception to make sure we
record the details to be presented to EL1 in the syndrome register.
In this patchset we provide all the infrastructure and fix basically
everything except data and insn abort exceptions. (The code that
actually reads env->exception.syndrome will be the AArch64 exception
entry code, which isn't in this patchset.)
* adding FP-enabled checks (including fixing the VFP-enable checks
for A32/T32 code to check the CPACR which an AArch64 EL1 will be
using as well as the FPSCR.EN which AArch32 Linux kernels use). I
apologise for the "add checks" part of the patchset being pretty
near unreviewable; I have done an exhaustive test to confirm there
are checks on every code path that needs them, though. I had thought
we could simply put the check at the top level of the decoder, but
this gives wrong syndrome information for undefined instructions
in the FP-related areas of the instruction space.
* update of the page-table-walk code to support 64-bit VAs
This still isn't enough to actually boot an AArch64 kernel, but it's
getting pretty close (remaining parts missing are a DC ZVA implementation,
a definition of a Cortex-A57, and exception entry/exit code, and we
have working code for all of those).
If anything in here doesn't seem to make enough sense without
the remaining code, just let me know and I'll hold onto it.
I think the "add AArch64 version of $foo register" patches will
be good to go into target-arm.next assuming I haven't messed up
patch 1 again, and then the rest of the patchset will be a rather
more maintainable size.
thanks
-- PMM
Peter Maydell (30):
target-arm: Fix raw read and write functions on AArch64 registers
target-arm: A64: Make cache ID registers visible to AArch64
target-arm: Implement AArch64 CurrentEL sysreg
target-arm: Implement AArch64 MIDR_EL1
target-arm: Implement AArch64 cache invalidate/clean ops
target-arm: Implement AArch64 TLB invalidate ops
target-arm: Implement AArch64 dummy MDSCR_EL1
target-arm: Implement AArch64 memory attribute registers
target-arm: Implement AArch64 SCTLR_EL1
target-arm: Implement AArch64 TCR_EL1
target-arm: Implement AArch64 VBAR_EL1
target-arm: Implement AArch64 TTBR*
target-arm: Implement AArch64 MPIDR
target-arm: Implement AArch64 generic timers
target-arm: Implement AArch64 ID and feature registers
target-arm: Implement AArch64 dummy breakpoint and watchpoint
registers
target-arm: Implement AArch64 OSLAR_EL1 sysreg as WI
target-arm: Get MMU index information correct for A64 code
target-arm: A64: Implement WFI
target-arm: Store AIF bits in env->pstate for AArch32
target-arm: Implement AArch64 DAIF system register
target-arm: A64: Implement MSR (immediate) instructions
target-arm: Implement AArch64 view of CPACR
target-arm: Add utility function for checking AA32/64 state of an EL
target-arm: Define exception record for AArch64 exceptions
target-arm: Provide correct syndrome information for cpreg access
traps
target-arm: Add support for generating exceptions with syndrome
information
target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set
target-arm: A64: Add assertion that FP access was checked
target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1
Rob Herring (1):
target-arm: Add v8 mmu translation support
cpu-exec.c | 4 +-
hw/arm/pxa2xx.c | 6 +-
linux-user/main.c | 56 ++--
target-arm/cpu-qom.h | 10 +
target-arm/cpu.c | 19 +-
target-arm/cpu.h | 262 ++++++++++++++++--
target-arm/cpu64.c | 1 +
target-arm/helper.c | 649 +++++++++++++++++++++++++++++++++++----------
target-arm/helper.h | 7 +-
target-arm/machine.c | 3 +
target-arm/op_helper.c | 52 +++-
target-arm/translate-a64.c | 404 ++++++++++++++++++++++++----
target-arm/translate.c | 167 +++++++++---
target-arm/translate.h | 15 +-
14 files changed, 1358 insertions(+), 297 deletions(-)
--
1.8.5
^ permalink raw reply [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 01/31] target-arm: Fix raw read and write functions on AArch64 registers
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
@ 2014-02-15 16:06 ` Peter Maydell
2014-02-26 0:17 ` Peter Crosthwaite
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 02/31] target-arm: A64: Make cache ID registers visible to AArch64 Peter Maydell
` (30 subsequent siblings)
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
The raw read and write functions were using the ARM_CP_64BIT flag in
ri->type to determine whether to treat the register's state field as
uint32_t or uint64_t; however AArch64 register info structs don't use
that flag. Abstract out the "how big is the field?" test into a
function and fix it to work for AArch64 registers. For this to work
we must ensure that the reginfo structs put into the hashtable have
the correct state field for their use, not the placeholder STATE_BOTH.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu.c | 2 +-
target-arm/cpu.h | 8 ++++++++
target-arm/helper.c | 8 ++++++--
3 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 6e7ce89..fe18b65 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -60,7 +60,7 @@ static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
return;
}
- if (ri->type & ARM_CP_64BIT) {
+ if (cpreg_field_is_64bit(ri)) {
CPREG_FIELD64(&cpu->env, ri) = ri->resetvalue;
} else {
CPREG_FIELD32(&cpu->env, ri) = ri->resetvalue;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 3c8a2db..4473fad 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -959,6 +959,14 @@ uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
*/
void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
+/* Return true if this reginfo struct's field in the cpu state struct
+ * is 64 bits wide.
+ */
+static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
+{
+ return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
+}
+
static inline bool cp_access_ok(int current_pl,
const ARMCPRegInfo *ri, int isread)
{
diff --git a/target-arm/helper.c b/target-arm/helper.c
index b547f04..1ecc55e 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -109,7 +109,7 @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
- if (ri->type & ARM_CP_64BIT) {
+ if (cpreg_field_is_64bit(ri)) {
return CPREG_FIELD64(env, ri);
} else {
return CPREG_FIELD32(env, ri);
@@ -119,7 +119,7 @@ static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
static void raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
- if (ri->type & ARM_CP_64BIT) {
+ if (cpreg_field_is_64bit(ri)) {
CPREG_FIELD64(env, ri) = value;
} else {
CPREG_FIELD32(env, ri) = value;
@@ -1962,6 +1962,10 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
if (opaque) {
r2->opaque = opaque;
}
+ /* reginfo passed to helpers is correct for the actual access,
+ * and is never ARM_CP_STATE_BOTH:
+ */
+ r2->state = state;
/* Make sure reginfo passed to helpers for wildcarded regs
* has the correct crm/opc1/opc2 for this reg, not CP_ANY:
*/
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 02/31] target-arm: A64: Make cache ID registers visible to AArch64
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 01/31] target-arm: Fix raw read and write functions on AArch64 registers Peter Maydell
@ 2014-02-15 16:06 ` Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 03/31] target-arm: Implement AArch64 CurrentEL sysreg Peter Maydell
` (29 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Make the cache ID system registers (CLIDR, CSSELR, CCSIDR, CTR)
visible to AArch64. These are mostly simple 64-bit extensions of the
existing 32 bit system registers and so can share reginfo definitions.
CTR needs to have a split definition, but we can clean up the
temporary user-mode implementation in favour of using the CPU-specified
reset value, and implement the system-mode-required semantics of
restricting its EL0 accessibility if SCTLR.UCT is not set.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/cpu.c | 2 ++
target-arm/cpu.h | 2 +-
target-arm/cpu64.c | 1 +
target-arm/helper.c | 31 +++++++++++++++++++++----------
4 files changed, 25 insertions(+), 11 deletions(-)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index fe18b65..8fed098 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -91,6 +91,8 @@ static void arm_cpu_reset(CPUState *s)
env->aarch64 = 1;
#if defined(CONFIG_USER_ONLY)
env->pstate = PSTATE_MODE_EL0t;
+ /* Userspace expects access to CTL_EL0 */
+ env->cp15.c1_sys |= SCTLR_UCT;
#else
env->pstate = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F
| PSTATE_MODE_EL1h;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 4473fad..8c4ed0f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -166,7 +166,7 @@ typedef struct CPUARMState {
/* System control coprocessor (cp15) */
struct {
uint32_t c0_cpuid;
- uint32_t c0_cssel; /* Cache size selection. */
+ uint64_t c0_cssel; /* Cache size selection. */
uint32_t c1_sys; /* System control register. */
uint32_t c1_coproc; /* Coprocessor access register. */
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
diff --git a/target-arm/cpu64.c b/target-arm/cpu64.c
index a639c2e..8426bf1 100644
--- a/target-arm/cpu64.c
+++ b/target-arm/cpu64.c
@@ -45,6 +45,7 @@ static void aarch64_any_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
set_feature(&cpu->env, ARM_FEATURE_V7MP);
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
+ cpu->ctr = 0x80030003; /* 32 byte I and D cacheline size, VIPT icache */
}
#endif
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 1ecc55e..2d573d9 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -629,9 +629,11 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
{ .name = "SCR", .cp = 15, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_scr),
.resetvalue = 0, },
- { .name = "CCSIDR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
+ { .name = "CCSIDR", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 0,
.access = PL1_R, .readfn = ccsidr_read, .type = ARM_CP_NO_MIGRATE },
- { .name = "CSSELR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0,
+ { .name = "CSSELR", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 2, .opc2 = 0,
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c0_cssel),
.writefn = csselr_write, .resetvalue = 0 },
/* Auxiliary ID register: this actually has an IMPDEF value but for now
@@ -1524,13 +1526,6 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "FPSR", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 4,
.access = PL0_RW, .readfn = aa64_fpsr_read, .writefn = aa64_fpsr_write },
- /* This claims a 32 byte cacheline size for icache and dcache, VIPT icache.
- * It will eventually need to have a CPU-specified reset value.
- */
- { .name = "CTR_EL0", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 0, .crm = 0,
- .access = PL0_R, .type = ARM_CP_CONST,
- .resetvalue = 0x80030003 },
/* Prohibit use of DC ZVA. OPTME: implement DC ZVA and allow its use.
* For system mode the DZP bit here will need to be computed, not constant.
*/
@@ -1550,6 +1545,17 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri,
tlb_flush(env, 1);
}
+static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ /* Only accessible in EL0 if SCTLR.UCT is set (and only in AArch64,
+ * but the AArch32 CTR has its own reginfo struct)
+ */
+ if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCT)) {
+ return CP_ACCESS_TRAP;
+ }
+ return CP_ACCESS_OK;
+}
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
@@ -1634,7 +1640,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.raw_writefn = raw_write,
};
ARMCPRegInfo clidr = {
- .name = "CLIDR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1,
+ .name = "CLIDR", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 1,
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->clidr
};
define_one_arm_cp_reg(cpu, &pmcr);
@@ -1713,6 +1720,10 @@ void register_cp_regs_for_features(ARMCPU *cpu)
{ .name = "CTR",
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
+ { .name = "CTR_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 0, .crm = 0,
+ .access = PL0_R, .accessfn = ctr_el0_access,
+ .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
{ .name = "TCMTR",
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 2,
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 03/31] target-arm: Implement AArch64 CurrentEL sysreg
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 01/31] target-arm: Fix raw read and write functions on AArch64 registers Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 02/31] target-arm: A64: Make cache ID registers visible to AArch64 Peter Maydell
@ 2014-02-15 16:06 ` Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 04/31] target-arm: Implement AArch64 MIDR_EL1 Peter Maydell
` (28 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the CurrentEL sysreg.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/cpu.h | 3 ++-
target-arm/helper.c | 3 +++
target-arm/translate-a64.c | 7 +++++++
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 8c4ed0f..632b4d1 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -731,7 +731,8 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
#define ARM_CP_NOP (ARM_CP_SPECIAL | (1 << 8))
#define ARM_CP_WFI (ARM_CP_SPECIAL | (2 << 8))
#define ARM_CP_NZCV (ARM_CP_SPECIAL | (3 << 8))
-#define ARM_LAST_SPECIAL ARM_CP_NZCV
+#define ARM_CP_CURRENTEL (ARM_CP_SPECIAL | (4 << 8))
+#define ARM_LAST_SPECIAL ARM_CP_CURRENTEL
/* Used only as a terminator for ARMCPRegInfo lists */
#define ARM_CP_SENTINEL 0xffff
/* Mask of only the flag bits in a type field */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2d573d9..73dcaf6 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1533,6 +1533,9 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
.opc0 = 3, .opc1 = 3, .opc2 = 7, .crn = 0, .crm = 0,
.access = PL0_R, .type = ARM_CP_CONST,
.resetvalue = 0x10 },
+ { .name = "CURRENTEL", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .opc2 = 2, .crn = 4, .crm = 2,
+ .access = PL1_R, .type = ARM_CP_CURRENTEL },
REGINFO_SENTINEL
};
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 3de9cad..7c55a90 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1216,6 +1216,13 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
gen_set_nzcv(tcg_rt);
}
return;
+ case ARM_CP_CURRENTEL:
+ /* Reads as current EL value from pstate, which is
+ * guaranteed to be constant by the tb flags.
+ */
+ tcg_rt = cpu_reg(s, rt);
+ tcg_gen_movi_i64(tcg_rt, s->current_pl << 2);
+ return;
default:
break;
}
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 04/31] target-arm: Implement AArch64 MIDR_EL1
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (2 preceding siblings ...)
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 03/31] target-arm: Implement AArch64 CurrentEL sysreg Peter Maydell
@ 2014-02-15 16:06 ` Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 05/31] target-arm: Implement AArch64 cache invalidate/clean ops Peter Maydell
` (27 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64 view of the MIDR system register
(for AArch64 it is a simple constant, unlike the complicated
mess that TI925 imposes on the 32-bit view).
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/helper.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 73dcaf6..cad6bbe 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1720,6 +1720,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.writefn = arm_cp_write_ignore, .raw_writefn = raw_write,
.fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid),
.type = ARM_CP_OVERRIDE },
+ { .name = "MIDR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .opc2 = 0, .crn = 0, .crm = 0,
+ .access = PL1_R, .resetvalue = cpu->midr, .type = ARM_CP_CONST },
{ .name = "CTR",
.cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1,
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr },
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 05/31] target-arm: Implement AArch64 cache invalidate/clean ops
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (3 preceding siblings ...)
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 04/31] target-arm: Implement AArch64 MIDR_EL1 Peter Maydell
@ 2014-02-15 16:06 ` Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 06/31] target-arm: Implement AArch64 TLB invalidate ops Peter Maydell
` (26 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement all the AArch64 cache invalidate and clean ops
(which are all NOPs since QEMU doesn't emulate the cache).
The only remaining unimplemented cache op is DC ZVA.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/cpu.c | 4 ++--
target-arm/helper.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 8fed098..2f94943 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -91,8 +91,8 @@ static void arm_cpu_reset(CPUState *s)
env->aarch64 = 1;
#if defined(CONFIG_USER_ONLY)
env->pstate = PSTATE_MODE_EL0t;
- /* Userspace expects access to CTL_EL0 */
- env->cp15.c1_sys |= SCTLR_UCT;
+ /* Userspace expects access to CTL_EL0 and the cache ops */
+ env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
#else
env->pstate = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F
| PSTATE_MODE_EL1h;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index cad6bbe..e1f1c4d 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1513,6 +1513,18 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
vfp_set_fpsr(env, value);
}
+static CPAccessResult aa64_cacheop_access(CPUARMState *env,
+ const ARMCPRegInfo *ri)
+{
+ /* Cache invalidate/clean: NOP, but EL0 must UNDEF unless
+ * SCTLR_EL1.UCI is set.
+ */
+ if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UCI)) {
+ return CP_ACCESS_TRAP;
+ }
+ return CP_ACCESS_OK;
+}
+
static const ARMCPRegInfo v8_cp_reginfo[] = {
/* Minimal set of EL0-visible registers. This will need to be expanded
* significantly for system emulation of AArch64 CPUs.
@@ -1536,6 +1548,41 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "CURRENTEL", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .opc2 = 2, .crn = 4, .crm = 2,
.access = PL1_R, .type = ARM_CP_CURRENTEL },
+ /* Cache ops: all NOPs since we don't emulate caches */
+ { .name = "IC_IALLUIS", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 1, .opc2 = 0,
+ .access = PL1_W, .type = ARM_CP_NOP },
+ { .name = "IC_IALLU", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 5, .opc2 = 0,
+ .access = PL1_W, .type = ARM_CP_NOP },
+ { .name = "IC_IVAU", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 5, .opc2 = 1,
+ .access = PL0_W, .type = ARM_CP_NOP,
+ .accessfn = aa64_cacheop_access },
+ { .name = "DC_IVAC", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 1,
+ .access = PL1_W, .type = ARM_CP_NOP },
+ { .name = "DC_ISW", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 6, .opc2 = 2,
+ .access = PL1_W, .type = ARM_CP_NOP },
+ { .name = "DC_CVAC", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 10, .opc2 = 1,
+ .access = PL0_W, .type = ARM_CP_NOP,
+ .accessfn = aa64_cacheop_access },
+ { .name = "DC_CSW", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 10, .opc2 = 2,
+ .access = PL1_W, .type = ARM_CP_NOP },
+ { .name = "DC_CVAU", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 11, .opc2 = 1,
+ .access = PL0_W, .type = ARM_CP_NOP,
+ .accessfn = aa64_cacheop_access },
+ { .name = "DC_CIVAC", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 3, .crn = 7, .crm = 14, .opc2 = 1,
+ .access = PL0_W, .type = ARM_CP_NOP,
+ .accessfn = aa64_cacheop_access },
+ { .name = "DC_CISW", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
+ .access = PL1_W, .type = ARM_CP_NOP },
REGINFO_SENTINEL
};
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 06/31] target-arm: Implement AArch64 TLB invalidate ops
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (4 preceding siblings ...)
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 05/31] target-arm: Implement AArch64 cache invalidate/clean ops Peter Maydell
@ 2014-02-15 16:06 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 07/31] target-arm: Implement AArch64 dummy MDSCR_EL1 Peter Maydell
` (25 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:06 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64 TLB invalidate operations. This is
the full set of TLBI ops defined for a CPU which doesn't
implement EL2 or EL3.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/helper.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index e1f1c4d..8184c38 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1525,6 +1525,30 @@ static CPAccessResult aa64_cacheop_access(CPUARMState *env,
return CP_ACCESS_OK;
}
+static void tlbi_aa64_va_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /* Invalidate by VA (AArch64 version) */
+ uint64_t pageaddr = value << 12;
+ tlb_flush_page(env, pageaddr);
+}
+
+static void tlbi_aa64_vaa_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /* Invalidate by VA, all ASIDs (AArch64 version) */
+ uint64_t pageaddr = value << 12;
+ tlb_flush_page(env, pageaddr);
+}
+
+static void tlbi_aa64_asid_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /* Invalidate by ASID (AArch64 version) */
+ int asid = extract64(value, 48, 16);
+ tlb_flush(env, asid == 0);
+}
+
static const ARMCPRegInfo v8_cp_reginfo[] = {
/* Minimal set of EL0-visible registers. This will need to be expanded
* significantly for system emulation of AArch64 CPUs.
@@ -1583,6 +1607,55 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "DC_CISW", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 7, .crm = 14, .opc2 = 2,
.access = PL1_W, .type = ARM_CP_NOP },
+ /* TLBI operations */
+ { .name = "TLBI_VMALLE1IS", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 0,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbiall_write },
+ { .name = "TLBI_VAE1IS", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 1,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_va_write },
+ { .name = "TLBI_ASIDE1IS", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 2,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_asid_write },
+ { .name = "TLBI_VAAE1IS", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 3,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_vaa_write },
+ { .name = "TLBI_VALE1IS", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 5,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_va_write },
+ { .name = "TLBI_VAALE1IS", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 3, .opc2 = 7,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_vaa_write },
+ { .name = "TLBI_VMALLE1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 0,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbiall_write },
+ { .name = "TLBI_VAE1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 1,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_va_write },
+ { .name = "TLBI_ASIDE1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 2,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_asid_write },
+ { .name = "TLBI_VAAE1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 3,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_vaa_write },
+ { .name = "TLBI_VALE1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 5,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_va_write },
+ { .name = "TLBI_VAALE1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 7,
+ .access = PL1_W, .type = ARM_CP_NO_MIGRATE,
+ .writefn = tlbi_aa64_vaa_write },
REGINFO_SENTINEL
};
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 07/31] target-arm: Implement AArch64 dummy MDSCR_EL1
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (5 preceding siblings ...)
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 06/31] target-arm: Implement AArch64 TLB invalidate ops Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 08/31] target-arm: Implement AArch64 memory attribute registers Peter Maydell
` (24 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
We don't support letting the guest do debug, but Linux prods the
monitor debug system control register anyway, so implement a dummy
RAZ/WI version.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/helper.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 8184c38..9be331b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1656,6 +1656,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
.opc0 = 1, .opc2 = 0, .crn = 8, .crm = 7, .opc2 = 7,
.access = PL1_W, .type = ARM_CP_NO_MIGRATE,
.writefn = tlbi_aa64_vaa_write },
+ /* Dummy implementation of monitor debug system control register:
+ * we don't support debug.
+ */
+ { .name = "MDSCR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
+ .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
REGINFO_SENTINEL
};
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 08/31] target-arm: Implement AArch64 memory attribute registers
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (6 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 07/31] target-arm: Implement AArch64 dummy MDSCR_EL1 Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 09/31] target-arm: Implement AArch64 SCTLR_EL1 Peter Maydell
` (23 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64 memory attribute registers. Since QEMU doesn't
model caches it does not need to care about memory attributes at all,
and we can simply make these read-as-written.
We did not previously implement the AArch32 versions of the MAIR
registers, which went unnoticed because of the overbroad TLB_LOCKDOWN
reginfo definition; provide them now to keep the 64<->32 register
relationship clear.
We already provided AMAIR registers for 32 bit as simple RAZ/WI;
extend that to provide a 64 bit RAZ/WI AMAIR_EL1.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/cpu.h | 3 +++
target-arm/helper.c | 24 +++++++++++++++++++++++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 632b4d1..51fa634 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -74,8 +74,10 @@
*/
#ifdef HOST_WORDS_BIGENDIAN
#define offsetoflow32(S, M) (offsetof(S, M) + sizeof(uint32_t))
+#define offsetofhigh32(S, M) offsetof(S, M)
#else
#define offsetoflow32(S, M) offsetof(S, M)
+#define offsetofhigh32(S, M) (offsetof(S, M) + sizeof(uint32_t))
#endif
/* Meanings of the ARMCPU object's two inbound GPIO lines */
@@ -197,6 +199,7 @@ typedef struct CPUARMState {
uint32_t c9_pmxevtyper; /* perf monitor event type */
uint32_t c9_pmuserenr; /* perf monitor user enable */
uint32_t c9_pminten; /* perf monitor interrupt enables */
+ uint64_t mair_el1;
uint32_t c12_vbar; /* vector base address register */
uint32_t c13_fcse; /* FCSE PID. */
uint32_t c13_context; /* Context ID. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 9be331b..0e459f1 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -641,6 +641,26 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
*/
{ .name = "AIDR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 1, .opc2 = 7,
.access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
+ /* MAIR can just read-as-written because we don't implement caches
+ * and so don't need to care about memory attributes.
+ */
+ { .name = "MAIR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0,
+ .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el1),
+ .resetvalue = 0 },
+ /* For non-long-descriptor page tables these are PRRR and NMRR;
+ * regardless they still act as reads-as-written for QEMU.
+ * The override is necessary because of the overly-broad TLB_LOCKDOWN
+ * definition.
+ */
+ { .name = "MAIR0", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE,
+ .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0, .access = PL1_RW,
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.mair_el1),
+ .resetfn = arm_cp_reset_ignore },
+ { .name = "MAIR1", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE,
+ .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1, .access = PL1_RW,
+ .fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el1),
+ .resetfn = arm_cp_reset_ignore },
REGINFO_SENTINEL
};
@@ -1467,9 +1487,11 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
/* NOP AMAIR0/1: the override is because these clash with the rather
* broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo.
*/
- { .name = "AMAIR0", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 0,
+ { .name = "AMAIR0", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 0,
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE,
.resetvalue = 0 },
+ /* AMAIR1 is mapped to AMAIR_EL1[63:32] */
{ .name = "AMAIR1", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 1,
.access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE,
.resetvalue = 0 },
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 09/31] target-arm: Implement AArch64 SCTLR_EL1
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (7 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 08/31] target-arm: Implement AArch64 memory attribute registers Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 10/31] target-arm: Implement AArch64 TCR_EL1 Peter Maydell
` (22 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64 view of the system control register SCTLR_EL1.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/cpu.h | 2 +-
target-arm/helper.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 51fa634..74b1122 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -169,7 +169,7 @@ typedef struct CPUARMState {
struct {
uint32_t c0_cpuid;
uint64_t c0_cssel; /* Cache size selection. */
- uint32_t c1_sys; /* System control register. */
+ uint64_t c1_sys; /* System control register. */
uint32_t c1_coproc; /* Coprocessor access register. */
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
uint32_t c1_scr; /* secure config register. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 0e459f1..0a9036a 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1948,7 +1948,8 @@ void register_cp_regs_for_features(ARMCPU *cpu)
/* Generic registers whose values depend on the implementation */
{
ARMCPRegInfo sctlr = {
- .name = "SCTLR", .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
+ .name = "SCTLR", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_sys),
.writefn = sctlr_write, .resetvalue = cpu->reset_sctlr,
.raw_writefn = raw_write,
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 10/31] target-arm: Implement AArch64 TCR_EL1
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (8 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 09/31] target-arm: Implement AArch64 SCTLR_EL1 Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 11/31] target-arm: Implement AArch64 VBAR_EL1 Peter Maydell
` (21 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64 TCR_EL1, which is the 64 bit view of
the AArch32 TTBCR. (The uses of the bits in the register are
completely different, but in any given situation the CPU will
always interpret them one way or the other. In fact for QEMU EL1
is always 64 bit, but we share the state field because this
is the correct mapping to permit a future implementation of EL2.)
We also make the AArch64 view the 'master' as far as migration
and reset is concerned.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/cpu.h | 2 +-
target-arm/helper.c | 19 ++++++++++++++++---
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 74b1122..4e87064 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -177,7 +177,7 @@ typedef struct CPUARMState {
uint32_t c2_base0_hi; /* MMU translation table base 0, high 32 bits */
uint32_t c2_base1; /* MMU translation table base 0. */
uint32_t c2_base1_hi; /* MMU translation table base 1, high 32 bits */
- uint32_t c2_control; /* MMU translation table base control. */
+ uint64_t c2_control; /* MMU translation table base control. */
uint32_t c2_mask; /* MMU translation table base selection mask. */
uint32_t c2_base_mask; /* MMU translation table base 0 mask. */
uint32_t c2_data; /* MPU data cachable bits. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 0a9036a..95c9cac 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1215,6 +1215,14 @@ static void vmsa_ttbcr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
env->cp15.c2_mask = 0;
}
+static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /* For AArch64 the A1 bit could result in a change of ASID, so TLB flush. */
+ tlb_flush(env, 1);
+ env->cp15.c2_control = value;
+}
+
static const ARMCPRegInfo vmsa_cp_reginfo[] = {
{ .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL1_RW,
@@ -1228,10 +1236,15 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
{ .name = "TTBR1", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
.access = PL1_RW,
.fieldoffset = offsetof(CPUARMState, cp15.c2_base1), .resetvalue = 0, },
- { .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
- .access = PL1_RW, .writefn = vmsa_ttbcr_write,
- .resetfn = vmsa_ttbcr_reset, .raw_writefn = vmsa_ttbcr_raw_write,
+ { .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
+ .access = PL1_RW, .writefn = vmsa_tcr_el1_write,
+ .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write,
.fieldoffset = offsetof(CPUARMState, cp15.c2_control) },
+ { .name = "TTBCR", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
+ .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, .writefn = vmsa_ttbcr_write,
+ .resetfn = arm_cp_reset_ignore, .raw_writefn = vmsa_ttbcr_raw_write,
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.c2_control) },
{ .name = "DFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c6_data),
.resetvalue = 0, },
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 11/31] target-arm: Implement AArch64 VBAR_EL1
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (9 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 10/31] target-arm: Implement AArch64 TCR_EL1 Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 12/31] target-arm: Implement AArch64 TTBR* Peter Maydell
` (20 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the A64 view of the VBAR system register.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/cpu.h | 2 +-
target-arm/helper.c | 9 ++++++++-
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 4e87064..06953ac 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -200,7 +200,7 @@ typedef struct CPUARMState {
uint32_t c9_pmuserenr; /* perf monitor user enable */
uint32_t c9_pminten; /* perf monitor interrupt enables */
uint64_t mair_el1;
- uint32_t c12_vbar; /* vector base address register */
+ uint64_t c12_vbar; /* vector base address register */
uint32_t c13_fcse; /* FCSE PID. */
uint32_t c13_context; /* Context ID. */
uint64_t tpidr_el0; /* User RW Thread register. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 95c9cac..59c21a1 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -533,6 +533,12 @@ static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri,
static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
+ /* Note that even though the AArch64 view of this register has bits
+ * [10:0] all RES0 we can only mask the bottom 5, to comply with the
+ * architectural requirements for bits which are RES0 only in some
+ * contexts. (ARMv8 would permit us to do no masking at all, but ARMv7
+ * requires the bottom five bits to be RAZ/WI because they're UNK/SBZP.)
+ */
env->cp15.c12_vbar = value & ~0x1Ful;
}
@@ -622,7 +628,8 @@ static const ARMCPRegInfo v7_cp_reginfo[] = {
.access = PL1_RW, .type = ARM_CP_NO_MIGRATE,
.fieldoffset = offsetof(CPUARMState, cp15.c9_pminten),
.resetvalue = 0, .writefn = pmintenclr_write, },
- { .name = "VBAR", .cp = 15, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
+ { .name = "VBAR", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL1_RW, .writefn = vbar_write,
.fieldoffset = offsetof(CPUARMState, cp15.c12_vbar),
.resetvalue = 0 },
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 12/31] target-arm: Implement AArch64 TTBR*
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (10 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 11/31] target-arm: Implement AArch64 VBAR_EL1 Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-26 6:33 ` Hu Tao
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 13/31] target-arm: Implement AArch64 MPIDR Peter Maydell
` (19 subsequent siblings)
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64 TTBR* registers. For v7 these were already 64 bits
to handle LPAE, but implemented as two separate uint32_t fields.
Combine them into a single uint64_t which can be used for all purposes.
Since this requires touching every use, take the opportunity to rename
the field to the architectural name.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/arm/pxa2xx.c | 2 +-
target-arm/cpu.h | 6 ++--
target-arm/helper.c | 89 ++++++++++++++++++-----------------------------------
3 files changed, 33 insertions(+), 64 deletions(-)
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index 64422f0..be6b5f6 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -276,7 +276,7 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
s->cpu->env.cp15.c1_sys = 0;
s->cpu->env.cp15.c1_coproc = 0;
- s->cpu->env.cp15.c2_base0 = 0;
+ s->cpu->env.cp15.ttbr0_el1 = 0;
s->cpu->env.cp15.c3 = 0;
s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */
s->pm_regs[RCSR >> 2] |= 0x8; /* Set GPR */
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 06953ac..7cbe69b 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -173,10 +173,8 @@ typedef struct CPUARMState {
uint32_t c1_coproc; /* Coprocessor access register. */
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
uint32_t c1_scr; /* secure config register. */
- uint32_t c2_base0; /* MMU translation table base 0. */
- uint32_t c2_base0_hi; /* MMU translation table base 0, high 32 bits */
- uint32_t c2_base1; /* MMU translation table base 0. */
- uint32_t c2_base1_hi; /* MMU translation table base 1, high 32 bits */
+ uint64_t ttbr0_el1; /* MMU translation table base 0. */
+ uint32_t ttbr1_el1; /* MMU translation table base 1. */
uint64_t c2_control; /* MMU translation table base control. */
uint32_t c2_mask; /* MMU translation table base selection mask. */
uint32_t c2_base_mask; /* MMU translation table base 0 mask. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 59c21a1..f5d9d2f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1230,6 +1230,18 @@ static void vmsa_tcr_el1_write(CPUARMState *env, const ARMCPRegInfo *ri,
env->cp15.c2_control = value;
}
+static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /* 64 bit accesses to the TTBRs can change the ASID and so we
+ * must flush the TLB.
+ */
+ if (cpreg_field_is_64bit(ri)) {
+ tlb_flush(env, 1);
+ }
+ raw_write(env, ri, value);
+}
+
static const ARMCPRegInfo vmsa_cp_reginfo[] = {
{ .name = "DFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 0,
.access = PL1_RW,
@@ -1237,12 +1249,14 @@ static const ARMCPRegInfo vmsa_cp_reginfo[] = {
{ .name = "IFSR", .cp = 15, .crn = 5, .crm = 0, .opc1 = 0, .opc2 = 1,
.access = PL1_RW,
.fieldoffset = offsetof(CPUARMState, cp15.c5_insn), .resetvalue = 0, },
- { .name = "TTBR0", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW,
- .fieldoffset = offsetof(CPUARMState, cp15.c2_base0), .resetvalue = 0, },
- { .name = "TTBR1", .cp = 15, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
- .access = PL1_RW,
- .fieldoffset = offsetof(CPUARMState, cp15.c2_base1), .resetvalue = 0, },
+ { .name = "TTBR0_EL1", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 0,
+ .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1),
+ .writefn = vmsa_ttbr_write, .resetvalue = 0 },
+ { .name = "TTBR1_EL1", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 1,
+ .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1),
+ .writefn = vmsa_ttbr_write, .resetvalue = 0 },
{ .name = "TCR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .crn = 2, .crm = 0, .opc1 = 0, .opc2 = 2,
.access = PL1_RW, .writefn = vmsa_tcr_el1_write,
@@ -1459,50 +1473,6 @@ static void par64_reset(CPUARMState *env, const ARMCPRegInfo *ri)
env->cp15.c7_par = 0;
}
-static uint64_t ttbr064_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- return ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0;
-}
-
-static void ttbr064_raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- env->cp15.c2_base0_hi = value >> 32;
- env->cp15.c2_base0 = value;
-}
-
-static void ttbr064_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- /* Writes to the 64 bit format TTBRs may change the ASID */
- tlb_flush(env, 1);
- ttbr064_raw_write(env, ri, value);
-}
-
-static void ttbr064_reset(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- env->cp15.c2_base0_hi = 0;
- env->cp15.c2_base0 = 0;
-}
-
-static uint64_t ttbr164_read(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- return ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1;
-}
-
-static void ttbr164_write(CPUARMState *env, const ARMCPRegInfo *ri,
- uint64_t value)
-{
- env->cp15.c2_base1_hi = value >> 32;
- env->cp15.c2_base1 = value;
-}
-
-static void ttbr164_reset(CPUARMState *env, const ARMCPRegInfo *ri)
-{
- env->cp15.c2_base1_hi = 0;
- env->cp15.c2_base1 = 0;
-}
-
static const ARMCPRegInfo lpae_cp_reginfo[] = {
/* NOP AMAIR0/1: the override is because these clash with the rather
* broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo.
@@ -1524,12 +1494,13 @@ static const ARMCPRegInfo lpae_cp_reginfo[] = {
.access = PL1_RW, .type = ARM_CP_64BIT,
.readfn = par64_read, .writefn = par64_write, .resetfn = par64_reset },
{ .name = "TTBR0", .cp = 15, .crm = 2, .opc1 = 0,
- .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr064_read,
- .writefn = ttbr064_write, .raw_writefn = ttbr064_raw_write,
- .resetfn = ttbr064_reset },
+ .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE,
+ .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el1),
+ .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore },
{ .name = "TTBR1", .cp = 15, .crm = 2, .opc1 = 1,
- .access = PL1_RW, .type = ARM_CP_64BIT, .readfn = ttbr164_read,
- .writefn = ttbr164_write, .resetfn = ttbr164_reset },
+ .access = PL1_RW, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE,
+ .fieldoffset = offsetof(CPUARMState, cp15.ttbr1_el1),
+ .writefn = vmsa_ttbr_write, .resetfn = arm_cp_reset_ignore },
REGINFO_SENTINEL
};
@@ -2918,9 +2889,9 @@ static uint32_t get_level1_table_address(CPUARMState *env, uint32_t address)
uint32_t table;
if (address & env->cp15.c2_mask)
- table = env->cp15.c2_base1 & 0xffffc000;
+ table = env->cp15.ttbr1_el1 & 0xffffc000;
else
- table = env->cp15.c2_base0 & env->cp15.c2_base_mask;
+ table = env->cp15.ttbr0_el1 & env->cp15.c2_base_mask;
table |= (address >> 18) & 0x3ffc;
return table;
@@ -3193,11 +3164,11 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
* we will always flush the TLB any time the ASID is changed).
*/
if (ttbr_select == 0) {
- ttbr = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0;
+ ttbr = env->cp15.ttbr0_el1;
epd = extract32(env->cp15.c2_control, 7, 1);
tsz = t0sz;
} else {
- ttbr = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1;
+ ttbr = env->cp15.ttbr1_el1;
epd = extract32(env->cp15.c2_control, 23, 1);
tsz = t1sz;
}
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 13/31] target-arm: Implement AArch64 MPIDR
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (11 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 12/31] target-arm: Implement AArch64 TTBR* Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 14/31] target-arm: Implement AArch64 generic timers Peter Maydell
` (18 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64 MPIDR system register.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/helper.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index f5d9d2f..c81e73f 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1435,7 +1435,8 @@ static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
CPUState *cs = CPU(arm_env_get_cpu(env));
uint32_t mpidr = cs->cpu_index;
- /* We don't support setting cluster ID ([8..11])
+ /* We don't support setting cluster ID ([8..11]) (known as Aff1
+ * in later ARM ARM versions), or any of the higher affinity level fields,
* so these bits always RAZ.
*/
if (arm_feature(env, ARM_FEATURE_V7MP)) {
@@ -1450,7 +1451,8 @@ static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri)
}
static const ARMCPRegInfo mpidr_cp_reginfo[] = {
- { .name = "MPIDR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
+ { .name = "MPIDR", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 5,
.access = PL1_R, .readfn = mpidr_read, .type = ARM_CP_NO_MIGRATE },
REGINFO_SENTINEL
};
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 14/31] target-arm: Implement AArch64 generic timers
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (12 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 13/31] target-arm: Implement AArch64 MPIDR Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 15/31] target-arm: Implement AArch64 ID and feature registers Peter Maydell
` (17 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64 view of the generic timer system registers.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu.h | 6 ++--
target-arm/helper.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 75 insertions(+), 14 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 7cbe69b..48419ae 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -104,7 +104,7 @@ struct arm_boot_info;
/* CPU state for each instance of a generic timer (in cp15 c14) */
typedef struct ARMGenericTimer {
uint64_t cval; /* Timer CompareValue register */
- uint32_t ctl; /* Timer Control register */
+ uint64_t ctl; /* Timer Control register */
} ARMGenericTimer;
#define GTIMER_PHYS 0
@@ -204,8 +204,8 @@ typedef struct CPUARMState {
uint64_t tpidr_el0; /* User RW Thread register. */
uint64_t tpidrro_el0; /* User RO Thread register. */
uint64_t tpidr_el1; /* Privileged Thread register. */
- uint32_t c14_cntfrq; /* Counter Frequency register */
- uint32_t c14_cntkctl; /* Timer Control register */
+ uint64_t c14_cntfrq; /* Counter Frequency register */
+ uint64_t c14_cntkctl; /* Timer Control register */
ARMGenericTimer c14_timer[NUM_GTIMERS];
uint32_t c15_cpar; /* XScale Coprocessor Access Register */
uint32_t c15_ticonfig; /* TI925T configuration byte. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index c81e73f..01fd9da 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -901,30 +901,55 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
* Our reset value matches the fixed frequency we implement the timer at.
*/
{ .name = "CNTFRQ", .cp = 15, .crn = 14, .crm = 0, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW | PL0_R,
+ .type = ARM_CP_NO_MIGRATE,
+ .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
+ .fieldoffset = offsetoflow32(CPUARMState, cp15.c14_cntfrq),
+ .resetfn = arm_cp_reset_ignore,
+ },
+ { .name = "CNTFRQ_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 0,
+ .access = PL1_RW | PL0_R, .accessfn = gt_cntfrq_access,
.fieldoffset = offsetof(CPUARMState, cp15.c14_cntfrq),
.resetvalue = (1000 * 1000 * 1000) / GTIMER_SCALE,
- .accessfn = gt_cntfrq_access,
},
/* overall control: mostly access permissions */
- { .name = "CNTKCTL", .cp = 15, .crn = 14, .crm = 1, .opc1 = 0, .opc2 = 0,
+ { .name = "CNTKCTL", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .opc1 = 0, .crn = 14, .crm = 1, .opc2 = 0,
.access = PL1_RW,
.fieldoffset = offsetof(CPUARMState, cp15.c14_cntkctl),
.resetvalue = 0,
},
/* per-timer control */
{ .name = "CNTP_CTL", .cp = 15, .crn = 14, .crm = 2, .opc1 = 0, .opc2 = 1,
+ .type = ARM_CP_IO | ARM_CP_NO_MIGRATE, .access = PL1_RW | PL0_R,
+ .accessfn = gt_ptimer_access,
+ .fieldoffset = offsetoflow32(CPUARMState,
+ cp15.c14_timer[GTIMER_PHYS].ctl),
+ .resetfn = arm_cp_reset_ignore,
+ .writefn = gt_ctl_write, .raw_writefn = raw_write,
+ },
+ { .name = "CNTP_CTL_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 1,
.type = ARM_CP_IO, .access = PL1_RW | PL0_R,
+ .accessfn = gt_ptimer_access,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].ctl),
.resetvalue = 0,
- .accessfn = gt_ptimer_access,
.writefn = gt_ctl_write, .raw_writefn = raw_write,
},
{ .name = "CNTV_CTL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 1,
+ .type = ARM_CP_IO | ARM_CP_NO_MIGRATE, .access = PL1_RW | PL0_R,
+ .accessfn = gt_vtimer_access,
+ .fieldoffset = offsetoflow32(CPUARMState,
+ cp15.c14_timer[GTIMER_VIRT].ctl),
+ .resetfn = arm_cp_reset_ignore,
+ .writefn = gt_ctl_write, .raw_writefn = raw_write,
+ },
+ { .name = "CNTV_CTL_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 1,
.type = ARM_CP_IO, .access = PL1_RW | PL0_R,
+ .accessfn = gt_vtimer_access,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].ctl),
.resetvalue = 0,
- .accessfn = gt_vtimer_access,
.writefn = gt_ctl_write, .raw_writefn = raw_write,
},
/* TimerValue views: a 32 bit downcounting view of the underlying state */
@@ -933,37 +958,73 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
.accessfn = gt_ptimer_access,
.readfn = gt_tval_read, .writefn = gt_tval_write,
},
+ { .name = "CNTP_TVAL_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 0,
+ .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R,
+ .readfn = gt_tval_read, .writefn = gt_tval_write,
+ },
{ .name = "CNTV_TVAL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 0,
.type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R,
.accessfn = gt_vtimer_access,
.readfn = gt_tval_read, .writefn = gt_tval_write,
},
+ { .name = "CNTV_TVAL_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 0,
+ .type = ARM_CP_NO_MIGRATE | ARM_CP_IO, .access = PL1_RW | PL0_R,
+ .readfn = gt_tval_read, .writefn = gt_tval_write,
+ },
/* The counter itself */
{ .name = "CNTPCT", .cp = 15, .crm = 14, .opc1 = 0,
.access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE | ARM_CP_IO,
.accessfn = gt_pct_access,
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
+ },
+ { .name = "CNTPCT_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 1,
+ .access = PL0_R, .type = ARM_CP_NO_MIGRATE | ARM_CP_IO,
+ .accessfn = gt_pct_access,
.readfn = gt_cnt_read, .resetfn = gt_cnt_reset,
},
{ .name = "CNTVCT", .cp = 15, .crm = 14, .opc1 = 1,
.access = PL0_R, .type = ARM_CP_64BIT | ARM_CP_NO_MIGRATE | ARM_CP_IO,
.accessfn = gt_vct_access,
+ .readfn = gt_cnt_read, .resetfn = arm_cp_reset_ignore,
+ },
+ { .name = "CNTVCT_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 0, .opc2 = 2,
+ .access = PL0_R, .type = ARM_CP_NO_MIGRATE | ARM_CP_IO,
+ .accessfn = gt_vct_access,
.readfn = gt_cnt_read, .resetfn = gt_cnt_reset,
},
/* Comparison value, indicating when the timer goes off */
{ .name = "CNTP_CVAL", .cp = 15, .crm = 14, .opc1 = 2,
.access = PL1_RW | PL0_R,
- .type = ARM_CP_64BIT | ARM_CP_IO,
+ .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_MIGRATE,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
- .resetvalue = 0,
- .accessfn = gt_ptimer_access,
+ .accessfn = gt_ptimer_access, .resetfn = arm_cp_reset_ignore,
+ .writefn = gt_cval_write, .raw_writefn = raw_write,
+ },
+ { .name = "CNTP_CVAL_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 2,
+ .access = PL1_RW | PL0_R,
+ .type = ARM_CP_IO,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval),
+ .resetvalue = 0, .accessfn = gt_vtimer_access,
.writefn = gt_cval_write, .raw_writefn = raw_write,
},
{ .name = "CNTV_CVAL", .cp = 15, .crm = 14, .opc1 = 3,
.access = PL1_RW | PL0_R,
- .type = ARM_CP_64BIT | ARM_CP_IO,
+ .type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_NO_MIGRATE,
.fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
- .resetvalue = 0,
- .accessfn = gt_vtimer_access,
+ .accessfn = gt_vtimer_access, .resetfn = arm_cp_reset_ignore,
+ .writefn = gt_cval_write, .raw_writefn = raw_write,
+ },
+ { .name = "CNTV_CVAL_EL0", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 2,
+ .access = PL1_RW | PL0_R,
+ .type = ARM_CP_IO,
+ .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].cval),
+ .resetvalue = 0, .accessfn = gt_vtimer_access,
.writefn = gt_cval_write, .raw_writefn = raw_write,
},
REGINFO_SENTINEL
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 15/31] target-arm: Implement AArch64 ID and feature registers
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (13 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 14/31] target-arm: Implement AArch64 generic timers Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 16/31] target-arm: Implement AArch64 dummy breakpoint and watchpoint registers Peter Maydell
` (16 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64-specific ID and feature registers. Although
many of these are currently not used by the architecture (and so
always zero for all implementations), we define the full set of
fields in the ARMCPU struct for symmetry.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/cpu-qom.h | 10 ++++++++++
target-arm/helper.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index afbd422..00234e1 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -132,6 +132,16 @@ typedef struct ARMCPU {
uint32_t id_isar3;
uint32_t id_isar4;
uint32_t id_isar5;
+ uint64_t id_aa64pfr0;
+ uint64_t id_aa64pfr1;
+ uint64_t id_aa64dfr0;
+ uint64_t id_aa64dfr1;
+ uint64_t id_aa64afr0;
+ uint64_t id_aa64afr1;
+ uint64_t id_aa64isar0;
+ uint64_t id_aa64isar1;
+ uint64_t id_aa64mmfr0;
+ uint64_t id_aa64mmfr1;
uint32_t clidr;
/* The elements of this array are the CCSIDR values for each cache,
* in the order L1DCache, L1ICache, L2DCache, L2ICache, etc.
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 01fd9da..0b2be71 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1856,6 +1856,51 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_arm_cp_regs(cpu, not_v7_cp_reginfo);
}
if (arm_feature(env, ARM_FEATURE_V8)) {
+ /* AArch64 ID registers, which all have impdef reset values */
+ ARMCPRegInfo v8_idregs[] = {
+ { .name = "ID_AA64PFR0_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 0,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64pfr0 },
+ { .name = "ID_AA64PFR1_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 4, .opc2 = 1,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64pfr1},
+ { .name = "ID_AA64DFR0_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 0,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64dfr0 },
+ { .name = "ID_AA64DFR1_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 1,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64dfr1 },
+ { .name = "ID_AA64AFR0_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 4,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64afr0 },
+ { .name = "ID_AA64AFR1_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 5, .opc2 = 5,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64afr1 },
+ { .name = "ID_AA64ISAR0_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 0,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64isar0 },
+ { .name = "ID_AA64ISAR1_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 6, .opc2 = 1,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64isar1 },
+ { .name = "ID_AA64MMFR0_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64mmfr0 },
+ { .name = "ID_AA64MMFR1_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 1,
+ .access = PL1_R, .type = ARM_CP_CONST,
+ .resetvalue = cpu->id_aa64mmfr1 },
+ REGINFO_SENTINEL
+ };
+ define_arm_cp_regs(cpu, v8_idregs);
define_arm_cp_regs(cpu, v8_cp_reginfo);
}
if (arm_feature(env, ARM_FEATURE_MPU)) {
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 16/31] target-arm: Implement AArch64 dummy breakpoint and watchpoint registers
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (14 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 15/31] target-arm: Implement AArch64 ID and feature registers Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 17/31] target-arm: Implement AArch64 OSLAR_EL1 sysreg as WI Peter Maydell
` (15 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
In AArch64 the breakpoint and watchpoint registers are mandatory, so the
kernel always accesses them on bootup. Implement dummy versions, which
read as written but have no actual effect.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/cpu.h | 4 ++++
target-arm/helper.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 48419ae..db74ab7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -216,6 +216,10 @@ typedef struct CPUARMState {
uint32_t c15_diagnostic; /* diagnostic register */
uint32_t c15_power_diagnostic;
uint32_t c15_power_control; /* power control */
+ uint64_t dbgbvr[16]; /* breakpoint value registers */
+ uint64_t dbgbcr[16]; /* breakpoint control registers */
+ uint64_t dbgwvr[16]; /* watchpoint value registers */
+ uint64_t dbgwcr[16]; /* watchpoint control registers */
} cp15;
struct {
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 0b2be71..0eb56ae 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1761,6 +1761,37 @@ static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri)
return CP_ACCESS_OK;
}
+static void define_aarch64_debug_regs(ARMCPU *cpu)
+{
+ /* Define breakpoint and watchpoint registers. These do nothing
+ * but read as written, for now.
+ */
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ ARMCPRegInfo dbgregs[] = {
+ { .name = "DBGBVR", .state = ARM_CP_STATE_AA64,
+ .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 4,
+ .access = PL1_RW,
+ .fieldoffset = offsetof(CPUARMState, cp15.dbgbvr[i]) },
+ { .name = "DBGBCR", .state = ARM_CP_STATE_AA64,
+ .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 5,
+ .access = PL1_RW,
+ .fieldoffset = offsetof(CPUARMState, cp15.dbgbcr[i]) },
+ { .name = "DBGWVR", .state = ARM_CP_STATE_AA64,
+ .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 6,
+ .access = PL1_RW,
+ .fieldoffset = offsetof(CPUARMState, cp15.dbgwvr[i]) },
+ { .name = "DBGWCR", .state = ARM_CP_STATE_AA64,
+ .opc0 = 2, .opc1 = 0, .crn = 0, .crm = i, .opc2 = 7,
+ .access = PL1_RW,
+ .fieldoffset = offsetof(CPUARMState, cp15.dbgwcr[i]) },
+ REGINFO_SENTINEL
+ };
+ define_arm_cp_regs(cpu, dbgregs);
+ }
+}
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
@@ -1902,6 +1933,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
};
define_arm_cp_regs(cpu, v8_idregs);
define_arm_cp_regs(cpu, v8_cp_reginfo);
+ define_aarch64_debug_regs(cpu);
}
if (arm_feature(env, ARM_FEATURE_MPU)) {
/* These are the MPU registers prior to PMSAv6. Any new
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 17/31] target-arm: Implement AArch64 OSLAR_EL1 sysreg as WI
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (15 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 16/31] target-arm: Implement AArch64 dummy breakpoint and watchpoint registers Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 18/31] target-arm: Get MMU index information correct for A64 code Peter Maydell
` (14 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Define a dummy version of the AArch64 OSLAR_EL1 system register
which just ignores writes. Linux will always write to this (it
is the OS lock used for debugging), but we don't support debug.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/helper.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 0eb56ae..5c2be64 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1738,6 +1738,10 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "MDSCR_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 2,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
+ /* We define a dummy WI OSLAR_EL1, because Linux writes to it. */
+ { .name = "OSLAR_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 2, .opc1 = 0, .crn = 1, .crm = 0, .opc2 = 4,
+ .access = PL1_W, .type = ARM_CP_NOP },
REGINFO_SENTINEL
};
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 18/31] target-arm: Get MMU index information correct for A64 code
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (16 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 17/31] target-arm: Implement AArch64 OSLAR_EL1 sysreg as WI Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-25 23:27 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 19/31] target-arm: A64: Implement WFI Peter Maydell
` (13 subsequent siblings)
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Emit the correct MMU index information for loads and stores from
A64 code, rather than hardwiring it to "always kernel mode",
by storing the exception level in the TB flags, and make
cpu_mmu_index() return the right answer when the CPU is in
AArch64 mode.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu.h | 11 ++++++++---
target-arm/translate-a64.c | 2 +-
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index db74ab7..ec0214d 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1057,7 +1057,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
#define MMU_USER_IDX 1
static inline int cpu_mmu_index (CPUARMState *env)
{
- return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0;
+ return arm_current_pl(env) ? 0 : 1;
}
#include "exec/cpu-all.h"
@@ -1084,7 +1084,9 @@ static inline int cpu_mmu_index (CPUARMState *env)
#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
-/* Bit usage when in AArch64 state: currently no bits defined */
+/* Bit usage when in AArch64 state */
+#define ARM_TBFLAG_AA64_EL_SHIFT 0
+#define ARM_TBFLAG_AA64_EL_MASK (0x3 << ARM_TBFLAG_AA64_EL_SHIFT)
/* some convenience accessor macros */
#define ARM_TBFLAG_AARCH64_STATE(F) \
@@ -1103,13 +1105,16 @@ static inline int cpu_mmu_index (CPUARMState *env)
(((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
#define ARM_TBFLAG_BSWAP_CODE(F) \
(((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
+#define ARM_TBFLAG_AA64_EL(F) \
+ (((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
if (is_a64(env)) {
*pc = env->pc;
- *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
+ *flags = ARM_TBFLAG_AARCH64_STATE_MASK
+ | (arm_current_pl(env) << ARM_TBFLAG_AA64_EL_SHIFT);
} else {
int privmode;
*pc = env->regs[15];
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 7c55a90..1714df2 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -8844,7 +8844,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
dc->condexec_mask = 0;
dc->condexec_cond = 0;
#if !defined(CONFIG_USER_ONLY)
- dc->user = 0;
+ dc->user = (ARM_TBFLAG_AA64_EL(tb->flags) == 0);
#endif
dc->vfp_enabled = 0;
dc->vec_len = 0;
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 19/31] target-arm: A64: Implement WFI
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (17 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 18/31] target-arm: Get MMU index information correct for A64 code Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-25 23:20 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 20/31] target-arm: Store AIF bits in env->pstate for AArch32 Peter Maydell
` (12 subsequent siblings)
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the WFI instruction for A64; this just involves wiring
up the instruction, and adding a gen_a64_set_pc_im() which was
accidentally omitted from the A64 decoder top loop.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/translate-a64.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 1714df2..948470f 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1065,9 +1065,11 @@ static void handle_hint(DisasContext *s, uint32_t insn,
switch (selector) {
case 0: /* NOP */
return;
+ case 3: /* WFI */
+ s->is_jmp = DISAS_WFI;
+ return;
case 1: /* YIELD */
case 2: /* WFE */
- case 3: /* WFI */
case 4: /* SEV */
case 5: /* SEVL */
/* we treat all as NOP at least for now */
@@ -8955,6 +8957,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
/* This is a special case because we don't want to just halt the CPU
* if trying to debug across a WFI.
*/
+ gen_a64_set_pc_im(dc->pc);
gen_helper_wfi(cpu_env);
break;
}
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 20/31] target-arm: Store AIF bits in env->pstate for AArch32
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (18 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 19/31] target-arm: A64: Implement WFI Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-25 23:25 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 21/31] target-arm: Implement AArch64 DAIF system register Peter Maydell
` (11 subsequent siblings)
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
To avoid complication in code that otherwise would not need to
care about whether EL1 is AArch32 or AArch64, we should store
the interrupt mask bits (CPSR.AIF in AArch32 and PSTATE.DAIF
in AArch64) in one place consistently regardless of EL1's mode.
Since AArch64 has an extra enable bit (D for debug exceptions)
which isn't visible in AArch32, this means we need to keep
the enables in env->pstate. (This is also consistent with the
general approach we're taking that we handle 32 bit CPUs as
being like AArch64/ARMv8 CPUs but which only run in 32 bit mode.)
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
cpu-exec.c | 4 ++--
hw/arm/pxa2xx.c | 4 ++--
target-arm/cpu.c | 8 ++++----
target-arm/cpu.h | 12 +++++++++---
target-arm/helper.c | 29 +++++++++++++++++------------
5 files changed, 34 insertions(+), 23 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index a6c01f4..ba28e31 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -474,7 +474,7 @@ int cpu_exec(CPUArchState *env)
}
#elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ
- && !(env->uncached_cpsr & CPSR_F)) {
+ && !(env->daif & PSTATE_F)) {
env->exception_index = EXCP_FIQ;
cc->do_interrupt(cpu);
next_tb = 0;
@@ -490,7 +490,7 @@ int cpu_exec(CPUArchState *env)
pc contains a magic address. */
if (interrupt_request & CPU_INTERRUPT_HARD
&& ((IS_M(env) && env->regs[15] < 0xfffffff0)
- || !(env->uncached_cpsr & CPSR_I))) {
+ || !(env->daif & PSTATE_I))) {
env->exception_index = EXCP_IRQ;
cc->do_interrupt(cpu);
next_tb = 0;
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index be6b5f6..f102470 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -272,8 +272,8 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
goto message;
case 3:
- s->cpu->env.uncached_cpsr =
- ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
+ s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC;
+ s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I;
s->cpu->env.cp15.c1_sys = 0;
s->cpu->env.cp15.c1_coproc = 0;
s->cpu->env.cp15.ttbr0_el1 = 0;
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 2f94943..7384e17 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -94,8 +94,7 @@ static void arm_cpu_reset(CPUState *s)
/* Userspace expects access to CTL_EL0 and the cache ops */
env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
#else
- env->pstate = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F
- | PSTATE_MODE_EL1h;
+ env->pstate = PSTATE_MODE_EL1h;
#endif
}
@@ -110,13 +109,14 @@ static void arm_cpu_reset(CPUState *s)
}
#else
/* SVC mode with interrupts disabled. */
- env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
+ env->uncached_cpsr = ARM_CPU_MODE_SVC;
+ env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
/* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
clear at reset. Initial SP and PC are loaded from ROM. */
if (IS_M(env)) {
uint32_t pc;
uint8_t *rom;
- env->uncached_cpsr &= ~CPSR_I;
+ env->daif &= ~PSTATE_I;
rom = rom_ptr(0);
if (rom) {
/* We should really use ldl_phys here, in case the guest
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index ec0214d..571b033 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -135,6 +135,7 @@ typedef struct CPUARMState {
* NZCV are kept in the split out env->CF/VF/NF/ZF, (which have the same
* semantics as for AArch32, as described in the comments on each field)
* nRW (also known as M[4]) is kept, inverted, in env->aarch64
+ * DAIF (exception masks) are kept in env->daif
* all other bits are stored in their correct places in env->pstate
*/
uint32_t pstate;
@@ -164,6 +165,7 @@ typedef struct CPUARMState {
uint32_t GE; /* cpsr[19:16] */
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
+ uint32_t daif; /* exception masks, in the bits they are in in PSTATE */
/* System control coprocessor (cp15) */
struct {
@@ -406,9 +408,11 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
#define CPSR_Z (1U << 30)
#define CPSR_N (1U << 31)
#define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V)
+#define CPSR_AIF (CPSR_A | CPSR_I | CPSR_F)
#define CPSR_IT (CPSR_IT_0_1 | CPSR_IT_2_7)
-#define CACHED_CPSR_BITS (CPSR_T | CPSR_GE | CPSR_IT | CPSR_Q | CPSR_NZCV)
+#define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \
+ | CPSR_NZCV)
/* Bits writable in user mode. */
#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE)
/* Execution state bits. MRS read as zero, MSR writes ignored. */
@@ -431,7 +435,8 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
#define PSTATE_Z (1U << 30)
#define PSTATE_N (1U << 31)
#define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V)
-#define CACHED_PSTATE_BITS (PSTATE_NZCV)
+#define PSTATE_DAIF (PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F)
+#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF)
/* Mode values for AArch64 */
#define PSTATE_MODE_EL3h 13
#define PSTATE_MODE_EL3t 12
@@ -452,7 +457,7 @@ static inline uint32_t pstate_read(CPUARMState *env)
ZF = (env->ZF == 0);
return (env->NF & 0x80000000) | (ZF << 30)
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3)
- | env->pstate;
+ | env->pstate | env->daif;
}
static inline void pstate_write(CPUARMState *env, uint32_t val)
@@ -461,6 +466,7 @@ static inline void pstate_write(CPUARMState *env, uint32_t val)
env->NF = val;
env->CF = (val >> 29) & 1;
env->VF = (val << 3) & 0x80000000;
+ env->daif = val & PSTATE_DAIF;
env->pstate = val & ~CACHED_PSTATE_BITS;
}
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 5c2be64..367fbbe 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2475,7 +2475,7 @@ uint32_t cpsr_read(CPUARMState *env)
(env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
| (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
| ((env->condexec_bits & 0xfc) << 8)
- | (env->GE << 16);
+ | (env->GE << 16) | env->daif;
}
void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
@@ -2502,6 +2502,9 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
env->GE = (val >> 16) & 0xf;
}
+ env->daif &= ~(CPSR_AIF & mask);
+ env->daif |= val & CPSR_AIF & mask;
+
if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
if (bad_mode_switch(env, val & CPSR_M)) {
/* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
@@ -2961,7 +2964,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
env->condexec_bits = 0;
/* Switch to the new mode, and to the correct instruction set. */
env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
- env->uncached_cpsr |= mask;
+ env->daif |= mask;
/* this is a lie, as the was no c1_sys on V4T/V5, but who cares
* and we should just guard the thumb mode on V4 */
if (arm_feature(env, ARM_FEATURE_V4T)) {
@@ -3631,12 +3634,12 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
case 9: /* PSP */
return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
case 16: /* PRIMASK */
- return (env->uncached_cpsr & CPSR_I) != 0;
+ return (env->daif & PSTATE_I) != 0;
case 17: /* BASEPRI */
case 18: /* BASEPRI_MAX */
return env->v7m.basepri;
case 19: /* FAULTMASK */
- return (env->uncached_cpsr & CPSR_F) != 0;
+ return (env->daif & PSTATE_F) != 0;
case 20: /* CONTROL */
return env->v7m.control;
default:
@@ -3683,10 +3686,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
env->v7m.other_sp = val;
break;
case 16: /* PRIMASK */
- if (val & 1)
- env->uncached_cpsr |= CPSR_I;
- else
- env->uncached_cpsr &= ~CPSR_I;
+ if (val & 1) {
+ env->daif |= PSTATE_I;
+ } else {
+ env->daif &= ~PSTATE_I;
+ }
break;
case 17: /* BASEPRI */
env->v7m.basepri = val & 0xff;
@@ -3697,10 +3701,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
env->v7m.basepri = val;
break;
case 19: /* FAULTMASK */
- if (val & 1)
- env->uncached_cpsr |= CPSR_F;
- else
- env->uncached_cpsr &= ~CPSR_F;
+ if (val & 1) {
+ env->daif |= PSTATE_F;
+ } else {
+ env->daif &= ~PSTATE_F;
+ }
break;
case 20: /* CONTROL */
env->v7m.control = val & 3;
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 21/31] target-arm: Implement AArch64 DAIF system register
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (19 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 20/31] target-arm: Store AIF bits in env->pstate for AArch32 Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-17 0:17 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 22/31] target-arm: A64: Implement MSR (immediate) instructions Peter Maydell
` (10 subsequent siblings)
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the DAIF system register which is a view of the
DAIF bits in PSTATE.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
target-arm/helper.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 367fbbe..c50ca5a 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1589,6 +1589,25 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
vfp_set_fpsr(env, value);
}
+static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
+ return CP_ACCESS_TRAP;
+ }
+ return CP_ACCESS_OK;
+}
+
+static uint64_t aa64_daif_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->daif;
+}
+
+static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->daif = value & PSTATE_DAIF;
+}
+
static CPAccessResult aa64_cacheop_access(CPUARMState *env,
const ARMCPRegInfo *ri)
{
@@ -1632,6 +1651,11 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ .name = "NZCV", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 2,
.access = PL0_RW, .type = ARM_CP_NZCV },
+ { .name = "DAIF", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 2,
+ .type = ARM_CP_NO_MIGRATE,
+ .access = PL0_RW, .accessfn = aa64_daif_access,
+ .readfn = aa64_daif_read, .writefn = aa64_daif_write },
{ .name = "FPCR", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
.access = PL0_RW, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 22/31] target-arm: A64: Implement MSR (immediate) instructions
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (20 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 21/31] target-arm: Implement AArch64 DAIF system register Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-25 8:32 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 23/31] target-arm: Implement AArch64 view of CPACR Peter Maydell
` (9 subsequent siblings)
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the MSR (immediate) instructions, which can update the
PSTATE SP and DAIF fields.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/helper.h | 2 ++
target-arm/op_helper.c | 25 +++++++++++++++++++++++++
target-arm/translate-a64.c | 25 ++++++++++++++++++++++++-
3 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 19bd620..4a063c1 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -63,6 +63,8 @@ DEF_HELPER_2(get_cp_reg, i32, env, ptr)
DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
+DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
+
DEF_HELPER_2(get_r13_banked, i32, env, i32)
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index eb0fccd..7d06d2f 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -319,6 +319,31 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip)
return ri->readfn(env, ri);
}
+void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
+{
+ /* MSR_i to update PSTATE. This is OK from EL0 only if UMA is set.
+ * Note that SPSel is never OK from EL0; we rely on handle_msr_i()
+ * to catch that case at translate time.
+ */
+ if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
+ raise_exception(env, EXCP_UDEF);
+ }
+
+ switch (op) {
+ case 0x05: /* SPSel */
+ env->pstate = deposit32(env->pstate, 0, 1, imm);
+ break;
+ case 0x1e: /* DAIFSet */
+ env->daif |= (imm << 6) & PSTATE_DAIF;
+ break;
+ case 0x1f: /* DAIFClear */
+ env->daif &= ~((imm << 6) & PSTATE_DAIF);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
The only way to do that in TCG is a conditional branch, which clobbers
all our temporaries. For now implement these as helper functions. */
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 948470f..1054e38 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1113,7 +1113,30 @@ static void handle_sync(DisasContext *s, uint32_t insn,
static void handle_msr_i(DisasContext *s, uint32_t insn,
unsigned int op1, unsigned int op2, unsigned int crm)
{
- unsupported_encoding(s, insn);
+ int op = op1 << 3 | op2;
+ switch (op) {
+ case 0x05: /* SPSel */
+ if (s->current_pl == 0) {
+ unallocated_encoding(s);
+ return;
+ }
+ /* fall through */
+ case 0x1e: /* DAIFSet */
+ case 0x1f: /* DAIFClear */
+ {
+ TCGv_i32 tcg_imm = tcg_const_i32(crm);
+ TCGv_i32 tcg_op = tcg_const_i32(op);
+ gen_a64_set_pc_im(s->pc - 4);
+ gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
+ tcg_temp_free_i32(tcg_imm);
+ tcg_temp_free_i32(tcg_op);
+ s->is_jmp = DISAS_UPDATE;
+ break;
+ }
+ default:
+ unallocated_encoding(s);
+ return;
+ }
}
static void gen_get_nzcv(TCGv_i64 tcg_rt)
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 23/31] target-arm: Implement AArch64 view of CPACR
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (21 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 22/31] target-arm: A64: Implement MSR (immediate) instructions Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-25 8:34 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 24/31] target-arm: Add utility function for checking AA32/64 state of an EL Peter Maydell
` (8 subsequent siblings)
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Implement the AArch64 view of the CPACR. The AArch64
CPACR is defined to have a lot of RES0 bits, but since
the architecture defines that RES0 bits may be implemented
as reads-as-written and we know that a v8 CPU will have
no registered coprocessors for cp0..cp13 we can safely
implement the whole register this way.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu.h | 2 +-
target-arm/helper.c | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 571b033..1f6f65d 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -172,7 +172,7 @@ typedef struct CPUARMState {
uint32_t c0_cpuid;
uint64_t c0_cssel; /* Cache size selection. */
uint64_t c1_sys; /* System control register. */
- uint32_t c1_coproc; /* Coprocessor access register. */
+ uint64_t c1_coproc; /* Coprocessor access register. */
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
uint32_t c1_scr; /* secure config register. */
uint64_t ttbr0_el1; /* MMU translation table base 0. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index c50ca5a..d35cc73 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -458,7 +458,8 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
*/
{ .name = "WFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0, },
- { .name = "CPACR", .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2,
+ { .name = "CPACR", .state = ARM_CP_STATE_BOTH, .opc0 = 3,
+ .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2,
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_coproc),
.resetvalue = 0, .writefn = cpacr_write },
REGINFO_SENTINEL
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 24/31] target-arm: Add utility function for checking AA32/64 state of an EL
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (22 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 23/31] target-arm: Implement AArch64 view of CPACR Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-25 8:36 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 25/31] target-arm: Define exception record for AArch64 exceptions Peter Maydell
` (7 subsequent siblings)
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
There are various situations where we need to behave differently
depending on whether a given exception level is in AArch64 or
AArch32 state. The state of the current exception level is stored
in env->aarch64, but there's no equivalent guest-visible architected
state bits for the status of the exception levels "above" the
current one which may still affect execution. At the moment we
only support EL1 (ie no EL2 or EL3) and insist that AArch64
capable CPUs run with EL1 in AArch64 state, but these may change
in the future, so abstract out the "what state is this?" check
into a utility function which can be enhanced later if necessary.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 1f6f65d..f530333 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -633,6 +633,22 @@ static inline int arm_feature(CPUARMState *env, int feature)
return (env->features & (1ULL << feature)) != 0;
}
+/* Return true if the specified exception level is running in AArch64 state. */
+static inline bool arm_el_is_aa64(CPUARMState *env, int el)
+{
+ /* We don't currently support EL2 or EL3, and this isn't valid for EL0
+ * (if we're in EL0, is_a64() is what you want, and if we're not in EL0
+ * then the state of EL0 isn't well defined.)
+ */
+ assert(el == 1);
+ /* AArch64-capable CPUs always run with EL1 in AArch64 mode. This
+ * is a QEMU-imposed simplification which we may wish to change later.
+ * If we in future support EL2 and/or EL3, then the state of lower
+ * exception levels is controlled by the HCR.RW and SCR.RW bits.
+ */
+ return arm_feature(env, ARM_FEATURE_AARCH64);
+}
+
void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
/* Interface between CPU and Interrupt controller. */
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 25/31] target-arm: Define exception record for AArch64 exceptions
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (23 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 24/31] target-arm: Add utility function for checking AA32/64 state of an EL Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 26/31] target-arm: Provide correct syndrome information for cpreg access traps Peter Maydell
` (6 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
For AArch32 exceptions, the only information provided about
the cause of an exception is the individual exception type (data
abort, undef, etc), which we store in env->exception_index. For
AArch64, the CPU provides much more detail about the cause of
the exception, which can be found in the syndrome register.
Create a set of fields in CPUARMState which must be filled in
whenever an exception is raised, so that exception entry can
correctly fill in the syndrome register for the guest.
This includes the information which in AArch32 appears in
the DFAR and IFAR (fault address registers) and the DFSR
and IFSR (fault status registers) for data aborts and
prefetch aborts, since if we end up taking the MMU fault
to AArch64 rather than AArch32 this will need to end up
in different system registers.
This patch does a refactoring which moves the setting of the
AArch32 DFAR/DFSR/IFAR/IFSR from the point where the exception
is raised to the point where it is taken. (This is no change
for cores with an MMU, retains the existing clearly incorrect
behaviour for ARM946 of trashing the MP access permissions
registers which share the c5_data and c5_insn state fields,
and has no effect for v7M because we don't implement its
MPU fault status or address registers.)
As a side effect of the cleanup we fix a bug in the AArch64
linux-user mode code where we were passing a 64 bit fault
address through the 32 bit c6_data/c6_insn fields: it now
goes via the always-64-bit exception.vaddress.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
linux-user/main.c | 56 ++++++++++++++++++++++------------------------------
target-arm/cpu.h | 15 ++++++++++++++
target-arm/helper.c | 23 ++++++++++++---------
target-arm/machine.c | 3 +++
4 files changed, 56 insertions(+), 41 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index cabc9e1..0d8e295 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -483,17 +483,17 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
addr = env->regs[2];
if (get_user_u64(oldval, env->regs[0])) {
- env->cp15.c6_data = env->regs[0];
+ env->exception.vaddress = env->regs[0];
goto segv;
};
if (get_user_u64(newval, env->regs[1])) {
- env->cp15.c6_data = env->regs[1];
+ env->exception.vaddress = env->regs[1];
goto segv;
};
if (get_user_u64(val, addr)) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto segv;
}
@@ -501,7 +501,7 @@ static void arm_kernel_cmpxchg64_helper(CPUARMState *env)
val = newval;
if (put_user_u64(val, addr)) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto segv;
};
@@ -523,7 +523,7 @@ segv:
info.si_errno = 0;
/* XXX: check env->error_code */
info.si_code = TARGET_SEGV_MAPERR;
- info._sifields._sigfault._addr = env->cp15.c6_data;
+ info._sifields._sigfault._addr = env->exception.vaddress;
queue_signal(env, info.si_signo, &info);
end_exclusive();
@@ -620,14 +620,14 @@ static int do_strex(CPUARMState *env)
abort();
}
if (segv) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto done;
}
if (size == 3) {
uint32_t valhi;
segv = get_user_u32(valhi, addr + 4);
if (segv) {
- env->cp15.c6_data = addr + 4;
+ env->exception.vaddress = addr + 4;
goto done;
}
val = deposit64(val, 32, 32, valhi);
@@ -650,14 +650,14 @@ static int do_strex(CPUARMState *env)
break;
}
if (segv) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto done;
}
if (size == 3) {
val = env->regs[(env->exclusive_info >> 12) & 0xf];
segv = put_user_u32(val, addr + 4);
if (segv) {
- env->cp15.c6_data = addr + 4;
+ env->exception.vaddress = addr + 4;
goto done;
}
}
@@ -832,12 +832,14 @@ void cpu_loop(CPUARMState *env)
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
+ case EXCP_STREX:
+ if (!do_strex(env)) {
+ break;
+ }
+ /* fall through for segv */
case EXCP_PREFETCH_ABORT:
- addr = env->cp15.c6_insn;
- goto do_segv;
case EXCP_DATA_ABORT:
- addr = env->cp15.c6_data;
- do_segv:
+ addr = env->exception.vaddress;
{
info.si_signo = SIGSEGV;
info.si_errno = 0;
@@ -865,12 +867,6 @@ void cpu_loop(CPUARMState *env)
if (do_kernel_trap(env))
goto error;
break;
- case EXCP_STREX:
- if (do_strex(env)) {
- addr = env->cp15.c6_data;
- goto do_segv;
- }
- break;
default:
error:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
@@ -933,7 +929,7 @@ static int do_strex_a64(CPUARMState *env)
abort();
}
if (segv) {
- env->cp15.c6_data = addr;
+ env->exception.vaddress = addr;
goto error;
}
if (val != env->exclusive_val) {
@@ -946,7 +942,7 @@ static int do_strex_a64(CPUARMState *env)
segv = get_user_u64(val, addr + 8);
}
if (segv) {
- env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
+ env->exception.vaddress = addr + (size == 2 ? 4 : 8);
goto error;
}
if (val != env->exclusive_high) {
@@ -979,7 +975,7 @@ static int do_strex_a64(CPUARMState *env)
segv = put_user_u64(val, addr + 8);
}
if (segv) {
- env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
+ env->exception.vaddress = addr + (size == 2 ? 4 : 8);
goto error;
}
}
@@ -1035,12 +1031,14 @@ void cpu_loop(CPUARMState *env)
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info);
break;
+ case EXCP_STREX:
+ if (!do_strex_a64(env)) {
+ break;
+ }
+ /* fall through for segv */
case EXCP_PREFETCH_ABORT:
- addr = env->cp15.c6_insn;
- goto do_segv;
case EXCP_DATA_ABORT:
- addr = env->cp15.c6_data;
- do_segv:
+ addr = env->exception.vaddress;
info.si_signo = SIGSEGV;
info.si_errno = 0;
/* XXX: check env->error_code */
@@ -1058,12 +1056,6 @@ void cpu_loop(CPUARMState *env)
queue_signal(env, info.si_signo, &info);
}
break;
- case EXCP_STREX:
- if (do_strex_a64(env)) {
- addr = env->cp15.c6_data;
- goto do_segv;
- }
- break;
default:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f530333..cf094c6 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -234,6 +234,21 @@ typedef struct CPUARMState {
int pending_exception;
} v7m;
+ /* Information associated with an exception about to be taken:
+ * code which raises an exception must set env->exception_index and
+ * the relevant parts of this structure; the cpu_do_interrupt function
+ * will then set the guest-visible registers as part of the exception
+ * entry process.
+ */
+ struct {
+ uint32_t syndrome; /* AArch64 format syndrome register */
+ uint32_t fsr; /* AArch32 format fault status register info */
+ uint64_t vaddress; /* virtual addr associated with exception, if any */
+ /* If we implement EL2 we will also need to store information
+ * about the intermediate physical address for stage 2 faults.
+ */
+ } exception;
+
/* Thumb-2 EE state. */
uint32_t teecr;
uint32_t teehbr;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d35cc73..2d66165 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2611,12 +2611,11 @@ void arm_cpu_do_interrupt(CPUState *cs)
int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
int mmu_idx)
{
+ env->exception.vaddress = address;
if (rw == 2) {
env->exception_index = EXCP_PREFETCH_ABORT;
- env->cp15.c6_insn = address;
} else {
env->exception_index = EXCP_DATA_ABORT;
- env->cp15.c6_data = address;
}
return 1;
}
@@ -2819,6 +2818,9 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
return;
case EXCP_PREFETCH_ABORT:
case EXCP_DATA_ABORT:
+ /* TODO: if we implemented the MPU registers, this is where we
+ * should set the MMFAR, etc from exception.fsr and exception.vaddress.
+ */
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
return;
case EXCP_BKPT:
@@ -2933,9 +2935,11 @@ void arm_cpu_do_interrupt(CPUState *cs)
return;
}
}
- env->cp15.c5_insn = 2;
+ env->exception.fsr = 2;
/* Fall through to prefetch abort. */
case EXCP_PREFETCH_ABORT:
+ env->cp15.c5_insn = env->exception.fsr;
+ env->cp15.c6_insn = env->exception.vaddress;
qemu_log_mask(CPU_LOG_INT, "...with IFSR 0x%x IFAR 0x%x\n",
env->cp15.c5_insn, env->cp15.c6_insn);
new_mode = ARM_CPU_MODE_ABT;
@@ -2944,6 +2948,8 @@ void arm_cpu_do_interrupt(CPUState *cs)
offset = 4;
break;
case EXCP_DATA_ABORT:
+ env->cp15.c5_data = env->exception.fsr;
+ env->cp15.c6_data = env->exception.vaddress;
qemu_log_mask(CPU_LOG_INT, "...with DFSR 0x%x DFAR 0x%x\n",
env->cp15.c5_data, env->cp15.c6_data);
new_mode = ARM_CPU_MODE_ABT;
@@ -3589,16 +3595,15 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address,
}
if (access_type == 2) {
- env->cp15.c5_insn = ret;
- env->cp15.c6_insn = address;
env->exception_index = EXCP_PREFETCH_ABORT;
} else {
- env->cp15.c5_data = ret;
- if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6))
- env->cp15.c5_data |= (1 << 11);
- env->cp15.c6_data = address;
+ if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6)) {
+ ret |= (1 << 11);
+ }
env->exception_index = EXCP_DATA_ABORT;
}
+ env->exception.vaddress = address;
+ env->exception.fsr = ret;
return 1;
}
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 8f9e7d4..fc8825e 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -257,6 +257,9 @@ const VMStateDescription vmstate_arm_cpu = {
VMSTATE_UINT64(env.exclusive_val, ARMCPU),
VMSTATE_UINT64(env.exclusive_high, ARMCPU),
VMSTATE_UINT64(env.features, ARMCPU),
+ VMSTATE_UINT32(env.exception.syndrome, ARMCPU),
+ VMSTATE_UINT32(env.exception.fsr, ARMCPU),
+ VMSTATE_UINT64(env.exception.vaddress, ARMCPU),
VMSTATE_TIMER(gt_timer[GTIMER_PHYS], ARMCPU),
VMSTATE_TIMER(gt_timer[GTIMER_VIRT], ARMCPU),
VMSTATE_END_OF_LIST()
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 26/31] target-arm: Provide correct syndrome information for cpreg access traps
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (24 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 25/31] target-arm: Define exception record for AArch64 exceptions Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 27/31] target-arm: Add support for generating exceptions with syndrome information Peter Maydell
` (5 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
For exceptions taken to AArch64, if a coprocessor/system register
access fails due to a trap or enable bit then the syndrome information
must include details of the failing instruction (crn/crm/opc1/opc2
fields, etc). Make the decoder construct the syndrome information
at translate time so it can be passed at runtime to the access-check
helper function and used as required.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu.h | 128 +++++++++++++++++++++++++++++++++++++++++++++
target-arm/helper.h | 2 +-
target-arm/op_helper.c | 8 +--
target-arm/translate-a64.c | 8 ++-
target-arm/translate.c | 45 +++++++++++++++-
5 files changed, 184 insertions(+), 7 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cf094c6..3ec752e 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -571,6 +571,134 @@ enum arm_fprounding {
int arm_rmode_to_sf(int rmode);
+/* Valid Syndrome Register EC field values */
+enum arm_exception_class {
+ EC_UNCATEGORIZED = 0,
+ EC_WFX_TRAP = 1,
+ EC_CP15RTTRAP = 3,
+ EC_CP15RRTTRAP = 4,
+ EC_CP14RTTRAP = 5,
+ EC_CP14DTTRAP = 6,
+ EC_ADVSIMDFPACCESSTRAP = 7,
+ EC_FPIDTRAP = 8,
+ EC_CP14RRTTRAP = 0xc,
+ EC_ILLEGALSTATE = 0xe,
+ EC_AA32_SVC = 0x11,
+ EC_AA32_HVC = 0x12,
+ EC_AA32_SMC = 0x13,
+ EC_AA64_SVC = 0x15,
+ EC_AA64_HVC = 0x16,
+ EC_AA64_SMC = 0x17,
+ EC_SYSTEMREGISTERTRAP = 0x18,
+ EC_INSNABORT = 0x20,
+ EC_INSNABORT_SAME_EL = 0x21,
+ EC_PCALIGNMENT = 0x22,
+ EC_DATAABORT = 0x24,
+ EC_DATAABORT_SAME_EL = 0x25,
+ EC_SPALIGNMENT = 0x26,
+ EC_AA32_FPTRAP = 0x28,
+ EC_AA64_FPTRAP = 0x2c,
+ EC_SERROR = 0x2f,
+ EC_BREAKPOINT = 0x30,
+ EC_BREAKPOINT_SAME_EL = 0x31,
+ EC_SOFTWARESTEP = 0x32,
+ EC_SOFTWARESTEP_SAME_EL = 0x33,
+ EC_WATCHPOINT = 0x34,
+ EC_WATCHPOINT_SAME_EL = 0x35,
+ EC_AA32_BKPT = 0x38,
+ EC_VECTORCATCH = 0x3a,
+ EC_AA64_BKPT = 0x3c,
+};
+
+#define ARM_EL_EC_SHIFT 26
+#define ARM_EL_IL_SHIFT 25
+#define ARM_EL_IL (1 << ARM_EL_IL_SHIFT)
+
+/* Utility functions for constructing various kinds of syndrome value.
+ * Note that in general we follow the AArch64 syndrome values; in a
+ * few cases the value in HSR for exceptions taken to AArch32 Hyp
+ * mode differs slightly, so if we ever implemented Hyp mode then the
+ * syndrome value would need some massaging on exception entry.
+ * (One example of this is that AArch64 defaults to IL bit set for
+ * exceptions which don't specifically indicate information about the
+ * trapping instruction, whereas AArch32 defaults to IL bit clear.)
+ */
+static inline uint32_t syn_uncategorized(void)
+{
+ return (EC_UNCATEGORIZED << ARM_EL_EC_SHIFT) | ARM_EL_IL;
+}
+
+static inline uint32_t syn_aa64_svc(uint32_t imm16)
+{
+ return (EC_AA64_SVC << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa32_svc(uint32_t imm16, bool is_thumb)
+{
+ return (EC_AA32_SVC << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
+ | (is_thumb ? 0 : ARM_EL_IL);
+}
+
+static inline uint32_t syn_aa64_bkpt(uint32_t imm16)
+{
+ return (EC_AA64_BKPT << ARM_EL_EC_SHIFT) | ARM_EL_IL | (imm16 & 0xffff);
+}
+
+static inline uint32_t syn_aa32_bkpt(uint32_t imm16, bool is_thumb)
+{
+ return (EC_AA32_BKPT << ARM_EL_EC_SHIFT) | (imm16 & 0xffff)
+ | (is_thumb ? 0 : ARM_EL_IL);
+}
+
+static inline uint32_t syn_aa64_sysregtrap(int op0, int op1, int op2,
+ int crn, int crm, int rt,
+ int isread)
+{
+ return (EC_SYSTEMREGISTERTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL
+ | (op0 << 20) | (op2 << 17) | (op1 << 14) | (crn << 10) | (rt << 5)
+ | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp14_rt_trap(int cv, int cond, int opc1, int opc2,
+ int crn, int crm, int rt, int isread,
+ bool is_thumb)
+{
+ return (EC_CP14RTTRAP << ARM_EL_EC_SHIFT)
+ | (is_thumb ? 0 : ARM_EL_IL)
+ | (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
+ | (crn << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp15_rt_trap(int cv, int cond, int opc1, int opc2,
+ int crn, int crm, int rt, int isread,
+ bool is_thumb)
+{
+ return (EC_CP15RTTRAP << ARM_EL_EC_SHIFT)
+ | (is_thumb ? 0 : ARM_EL_IL)
+ | (cv << 24) | (cond << 20) | (opc2 << 17) | (opc1 << 14)
+ | (crn << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp14_rrt_trap(int cv, int cond, int opc1, int crm,
+ int rt, int rt2, int isread,
+ bool is_thumb)
+{
+ return (EC_CP14RRTTRAP << ARM_EL_EC_SHIFT)
+ | (is_thumb ? 0 : ARM_EL_IL)
+ | (cv << 24) | (cond << 20) | (opc1 << 16)
+ | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
+static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
+ int rt, int rt2, int isread,
+ bool is_thumb)
+{
+ return (EC_CP15RRTTRAP << ARM_EL_EC_SHIFT)
+ | (is_thumb ? 0 : ARM_EL_IL)
+ | (cv << 24) | (cond << 20) | (opc1 << 16)
+ | (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
+}
+
enum arm_cpu_mode {
ARM_CPU_MODE_USR = 0x10,
ARM_CPU_MODE_FIQ = 0x11,
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 4a063c1..174c615 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -57,7 +57,7 @@ DEF_HELPER_1(cpsr_read, i32, env)
DEF_HELPER_3(v7m_msr, void, env, i32, i32)
DEF_HELPER_2(v7m_mrs, i32, env, i32)
-DEF_HELPER_2(access_check_cp_reg, void, env, ptr)
+DEF_HELPER_3(access_check_cp_reg, void, env, ptr, i32)
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 7d06d2f..fa383b3 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -273,17 +273,17 @@ void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val)
}
}
-void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip)
+void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome)
{
const ARMCPRegInfo *ri = rip;
switch (ri->accessfn(env, ri)) {
case CP_ACCESS_OK:
return;
case CP_ACCESS_TRAP:
+ env->exception.syndrome = syndrome;
+ break;
case CP_ACCESS_TRAP_UNCATEGORIZED:
- /* These cases will eventually need to generate different
- * syndrome information.
- */
+ env->exception.syndrome = syn_uncategorized();
break;
default:
g_assert_not_reached();
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 1054e38..d42f23f 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1223,10 +1223,16 @@ static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
* runtime; this may result in an exception.
*/
TCGv_ptr tmpptr;
+ TCGv_i32 tcg_syn;
+ uint32_t syndrome;
+
gen_a64_set_pc_im(s->pc - 4);
tmpptr = tcg_const_ptr(ri);
- gen_helper_access_check_cp_reg(cpu_env, tmpptr);
+ syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
+ tcg_syn = tcg_const_i32(syndrome);
+ gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
tcg_temp_free_ptr(tmpptr);
+ tcg_temp_free_i32(tcg_syn);
}
/* Handle special cases first */
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 6ccf0ba..42eb785 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6842,10 +6842,53 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
* runtime; this may result in an exception.
*/
TCGv_ptr tmpptr;
+ TCGv_i32 tcg_syn;
+ uint32_t syndrome;
+
+ /* Note that since we are an implementation which takes an
+ * exception on a trapped conditional instruction only if the
+ * instruction passes its condition code check, we can take
+ * advantage of the clause in the ARM ARM that allows us to set
+ * the COND field in the instruction to 0xE in all cases.
+ * We could fish the actual condition out of the insn (ARM)
+ * or the condexec bits (Thumb) but it isn't necessary.
+ */
+ switch (cpnum) {
+ case 14:
+ if (is64) {
+ syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
+ isread, s->thumb);
+ } else {
+ syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
+ rt, isread, s->thumb);
+ }
+ break;
+ case 15:
+ if (is64) {
+ syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
+ isread, s->thumb);
+ } else {
+ syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
+ rt, isread, s->thumb);
+ }
+ break;
+ default:
+ /* ARMv8 defines that only coprocessors 14 and 15 exist,
+ * so this can only happen if this is an ARMv7 or earlier CPU,
+ * in which case the syndrome information won't actually be
+ * guest visible.
+ */
+ assert(!arm_feature(env, ARM_FEATURE_V8));
+ syndrome = syn_uncategorized();
+ break;
+ }
+
gen_set_pc_im(s, s->pc);
tmpptr = tcg_const_ptr(ri);
- gen_helper_access_check_cp_reg(cpu_env, tmpptr);
+ tcg_syn = tcg_const_i32(syndrome);
+ gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
tcg_temp_free_ptr(tmpptr);
+ tcg_temp_free_i32(tcg_syn);
}
/* Handle special cases first */
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 27/31] target-arm: Add support for generating exceptions with syndrome information
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (25 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 26/31] target-arm: Provide correct syndrome information for cpreg access traps Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 28/31] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set Peter Maydell
` (4 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Add new helpers exception_with_syndrome (for generating an exception
with syndrome information) and exception_uncategorized (for generating
an exception with "Unknown or Uncategorized Reason", which have a syndrome
register value of zero), and use them to generate the correct syndrome
information for exceptions which are raised directly from generated code.
This patch includes moving the A32/T32 gen_exception_insn functions
further up in the source file; they will be needed for "VFP/Neon disabled"
exception generation later.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu.h | 14 ++++++
target-arm/helper.h | 3 +-
target-arm/op_helper.c | 19 ++++++++-
target-arm/translate-a64.c | 49 +++++++++++++++------
target-arm/translate.c | 103 ++++++++++++++++++++++++++++-----------------
target-arm/translate.h | 4 ++
6 files changed, 138 insertions(+), 54 deletions(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 3ec752e..bf8b7d5 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -52,6 +52,20 @@
#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */
#define EXCP_STREX 10
+static inline bool excp_is_internal(int excp)
+{
+ /* Return true if this exception number represents a QEMU-internal
+ * exception that will not be passed to the guest.
+ */
+ return excp == EXCP_INTERRUPT
+ || excp == EXCP_HLT
+ || excp == EXCP_DEBUG
+ || excp == EXCP_HALTED
+ || excp == EXCP_EXCEPTION_EXIT
+ || excp == EXCP_KERNEL_TRAP
+ || excp == EXCP_STREX;
+}
+
#define ARMV7M_EXCP_RESET 1
#define ARMV7M_EXCP_NMI 2
#define ARMV7M_EXCP_HARD 3
diff --git a/target-arm/helper.h b/target-arm/helper.h
index 174c615..8986fcd 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -48,7 +48,8 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
-DEF_HELPER_2(exception, void, env, i32)
+DEF_HELPER_2(exception_internal, void, env, i32)
+DEF_HELPER_3(exception_with_syndrome, void, env, i32, i32)
DEF_HELPER_1(wfi, void, env)
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index fa383b3..0149e2f 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -225,9 +225,26 @@ void HELPER(wfi)(CPUARMState *env)
cpu_loop_exit(env);
}
-void HELPER(exception)(CPUARMState *env, uint32_t excp)
+/* Raise an internal-to-QEMU exception. This is limited to only
+ * those EXCP values which are special cases for QEMU to interrupt
+ * execution and not to be used for exceptions which are passed to
+ * the guest (those must all have syndrome information and thus should
+ * use exception_with_syndrome).
+ */
+void HELPER(exception_internal)(CPUARMState *env, uint32_t excp)
+{
+ assert(excp_is_internal(excp));
+ env->exception_index = excp;
+ cpu_loop_exit(env);
+}
+
+/* Raise an exception with the specified syndrome register value */
+void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
+ uint32_t syndrome)
{
+ assert(!excp_is_internal(excp));
env->exception_index = excp;
+ env->exception.syndrome = syndrome;
cpu_loop_exit(env);
}
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index d42f23f..af43aab 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -170,18 +170,37 @@ void gen_a64_set_pc_im(uint64_t val)
tcg_gen_movi_i64(cpu_pc, val);
}
-static void gen_exception(int excp)
+static void gen_exception_internal(int excp)
{
- TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_movi_i32(tmp, excp);
- gen_helper_exception(cpu_env, tmp);
- tcg_temp_free_i32(tmp);
+ TCGv_i32 tcg_excp = tcg_const_i32(excp);
+
+ assert(excp_is_internal(excp));
+ gen_helper_exception_internal(cpu_env, tcg_excp);
+ tcg_temp_free_i32(tcg_excp);
+}
+
+static void gen_exception(int excp, uint32_t syndrome)
+{
+ TCGv_i32 tcg_excp = tcg_const_i32(excp);
+ TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
+
+ gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn);
+ tcg_temp_free_i32(tcg_syn);
+ tcg_temp_free_i32(tcg_excp);
+}
+
+static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
+{
+ gen_a64_set_pc_im(s->pc - offset);
+ gen_exception_internal(excp);
+ s->is_jmp = DISAS_EXC;
}
-static void gen_exception_insn(DisasContext *s, int offset, int excp)
+static void gen_exception_insn(DisasContext *s, int offset, int excp,
+ uint32_t syndrome)
{
gen_a64_set_pc_im(s->pc - offset);
- gen_exception(excp);
+ gen_exception(excp, syndrome);
s->is_jmp = DISAS_EXC;
}
@@ -213,7 +232,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
} else {
gen_a64_set_pc_im(dest);
if (s->singlestep_enabled) {
- gen_exception(EXCP_DEBUG);
+ gen_exception_internal(EXCP_DEBUG);
}
tcg_gen_exit_tb(0);
s->is_jmp = DISAS_JUMP;
@@ -222,7 +241,8 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
static void unallocated_encoding(DisasContext *s)
{
- gen_exception_insn(s, 4, EXCP_UDEF);
+ /* Unallocated and reserved encodings are uncategorized */
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
}
#define unsupported_encoding(s, insn) \
@@ -1354,6 +1374,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
{
int opc = extract32(insn, 21, 3);
int op2_ll = extract32(insn, 0, 5);
+ int imm16 = extract32(insn, 5, 16);
switch (opc) {
case 0:
@@ -1364,7 +1385,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
unallocated_encoding(s);
break;
}
- gen_exception_insn(s, 0, EXCP_SWI);
+ gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
break;
case 1:
if (op2_ll != 0) {
@@ -1372,7 +1393,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
break;
}
/* BRK */
- gen_exception_insn(s, 0, EXCP_BKPT);
+ gen_exception_insn(s, 0, EXCP_BKPT, syn_aa64_bkpt(imm16));
break;
case 2:
if (op2_ll != 0) {
@@ -1521,7 +1542,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
tcg_gen_mov_i64(cpu_exclusive_test, addr);
tcg_gen_movi_i32(cpu_exclusive_info,
size | is_pair << 2 | (rd << 4) | (rt << 9) | (rt2 << 14));
- gen_exception_insn(s, 4, EXCP_STREX);
+ gen_exception_internal_insn(s, 4, EXCP_STREX);
}
#else
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
@@ -8901,7 +8922,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == dc->pc) {
- gen_exception_insn(dc, 0, EXCP_DEBUG);
+ gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
/* Advance PC so that clearing the breakpoint will
invalidate this TB. */
dc->pc += 2;
@@ -8964,7 +8985,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
if (dc->is_jmp != DISAS_JUMP) {
gen_a64_set_pc_im(dc->pc);
}
- gen_exception(EXCP_DEBUG);
+ gen_exception_internal(EXCP_DEBUG);
} else {
switch (dc->is_jmp) {
case DISAS_NEXT:
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 42eb785..30eafc3 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -182,12 +182,23 @@ static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
/* Set NZCV flags from the high 4 bits of var. */
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
-static void gen_exception(int excp)
+static void gen_exception_internal(int excp)
{
- TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_movi_i32(tmp, excp);
- gen_helper_exception(cpu_env, tmp);
- tcg_temp_free_i32(tmp);
+ TCGv_i32 tcg_excp = tcg_const_i32(excp);
+
+ assert(excp_is_internal(excp));
+ gen_helper_exception_internal(cpu_env, tcg_excp);
+ tcg_temp_free_i32(tcg_excp);
+}
+
+static void gen_exception(int excp, uint32_t syndrome)
+{
+ TCGv_i32 tcg_excp = tcg_const_i32(excp);
+ TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
+
+ gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn);
+ tcg_temp_free_i32(tcg_syn);
+ tcg_temp_free_i32(tcg_excp);
}
static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
@@ -899,6 +910,33 @@ static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
tcg_gen_movi_i32(cpu_R[15], val);
}
+static inline void
+gen_set_condexec (DisasContext *s)
+{
+ if (s->condexec_mask) {
+ uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
+ TCGv_i32 tmp = tcg_temp_new_i32();
+ tcg_gen_movi_i32(tmp, val);
+ store_cpu_field(tmp, condexec_bits);
+ }
+}
+
+static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
+{
+ gen_set_condexec(s);
+ gen_set_pc_im(s, s->pc - offset);
+ gen_exception_internal(excp);
+ s->is_jmp = DISAS_JUMP;
+}
+
+static void gen_exception_insn(DisasContext *s, int offset, int excp, int syn)
+{
+ gen_set_condexec(s);
+ gen_set_pc_im(s, s->pc - offset);
+ gen_exception(excp, syn);
+ s->is_jmp = DISAS_JUMP;
+}
+
/* Force a TB lookup after an instruction that changes the CPU state. */
static inline void gen_lookup_tb(DisasContext *s)
{
@@ -3912,25 +3950,6 @@ static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
s->is_jmp = DISAS_UPDATE;
}
-static inline void
-gen_set_condexec (DisasContext *s)
-{
- if (s->condexec_mask) {
- uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
- TCGv_i32 tmp = tcg_temp_new_i32();
- tcg_gen_movi_i32(tmp, val);
- store_cpu_field(tmp, condexec_bits);
- }
-}
-
-static void gen_exception_insn(DisasContext *s, int offset, int excp)
-{
- gen_set_condexec(s);
- gen_set_pc_im(s, s->pc - offset);
- gen_exception(excp);
- s->is_jmp = DISAS_JUMP;
-}
-
static void gen_nop_hint(DisasContext *s, int val)
{
switch (val) {
@@ -7140,7 +7159,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
tcg_gen_movi_i32(cpu_exclusive_info,
size | (rd << 4) | (rt << 8) | (rt2 << 12));
- gen_exception_insn(s, 4, EXCP_STREX);
+ gen_exception_internal_insn(s, 4, EXCP_STREX);
}
#else
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
@@ -7620,6 +7639,8 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
store_reg(s, rd, tmp);
break;
case 7:
+ {
+ int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
/* SMC instruction (op1 == 3)
and undefined instructions (op1 == 0 || op1 == 2)
will trap */
@@ -7628,8 +7649,9 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
}
/* bkpt */
ARCH(5);
- gen_exception_insn(s, 4, EXCP_BKPT);
+ gen_exception_insn(s, 4, EXCP_BKPT, syn_aa32_bkpt(imm16, false));
break;
+ }
case 0x8: /* signed multiply */
case 0xa:
case 0xc:
@@ -8636,11 +8658,12 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
case 0xf:
/* swi */
gen_set_pc_im(s, s->pc);
+ s->svc_imm = extract32(insn, 0, 24);
s->is_jmp = DISAS_SWI;
break;
default:
illegal_op:
- gen_exception_insn(s, 4, EXCP_UDEF);
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
break;
}
}
@@ -10425,9 +10448,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
break;
case 0xe: /* bkpt */
+ {
+ int imm8 = extract32(insn, 0, 8);
ARCH(5);
- gen_exception_insn(s, 2, EXCP_BKPT);
+ gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true));
break;
+ }
case 0xa: /* rev */
ARCH(6);
@@ -10544,6 +10570,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
if (cond == 0xf) {
/* swi */
gen_set_pc_im(s, s->pc);
+ s->svc_imm = extract32(insn, 0, 8);
s->is_jmp = DISAS_SWI;
break;
}
@@ -10579,11 +10606,11 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
}
return;
undef32:
- gen_exception_insn(s, 4, EXCP_UDEF);
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
return;
illegal_op:
undef:
- gen_exception_insn(s, 2, EXCP_UDEF);
+ gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized());
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
@@ -10703,7 +10730,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
if (dc->pc >= 0xffff0000) {
/* We always get here via a jump, so know we are not in a
conditional execution block. */
- gen_exception(EXCP_KERNEL_TRAP);
+ gen_exception_internal(EXCP_KERNEL_TRAP);
dc->is_jmp = DISAS_UPDATE;
break;
}
@@ -10711,7 +10738,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
if (dc->pc >= 0xfffffff0 && IS_M(env)) {
/* We always get here via a jump, so know we are not in a
conditional execution block. */
- gen_exception(EXCP_EXCEPTION_EXIT);
+ gen_exception_internal(EXCP_EXCEPTION_EXIT);
dc->is_jmp = DISAS_UPDATE;
break;
}
@@ -10720,7 +10747,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == dc->pc) {
- gen_exception_insn(dc, 0, EXCP_DEBUG);
+ gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
/* Advance PC so that clearing the breakpoint will
invalidate this TB. */
dc->pc += 2;
@@ -10800,9 +10827,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
if (dc->condjmp) {
gen_set_condexec(dc);
if (dc->is_jmp == DISAS_SWI) {
- gen_exception(EXCP_SWI);
+ gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
} else {
- gen_exception(EXCP_DEBUG);
+ gen_exception_internal(EXCP_DEBUG);
}
gen_set_label(dc->condlabel);
}
@@ -10812,11 +10839,11 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
}
gen_set_condexec(dc);
if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
- gen_exception(EXCP_SWI);
+ gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
} else {
/* FIXME: Single stepping a WFI insn will not halt
the CPU. */
- gen_exception(EXCP_DEBUG);
+ gen_exception_internal(EXCP_DEBUG);
}
} else {
/* While branches must always occur at the end of an IT block,
@@ -10845,7 +10872,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
gen_helper_wfi(cpu_env);
break;
case DISAS_SWI:
- gen_exception(EXCP_SWI);
+ gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
break;
}
if (dc->condjmp) {
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 67da699..fa029a0 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -23,6 +23,10 @@ typedef struct DisasContext {
int vfp_enabled;
int vec_len;
int vec_stride;
+ /* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
+ * so that top level loop can generate correct syndrome information.
+ */
+ uint32_t svc_imm;
int aarch64;
int current_pl;
GHashTable *cp_regs;
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 28/31] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (26 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 27/31] target-arm: Add support for generating exceptions with syndrome information Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 29/31] target-arm: A64: Add assertion that FP access was checked Peter Maydell
` (3 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
For the A64 instruction set, the only FP/Neon disable trap
is the CPACR FPEN bits, which may indicate "enabled", "disabled"
or "disabled for EL0". Add a bit to the AArch64 tb flags indicating
whether FP/Neon access is currently enabled and make the decoder
emit code to raise exceptions on use of FP/Neon insns if it is not.
We use a new flag in DisasContext rather than borrowing the
existing vfp_enabled flag because the A32/T32 decoder is going
to need both.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
I'm aware this is a rather hard to review patch; sorry.
I have done an exhaustive check that we have fp access checks
in all code paths with the aid of the assertions added in the
next patch plus the code-coverage hack patch I posted to the
list earlier.
For the record, this patch is correct for all commits up to:
target-arm: A64: Implement remaining 3-same instructions
If we add further SIMD instructions before this patch hits
master, it will need additional fp access check hunks...
---
target-arm/cpu.c | 7 ++
target-arm/cpu.h | 16 ++++
target-arm/translate-a64.c | 234 ++++++++++++++++++++++++++++++++++++++++++++-
target-arm/translate.h | 3 +-
4 files changed, 254 insertions(+), 6 deletions(-)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 7384e17..fbb5755 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -93,9 +93,16 @@ static void arm_cpu_reset(CPUState *s)
env->pstate = PSTATE_MODE_EL0t;
/* Userspace expects access to CTL_EL0 and the cache ops */
env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
+ /* and to the FP/Neon instructions */
+ env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3);
#else
env->pstate = PSTATE_MODE_EL1h;
#endif
+ } else {
+#if defined(CONFIG_USER_ONLY)
+ /* Userspace expects access to cp10 and cp11 for FP/Neon */
+ env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 4, 0xf);
+#endif
}
#if defined(CONFIG_USER_ONLY)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index bf8b7d5..6b7b1d0 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -713,6 +713,13 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
| (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
}
+static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_thumb)
+{
+ return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
+ | (is_thumb ? 0 : ARM_EL_IL)
+ | (cv << 24) | (cond << 20);
+}
+
enum arm_cpu_mode {
ARM_CPU_MODE_USR = 0x10,
ARM_CPU_MODE_FIQ = 0x11,
@@ -1266,6 +1273,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
/* Bit usage when in AArch64 state */
#define ARM_TBFLAG_AA64_EL_SHIFT 0
#define ARM_TBFLAG_AA64_EL_MASK (0x3 << ARM_TBFLAG_AA64_EL_SHIFT)
+#define ARM_TBFLAG_AA64_FPEN_SHIFT 2
+#define ARM_TBFLAG_AA64_FPEN_MASK (1 << ARM_TBFLAG_AA64_FPEN_SHIFT)
/* some convenience accessor macros */
#define ARM_TBFLAG_AARCH64_STATE(F) \
@@ -1286,14 +1295,21 @@ static inline int cpu_mmu_index (CPUARMState *env)
(((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
#define ARM_TBFLAG_AA64_EL(F) \
(((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
+#define ARM_TBFLAG_AA64_FPEN(F) \
+ (((F) & ARM_TBFLAG_AA64_FPEN_MASK) >> ARM_TBFLAG_AA64_FPEN_SHIFT)
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
+ int fpen = extract32(env->cp15.c1_coproc, 20, 2);
+
if (is_a64(env)) {
*pc = env->pc;
*flags = ARM_TBFLAG_AARCH64_STATE_MASK
| (arm_current_pl(env) << ARM_TBFLAG_AA64_EL_SHIFT);
+ if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
+ *flags |= ARM_TBFLAG_AA64_FPEN_MASK;
+ }
} else {
int privmode;
*pc = env->regs[15];
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index af43aab..987b0b4 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -871,6 +871,23 @@ static void do_vec_ld(DisasContext *s, int destidx, int element,
tcg_temp_free_i64(tcg_tmp);
}
+/* Check that FP/Neon access is enabled. If it is, return
+ * true. If not, emit code to generate an appropriate exception,
+ * and return false; the caller should not emit any code for
+ * the instruction. Note that this check must happen after all
+ * unallocated-encoding checks (otherwise the syndrome information
+ * for the resulting exception will be incorrect).
+ */
+static inline bool fp_access_check(DisasContext *s)
+{
+ if (s->cpacr_fpen) {
+ return true;
+ }
+
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, false));
+ return false;
+}
+
/*
* This utility function is for doing register extension with an
* optional shift. You will likely want to pass a temporary for the
@@ -1709,6 +1726,9 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
return;
}
size = 2 + opc;
+ if (!fp_access_check(s)) {
+ return;
+ }
} else {
if (opc == 3) {
/* PRFM (literal) : prefetch */
@@ -1818,6 +1838,10 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
break;
}
+ if (is_vector && !fp_access_check(s)) {
+ return;
+ }
+
offset <<= size;
if (rn == 31) {
@@ -1909,6 +1933,9 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
return;
}
is_store = ((opc & 1) == 0);
+ if (!fp_access_check(s)) {
+ return;
+ }
} else {
if (size == 3 && opc == 2) {
/* PRFM - prefetch */
@@ -2024,6 +2051,9 @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn)
return;
}
is_store = !extract32(opc, 0, 1);
+ if (!fp_access_check(s)) {
+ return;
+ }
} else {
if (size == 3 && opc == 2) {
/* PRFM - prefetch */
@@ -2104,6 +2134,9 @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn)
return;
}
is_store = !extract32(opc, 0, 1);
+ if (!fp_access_check(s)) {
+ return;
+ }
} else {
if (size == 3 && opc == 2) {
/* PRFM - prefetch */
@@ -2261,6 +2294,10 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
if (rn == 31) {
gen_check_sp_alignment(s);
}
@@ -2387,6 +2424,10 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
g_assert_not_reached();
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
ebytes = 1 << scale;
if (rn == 31) {
@@ -3864,6 +3905,10 @@ static void disas_fp_compare(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
handle_fp_compare(s, type, rn, rm, opc & 1, opc & 2);
}
@@ -3892,6 +3937,10 @@ static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
if (cond < 0x0e) { /* not always */
int label_match = gen_new_label();
label_continue = gen_new_label();
@@ -3948,6 +3997,10 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
if (cond < 0x0e) { /* not always */
int label_match = gen_new_label();
label_continue = gen_new_label();
@@ -4165,6 +4218,10 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
unallocated_encoding(s);
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
break;
}
@@ -4174,9 +4231,17 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn)
/* 32-to-32 and 64-to-64 ops */
switch (type) {
case 0:
+ if (!fp_access_check(s)) {
+ return;
+ }
+
handle_fp_1src_single(s, opcode, rd, rn);
break;
case 1:
+ if (!fp_access_check(s)) {
+ return;
+ }
+
handle_fp_1src_double(s, opcode, rd, rn);
break;
default:
@@ -4316,9 +4381,15 @@ static void disas_fp_2src(DisasContext *s, uint32_t insn)
switch (type) {
case 0:
+ if (!fp_access_check(s)) {
+ return;
+ }
handle_fp_2src_single(s, opcode, rd, rn, rm);
break;
case 1:
+ if (!fp_access_check(s)) {
+ return;
+ }
handle_fp_2src_double(s, opcode, rd, rn, rm);
break;
default:
@@ -4420,9 +4491,15 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn)
switch (type) {
case 0:
+ if (!fp_access_check(s)) {
+ return;
+ }
handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
break;
case 1:
+ if (!fp_access_check(s)) {
+ return;
+ }
handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
break;
default:
@@ -4449,6 +4526,10 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
/* The imm8 encodes the sign bit, enough bits to represent
* an exponent in the range 01....1xx to 10....0xx,
* and the most significant 4 bits of the mantissa; see
@@ -4635,6 +4716,10 @@ static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
}
@@ -4734,6 +4819,9 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
break;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
handle_fmov(s, rd, rn, type, itof);
} else {
/* actual FP conversions */
@@ -4744,6 +4832,9 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
}
}
@@ -4844,6 +4935,10 @@ static void disas_simd_ext(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
tcg_resh = tcg_temp_new_i64();
tcg_resl = tcg_temp_new_i64();
@@ -4914,6 +5009,10 @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
/* This does a table lookup: for every byte element in the input
* we index into a table formed from up to four vector registers,
* and then the output is the result of the lookups. Our helper
@@ -4984,6 +5083,10 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
tcg_resl = tcg_const_i64(0);
tcg_resh = tcg_const_i64(0);
tcg_res = tcg_temp_new_i64();
@@ -5117,6 +5220,10 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
esize = 8 << size;
elements = (is_q ? 128 : 64) / esize;
@@ -5249,6 +5356,10 @@ static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
index = imm5 >> (size + 1);
tmp = tcg_temp_new_i64();
@@ -5283,6 +5394,10 @@ static void handle_simd_dupes(DisasContext *s, int rd, int rn,
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
index = imm5 >> (size + 1);
/* This instruction just extracts the specified element and
@@ -5315,6 +5430,11 @@ static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn,
unallocated_encoding(s);
return;
}
+
+ if (!fp_access_check(s)) {
+ return;
+ }
+
for (i = 0; i < elements; i++) {
write_vec_element(s, cpu_reg(s, rn), rd, i, size);
}
@@ -5344,6 +5464,11 @@ static void handle_simd_inse(DisasContext *s, int rd, int rn,
unallocated_encoding(s);
return;
}
+
+ if (!fp_access_check(s)) {
+ return;
+ }
+
dst_index = extract32(imm5, 1+size, 5);
src_index = extract32(imm4, size, 4);
@@ -5376,6 +5501,10 @@ static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
idx = extract32(imm5, 1 + size, 4 - size);
write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
}
@@ -5413,6 +5542,11 @@ static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed,
return;
}
}
+
+ if (!fp_access_check(s)) {
+ return;
+ }
+
element = extract32(imm5, 1+size, 4);
tcg_rd = cpu_reg(s, rd);
@@ -5505,6 +5639,10 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
/* See AdvSIMDExpandImm() in ARM ARM */
switch (cmode_3_1) {
case 0: /* Replicate(Zeros(24):imm8, 2) */
@@ -5653,6 +5791,10 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
unallocated_encoding(s);
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
TCGV_UNUSED_PTR(fpst);
break;
case 0xc: /* FMAXNMP */
@@ -5665,6 +5807,10 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
unallocated_encoding(s);
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
size = extract32(size, 0, 1) ? 3 : 2;
fpst = get_fpstatus_ptr();
break;
@@ -5867,6 +6013,10 @@ static void handle_scalar_simd_shri(DisasContext *s,
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
switch (opcode) {
case 0x02: /* SSRA / USRA (accumulate) */
accumulate = true;
@@ -5917,6 +6067,10 @@ static void handle_scalar_simd_shli(DisasContext *s, bool insert,
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
tcg_rn = read_fp_dreg(s, rn);
tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
@@ -5995,6 +6149,10 @@ static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
if (size == 2) {
TCGv_i64 tcg_op1 = tcg_temp_new_i64();
TCGv_i64 tcg_op2 = tcg_temp_new_i64();
@@ -6379,6 +6537,10 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
handle_3same_float(s, extract32(size, 0, 1), 1, fpopcode, rd, rn, rm);
return;
}
@@ -6411,6 +6573,10 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
tcg_rd = tcg_temp_new_i64();
if (size == 3) {
@@ -6561,7 +6727,13 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
int size, int rn, int rd)
{
bool is_double = (size == 3);
- TCGv_ptr fpst = get_fpstatus_ptr();
+ TCGv_ptr fpst;
+
+ if (!fp_access_check(s)) {
+ return;
+ }
+
+ fpst = get_fpstatus_ptr();
if (is_double) {
TCGv_i64 tcg_op = tcg_temp_new_i64();
@@ -6743,6 +6915,10 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
if (size == 3) {
TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
TCGv_i64 tcg_rd = tcg_temp_new_i64();
@@ -6785,6 +6961,10 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
switch (opcode) {
case 0x02: /* SSRA / USRA (accumulate) */
accumulate = true;
@@ -6849,6 +7029,10 @@ static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
for (i = 0; i < elements; i++) {
read_vec_element(s, tcg_rn, rn, i, size);
if (insert) {
@@ -6884,6 +7068,10 @@ static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u,
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
/* For the LL variants the store is larger than the load,
* so if rd == rn we would overwrite parts of our input.
* So load everything right now and use shifts in the main loop.
@@ -7173,6 +7361,10 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
unallocated_encoding(s);
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm);
break;
default:
@@ -7191,11 +7383,15 @@ static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
int size = extract32(insn, 22, 2);
bool is_u = extract32(insn, 29, 1);
bool is_q = extract32(insn, 30, 1);
- TCGv_i64 tcg_op1 = tcg_temp_new_i64();
- TCGv_i64 tcg_op2 = tcg_temp_new_i64();
- TCGv_i64 tcg_res[2];
+ TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
int pass;
+ if (!fp_access_check(s)) {
+ return;
+ }
+
+ tcg_op1 = tcg_temp_new_i64();
+ tcg_op2 = tcg_temp_new_i64();
tcg_res[0] = tcg_temp_new_i64();
tcg_res[1] = tcg_temp_new_i64();
@@ -7298,6 +7494,10 @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
TCGV_UNUSED_PTR(fpst);
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
/* These operations work on the concatenated rm:rn, with each pair of
* adjacent elements being operated on to produce an element in the result.
*/
@@ -7490,6 +7690,10 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
case 0x5f: /* FDIV */
case 0x7a: /* FABD */
case 0x7c: /* FCMGT */
+ if (!fp_access_check(s)) {
+ return;
+ }
+
handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
return;
default:
@@ -7544,6 +7748,10 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
break;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
if (size == 3) {
for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
TCGv_i64 tcg_op1 = tcg_temp_new_i64();
@@ -7936,6 +8144,10 @@ static void handle_rev(DisasContext *s, int opcode, bool u,
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
if (size == 0) {
/* Special case bytes, use bswap op on each group of elements */
int groups = dsize / (8 << grp_size);
@@ -8031,6 +8243,10 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
unallocated_encoding(s);
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
handle_2misc_narrow(s, opcode, u, is_q, size, rn, rd);
return;
case 0x2: /* SADDLP, UADDLP */
@@ -8139,6 +8355,10 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
return;
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
if (size == 3) {
/* All 64-bit element operations can be shared with scalar 2misc */
int pass;
@@ -8400,6 +8620,10 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn)
}
}
+ if (!fp_access_check(s)) {
+ return;
+ }
+
if (is_fp) {
fpst = get_fpstatus_ptr();
} else {
@@ -8898,7 +9122,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
#if !defined(CONFIG_USER_ONLY)
dc->user = (ARM_TBFLAG_AA64_EL(tb->flags) == 0);
#endif
- dc->vfp_enabled = 0;
+ dc->cpacr_fpen = ARM_TBFLAG_AA64_FPEN(tb->flags);
dc->vec_len = 0;
dc->vec_stride = 0;
dc->cp_regs = cpu->cp_regs;
diff --git a/target-arm/translate.h b/target-arm/translate.h
index fa029a0..2adf0bc 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -20,7 +20,8 @@ typedef struct DisasContext {
#if !defined(CONFIG_USER_ONLY)
int user;
#endif
- int vfp_enabled;
+ bool cpacr_fpen; /* FP enabled via CPACR.FPEN */
+ bool vfp_enabled; /* FP enabled via FPSCR.EN */
int vec_len;
int vec_stride;
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 29/31] target-arm: A64: Add assertion that FP access was checked
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (27 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 28/31] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 30/31] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1 Peter Maydell
` (2 subsequent siblings)
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
Because unallocated encodings generate different exception syndrome
information from traps due to FP being disabled, we can't do a single
"is fp access disabled" check at a high level in the decode tree.
To help in catching bugs where the access check was forgotten in some
code path, we set this flag when the access check is done, and assert
that it is set at the point where we actually touch the FP regs.
This requires us to pass the DisasContext to the vec_reg_offset
and fp_reg_offset functions.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/translate-a64.c | 74 +++++++++++++++++++++++++++++++---------------
target-arm/translate.h | 8 +++++
2 files changed, 58 insertions(+), 24 deletions(-)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 987b0b4..7c0abc7 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -347,11 +347,29 @@ static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
return v;
}
+/* We should have at some point before trying to access an FP register
+ * done the necessary access check, so assert that (a) we did the check
+ * and (b) we didn't then just plough ahead anyway if it failed.
+ *.Print the instruction pattern in the abort message so we can figure
+ * out what we need to fix if a user encounters this problem in the wild.
+ */
+static inline void assert_fp_access_checked(DisasContext *s)
+{
+#ifdef CONFIG_DEBUG_TCG
+ if (unlikely(!s->fp_access_checked || !s->cpacr_fpen)) {
+ fprintf(stderr, "target-arm: FP access check missing for "
+ "instruction 0x%08x\n", s->insn);
+ abort();
+ }
+#endif
+}
+
/* Return the offset into CPUARMState of an element of specified
* size, 'element' places in from the least significant end of
* the FP/vector register Qn.
*/
-static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
+static inline int vec_reg_offset(DisasContext *s, int regno,
+ int element, TCGMemOp size)
{
int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
#ifdef HOST_WORDS_BIGENDIAN
@@ -366,6 +384,7 @@ static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
#else
offs += element * (1 << size);
#endif
+ assert_fp_access_checked(s);
return offs;
}
@@ -374,18 +393,20 @@ static inline int vec_reg_offset(int regno, int element, TCGMemOp size)
* Dn, Sn, Hn or Bn).
* (Note that this is not the same mapping as for A32; see cpu.h)
*/
-static inline int fp_reg_offset(int regno, TCGMemOp size)
+static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size)
{
int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
#ifdef HOST_WORDS_BIGENDIAN
offs += (8 - (1 << size));
#endif
+ assert_fp_access_checked(s);
return offs;
}
/* Offset of the high half of the 128 bit vector Qn */
-static inline int fp_reg_hi_offset(int regno)
+static inline int fp_reg_hi_offset(DisasContext *s, int regno)
{
+ assert_fp_access_checked(s);
return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
}
@@ -399,7 +420,7 @@ static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
{
TCGv_i64 v = tcg_temp_new_i64();
- tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
+ tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
return v;
}
@@ -407,7 +428,7 @@ static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
{
TCGv_i32 v = tcg_temp_new_i32();
- tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(reg, MO_32));
+ tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(s, reg, MO_32));
return v;
}
@@ -415,8 +436,8 @@ static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
{
TCGv_i64 tcg_zero = tcg_const_i64(0);
- tcg_gen_st_i64(v, cpu_env, fp_reg_offset(reg, MO_64));
- tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(reg));
+ tcg_gen_st_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
+ tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(s, reg));
tcg_temp_free_i64(tcg_zero);
}
@@ -674,14 +695,14 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
{
/* This writes the bottom N bits of a 128 bit wide vector to memory */
TCGv_i64 tmp = tcg_temp_new_i64();
- tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64));
+ tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
if (size < 4) {
tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
} else {
TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s));
- tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(srcidx));
+ tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
tcg_temp_free_i64(tcg_hiaddr);
@@ -714,8 +735,8 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
tcg_temp_free_i64(tcg_hiaddr);
}
- tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(destidx, MO_64));
- tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(destidx));
+ tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
+ tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
tcg_temp_free_i64(tmplo);
tcg_temp_free_i64(tmphi);
@@ -737,7 +758,7 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
int element, TCGMemOp memop)
{
- int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
+ int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
switch (memop) {
case MO_8:
tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
@@ -769,7 +790,7 @@ static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
int element, TCGMemOp memop)
{
- int vect_off = vec_reg_offset(srcidx, element, memop & MO_SIZE);
+ int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
switch (memop) {
case MO_8:
tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off);
@@ -796,7 +817,7 @@ static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
int element, TCGMemOp memop)
{
- int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
+ int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
switch (memop) {
case MO_8:
tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
@@ -818,7 +839,7 @@ static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
int destidx, int element, TCGMemOp memop)
{
- int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
+ int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
switch (memop) {
case MO_8:
tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
@@ -880,6 +901,9 @@ static void do_vec_ld(DisasContext *s, int destidx, int element,
*/
static inline bool fp_access_check(DisasContext *s)
{
+ assert(!s->fp_access_checked);
+ s->fp_access_checked = true;
+
if (s->cpacr_fpen) {
return true;
}
@@ -4738,9 +4762,9 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
/* 32 bit */
TCGv_i64 tmp = tcg_temp_new_i64();
tcg_gen_ext32u_i64(tmp, tcg_rn);
- tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(rd, MO_64));
+ tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(s, rd, MO_64));
tcg_gen_movi_i64(tmp, 0);
- tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
+ tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd));
tcg_temp_free_i64(tmp);
break;
}
@@ -4748,14 +4772,14 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
{
/* 64 bit */
TCGv_i64 tmp = tcg_const_i64(0);
- tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(rd, MO_64));
- tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd));
+ tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(s, rd, MO_64));
+ tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd));
tcg_temp_free_i64(tmp);
break;
}
case 2:
/* 64 bit to top half. */
- tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(rd));
+ tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd));
break;
}
} else {
@@ -4764,15 +4788,15 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
switch (type) {
case 0:
/* 32 bit */
- tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_32));
+ tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_32));
break;
case 1:
/* 64 bit */
- tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_64));
+ tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_64));
break;
case 2:
/* 64 bits from top half */
- tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(rn));
+ tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(s, rn));
break;
}
}
@@ -5717,7 +5741,7 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
tcg_rd = new_tmp_a64(s);
for (i = 0; i < 2; i++) {
- int foffs = i ? fp_reg_hi_offset(rd) : fp_reg_offset(rd, MO_64);
+ int foffs = i ? fp_reg_hi_offset(s, rd) : fp_reg_offset(s, rd, MO_64);
if (i == 1 && !is_q) {
/* non-quad ops clear high half of vector */
@@ -9055,6 +9079,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
s->insn = insn;
s->pc += 4;
+ s->fp_access_checked = false;
+
switch (extract32(insn, 25, 4)) {
case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
unallocated_encoding(s);
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 2adf0bc..a42e64d 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -31,6 +31,14 @@ typedef struct DisasContext {
int aarch64;
int current_pl;
GHashTable *cp_regs;
+ /* Because unallocated encodings generate different exception syndrome
+ * information from traps due to FP being disabled, we can't do a single
+ * "is fp access disabled" check at a high level in the decode tree.
+ * To help in catching bugs where the access check was forgotten in some
+ * code path, we set this flag when the access check is done, and assert
+ * that it is set at the point where we actually touch the FP regs.
+ */
+ bool fp_access_checked;
#define TMP_A64_MAX 16
int tmp_a64_count;
TCGv_i64 tmp_a64[TMP_A64_MAX];
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 30/31] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (28 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 29/31] target-arm: A64: Add assertion that FP access was checked Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support Peter Maydell
2014-02-25 20:16 ` [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
The current A32/T32 decoder bases its "is VFP/Neon enabled?" check
on the FPSCR.EN bit. This is correct if EL1 is AArch32, but for
an AArch64 EL1 the logic is different: it must act as if FPSCR.EN
is always set. Instead, trapping must happen according to CPACR
bits for cp10/cp11; these cover all of FP/Neon, including the
FPSCR/FPSID/MVFR register accesses which FPSCR.EN does not affect.
Add support for CPACR checks (which are also required for ARMv7,
but were unimplemented because Linux happens not to use them)
and make sure they generate exceptions with the correct syndrome.
We actually return incorrect syndrome information for cases
where FP is disabled but the specific instruction bit pattern
is unallocated: strictly these should be the Uncategorized
exception, not a "SIMD disabled" exception. This should be
mostly harmless, and the structure of the A32/T32 VFP/Neon
decoder makes it painful to put the 'FP disabled?' checks in
the right places.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/cpu.h | 10 +++++++++-
target-arm/translate.c | 19 +++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 6b7b1d0..085529f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -1269,6 +1269,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
#define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
#define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
+#define ARM_TBFLAG_CPACR_FPEN_SHIFT 17
+#define ARM_TBFLAG_CPACR_FPEN_MASK (1 << ARM_TBFLAG_CPACR_FPEN_SHIFT)
/* Bit usage when in AArch64 state */
#define ARM_TBFLAG_AA64_EL_SHIFT 0
@@ -1293,6 +1295,8 @@ static inline int cpu_mmu_index (CPUARMState *env)
(((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
#define ARM_TBFLAG_BSWAP_CODE(F) \
(((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
+#define ARM_TBFLAG_CPACR_FPEN(F) \
+ (((F) & ARM_TBFLAG_CPACR_FPEN_MASK) >> ARM_TBFLAG_CPACR_FPEN_SHIFT)
#define ARM_TBFLAG_AA64_EL(F) \
(((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
#define ARM_TBFLAG_AA64_FPEN(F) \
@@ -1326,9 +1330,13 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
if (privmode) {
*flags |= ARM_TBFLAG_PRIV_MASK;
}
- if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
+ if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
+ || arm_el_is_aa64(env, 1)) {
*flags |= ARM_TBFLAG_VFPEN_MASK;
}
+ if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) {
+ *flags |= ARM_TBFLAG_CPACR_FPEN_MASK;
+ }
}
*cs_base = 0;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 30eafc3..a15c237 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2951,6 +2951,12 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
if (!arm_feature(env, ARM_FEATURE_VFP))
return 1;
+ if (!s->cpacr_fpen) {
+ gen_exception_insn(s, 4, EXCP_UDEF,
+ syn_fp_access_trap(1, 0xe, s->thumb));
+ return 0;
+ }
+
if (!s->vfp_enabled) {
/* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
if ((insn & 0x0fe00fff) != 0x0ee00a10)
@@ -4228,6 +4234,12 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
TCGv_i32 tmp2;
TCGv_i64 tmp64;
+ if (!s->cpacr_fpen) {
+ gen_exception_insn(s, 4, EXCP_UDEF,
+ syn_fp_access_trap(1, 0xe, s->thumb));
+ return 0;
+ }
+
if (!s->vfp_enabled)
return 1;
VFP_DREG_D(rd, insn);
@@ -4950,6 +4962,12 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins
TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
TCGv_i64 tmp64;
+ if (!s->cpacr_fpen) {
+ gen_exception_insn(s, 4, EXCP_UDEF,
+ syn_fp_access_trap(1, 0xe, s->thumb));
+ return 0;
+ }
+
if (!s->vfp_enabled)
return 1;
q = (insn & (1 << 6)) != 0;
@@ -10660,6 +10678,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
#if !defined(CONFIG_USER_ONLY)
dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
#endif
+ dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (29 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 30/31] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1 Peter Maydell
@ 2014-02-15 16:07 ` Peter Maydell
2014-02-26 2:49 ` Hu Tao
2014-02-25 20:16 ` [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
31 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-15 16:07 UTC (permalink / raw)
To: qemu-devel
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz,
Alexander Graf, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, Alex Bennée, kvmarm, Christoffer Dall,
Richard Henderson
From: Rob Herring <rob.herring@linaro.org>
Add support for v8 page table walks. This supports stage 1 translations
for 4KB, 16KB and 64KB page sizes starting with 0 or 1 level.
Signed-off-by: Rob Herring <rob.herring@linaro.org>
[PMM: fix style nits, fold in 16/64K page support patch, use
arm_el_is_aa64() to decide whether to do 64 bit page table walk]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/helper.c | 85 +++++++++++++++++++++++++++++++++++------------------
1 file changed, 56 insertions(+), 29 deletions(-)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2d66165..740bf42 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -7,7 +7,7 @@
#include "qemu/bitops.h"
#ifndef CONFIG_USER_ONLY
-static inline int get_phys_addr(CPUARMState *env, uint32_t address,
+static inline int get_phys_addr(CPUARMState *env, target_ulong address,
int access_type, int is_user,
hwaddr *phys_ptr, int *prot,
target_ulong *page_size);
@@ -1062,8 +1062,9 @@ static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
*/
static inline bool extended_addresses_enabled(CPUARMState *env)
{
- return arm_feature(env, ARM_FEATURE_LPAE)
- && (env->cp15.c2_control & (1U << 31));
+ return arm_feature(env, ARM_FEATURE_V8)
+ || (arm_feature(env, ARM_FEATURE_LPAE)
+ && (env->cp15.c2_control & (1U << 31)));
}
static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -3291,7 +3292,7 @@ typedef enum {
permission_fault = 3,
} MMUFaultType;
-static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
+static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
int access_type, int is_user,
hwaddr *phys_ptr, int *prot,
target_ulong *page_size_ptr)
@@ -3300,26 +3301,28 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
MMUFaultType fault_type = translation_fault;
uint32_t level = 1;
uint32_t epd;
- uint32_t tsz;
+ int32_t tsz;
+ uint32_t tg;
uint64_t ttbr;
int ttbr_select;
- int n;
- hwaddr descaddr;
+ hwaddr descaddr, descmask;
uint32_t tableattrs;
target_ulong page_size;
uint32_t attrs;
+ int32_t granule_sz = 9;
+ int32_t va_size = arm_el_is_aa64(env, 1) ? 64 : 32;
/* Determine whether this address is in the region controlled by
* TTBR0 or TTBR1 (or if it is in neither region and should fault).
* This is a Non-secure PL0/1 stage 1 translation, so controlled by
* TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
*/
- uint32_t t0sz = extract32(env->cp15.c2_control, 0, 3);
- uint32_t t1sz = extract32(env->cp15.c2_control, 16, 3);
- if (t0sz && !extract32(address, 32 - t0sz, t0sz)) {
+ uint32_t t0sz = extract32(env->cp15.c2_control, 0, 5);
+ uint32_t t1sz = extract32(env->cp15.c2_control, 16, 5);
+ if (t0sz && !extract64(address, va_size - t0sz, t0sz)) {
/* there is a ttbr0 region and we are in it (high bits all zero) */
ttbr_select = 0;
- } else if (t1sz && !extract32(~address, 32 - t1sz, t1sz)) {
+ } else if (t1sz && !extract64(~address, va_size - t1sz, t1sz)) {
/* there is a ttbr1 region and we are in it (high bits all one) */
ttbr_select = 1;
} else if (!t0sz) {
@@ -3345,10 +3348,26 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
ttbr = env->cp15.ttbr0_el1;
epd = extract32(env->cp15.c2_control, 7, 1);
tsz = t0sz;
+
+ tg = extract32(env->cp15.c2_control, 14, 2);
+ if (tg == 1) { /* 64KB pages */
+ granule_sz = 13;
+ }
+ if (tg == 2) { /* 16KB pages */
+ granule_sz = 11;
+ }
} else {
ttbr = env->cp15.ttbr1_el1;
epd = extract32(env->cp15.c2_control, 23, 1);
tsz = t1sz;
+
+ tg = extract32(env->cp15.c2_control, 30, 2);
+ if (tg == 3) { /* 64KB pages */
+ granule_sz = 13;
+ }
+ if (tg == 1) { /* 16KB pages */
+ granule_sz = 11;
+ }
}
if (epd) {
@@ -3356,34 +3375,37 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
goto do_fault;
}
- /* If the region is small enough we will skip straight to a 2nd level
- * lookup. This affects the number of bits of the address used in
- * combination with the TTBR to find the first descriptor. ('n' here
- * matches the usage in the ARM ARM sB3.6.6, where bits [39..n] are
- * from the TTBR, [n-1..3] from the vaddr, and [2..0] always zero).
+ /* The starting level depends on the virtual address size which can be
+ * up to 48-bits and the translation granule size.
*/
- if (tsz > 1) {
- level = 2;
- n = 14 - tsz;
+ if ((va_size - tsz) > (granule_sz * 4 + 3)) {
+ level = 0;
+ } else if ((va_size - tsz) > (granule_sz * 3 + 3)) {
+ level = 1;
} else {
- n = 5 - tsz;
+ level = 2;
}
/* Clear the vaddr bits which aren't part of the within-region address,
* so that we don't have to special case things when calculating the
* first descriptor address.
*/
- address &= (0xffffffffU >> tsz);
+ if (tsz) {
+ address &= (1ULL << (va_size - tsz)) - 1;
+ }
+
+ descmask = (1ULL << (granule_sz + 3)) - 1;
/* Now we can extract the actual base address from the TTBR */
- descaddr = extract64(ttbr, 0, 40);
- descaddr &= ~((1ULL << n) - 1);
+ descaddr = extract64(ttbr, 0, 48);
+ descaddr &= ~descmask;
tableattrs = 0;
for (;;) {
uint64_t descriptor;
- descaddr |= ((address >> (9 * (4 - level))) & 0xff8);
+ descaddr |= (address >> (granule_sz * (4 - level))) & descmask;
+ descaddr &= ~7ULL;
descriptor = ldq_phys(descaddr);
if (!(descriptor & 1) ||
(!(descriptor & 2) && (level == 3))) {
@@ -3406,11 +3428,16 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
* These are basically the same thing, although the number
* of bits we pull in from the vaddr varies.
*/
- page_size = (1 << (39 - (9 * level)));
+ page_size = (1 << ((granule_sz * (4 - level)) + 3));
descaddr |= (address & (page_size - 1));
/* Extract attributes from the descriptor and merge with table attrs */
- attrs = extract64(descriptor, 2, 10)
- | (extract64(descriptor, 52, 12) << 10);
+ if (arm_feature(env, ARM_FEATURE_V8)) {
+ attrs = extract64(descriptor, 2, 10)
+ | (extract64(descriptor, 53, 11) << 10);
+ } else {
+ attrs = extract64(descriptor, 2, 10)
+ | (extract64(descriptor, 52, 12) << 10);
+ }
attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
attrs |= extract32(tableattrs, 3, 1) << 5; /* APTable[1] => AP[2] */
/* The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
@@ -3544,7 +3571,7 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
* @prot: set to the permissions for the page containing phys_ptr
* @page_size: set to the size of the page containing phys_ptr
*/
-static inline int get_phys_addr(CPUARMState *env, uint32_t address,
+static inline int get_phys_addr(CPUARMState *env, target_ulong address,
int access_type, int is_user,
hwaddr *phys_ptr, int *prot,
target_ulong *page_size)
@@ -3589,7 +3616,7 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address,
if (ret == 0) {
/* Map a single [sub]page. */
phys_addr &= ~(hwaddr)0x3ff;
- address &= ~(uint32_t)0x3ff;
+ address &= ~(target_ulong)0x3ff;
tlb_set_page (env, address, phys_addr, prot, mmu_idx, page_size);
return 0;
}
--
1.8.5
^ permalink raw reply related [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 21/31] target-arm: Implement AArch64 DAIF system register
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 21/31] target-arm: Implement AArch64 DAIF system register Peter Maydell
@ 2014-02-17 0:17 ` Peter Crosthwaite
2014-02-17 8:51 ` Peter Maydell
2014-02-28 13:48 ` Peter Maydell
0 siblings, 2 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2014-02-17 0:17 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> Implement the DAIF system register which is a view of the
> DAIF bits in PSTATE.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> target-arm/helper.c | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 367fbbe..c50ca5a 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -1589,6 +1589,25 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> vfp_set_fpsr(env, value);
> }
>
> +static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
> + return CP_ACCESS_TRAP;
> + }
> + return CP_ACCESS_OK;
> +}
> +
> +static uint64_t aa64_daif_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + return env->daif;
> +}
Is it better to just define the .fieldoffset and do away with the
default-behaving read handler? My understanding is this will avoid a
call out to helper context when running under TCG as well, leading to
a slight perf increase.
Regards,
Peter
> +
> +static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + env->daif = value & PSTATE_DAIF;
> +}
> +
> static CPAccessResult aa64_cacheop_access(CPUARMState *env,
> const ARMCPRegInfo *ri)
> {
> @@ -1632,6 +1651,11 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
> { .name = "NZCV", .state = ARM_CP_STATE_AA64,
> .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 2,
> .access = PL0_RW, .type = ARM_CP_NZCV },
> + { .name = "DAIF", .state = ARM_CP_STATE_AA64,
> + .opc0 = 3, .opc1 = 3, .opc2 = 1, .crn = 4, .crm = 2,
> + .type = ARM_CP_NO_MIGRATE,
> + .access = PL0_RW, .accessfn = aa64_daif_access,
> + .readfn = aa64_daif_read, .writefn = aa64_daif_write },
> { .name = "FPCR", .state = ARM_CP_STATE_AA64,
> .opc0 = 3, .opc1 = 3, .opc2 = 0, .crn = 4, .crm = 4,
> .access = PL0_RW, .readfn = aa64_fpcr_read, .writefn = aa64_fpcr_write },
> --
> 1.8.5
>
>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 21/31] target-arm: Implement AArch64 DAIF system register
2014-02-17 0:17 ` Peter Crosthwaite
@ 2014-02-17 8:51 ` Peter Maydell
2014-02-28 13:48 ` Peter Maydell
1 sibling, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-17 8:51 UTC (permalink / raw)
To: Peter Crosthwaite
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On 17 February 2014 00:17, Peter Crosthwaite
<peter.crosthwaite@xilinx.com> wrote:
> On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
>> Implement the DAIF system register which is a view of the
>> DAIF bits in PSTATE.
>>
>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
>> Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>> ---
>> target-arm/helper.c | 24 ++++++++++++++++++++++++
>> 1 file changed, 24 insertions(+)
>>
>> diff --git a/target-arm/helper.c b/target-arm/helper.c
>> index 367fbbe..c50ca5a 100644
>> --- a/target-arm/helper.c
>> +++ b/target-arm/helper.c
>> @@ -1589,6 +1589,25 @@ static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri,
>> vfp_set_fpsr(env, value);
>> }
>>
>> +static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInfo *ri)
>> +{
>> + if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
>> + return CP_ACCESS_TRAP;
>> + }
>> + return CP_ACCESS_OK;
>> +}
>> +
>> +static uint64_t aa64_daif_read(CPUARMState *env, const ARMCPRegInfo *ri)
>> +{
>> + return env->daif;
>> +}
>
> Is it better to just define the .fieldoffset and do away with the
> default-behaving read handler? My understanding is this will avoid a
> call out to helper context when running under TCG as well, leading to
> a slight perf increase.
Yeah; I think this was just a holdover from when it was reading
from pstate and so had to mask out the other bits.
thanks
-- PMM
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 22/31] target-arm: A64: Implement MSR (immediate) instructions
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 22/31] target-arm: A64: Implement MSR (immediate) instructions Peter Maydell
@ 2014-02-25 8:32 ` Peter Crosthwaite
0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2014-02-25 8:32 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> Implement the MSR (immediate) instructions, which can update the
> PSTATE SP and DAIF fields.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> target-arm/helper.h | 2 ++
> target-arm/op_helper.c | 25 +++++++++++++++++++++++++
> target-arm/translate-a64.c | 25 ++++++++++++++++++++++++-
> 3 files changed, 51 insertions(+), 1 deletion(-)
>
> diff --git a/target-arm/helper.h b/target-arm/helper.h
> index 19bd620..4a063c1 100644
> --- a/target-arm/helper.h
> +++ b/target-arm/helper.h
> @@ -63,6 +63,8 @@ DEF_HELPER_2(get_cp_reg, i32, env, ptr)
> DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
> DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
>
> +DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
> +
> DEF_HELPER_2(get_r13_banked, i32, env, i32)
> DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
>
> diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
> index eb0fccd..7d06d2f 100644
> --- a/target-arm/op_helper.c
> +++ b/target-arm/op_helper.c
> @@ -319,6 +319,31 @@ uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip)
> return ri->readfn(env, ri);
> }
>
> +void HELPER(msr_i_pstate)(CPUARMState *env, uint32_t op, uint32_t imm)
> +{
> + /* MSR_i to update PSTATE. This is OK from EL0 only if UMA is set.
> + * Note that SPSel is never OK from EL0; we rely on handle_msr_i()
> + * to catch that case at translate time.
> + */
> + if (arm_current_pl(env) == 0 && !(env->cp15.c1_sys & SCTLR_UMA)) {
> + raise_exception(env, EXCP_UDEF);
> + }
> +
> + switch (op) {
> + case 0x05: /* SPSel */
> + env->pstate = deposit32(env->pstate, 0, 1, imm);
> + break;
> + case 0x1e: /* DAIFSet */
> + env->daif |= (imm << 6) & PSTATE_DAIF;
> + break;
> + case 0x1f: /* DAIFClear */
> + env->daif &= ~((imm << 6) & PSTATE_DAIF);
> + break;
> + default:
> + g_assert_not_reached();
> + }
> +}
> +
> /* ??? Flag setting arithmetic is awkward because we need to do comparisons.
> The only way to do that in TCG is a conditional branch, which clobbers
> all our temporaries. For now implement these as helper functions. */
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index 948470f..1054e38 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c
> @@ -1113,7 +1113,30 @@ static void handle_sync(DisasContext *s, uint32_t insn,
> static void handle_msr_i(DisasContext *s, uint32_t insn,
> unsigned int op1, unsigned int op2, unsigned int crm)
> {
> - unsupported_encoding(s, insn);
> + int op = op1 << 3 | op2;
> + switch (op) {
> + case 0x05: /* SPSel */
> + if (s->current_pl == 0) {
> + unallocated_encoding(s);
> + return;
> + }
> + /* fall through */
> + case 0x1e: /* DAIFSet */
> + case 0x1f: /* DAIFClear */
> + {
> + TCGv_i32 tcg_imm = tcg_const_i32(crm);
> + TCGv_i32 tcg_op = tcg_const_i32(op);
> + gen_a64_set_pc_im(s->pc - 4);
> + gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
> + tcg_temp_free_i32(tcg_imm);
> + tcg_temp_free_i32(tcg_op);
> + s->is_jmp = DISAS_UPDATE;
> + break;
> + }
> + default:
> + unallocated_encoding(s);
> + return;
> + }
> }
>
> static void gen_get_nzcv(TCGv_i64 tcg_rt)
> --
> 1.8.5
>
>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 23/31] target-arm: Implement AArch64 view of CPACR
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 23/31] target-arm: Implement AArch64 view of CPACR Peter Maydell
@ 2014-02-25 8:34 ` Peter Crosthwaite
0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2014-02-25 8:34 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> Implement the AArch64 view of the CPACR. The AArch64
> CPACR is defined to have a lot of RES0 bits, but since
> the architecture defines that RES0 bits may be implemented
> as reads-as-written and we know that a v8 CPU will have
> no registered coprocessors for cp0..cp13 we can safely
> implement the whole register this way.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> target-arm/cpu.h | 2 +-
> target-arm/helper.c | 3 ++-
> 2 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 571b033..1f6f65d 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -172,7 +172,7 @@ typedef struct CPUARMState {
> uint32_t c0_cpuid;
> uint64_t c0_cssel; /* Cache size selection. */
> uint64_t c1_sys; /* System control register. */
> - uint32_t c1_coproc; /* Coprocessor access register. */
> + uint64_t c1_coproc; /* Coprocessor access register. */
> uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
> uint32_t c1_scr; /* secure config register. */
> uint64_t ttbr0_el1; /* MMU translation table base 0. */
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index c50ca5a..d35cc73 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -458,7 +458,8 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
> */
> { .name = "WFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1,
> .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0, },
> - { .name = "CPACR", .cp = 15, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2,
> + { .name = "CPACR", .state = ARM_CP_STATE_BOTH, .opc0 = 3,
> + .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2,
> .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_coproc),
> .resetvalue = 0, .writefn = cpacr_write },
> REGINFO_SENTINEL
> --
> 1.8.5
>
>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 24/31] target-arm: Add utility function for checking AA32/64 state of an EL
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 24/31] target-arm: Add utility function for checking AA32/64 state of an EL Peter Maydell
@ 2014-02-25 8:36 ` Peter Crosthwaite
0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2014-02-25 8:36 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> There are various situations where we need to behave differently
> depending on whether a given exception level is in AArch64 or
> AArch32 state. The state of the current exception level is stored
> in env->aarch64, but there's no equivalent guest-visible architected
> state bits for the status of the exception levels "above" the
> current one which may still affect execution. At the moment we
> only support EL1 (ie no EL2 or EL3) and insist that AArch64
> capable CPUs run with EL1 in AArch64 state, but these may change
> in the future, so abstract out the "what state is this?" check
> into a utility function which can be enhanced later if necessary.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> target-arm/cpu.h | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 1f6f65d..f530333 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -633,6 +633,22 @@ static inline int arm_feature(CPUARMState *env, int feature)
> return (env->features & (1ULL << feature)) != 0;
> }
>
> +/* Return true if the specified exception level is running in AArch64 state. */
> +static inline bool arm_el_is_aa64(CPUARMState *env, int el)
> +{
> + /* We don't currently support EL2 or EL3, and this isn't valid for EL0
> + * (if we're in EL0, is_a64() is what you want, and if we're not in EL0
> + * then the state of EL0 isn't well defined.)
> + */
> + assert(el == 1);
> + /* AArch64-capable CPUs always run with EL1 in AArch64 mode. This
> + * is a QEMU-imposed simplification which we may wish to change later.
> + * If we in future support EL2 and/or EL3, then the state of lower
> + * exception levels is controlled by the HCR.RW and SCR.RW bits.
> + */
> + return arm_feature(env, ARM_FEATURE_AARCH64);
> +}
> +
> void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf);
>
> /* Interface between CPU and Interrupt controller. */
> --
> 1.8.5
>
>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
` (30 preceding siblings ...)
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support Peter Maydell
@ 2014-02-25 20:16 ` Peter Maydell
31 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-25 20:16 UTC (permalink / raw)
To: QEMU Developers
Cc: Rob Herring, Peter Crosthwaite, Laurent Desnogues, Patch Tracking,
Michael Matz, Alexander Graf, Claudio Fontana, Dirk Mueller,
Will Newton, Alex Bennée, kvmarm@lists.cs.columbia.edu,
Christoffer Dall, Richard Henderson
On 15 February 2014 16:06, Peter Maydell <peter.maydell@linaro.org> wrote:
> Here's the latest patchset aimed towards implementing AArch64
> system emulation.
> Peter Maydell (30):
> target-arm: Fix raw read and write functions on AArch64 registers
> target-arm: A64: Make cache ID registers visible to AArch64
> target-arm: Implement AArch64 CurrentEL sysreg
> target-arm: Implement AArch64 MIDR_EL1
> target-arm: Implement AArch64 cache invalidate/clean ops
> target-arm: Implement AArch64 TLB invalidate ops
> target-arm: Implement AArch64 dummy MDSCR_EL1
> target-arm: Implement AArch64 memory attribute registers
> target-arm: Implement AArch64 SCTLR_EL1
> target-arm: Implement AArch64 TCR_EL1
> target-arm: Implement AArch64 VBAR_EL1
> target-arm: Implement AArch64 TTBR*
> target-arm: Implement AArch64 MPIDR
> target-arm: Implement AArch64 generic timers
> target-arm: Implement AArch64 ID and feature registers
> target-arm: Implement AArch64 dummy breakpoint and watchpoint
> registers
> target-arm: Implement AArch64 OSLAR_EL1 sysreg as WI
> target-arm: Get MMU index information correct for A64 code
> target-arm: A64: Implement WFI
> target-arm: Store AIF bits in env->pstate for AArch32
> target-arm: Implement AArch64 DAIF system register
> target-arm: A64: Implement MSR (immediate) instructions
> target-arm: Implement AArch64 view of CPACR
> target-arm: Add utility function for checking AA32/64 state of an EL
I'm going to put all the above except for "Implement AArch64
DAIF system register" (which had a review nit that needs fixing)
into target-arm.next. Patches 2-17 and 22-24 have all been
reviewed; 1, 18, 19 and 20 have had no adverse comment and
are generally fairly straightforward, and they've been on
list for a while now so I think they're ok to go in.
> target-arm: Define exception record for AArch64 exceptions
> target-arm: Provide correct syndrome information for cpreg access
> traps
> target-arm: Add support for generating exceptions with syndrome
> information
> target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set
> target-arm: A64: Add assertion that FP access was checked
> target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1
>
> Rob Herring (1):
> target-arm: Add v8 mmu translation support
Nobody's reviewed these yet, so I'll hold on to them and
send them out with the next version of this patchset, which
might even have enough patches in it to actually boot a guest.
[I'm not planning to try to get system emulation into
QEMU 2.0; I think it's good to get the bulk of the
underlying foundational work in, though, so that the
remaining patchset is more manageable.]
thanks
-- PMM
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 19/31] target-arm: A64: Implement WFI
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 19/31] target-arm: A64: Implement WFI Peter Maydell
@ 2014-02-25 23:20 ` Peter Crosthwaite
0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2014-02-25 23:20 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> Implement the WFI instruction for A64; this just involves wiring
> up the instruction, and adding a gen_a64_set_pc_im() which was
> accidentally omitted from the A64 decoder top loop.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Sorry about the delay
> ---
> target-arm/translate-a64.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index 1714df2..948470f 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c
> @@ -1065,9 +1065,11 @@ static void handle_hint(DisasContext *s, uint32_t insn,
> switch (selector) {
> case 0: /* NOP */
> return;
> + case 3: /* WFI */
> + s->is_jmp = DISAS_WFI;
> + return;
> case 1: /* YIELD */
> case 2: /* WFE */
> - case 3: /* WFI */
> case 4: /* SEV */
> case 5: /* SEVL */
> /* we treat all as NOP at least for now */
> @@ -8955,6 +8957,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
> /* This is a special case because we don't want to just halt the CPU
> * if trying to debug across a WFI.
> */
> + gen_a64_set_pc_im(dc->pc);
> gen_helper_wfi(cpu_env);
> break;
> }
> --
> 1.8.5
>
>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 20/31] target-arm: Store AIF bits in env->pstate for AArch32
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 20/31] target-arm: Store AIF bits in env->pstate for AArch32 Peter Maydell
@ 2014-02-25 23:25 ` Peter Crosthwaite
0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2014-02-25 23:25 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> To avoid complication in code that otherwise would not need to
> care about whether EL1 is AArch32 or AArch64, we should store
> the interrupt mask bits (CPSR.AIF in AArch32 and PSTATE.DAIF
> in AArch64) in one place consistently regardless of EL1's mode.
> Since AArch64 has an extra enable bit (D for debug exceptions)
> which isn't visible in AArch32, this means we need to keep
> the enables in env->pstate. (This is also consistent with the
> general approach we're taking that we handle 32 bit CPUs as
> being like AArch64/ARMv8 CPUs but which only run in 32 bit mode.)
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> cpu-exec.c | 4 ++--
> hw/arm/pxa2xx.c | 4 ++--
> target-arm/cpu.c | 8 ++++----
> target-arm/cpu.h | 12 +++++++++---
> target-arm/helper.c | 29 +++++++++++++++++------------
> 5 files changed, 34 insertions(+), 23 deletions(-)
>
> diff --git a/cpu-exec.c b/cpu-exec.c
> index a6c01f4..ba28e31 100644
> --- a/cpu-exec.c
> +++ b/cpu-exec.c
> @@ -474,7 +474,7 @@ int cpu_exec(CPUArchState *env)
> }
> #elif defined(TARGET_ARM)
> if (interrupt_request & CPU_INTERRUPT_FIQ
> - && !(env->uncached_cpsr & CPSR_F)) {
> + && !(env->daif & PSTATE_F)) {
> env->exception_index = EXCP_FIQ;
> cc->do_interrupt(cpu);
> next_tb = 0;
> @@ -490,7 +490,7 @@ int cpu_exec(CPUArchState *env)
> pc contains a magic address. */
> if (interrupt_request & CPU_INTERRUPT_HARD
> && ((IS_M(env) && env->regs[15] < 0xfffffff0)
> - || !(env->uncached_cpsr & CPSR_I))) {
> + || !(env->daif & PSTATE_I))) {
> env->exception_index = EXCP_IRQ;
> cc->do_interrupt(cpu);
> next_tb = 0;
> diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
> index be6b5f6..f102470 100644
> --- a/hw/arm/pxa2xx.c
> +++ b/hw/arm/pxa2xx.c
> @@ -272,8 +272,8 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
> goto message;
>
> case 3:
> - s->cpu->env.uncached_cpsr =
> - ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
> + s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC;
> + s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I;
> s->cpu->env.cp15.c1_sys = 0;
> s->cpu->env.cp15.c1_coproc = 0;
> s->cpu->env.cp15.ttbr0_el1 = 0;
> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index 2f94943..7384e17 100644
> --- a/target-arm/cpu.c
> +++ b/target-arm/cpu.c
> @@ -94,8 +94,7 @@ static void arm_cpu_reset(CPUState *s)
> /* Userspace expects access to CTL_EL0 and the cache ops */
> env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
> #else
> - env->pstate = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F
> - | PSTATE_MODE_EL1h;
> + env->pstate = PSTATE_MODE_EL1h;
> #endif
> }
>
> @@ -110,13 +109,14 @@ static void arm_cpu_reset(CPUState *s)
> }
> #else
> /* SVC mode with interrupts disabled. */
> - env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
> + env->uncached_cpsr = ARM_CPU_MODE_SVC;
> + env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
> /* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
> clear at reset. Initial SP and PC are loaded from ROM. */
> if (IS_M(env)) {
> uint32_t pc;
> uint8_t *rom;
> - env->uncached_cpsr &= ~CPSR_I;
> + env->daif &= ~PSTATE_I;
> rom = rom_ptr(0);
> if (rom) {
> /* We should really use ldl_phys here, in case the guest
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index ec0214d..571b033 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -135,6 +135,7 @@ typedef struct CPUARMState {
> * NZCV are kept in the split out env->CF/VF/NF/ZF, (which have the same
> * semantics as for AArch32, as described in the comments on each field)
> * nRW (also known as M[4]) is kept, inverted, in env->aarch64
> + * DAIF (exception masks) are kept in env->daif
> * all other bits are stored in their correct places in env->pstate
> */
> uint32_t pstate;
> @@ -164,6 +165,7 @@ typedef struct CPUARMState {
> uint32_t GE; /* cpsr[19:16] */
> uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
> uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
> + uint32_t daif; /* exception masks, in the bits they are in in PSTATE */
>
> /* System control coprocessor (cp15) */
> struct {
> @@ -406,9 +408,11 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
> #define CPSR_Z (1U << 30)
> #define CPSR_N (1U << 31)
> #define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V)
> +#define CPSR_AIF (CPSR_A | CPSR_I | CPSR_F)
>
> #define CPSR_IT (CPSR_IT_0_1 | CPSR_IT_2_7)
> -#define CACHED_CPSR_BITS (CPSR_T | CPSR_GE | CPSR_IT | CPSR_Q | CPSR_NZCV)
> +#define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \
> + | CPSR_NZCV)
> /* Bits writable in user mode. */
> #define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE)
> /* Execution state bits. MRS read as zero, MSR writes ignored. */
> @@ -431,7 +435,8 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
> #define PSTATE_Z (1U << 30)
> #define PSTATE_N (1U << 31)
> #define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V)
> -#define CACHED_PSTATE_BITS (PSTATE_NZCV)
> +#define PSTATE_DAIF (PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F)
> +#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF)
> /* Mode values for AArch64 */
> #define PSTATE_MODE_EL3h 13
> #define PSTATE_MODE_EL3t 12
> @@ -452,7 +457,7 @@ static inline uint32_t pstate_read(CPUARMState *env)
> ZF = (env->ZF == 0);
> return (env->NF & 0x80000000) | (ZF << 30)
> | (env->CF << 29) | ((env->VF & 0x80000000) >> 3)
> - | env->pstate;
> + | env->pstate | env->daif;
> }
>
> static inline void pstate_write(CPUARMState *env, uint32_t val)
> @@ -461,6 +466,7 @@ static inline void pstate_write(CPUARMState *env, uint32_t val)
> env->NF = val;
> env->CF = (val >> 29) & 1;
> env->VF = (val << 3) & 0x80000000;
> + env->daif = val & PSTATE_DAIF;
> env->pstate = val & ~CACHED_PSTATE_BITS;
> }
>
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 5c2be64..367fbbe 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -2475,7 +2475,7 @@ uint32_t cpsr_read(CPUARMState *env)
> (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
> | (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
> | ((env->condexec_bits & 0xfc) << 8)
> - | (env->GE << 16);
> + | (env->GE << 16) | env->daif;
> }
>
> void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
> @@ -2502,6 +2502,9 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
> env->GE = (val >> 16) & 0xf;
> }
>
> + env->daif &= ~(CPSR_AIF & mask);
> + env->daif |= val & CPSR_AIF & mask;
> +
> if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
> if (bad_mode_switch(env, val & CPSR_M)) {
> /* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
> @@ -2961,7 +2964,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
> env->condexec_bits = 0;
> /* Switch to the new mode, and to the correct instruction set. */
> env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
> - env->uncached_cpsr |= mask;
> + env->daif |= mask;
> /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
> * and we should just guard the thumb mode on V4 */
> if (arm_feature(env, ARM_FEATURE_V4T)) {
> @@ -3631,12 +3634,12 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
> case 9: /* PSP */
> return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
> case 16: /* PRIMASK */
> - return (env->uncached_cpsr & CPSR_I) != 0;
> + return (env->daif & PSTATE_I) != 0;
> case 17: /* BASEPRI */
> case 18: /* BASEPRI_MAX */
> return env->v7m.basepri;
> case 19: /* FAULTMASK */
> - return (env->uncached_cpsr & CPSR_F) != 0;
> + return (env->daif & PSTATE_F) != 0;
> case 20: /* CONTROL */
> return env->v7m.control;
> default:
> @@ -3683,10 +3686,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
> env->v7m.other_sp = val;
> break;
> case 16: /* PRIMASK */
> - if (val & 1)
> - env->uncached_cpsr |= CPSR_I;
> - else
> - env->uncached_cpsr &= ~CPSR_I;
> + if (val & 1) {
> + env->daif |= PSTATE_I;
> + } else {
> + env->daif &= ~PSTATE_I;
> + }
> break;
> case 17: /* BASEPRI */
> env->v7m.basepri = val & 0xff;
> @@ -3697,10 +3701,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
> env->v7m.basepri = val;
> break;
> case 19: /* FAULTMASK */
> - if (val & 1)
> - env->uncached_cpsr |= CPSR_F;
> - else
> - env->uncached_cpsr &= ~CPSR_F;
> + if (val & 1) {
> + env->daif |= PSTATE_F;
> + } else {
> + env->daif &= ~PSTATE_F;
> + }
> break;
> case 20: /* CONTROL */
> env->v7m.control = val & 3;
> --
> 1.8.5
>
>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 18/31] target-arm: Get MMU index information correct for A64 code
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 18/31] target-arm: Get MMU index information correct for A64 code Peter Maydell
@ 2014-02-25 23:27 ` Peter Crosthwaite
0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2014-02-25 23:27 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> Emit the correct MMU index information for loads and stores from
> A64 code, rather than hardwiring it to "always kernel mode",
> by storing the exception level in the TB flags, and make
> cpu_mmu_index() return the right answer when the CPU is in
> AArch64 mode.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> target-arm/cpu.h | 11 ++++++++---
> target-arm/translate-a64.c | 2 +-
> 2 files changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index db74ab7..ec0214d 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -1057,7 +1057,7 @@ static inline CPUARMState *cpu_init(const char *cpu_model)
> #define MMU_USER_IDX 1
> static inline int cpu_mmu_index (CPUARMState *env)
> {
> - return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0;
> + return arm_current_pl(env) ? 0 : 1;
> }
>
> #include "exec/cpu-all.h"
> @@ -1084,7 +1084,9 @@ static inline int cpu_mmu_index (CPUARMState *env)
> #define ARM_TBFLAG_BSWAP_CODE_SHIFT 16
> #define ARM_TBFLAG_BSWAP_CODE_MASK (1 << ARM_TBFLAG_BSWAP_CODE_SHIFT)
>
> -/* Bit usage when in AArch64 state: currently no bits defined */
> +/* Bit usage when in AArch64 state */
> +#define ARM_TBFLAG_AA64_EL_SHIFT 0
> +#define ARM_TBFLAG_AA64_EL_MASK (0x3 << ARM_TBFLAG_AA64_EL_SHIFT)
>
> /* some convenience accessor macros */
> #define ARM_TBFLAG_AARCH64_STATE(F) \
> @@ -1103,13 +1105,16 @@ static inline int cpu_mmu_index (CPUARMState *env)
> (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
> #define ARM_TBFLAG_BSWAP_CODE(F) \
> (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT)
> +#define ARM_TBFLAG_AA64_EL(F) \
> + (((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT)
>
> static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
> target_ulong *cs_base, int *flags)
> {
> if (is_a64(env)) {
> *pc = env->pc;
> - *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
> + *flags = ARM_TBFLAG_AARCH64_STATE_MASK
> + | (arm_current_pl(env) << ARM_TBFLAG_AA64_EL_SHIFT);
> } else {
> int privmode;
> *pc = env->regs[15];
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index 7c55a90..1714df2 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c
> @@ -8844,7 +8844,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
> dc->condexec_mask = 0;
> dc->condexec_cond = 0;
> #if !defined(CONFIG_USER_ONLY)
> - dc->user = 0;
> + dc->user = (ARM_TBFLAG_AA64_EL(tb->flags) == 0);
> #endif
> dc->vfp_enabled = 0;
> dc->vec_len = 0;
> --
> 1.8.5
>
>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 01/31] target-arm: Fix raw read and write functions on AArch64 registers
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 01/31] target-arm: Fix raw read and write functions on AArch64 registers Peter Maydell
@ 2014-02-26 0:17 ` Peter Crosthwaite
0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2014-02-26 0:17 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On Sun, Feb 16, 2014 at 2:06 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> The raw read and write functions were using the ARM_CP_64BIT flag in
> ri->type to determine whether to treat the register's state field as
> uint32_t or uint64_t; however AArch64 register info structs don't use
> that flag. Abstract out the "how big is the field?" test into a
> function and fix it to work for AArch64 registers. For this to work
> we must ensure that the reginfo structs put into the hashtable have
> the correct state field for their use, not the placeholder STATE_BOTH.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> target-arm/cpu.c | 2 +-
> target-arm/cpu.h | 8 ++++++++
> target-arm/helper.c | 8 ++++++--
> 3 files changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index 6e7ce89..fe18b65 100644
> --- a/target-arm/cpu.c
> +++ b/target-arm/cpu.c
> @@ -60,7 +60,7 @@ static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
> return;
> }
>
> - if (ri->type & ARM_CP_64BIT) {
> + if (cpreg_field_is_64bit(ri)) {
> CPREG_FIELD64(&cpu->env, ri) = ri->resetvalue;
> } else {
> CPREG_FIELD32(&cpu->env, ri) = ri->resetvalue;
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 3c8a2db..4473fad 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -959,6 +959,14 @@ uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri);
> */
> void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque);
>
> +/* Return true if this reginfo struct's field in the cpu state struct
> + * is 64 bits wide.
> + */
> +static inline bool cpreg_field_is_64bit(const ARMCPRegInfo *ri)
> +{
> + return (ri->state == ARM_CP_STATE_AA64) || (ri->type & ARM_CP_64BIT);
> +}
> +
> static inline bool cp_access_ok(int current_pl,
> const ARMCPRegInfo *ri, int isread)
> {
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index b547f04..1ecc55e 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -109,7 +109,7 @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
>
> static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
> {
> - if (ri->type & ARM_CP_64BIT) {
> + if (cpreg_field_is_64bit(ri)) {
> return CPREG_FIELD64(env, ri);
> } else {
> return CPREG_FIELD32(env, ri);
> @@ -119,7 +119,7 @@ static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri)
> static void raw_write(CPUARMState *env, const ARMCPRegInfo *ri,
> uint64_t value)
> {
> - if (ri->type & ARM_CP_64BIT) {
> + if (cpreg_field_is_64bit(ri)) {
> CPREG_FIELD64(env, ri) = value;
> } else {
> CPREG_FIELD32(env, ri) = value;
> @@ -1962,6 +1962,10 @@ static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r,
> if (opaque) {
> r2->opaque = opaque;
> }
> + /* reginfo passed to helpers is correct for the actual access,
> + * and is never ARM_CP_STATE_BOTH:
> + */
> + r2->state = state;
> /* Make sure reginfo passed to helpers for wildcarded regs
> * has the correct crm/opc1/opc2 for this reg, not CP_ANY:
> */
> --
> 1.8.5
>
>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support Peter Maydell
@ 2014-02-26 2:49 ` Hu Tao
2014-02-26 3:32 ` Hu Tao
0 siblings, 1 reply; 51+ messages in thread
From: Hu Tao @ 2014-02-26 2:49 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Peter Crosthwaite, Laurent Desnogues, patches,
Michael Matz, qemu-devel, Claudio Fontana, Dirk Mueller,
Will Newton, kvmarm, Richard Henderson
On Sat, Feb 15, 2014 at 04:07:24PM +0000, Peter Maydell wrote:
> From: Rob Herring <rob.herring@linaro.org>
>
> Add support for v8 page table walks. This supports stage 1 translations
> for 4KB, 16KB and 64KB page sizes starting with 0 or 1 level.
>
> Signed-off-by: Rob Herring <rob.herring@linaro.org>
> [PMM: fix style nits, fold in 16/64K page support patch, use
> arm_el_is_aa64() to decide whether to do 64 bit page table walk]
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
> target-arm/helper.c | 85 +++++++++++++++++++++++++++++++++++------------------
> 1 file changed, 56 insertions(+), 29 deletions(-)
>
> diff --git a/target-arm/helper.c b/target-arm/helper.c
> index 2d66165..740bf42 100644
> --- a/target-arm/helper.c
> +++ b/target-arm/helper.c
> @@ -7,7 +7,7 @@
> #include "qemu/bitops.h"
>
> #ifndef CONFIG_USER_ONLY
> -static inline int get_phys_addr(CPUARMState *env, uint32_t address,
> +static inline int get_phys_addr(CPUARMState *env, target_ulong address,
> int access_type, int is_user,
> hwaddr *phys_ptr, int *prot,
> target_ulong *page_size);
> @@ -1062,8 +1062,9 @@ static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
> */
> static inline bool extended_addresses_enabled(CPUARMState *env)
> {
> - return arm_feature(env, ARM_FEATURE_LPAE)
> - && (env->cp15.c2_control & (1U << 31));
> + return arm_feature(env, ARM_FEATURE_V8)
> + || (arm_feature(env, ARM_FEATURE_LPAE)
> + && (env->cp15.c2_control & (1U << 31)));
> }
>
> static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri)
> @@ -3291,7 +3292,7 @@ typedef enum {
> permission_fault = 3,
> } MMUFaultType;
>
> -static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
> +static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
> int access_type, int is_user,
> hwaddr *phys_ptr, int *prot,
> target_ulong *page_size_ptr)
> @@ -3300,26 +3301,28 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
> MMUFaultType fault_type = translation_fault;
> uint32_t level = 1;
> uint32_t epd;
> - uint32_t tsz;
> + int32_t tsz;
> + uint32_t tg;
> uint64_t ttbr;
> int ttbr_select;
> - int n;
> - hwaddr descaddr;
> + hwaddr descaddr, descmask;
> uint32_t tableattrs;
> target_ulong page_size;
> uint32_t attrs;
> + int32_t granule_sz = 9;
> + int32_t va_size = arm_el_is_aa64(env, 1) ? 64 : 32;
>
> /* Determine whether this address is in the region controlled by
> * TTBR0 or TTBR1 (or if it is in neither region and should fault).
> * This is a Non-secure PL0/1 stage 1 translation, so controlled by
> * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
> */
> - uint32_t t0sz = extract32(env->cp15.c2_control, 0, 3);
> - uint32_t t1sz = extract32(env->cp15.c2_control, 16, 3);
> - if (t0sz && !extract32(address, 32 - t0sz, t0sz)) {
> + uint32_t t0sz = extract32(env->cp15.c2_control, 0, 5);
> + uint32_t t1sz = extract32(env->cp15.c2_control, 16, 5);
t0sz is bit [5:0], so shouldn't we extract 6 bits here? same for t1sz.
> + if (t0sz && !extract64(address, va_size - t0sz, t0sz)) {
> /* there is a ttbr0 region and we are in it (high bits all zero) */
> ttbr_select = 0;
> - } else if (t1sz && !extract32(~address, 32 - t1sz, t1sz)) {
> + } else if (t1sz && !extract64(~address, va_size - t1sz, t1sz)) {
> /* there is a ttbr1 region and we are in it (high bits all one) */
> ttbr_select = 1;
> } else if (!t0sz) {
Can't be true for Aarch64. the VA address space has a maximum address width
of 48 bits(page D5-1712 of ARM DDI 0487A.a), that means t0sz and t1sz should
have a minimum value of 16.
> @@ -3345,10 +3348,26 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
> ttbr = env->cp15.ttbr0_el1;
> epd = extract32(env->cp15.c2_control, 7, 1);
> tsz = t0sz;
> +
> + tg = extract32(env->cp15.c2_control, 14, 2);
> + if (tg == 1) { /* 64KB pages */
> + granule_sz = 13;
> + }
> + if (tg == 2) { /* 16KB pages */
> + granule_sz = 11;
> + }
0 -> 4k-page, 1 -> 64k-page, 2 -> 16k-page, looks strange but this is
what the doc says.
> } else {
> ttbr = env->cp15.ttbr1_el1;
> epd = extract32(env->cp15.c2_control, 23, 1);
> tsz = t1sz;
> +
> + tg = extract32(env->cp15.c2_control, 30, 2);
> + if (tg == 3) { /* 64KB pages */
> + granule_sz = 13;
> + }
> + if (tg == 1) { /* 16KB pages */
> + granule_sz = 11;
> + }
> }
>
> if (epd) {
> @@ -3356,34 +3375,37 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
> goto do_fault;
> }
>
> - /* If the region is small enough we will skip straight to a 2nd level
> - * lookup. This affects the number of bits of the address used in
> - * combination with the TTBR to find the first descriptor. ('n' here
> - * matches the usage in the ARM ARM sB3.6.6, where bits [39..n] are
> - * from the TTBR, [n-1..3] from the vaddr, and [2..0] always zero).
> + /* The starting level depends on the virtual address size which can be
> + * up to 48-bits and the translation granule size.
> */
> - if (tsz > 1) {
> - level = 2;
> - n = 14 - tsz;
> + if ((va_size - tsz) > (granule_sz * 4 + 3)) {
> + level = 0;
> + } else if ((va_size - tsz) > (granule_sz * 3 + 3)) {
> + level = 1;
> } else {
> - n = 5 - tsz;
> + level = 2;
> }
>
> /* Clear the vaddr bits which aren't part of the within-region address,
> * so that we don't have to special case things when calculating the
> * first descriptor address.
> */
> - address &= (0xffffffffU >> tsz);
> + if (tsz) {
> + address &= (1ULL << (va_size - tsz)) - 1;
> + }
> +
> + descmask = (1ULL << (granule_sz + 3)) - 1;
>
> /* Now we can extract the actual base address from the TTBR */
> - descaddr = extract64(ttbr, 0, 40);
> - descaddr &= ~((1ULL << n) - 1);
> + descaddr = extract64(ttbr, 0, 48);
> + descaddr &= ~descmask;
>
> tableattrs = 0;
> for (;;) {
> uint64_t descriptor;
>
> - descaddr |= ((address >> (9 * (4 - level))) & 0xff8);
> + descaddr |= (address >> (granule_sz * (4 - level))) & descmask;
> + descaddr &= ~7ULL;
> descriptor = ldq_phys(descaddr);
> if (!(descriptor & 1) ||
> (!(descriptor & 2) && (level == 3))) {
> @@ -3406,11 +3428,16 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
> * These are basically the same thing, although the number
> * of bits we pull in from the vaddr varies.
> */
> - page_size = (1 << (39 - (9 * level)));
> + page_size = (1 << ((granule_sz * (4 - level)) + 3));
> descaddr |= (address & (page_size - 1));
> /* Extract attributes from the descriptor and merge with table attrs */
> - attrs = extract64(descriptor, 2, 10)
> - | (extract64(descriptor, 52, 12) << 10);
> + if (arm_feature(env, ARM_FEATURE_V8)) {
> + attrs = extract64(descriptor, 2, 10)
> + | (extract64(descriptor, 53, 11) << 10);
> + } else {
> + attrs = extract64(descriptor, 2, 10)
> + | (extract64(descriptor, 52, 12) << 10);
> + }
> attrs |= extract32(tableattrs, 0, 2) << 11; /* XN, PXN */
> attrs |= extract32(tableattrs, 3, 1) << 5; /* APTable[1] => AP[2] */
> /* The sense of AP[1] vs APTable[0] is reversed, as APTable[0] == 1
> @@ -3544,7 +3571,7 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
> * @prot: set to the permissions for the page containing phys_ptr
> * @page_size: set to the size of the page containing phys_ptr
> */
> -static inline int get_phys_addr(CPUARMState *env, uint32_t address,
> +static inline int get_phys_addr(CPUARMState *env, target_ulong address,
> int access_type, int is_user,
> hwaddr *phys_ptr, int *prot,
> target_ulong *page_size)
> @@ -3589,7 +3616,7 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address,
> if (ret == 0) {
> /* Map a single [sub]page. */
> phys_addr &= ~(hwaddr)0x3ff;
> - address &= ~(uint32_t)0x3ff;
> + address &= ~(target_ulong)0x3ff;
> tlb_set_page (env, address, phys_addr, prot, mmu_idx, page_size);
> return 0;
> }
> --
> 1.8.5
>
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support
2014-02-26 2:49 ` Hu Tao
@ 2014-02-26 3:32 ` Hu Tao
2014-02-26 10:31 ` Peter Maydell
0 siblings, 1 reply; 51+ messages in thread
From: Hu Tao @ 2014-02-26 3:32 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Peter Crosthwaite, patches, Michael Matz, qemu-devel,
Claudio Fontana, Dirk Mueller, Will Newton, Laurent Desnogues,
kvmarm, Richard Henderson
On Wed, Feb 26, 2014 at 10:49:59AM +0800, Hu Tao wrote:
> On Sat, Feb 15, 2014 at 04:07:24PM +0000, Peter Maydell wrote:
> > From: Rob Herring <rob.herring@linaro.org>
> >
> > Add support for v8 page table walks. This supports stage 1 translations
> > for 4KB, 16KB and 64KB page sizes starting with 0 or 1 level.
> >
> > Signed-off-by: Rob Herring <rob.herring@linaro.org>
> > [PMM: fix style nits, fold in 16/64K page support patch, use
> > arm_el_is_aa64() to decide whether to do 64 bit page table walk]
> > Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> > ---
> > target-arm/helper.c | 85 +++++++++++++++++++++++++++++++++++------------------
> > 1 file changed, 56 insertions(+), 29 deletions(-)
> >
> > diff --git a/target-arm/helper.c b/target-arm/helper.c
> > index 2d66165..740bf42 100644
> > --- a/target-arm/helper.c
> > +++ b/target-arm/helper.c
> > @@ -7,7 +7,7 @@
> > #include "qemu/bitops.h"
> >
> > #ifndef CONFIG_USER_ONLY
> > -static inline int get_phys_addr(CPUARMState *env, uint32_t address,
> > +static inline int get_phys_addr(CPUARMState *env, target_ulong address,
> > int access_type, int is_user,
> > hwaddr *phys_ptr, int *prot,
> > target_ulong *page_size);
> > @@ -1062,8 +1062,9 @@ static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
> > */
> > static inline bool extended_addresses_enabled(CPUARMState *env)
> > {
> > - return arm_feature(env, ARM_FEATURE_LPAE)
> > - && (env->cp15.c2_control & (1U << 31));
> > + return arm_feature(env, ARM_FEATURE_V8)
> > + || (arm_feature(env, ARM_FEATURE_LPAE)
> > + && (env->cp15.c2_control & (1U << 31)));
> > }
> >
> > static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri)
> > @@ -3291,7 +3292,7 @@ typedef enum {
> > permission_fault = 3,
> > } MMUFaultType;
> >
> > -static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
> > +static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
> > int access_type, int is_user,
> > hwaddr *phys_ptr, int *prot,
> > target_ulong *page_size_ptr)
> > @@ -3300,26 +3301,28 @@ static int get_phys_addr_lpae(CPUARMState *env, uint32_t address,
> > MMUFaultType fault_type = translation_fault;
> > uint32_t level = 1;
> > uint32_t epd;
> > - uint32_t tsz;
> > + int32_t tsz;
> > + uint32_t tg;
> > uint64_t ttbr;
> > int ttbr_select;
> > - int n;
> > - hwaddr descaddr;
> > + hwaddr descaddr, descmask;
> > uint32_t tableattrs;
> > target_ulong page_size;
> > uint32_t attrs;
> > + int32_t granule_sz = 9;
> > + int32_t va_size = arm_el_is_aa64(env, 1) ? 64 : 32;
> >
> > /* Determine whether this address is in the region controlled by
> > * TTBR0 or TTBR1 (or if it is in neither region and should fault).
> > * This is a Non-secure PL0/1 stage 1 translation, so controlled by
> > * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
> > */
> > - uint32_t t0sz = extract32(env->cp15.c2_control, 0, 3);
> > - uint32_t t1sz = extract32(env->cp15.c2_control, 16, 3);
> > - if (t0sz && !extract32(address, 32 - t0sz, t0sz)) {
> > + uint32_t t0sz = extract32(env->cp15.c2_control, 0, 5);
> > + uint32_t t1sz = extract32(env->cp15.c2_control, 16, 5);
>
> t0sz is bit [5:0], so shouldn't we extract 6 bits here? same for t1sz.
>
> > + if (t0sz && !extract64(address, va_size - t0sz, t0sz)) {
> > /* there is a ttbr0 region and we are in it (high bits all zero) */
> > ttbr_select = 0;
> > - } else if (t1sz && !extract32(~address, 32 - t1sz, t1sz)) {
> > + } else if (t1sz && !extract64(~address, va_size - t1sz, t1sz)) {
> > /* there is a ttbr1 region and we are in it (high bits all one) */
> > ttbr_select = 1;
> > } else if (!t0sz) {
>
> Can't be true for Aarch64. the VA address space has a maximum address width
> of 48 bits(page D5-1712 of ARM DDI 0487A.a), that means t0sz and t1sz should
> have a minimum value of 16.
It doesn't matter here. Maybe we should check the value when writing to
TCR_EL1. What's the behaviour when writing an invalid tsz to TCR_EL1?
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 12/31] target-arm: Implement AArch64 TTBR*
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 12/31] target-arm: Implement AArch64 TTBR* Peter Maydell
@ 2014-02-26 6:33 ` Hu Tao
2014-02-26 9:50 ` Peter Maydell
0 siblings, 1 reply; 51+ messages in thread
From: Hu Tao @ 2014-02-26 6:33 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Peter Crosthwaite, Laurent Desnogues, patches,
Michael Matz, qemu-devel, Alexander Graf, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée, kvmarm,
Christoffer Dall, Richard Henderson
On Sat, Feb 15, 2014 at 04:07:05PM +0000, Peter Maydell wrote:
<...>
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index 06953ac..7cbe69b 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -173,10 +173,8 @@ typedef struct CPUARMState {
> uint32_t c1_coproc; /* Coprocessor access register. */
> uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
> uint32_t c1_scr; /* secure config register. */
> - uint32_t c2_base0; /* MMU translation table base 0. */
> - uint32_t c2_base0_hi; /* MMU translation table base 0, high 32 bits */
> - uint32_t c2_base1; /* MMU translation table base 0. */
> - uint32_t c2_base1_hi; /* MMU translation table base 1, high 32 bits */
> + uint64_t ttbr0_el1; /* MMU translation table base 0. */
> + uint32_t ttbr1_el1; /* MMU translation table base 1. */
s/32/64/
> uint64_t c2_control; /* MMU translation table base control. */
> uint32_t c2_mask; /* MMU translation table base selection mask. */
> uint32_t c2_base_mask; /* MMU translation table base 0 mask. */
<...>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 12/31] target-arm: Implement AArch64 TTBR*
2014-02-26 6:33 ` Hu Tao
@ 2014-02-26 9:50 ` Peter Maydell
0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-02-26 9:50 UTC (permalink / raw)
To: Hu Tao
Cc: Rob Herring, Peter Crosthwaite, Laurent Desnogues, Patch Tracking,
Michael Matz, QEMU Developers, Alexander Graf, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On 26 February 2014 06:33, Hu Tao <hutao@cn.fujitsu.com> wrote:
> On Sat, Feb 15, 2014 at 04:07:05PM +0000, Peter Maydell wrote:
>
> <...>
>
>> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
>> index 06953ac..7cbe69b 100644
>> --- a/target-arm/cpu.h
>> +++ b/target-arm/cpu.h
>> @@ -173,10 +173,8 @@ typedef struct CPUARMState {
>> uint32_t c1_coproc; /* Coprocessor access register. */
>> uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
>> uint32_t c1_scr; /* secure config register. */
>> - uint32_t c2_base0; /* MMU translation table base 0. */
>> - uint32_t c2_base0_hi; /* MMU translation table base 0, high 32 bits */
>> - uint32_t c2_base1; /* MMU translation table base 0. */
>> - uint32_t c2_base1_hi; /* MMU translation table base 1, high 32 bits */
>> + uint64_t ttbr0_el1; /* MMU translation table base 0. */
>> + uint32_t ttbr1_el1; /* MMU translation table base 1. */
>
> s/32/64/
Nice catch, not sure how I missed that.
thanks
-- PMM
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support
2014-02-26 3:32 ` Hu Tao
@ 2014-02-26 10:31 ` Peter Maydell
2014-02-26 19:47 ` Rob Herring
0 siblings, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-26 10:31 UTC (permalink / raw)
To: Hu Tao
Cc: Rob Herring, Peter Crosthwaite, Patch Tracking, Michael Matz,
QEMU Developers, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, kvmarm@lists.cs.columbia.edu,
Richard Henderson
On 26 February 2014 03:32, Hu Tao <hutao@cn.fujitsu.com> wrote:
> On Wed, Feb 26, 2014 at 10:49:59AM +0800, Hu Tao wrote:
>> On Sat, Feb 15, 2014 at 04:07:24PM +0000, Peter Maydell wrote:
>> > From: Rob Herring <rob.herring@linaro.org>
>> > /* Determine whether this address is in the region controlled by
>> > * TTBR0 or TTBR1 (or if it is in neither region and should fault).
>> > * This is a Non-secure PL0/1 stage 1 translation, so controlled by
>> > * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
>> > */
>> > - uint32_t t0sz = extract32(env->cp15.c2_control, 0, 3);
>> > - uint32_t t1sz = extract32(env->cp15.c2_control, 16, 3);
>> > - if (t0sz && !extract32(address, 32 - t0sz, t0sz)) {
>> > + uint32_t t0sz = extract32(env->cp15.c2_control, 0, 5);
>> > + uint32_t t1sz = extract32(env->cp15.c2_control, 16, 5);
>>
>> t0sz is bit [5:0], so shouldn't we extract 6 bits here? same for t1sz.
Yes.
>> > + if (t0sz && !extract64(address, va_size - t0sz, t0sz)) {
>> > /* there is a ttbr0 region and we are in it (high bits all zero) */
>> > ttbr_select = 0;
>> > - } else if (t1sz && !extract32(~address, 32 - t1sz, t1sz)) {
>> > + } else if (t1sz && !extract64(~address, va_size - t1sz, t1sz)) {
>> > /* there is a ttbr1 region and we are in it (high bits all one) */
>> > ttbr_select = 1;
>> > } else if (!t0sz) {
>>
>> Can't be true for Aarch64. the VA address space has a maximum address width
>> of 48 bits(page D5-1712 of ARM DDI 0487A.a), that means t0sz and t1sz should
>> have a minimum value of 16.
>
> It doesn't matter here. Maybe we should check the value when writing to
> TCR_EL1. What's the behaviour when writing an invalid tsz to TCR_EL1?
I haven't checked through all the details, but it looks like the answer is
you can write anything, and the pseudocode for AArch64.TranslationTableWalk
specifies what happens if the tsz is outside the expected range (we
clamp tablesize to be 25 <= tablesize <= 48).
I'm not sure we've correctly implemented the handling specified under
the AddrTop() pseudocode function either.
thanks
-- PMM
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support
2014-02-26 10:31 ` Peter Maydell
@ 2014-02-26 19:47 ` Rob Herring
2014-03-01 19:58 ` Peter Maydell
0 siblings, 1 reply; 51+ messages in thread
From: Rob Herring @ 2014-02-26 19:47 UTC (permalink / raw)
To: Peter Maydell
Cc: Peter Crosthwaite, Patch Tracking, Hu Tao, Michael Matz,
QEMU Developers, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, kvmarm@lists.cs.columbia.edu,
Richard Henderson
On Wed, Feb 26, 2014 at 4:31 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 26 February 2014 03:32, Hu Tao <hutao@cn.fujitsu.com> wrote:
>> On Wed, Feb 26, 2014 at 10:49:59AM +0800, Hu Tao wrote:
>>> On Sat, Feb 15, 2014 at 04:07:24PM +0000, Peter Maydell wrote:
>>> > From: Rob Herring <rob.herring@linaro.org>
>
>>> > /* Determine whether this address is in the region controlled by
>>> > * TTBR0 or TTBR1 (or if it is in neither region and should fault).
>>> > * This is a Non-secure PL0/1 stage 1 translation, so controlled by
>>> > * TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
>>> > */
>>> > - uint32_t t0sz = extract32(env->cp15.c2_control, 0, 3);
>>> > - uint32_t t1sz = extract32(env->cp15.c2_control, 16, 3);
>>> > - if (t0sz && !extract32(address, 32 - t0sz, t0sz)) {
>>> > + uint32_t t0sz = extract32(env->cp15.c2_control, 0, 5);
>>> > + uint32_t t1sz = extract32(env->cp15.c2_control, 16, 5);
>>>
>>> t0sz is bit [5:0], so shouldn't we extract 6 bits here? same for t1sz.
>
> Yes.
>
>>> > + if (t0sz && !extract64(address, va_size - t0sz, t0sz)) {
>>> > /* there is a ttbr0 region and we are in it (high bits all zero) */
>>> > ttbr_select = 0;
>>> > - } else if (t1sz && !extract32(~address, 32 - t1sz, t1sz)) {
>>> > + } else if (t1sz && !extract64(~address, va_size - t1sz, t1sz)) {
>>> > /* there is a ttbr1 region and we are in it (high bits all one) */
>>> > ttbr_select = 1;
>>> > } else if (!t0sz) {
>>>
>>> Can't be true for Aarch64. the VA address space has a maximum address width
>>> of 48 bits(page D5-1712 of ARM DDI 0487A.a), that means t0sz and t1sz should
>>> have a minimum value of 16.
>>
>> It doesn't matter here. Maybe we should check the value when writing to
>> TCR_EL1. What's the behaviour when writing an invalid tsz to TCR_EL1?
>
> I haven't checked through all the details, but it looks like the answer is
> you can write anything, and the pseudocode for AArch64.TranslationTableWalk
> specifies what happens if the tsz is outside the expected range (we
> clamp tablesize to be 25 <= tablesize <= 48).
>
> I'm not sure we've correctly implemented the handling specified under
> the AddrTop() pseudocode function either.
Tagged addresses would probably be broken in other places as well as I
don't think we handle all of the BranchTo() pseudocode. I'm not sure
anything is using tagged addresses ATM.
I've fixed the above issues and found another issue on v7 LPAE with
the ttbr masking. I believe it to be correct now, but my formula does
not match the pseudocode which is:
baselowerbound = 3 + tablesize - stride*(3-level) - grainsize;
baseaddress = base<47:baselowerbound>:Zeros(baselowerbound);
This formula appears to be wrong AFAICT. Take a couple of examples:
level=1,tablesize=32: 3 + 32 - 12*2 - 9 = 2 (correct value is 5)
level=0,tablesize=48: 3 + 48 - 12*3 - 9 = 6 (correct value is 12)
Here are the fixes I've made. I've pushed an updated patch here:
git://git.linaro.org/people/rob.herring/qemu.git v8-mmu
Rob
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 8849df6..9f7b4f0 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -3315,19 +3315,37 @@ static int get_phys_addr_lpae(CPUARMState
*env, target_ulong address,
target_ulong page_size;
uint32_t attrs;
int32_t granule_sz = 9;
- int32_t va_size = arm_el_is_aa64(env, 1) ? 64 : 32;
+ int32_t va_size = 32;
+ int32_t tbi = 0;
+
+ if (arm_el_is_aa64(env, 1)) {
+ va_size = 64;
+ if (extract64(address, 55, 1))
+ tbi = extract32(env->cp15.c2_control, 38, 1);
+ else
+ tbi = extract32(env->cp15.c2_control, 37, 1);
+ tbi *= 8;
+ }
/* Determine whether this address is in the region controlled by
* TTBR0 or TTBR1 (or if it is in neither region and should fault).
* This is a Non-secure PL0/1 stage 1 translation, so controlled by
* TTBCR/TTBR0/TTBR1 in accordance with ARM ARM DDI0406C table B-32:
*/
- uint32_t t0sz = extract32(env->cp15.c2_control, 0, 5);
- uint32_t t1sz = extract32(env->cp15.c2_control, 16, 5);
- if (t0sz && !extract64(address, va_size - t0sz, t0sz)) {
+ uint32_t t0sz = extract32(env->cp15.c2_control, 0, 6);
+ if (arm_el_is_aa64(env, 1)) {
+ t0sz = MIN(t0sz, 39);
+ t0sz = MAX(t0sz, 16);
+ }
+ uint32_t t1sz = extract32(env->cp15.c2_control, 16, 6);
+ if (arm_el_is_aa64(env, 1)) {
+ t1sz = MIN(t1sz, 39);
+ t1sz = MAX(t1sz, 16);
+ }
+ if (t0sz && !extract64(address, va_size - t0sz, t0sz - tbi)) {
/* there is a ttbr0 region and we are in it (high bits all zero) */
ttbr_select = 0;
- } else if (t1sz && !extract64(~address, va_size - t1sz, t1sz)) {
+ } else if (t1sz && !extract64(~address, va_size - t1sz, t1sz - tbi)) {
/* there is a ttbr1 region and we are in it (high bits all one) */
ttbr_select = 1;
} else if (!t0sz) {
@@ -3403,7 +3421,7 @@ static int get_phys_addr_lpae(CPUARMState *env,
target_ulong address,
/* Now we can extract the actual base address from the TTBR */
descaddr = extract64(ttbr, 0, 48);
- descaddr &= ~descmask;
+ descaddr &= ~((1ULL << (va_size - tsz - (granule_sz * (4 - level)))) - 1);
tableattrs = 0;
for (;;) {
^ permalink raw reply related [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 21/31] target-arm: Implement AArch64 DAIF system register
2014-02-17 0:17 ` Peter Crosthwaite
2014-02-17 8:51 ` Peter Maydell
@ 2014-02-28 13:48 ` Peter Maydell
2014-02-28 23:32 ` Peter Crosthwaite
1 sibling, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2014-02-28 13:48 UTC (permalink / raw)
To: Peter Crosthwaite
Cc: Rob Herring, Laurent Desnogues, Patch Tracking, Michael Matz,
Alexander Graf, qemu-devel@nongnu.org Developers, Claudio Fontana,
Dirk Mueller, Will Newton, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On 17 February 2014 00:17, Peter Crosthwaite
<peter.crosthwaite@xilinx.com> wrote:
> On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
>> Implement the DAIF system register which is a view of the
>> DAIF bits in PSTATE.
>> +static uint64_t aa64_daif_read(CPUARMState *env, const ARMCPRegInfo *ri)
>> +{
>> + return env->daif;
>> +}
>
> Is it better to just define the .fieldoffset and do away with the
> default-behaving read handler? My understanding is this will avoid a
> call out to helper context when running under TCG as well, leading to
> a slight perf increase.
I've just remembered why I didn't do this : env->daif is 32 bits,
which means you can't use it as a fieldoffset for a 64 bit sysreg.
thanks
-- PMM
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 21/31] target-arm: Implement AArch64 DAIF system register
2014-02-28 13:48 ` Peter Maydell
@ 2014-02-28 23:32 ` Peter Crosthwaite
0 siblings, 0 replies; 51+ messages in thread
From: Peter Crosthwaite @ 2014-02-28 23:32 UTC (permalink / raw)
To: Peter Maydell
Cc: Rob Herring, Patch Tracking, Michael Matz,
qemu-devel@nongnu.org Developers, Alexander Graf, Claudio Fontana,
Dirk Mueller, Will Newton, Laurent Desnogues, Alex Bennée,
kvmarm@lists.cs.columbia.edu, Christoffer Dall, Richard Henderson
On Fri, Feb 28, 2014 at 11:48 PM, Peter Maydell
<peter.maydell@linaro.org> wrote:
> On 17 February 2014 00:17, Peter Crosthwaite
> <peter.crosthwaite@xilinx.com> wrote:
>> On Sun, Feb 16, 2014 at 2:07 AM, Peter Maydell <peter.maydell@linaro.org> wrote:
>>> Implement the DAIF system register which is a view of the
>>> DAIF bits in PSTATE.
>
>>> +static uint64_t aa64_daif_read(CPUARMState *env, const ARMCPRegInfo *ri)
>>> +{
>>> + return env->daif;
>>> +}
>>
>> Is it better to just define the .fieldoffset and do away with the
>> default-behaving read handler? My understanding is this will avoid a
>> call out to helper context when running under TCG as well, leading to
>> a slight perf increase.
>
> I've just remembered why I didn't do this : env->daif is 32 bits,
> which means you can't use it as a fieldoffset for a 64 bit sysreg.
>
Should env->daif just be extended to 64b then?
Regards,
Peter
> thanks
> -- PMM
>
^ permalink raw reply [flat|nested] 51+ messages in thread
* Re: [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support
2014-02-26 19:47 ` Rob Herring
@ 2014-03-01 19:58 ` Peter Maydell
0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2014-03-01 19:58 UTC (permalink / raw)
To: Rob Herring
Cc: Peter Crosthwaite, Patch Tracking, Hu Tao, Michael Matz,
QEMU Developers, Claudio Fontana, Dirk Mueller, Will Newton,
Laurent Desnogues, kvmarm@lists.cs.columbia.edu,
Richard Henderson
On 26 February 2014 19:47, Rob Herring <rob.herring@linaro.org> wrote:
> Tagged addresses would probably be broken in other places as well as I
> don't think we handle all of the BranchTo() pseudocode. I'm not sure
> anything is using tagged addresses ATM.
Yeah, I agree we would need to fix other places too at some point.
> I've fixed the above issues and found another issue on v7 LPAE with
> the ttbr masking. I believe it to be correct now, but my formula does
> not match the pseudocode which is:
>
> baselowerbound = 3 + tablesize - stride*(3-level) - grainsize;
> baseaddress = base<47:baselowerbound>:Zeros(baselowerbound);
>
> This formula appears to be wrong AFAICT. Take a couple of examples:
>
> level=1,tablesize=32: 3 + 32 - 12*2 - 9 = 2 (correct value is 5)
> level=0,tablesize=48: 3 + 48 - 12*3 - 9 = 6 (correct value is 12)
Your examples seem to have the stride and grainsize the wrong
way round. grainsize is 16, 14, or 12, and stride is grainsize - 3.
So for the first one: 3 + 32 - 9*2 - 12 == 5
and for the second: 3 + 48 - 9*3 - 12 == 12
thanks
-- PMM
^ permalink raw reply [flat|nested] 51+ messages in thread
end of thread, other threads:[~2014-03-01 19:59 UTC | newest]
Thread overview: 51+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-15 16:06 [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 01/31] target-arm: Fix raw read and write functions on AArch64 registers Peter Maydell
2014-02-26 0:17 ` Peter Crosthwaite
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 02/31] target-arm: A64: Make cache ID registers visible to AArch64 Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 03/31] target-arm: Implement AArch64 CurrentEL sysreg Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 04/31] target-arm: Implement AArch64 MIDR_EL1 Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 05/31] target-arm: Implement AArch64 cache invalidate/clean ops Peter Maydell
2014-02-15 16:06 ` [Qemu-devel] [PATCH v3 06/31] target-arm: Implement AArch64 TLB invalidate ops Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 07/31] target-arm: Implement AArch64 dummy MDSCR_EL1 Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 08/31] target-arm: Implement AArch64 memory attribute registers Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 09/31] target-arm: Implement AArch64 SCTLR_EL1 Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 10/31] target-arm: Implement AArch64 TCR_EL1 Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 11/31] target-arm: Implement AArch64 VBAR_EL1 Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 12/31] target-arm: Implement AArch64 TTBR* Peter Maydell
2014-02-26 6:33 ` Hu Tao
2014-02-26 9:50 ` Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 13/31] target-arm: Implement AArch64 MPIDR Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 14/31] target-arm: Implement AArch64 generic timers Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 15/31] target-arm: Implement AArch64 ID and feature registers Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 16/31] target-arm: Implement AArch64 dummy breakpoint and watchpoint registers Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 17/31] target-arm: Implement AArch64 OSLAR_EL1 sysreg as WI Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 18/31] target-arm: Get MMU index information correct for A64 code Peter Maydell
2014-02-25 23:27 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 19/31] target-arm: A64: Implement WFI Peter Maydell
2014-02-25 23:20 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 20/31] target-arm: Store AIF bits in env->pstate for AArch32 Peter Maydell
2014-02-25 23:25 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 21/31] target-arm: Implement AArch64 DAIF system register Peter Maydell
2014-02-17 0:17 ` Peter Crosthwaite
2014-02-17 8:51 ` Peter Maydell
2014-02-28 13:48 ` Peter Maydell
2014-02-28 23:32 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 22/31] target-arm: A64: Implement MSR (immediate) instructions Peter Maydell
2014-02-25 8:32 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 23/31] target-arm: Implement AArch64 view of CPACR Peter Maydell
2014-02-25 8:34 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 24/31] target-arm: Add utility function for checking AA32/64 state of an EL Peter Maydell
2014-02-25 8:36 ` Peter Crosthwaite
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 25/31] target-arm: Define exception record for AArch64 exceptions Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 26/31] target-arm: Provide correct syndrome information for cpreg access traps Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 27/31] target-arm: Add support for generating exceptions with syndrome information Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 28/31] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 29/31] target-arm: A64: Add assertion that FP access was checked Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 30/31] target-arm: Fix VFP enables for AArch32 EL0 under AArch64 EL1 Peter Maydell
2014-02-15 16:07 ` [Qemu-devel] [PATCH v3 31/31] target-arm: Add v8 mmu translation support Peter Maydell
2014-02-26 2:49 ` Hu Tao
2014-02-26 3:32 ` Hu Tao
2014-02-26 10:31 ` Peter Maydell
2014-02-26 19:47 ` Rob Herring
2014-03-01 19:58 ` Peter Maydell
2014-02-25 20:16 ` [Qemu-devel] [PATCH v3 00/31] A64 system emulation prequisites Peter Maydell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).