From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [PULL 29/48] target/arm: Add VHE system register redirection and aliasing
Date: Fri, 7 Feb 2020 14:33:24 +0000 [thread overview]
Message-ID: <20200207143343.30322-30-peter.maydell@linaro.org> (raw)
In-Reply-To: <20200207143343.30322-1-peter.maydell@linaro.org>
From: Richard Henderson <richard.henderson@linaro.org>
Several of the EL1/0 registers are redirected to the EL2 version when in
EL2 and HCR_EL2.E2H is set. Many of these registers have side effects.
Link together the two ARMCPRegInfo structures after they have been
properly instantiated. Install common dispatch routines to all of the
relevant registers.
The same set of registers that are redirected also have additional
EL12/EL02 aliases created to access the original register that was
redirected.
Omit the generic timer registers from redirection here, because we'll
need multiple kinds of redirection from both EL0 and EL2.
Tested-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20200206105448.4726-29-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/cpu.h | 13 ++++
target/arm/helper.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 175 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index ded1e8e0a89..d091a7e2e87 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2576,6 +2576,19 @@ struct ARMCPRegInfo {
* fieldoffset is 0 then no reset will be done.
*/
CPResetFn *resetfn;
+
+ /*
+ * "Original" writefn and readfn.
+ * For ARMv8.1-VHE register aliases, we overwrite the read/write
+ * accessor functions of various EL1/EL0 to perform the runtime
+ * check for which sysreg should actually be modified, and then
+ * forwards the operation. Before overwriting the accessors,
+ * the original function is copied here, so that accesses that
+ * really do go to the EL1/EL0 version proceed normally.
+ * (The corresponding EL2 register is linked via opaque.)
+ */
+ CPReadFn *orig_readfn;
+ CPWriteFn *orig_writefn;
};
/* Macros which are lvalues for the field in CPUARMState for the
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 2aa04d06131..8f7620f2434 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5358,6 +5358,158 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
REGINFO_SENTINEL
};
+#ifndef CONFIG_USER_ONLY
+/* Test if system register redirection is to occur in the current state. */
+static bool redirect_for_e2h(CPUARMState *env)
+{
+ return arm_current_el(env) == 2 && (arm_hcr_el2_eff(env) & HCR_E2H);
+}
+
+static uint64_t el2_e2h_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ CPReadFn *readfn;
+
+ if (redirect_for_e2h(env)) {
+ /* Switch to the saved EL2 version of the register. */
+ ri = ri->opaque;
+ readfn = ri->readfn;
+ } else {
+ readfn = ri->orig_readfn;
+ }
+ if (readfn == NULL) {
+ readfn = raw_read;
+ }
+ return readfn(env, ri);
+}
+
+static void el2_e2h_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ CPWriteFn *writefn;
+
+ if (redirect_for_e2h(env)) {
+ /* Switch to the saved EL2 version of the register. */
+ ri = ri->opaque;
+ writefn = ri->writefn;
+ } else {
+ writefn = ri->orig_writefn;
+ }
+ if (writefn == NULL) {
+ writefn = raw_write;
+ }
+ writefn(env, ri, value);
+}
+
+static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu)
+{
+ struct E2HAlias {
+ uint32_t src_key, dst_key, new_key;
+ const char *src_name, *dst_name, *new_name;
+ bool (*feature)(const ARMISARegisters *id);
+ };
+
+#define K(op0, op1, crn, crm, op2) \
+ ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2)
+
+ static const struct E2HAlias aliases[] = {
+ { K(3, 0, 1, 0, 0), K(3, 4, 1, 0, 0), K(3, 5, 1, 0, 0),
+ "SCTLR", "SCTLR_EL2", "SCTLR_EL12" },
+ { K(3, 0, 1, 0, 2), K(3, 4, 1, 1, 2), K(3, 5, 1, 0, 2),
+ "CPACR", "CPTR_EL2", "CPACR_EL12" },
+ { K(3, 0, 2, 0, 0), K(3, 4, 2, 0, 0), K(3, 5, 2, 0, 0),
+ "TTBR0_EL1", "TTBR0_EL2", "TTBR0_EL12" },
+ { K(3, 0, 2, 0, 1), K(3, 4, 2, 0, 1), K(3, 5, 2, 0, 1),
+ "TTBR1_EL1", "TTBR1_EL2", "TTBR1_EL12" },
+ { K(3, 0, 2, 0, 2), K(3, 4, 2, 0, 2), K(3, 5, 2, 0, 2),
+ "TCR_EL1", "TCR_EL2", "TCR_EL12" },
+ { K(3, 0, 4, 0, 0), K(3, 4, 4, 0, 0), K(3, 5, 4, 0, 0),
+ "SPSR_EL1", "SPSR_EL2", "SPSR_EL12" },
+ { K(3, 0, 4, 0, 1), K(3, 4, 4, 0, 1), K(3, 5, 4, 0, 1),
+ "ELR_EL1", "ELR_EL2", "ELR_EL12" },
+ { K(3, 0, 5, 1, 0), K(3, 4, 5, 1, 0), K(3, 5, 5, 1, 0),
+ "AFSR0_EL1", "AFSR0_EL2", "AFSR0_EL12" },
+ { K(3, 0, 5, 1, 1), K(3, 4, 5, 1, 1), K(3, 5, 5, 1, 1),
+ "AFSR1_EL1", "AFSR1_EL2", "AFSR1_EL12" },
+ { K(3, 0, 5, 2, 0), K(3, 4, 5, 2, 0), K(3, 5, 5, 2, 0),
+ "ESR_EL1", "ESR_EL2", "ESR_EL12" },
+ { K(3, 0, 6, 0, 0), K(3, 4, 6, 0, 0), K(3, 5, 6, 0, 0),
+ "FAR_EL1", "FAR_EL2", "FAR_EL12" },
+ { K(3, 0, 10, 2, 0), K(3, 4, 10, 2, 0), K(3, 5, 10, 2, 0),
+ "MAIR_EL1", "MAIR_EL2", "MAIR_EL12" },
+ { K(3, 0, 10, 3, 0), K(3, 4, 10, 3, 0), K(3, 5, 10, 3, 0),
+ "AMAIR0", "AMAIR_EL2", "AMAIR_EL12" },
+ { K(3, 0, 12, 0, 0), K(3, 4, 12, 0, 0), K(3, 5, 12, 0, 0),
+ "VBAR", "VBAR_EL2", "VBAR_EL12" },
+ { K(3, 0, 13, 0, 1), K(3, 4, 13, 0, 1), K(3, 5, 13, 0, 1),
+ "CONTEXTIDR_EL1", "CONTEXTIDR_EL2", "CONTEXTIDR_EL12" },
+ { K(3, 0, 14, 1, 0), K(3, 4, 14, 1, 0), K(3, 5, 14, 1, 0),
+ "CNTKCTL", "CNTHCTL_EL2", "CNTKCTL_EL12" },
+
+ /*
+ * Note that redirection of ZCR is mentioned in the description
+ * of ZCR_EL2, and aliasing in the description of ZCR_EL1, but
+ * not in the summary table.
+ */
+ { K(3, 0, 1, 2, 0), K(3, 4, 1, 2, 0), K(3, 5, 1, 2, 0),
+ "ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve },
+
+ /* TODO: ARMv8.2-SPE -- PMSCR_EL2 */
+ /* TODO: ARMv8.4-Trace -- TRFCR_EL2 */
+ };
+#undef K
+
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(aliases); i++) {
+ const struct E2HAlias *a = &aliases[i];
+ ARMCPRegInfo *src_reg, *dst_reg;
+
+ if (a->feature && !a->feature(&cpu->isar)) {
+ continue;
+ }
+
+ src_reg = g_hash_table_lookup(cpu->cp_regs, &a->src_key);
+ dst_reg = g_hash_table_lookup(cpu->cp_regs, &a->dst_key);
+ g_assert(src_reg != NULL);
+ g_assert(dst_reg != NULL);
+
+ /* Cross-compare names to detect typos in the keys. */
+ g_assert(strcmp(src_reg->name, a->src_name) == 0);
+ g_assert(strcmp(dst_reg->name, a->dst_name) == 0);
+
+ /* None of the core system registers use opaque; we will. */
+ g_assert(src_reg->opaque == NULL);
+
+ /* Create alias before redirection so we dup the right data. */
+ if (a->new_key) {
+ ARMCPRegInfo *new_reg = g_memdup(src_reg, sizeof(ARMCPRegInfo));
+ uint32_t *new_key = g_memdup(&a->new_key, sizeof(uint32_t));
+ bool ok;
+
+ new_reg->name = a->new_name;
+ new_reg->type |= ARM_CP_ALIAS;
+ /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */
+ new_reg->access &= PL2_RW | PL3_RW;
+
+ ok = g_hash_table_insert(cpu->cp_regs, new_key, new_reg);
+ g_assert(ok);
+ }
+
+ src_reg->opaque = dst_reg;
+ src_reg->orig_readfn = src_reg->readfn ?: raw_read;
+ src_reg->orig_writefn = src_reg->writefn ?: raw_write;
+ if (!src_reg->raw_readfn) {
+ src_reg->raw_readfn = raw_read;
+ }
+ if (!src_reg->raw_writefn) {
+ src_reg->raw_writefn = raw_write;
+ }
+ src_reg->readfn = el2_e2h_read;
+ src_reg->writefn = el2_e2h_write;
+ }
+}
+#endif
+
static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
{
@@ -7291,6 +7443,16 @@ void register_cp_regs_for_features(ARMCPU *cpu)
: cpu_isar_feature(aa32_predinv, cpu)) {
define_arm_cp_regs(cpu, predinv_reginfo);
}
+
+#ifndef CONFIG_USER_ONLY
+ /*
+ * Register redirections and aliases must be done last,
+ * after the registers from the other extensions have been defined.
+ */
+ if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
+ define_arm_vh_e2h_redirects_aliases(cpu);
+ }
+#endif
}
void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
--
2.20.1
next prev parent reply other threads:[~2020-02-07 14:53 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-07 14:32 [PULL 00/48] target-arm queue Peter Maydell
2020-02-07 14:32 ` [PULL 01/48] target/arm/monitor: query-cpu-model-expansion crashed qemu when using machine type none Peter Maydell
2020-02-07 14:32 ` [PULL 02/48] target/arm: Define isar_feature_aa64_vh Peter Maydell
2020-02-07 14:32 ` [PULL 03/48] target/arm: Enable HCR_E2H for VHE Peter Maydell
2020-02-07 14:32 ` [PULL 04/48] target/arm: Add CONTEXTIDR_EL2 Peter Maydell
2020-02-07 14:33 ` [PULL 05/48] target/arm: Add TTBR1_EL2 Peter Maydell
2020-02-07 14:33 ` [PULL 06/48] target/arm: Update CNTVCT_EL0 for VHE Peter Maydell
2020-02-07 14:33 ` [PULL 07/48] target/arm: Split out vae1_tlbmask Peter Maydell
2020-02-07 14:33 ` [PULL 08/48] target/arm: Split out alle1_tlbmask Peter Maydell
2020-02-07 14:33 ` [PULL 09/48] target/arm: Simplify tlb_force_broadcast alternatives Peter Maydell
2020-02-07 14:33 ` [PULL 10/48] target/arm: Rename ARMMMUIdx*_S12NSE* to ARMMMUIdx*_E10_* Peter Maydell
2020-02-07 14:33 ` [PULL 11/48] target/arm: Rename ARMMMUIdx_S2NS to ARMMMUIdx_Stage2 Peter Maydell
2020-02-07 14:33 ` [PULL 12/48] target/arm: Rename ARMMMUIdx_S1NSE* to ARMMMUIdx_Stage1_E* Peter Maydell
2020-02-07 14:33 ` [PULL 13/48] target/arm: Rename ARMMMUIdx_S1SE[01] to ARMMMUIdx_SE10_[01] Peter Maydell
2020-02-07 14:33 ` [PULL 14/48] target/arm: Rename ARMMMUIdx*_S1E3 to ARMMMUIdx*_SE3 Peter Maydell
2020-02-07 14:33 ` [PULL 15/48] target/arm: Rename ARMMMUIdx_S1E2 to ARMMMUIdx_E2 Peter Maydell
2020-02-07 14:33 ` [PULL 16/48] target/arm: Recover 4 bits from TBFLAGs Peter Maydell
2020-02-07 14:33 ` [PULL 17/48] target/arm: Expand TBFLAG_ANY.MMUIDX to 4 bits Peter Maydell
2020-02-07 14:33 ` [PULL 18/48] target/arm: Rearrange ARMMMUIdxBit Peter Maydell
2020-02-07 14:33 ` [PULL 19/48] target/arm: Tidy ARMMMUIdx m-profile definitions Peter Maydell
2020-02-07 14:33 ` [PULL 20/48] target/arm: Reorganize ARMMMUIdx Peter Maydell
2020-02-07 14:33 ` [PULL 21/48] target/arm: Add regime_has_2_ranges Peter Maydell
2020-02-07 14:33 ` [PULL 22/48] target/arm: Update arm_mmu_idx for VHE Peter Maydell
2020-02-07 14:33 ` [PULL 23/48] target/arm: Update arm_sctlr " Peter Maydell
2020-02-07 14:33 ` [PULL 24/48] target/arm: Update aa64_zva_access for EL2 Peter Maydell
2020-02-07 14:33 ` [PULL 25/48] target/arm: Update ctr_el0_access " Peter Maydell
2020-02-07 14:33 ` [PULL 26/48] target/arm: Add the hypervisor virtual counter Peter Maydell
2020-02-07 14:33 ` [PULL 27/48] target/arm: Update timer access for VHE Peter Maydell
2020-02-07 14:33 ` [PULL 28/48] target/arm: Update define_one_arm_cp_reg_with_opaque " Peter Maydell
2020-02-07 14:33 ` Peter Maydell [this message]
2020-02-07 14:33 ` [PULL 30/48] target/arm: Add VHE timer register redirection and aliasing Peter Maydell
2020-02-07 14:33 ` [PULL 31/48] target/arm: Flush tlb for ASID changes in EL2&0 translation regime Peter Maydell
2020-02-07 14:33 ` [PULL 32/48] target/arm: Flush tlbs for E2&0 " Peter Maydell
2020-02-07 14:33 ` [PULL 33/48] target/arm: Update arm_phys_excp_target_el for TGE Peter Maydell
2020-02-07 14:33 ` [PULL 34/48] target/arm: Update {fp,sve}_exception_el for VHE Peter Maydell
2020-02-07 14:33 ` [PULL 35/48] target/arm: check TGE and E2H flags for EL0 pauth traps Peter Maydell
2020-02-07 14:33 ` [PULL 36/48] target/arm: Update get_a64_user_mem_index for VHE Peter Maydell
2020-02-07 14:33 ` [PULL 37/48] target/arm: Update arm_cpu_do_interrupt_aarch64 " Peter Maydell
2020-02-07 14:33 ` [PULL 38/48] target/arm: Enable ARMv8.1-VHE in -cpu max Peter Maydell
2020-02-07 14:33 ` [PULL 39/48] target/arm: Move arm_excp_unmasked to cpu.c Peter Maydell
2020-02-07 14:33 ` [PULL 40/48] target/arm: Pass more cpu state to arm_excp_unmasked Peter Maydell
2020-02-07 14:33 ` [PULL 41/48] target/arm: Use bool for unmasked in arm_excp_unmasked Peter Maydell
2020-02-07 14:33 ` [PULL 42/48] target/arm: Raise only one interrupt in arm_cpu_exec_interrupt Peter Maydell
2020-02-07 14:33 ` [PULL 43/48] bcm2835_dma: Fix the ylen loop in TD mode Peter Maydell
2020-02-07 14:33 ` [PULL 44/48] bcm2835_dma: Re-initialize xlen " Peter Maydell
2020-02-07 14:33 ` [PULL 45/48] docs/arm-cpu-features: Make kvm-no-adjvtime comment clearer Peter Maydell
2020-02-07 14:33 ` [PULL 46/48] armv7m_systick: delay timer_new to avoid memleaks Peter Maydell
2020-02-07 14:33 ` [PULL 47/48] stm32f2xx_timer: " Peter Maydell
2020-02-07 14:33 ` [PULL 48/48] stellaris: " Peter Maydell
2020-02-10 12:06 ` [PULL 00/48] target-arm queue Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200207143343.30322-30-peter.maydell@linaro.org \
--to=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).