From nobody Fri Oct 10 09:21:35 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1604932181; cv=none; d=zohomail.com; s=zohoarc; b=k5LSDo/FM6lJT/HG8HQ3X+3+1pfi/eHdYbLkdpuVqvj3o0LThIKJ4OQdYq2G0TSwzVZhtRlFZ+KyhRvkBahfhPsv8iXNPCQuNPpxo74V9NenzsZUKiDXJIMXU4Oe2vO+JqUT022SIQtILjwoC73ns4rle+4gdXyW8BYvc+Ij57s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1604932181; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=guWYLJjJ5bGZirN+ZTF1ini94uNM0e+07qhYCOapSlU=; b=AEY0exnaGS6NS8EfY4e2OUxDDmzepn0/b26X/Pojncex2JQMf+yNZZNj62qEuNNsct+yQxpsPjjDFCP9wkbR8l45kJy7+ls5jdMWIsZB0E12IAvc9QyUgsN6zPx4h+uTWyuBot21+Kdd4mOhkzW+aH4ku0zgY90qwAjyeLfHSCc= ARC-Authentication-Results: i=1; mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1604932181893960.6212582145507; Mon, 9 Nov 2020 06:29:41 -0800 (PST) Received: from localhost ([::1]:34554 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kc8Au-0008SR-LN for importer@patchew.org; Mon, 09 Nov 2020 09:29:40 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:40488) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kc7sj-0003Pf-RQ; Mon, 09 Nov 2020 09:10:53 -0500 Received: from poy.remlab.net ([2001:41d0:2:5a1a::]:60192 helo=ns207790.ip-94-23-215.eu) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kc7sf-0002qN-FD; Mon, 09 Nov 2020 09:10:53 -0500 Received: from basile.remlab.net (ip6-localhost [IPv6:::1]) by ns207790.ip-94-23-215.eu (Postfix) with ESMTP id D71DC6053E; Mon, 9 Nov 2020 15:10:23 +0100 (CET) From: remi.denis.courmont@huawei.com To: qemu-arm@nongnu.org Subject: [PATCH 12/17] target/arm: secure stage 2 translation regime Date: Mon, 9 Nov 2020 16:10:15 +0200 Message-Id: <20201109141020.27234-12-remi.denis.courmont@huawei.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <5554493.MhkbZ0Pkbq@basile.remlab.net> References: <5554493.MhkbZ0Pkbq@basile.remlab.net> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:41d0:2:5a1a::; envelope-from=remi@remlab.net; helo=ns207790.ip-94-23-215.eu X-detected-operating-system: by eggs.gnu.org: First seen = 2020/11/09 08:56:07 X-ACL-Warn: Detected OS = ??? X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.249, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" From: R=C3=A9mi Denis-Courmont Signed-off-by: R=C3=A9mi Denis-Courmont --- target/arm/cpu.h | 11 ++++- target/arm/helper.c | 96 ++++++++++++++++++++++++++++++++---------- target/arm/internals.h | 24 +++++++++++ 3 files changed, 107 insertions(+), 24 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 7a03869d26..c5535716c6 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -168,6 +168,11 @@ typedef struct { uint32_t base_mask; } TCR; =20 +#define VTCR_NSW (1u << 29) +#define VTCR_NSA (1u << 30) +#define VSTCR_SW VTCR_NSW +#define VSTCR_SA VTCR_NSA + /* Define a maximum sized vector register. * For 32-bit, this is a 128-bit NEON/AdvSIMD register. * For 64-bit, this is a 2048-bit SVE register. @@ -2988,6 +2993,9 @@ typedef enum ARMMMUIdx { ARMMMUIdx_Stage1_E0 =3D 0 | ARM_MMU_IDX_NOTLB, ARMMMUIdx_Stage1_E1 =3D 1 | ARM_MMU_IDX_NOTLB, ARMMMUIdx_Stage1_E1_PAN =3D 2 | ARM_MMU_IDX_NOTLB, + ARMMMUIdx_Stage1_SE0 =3D 3 | ARM_MMU_IDX_NOTLB, + ARMMMUIdx_Stage1_SE1 =3D 4 | ARM_MMU_IDX_NOTLB, + ARMMMUIdx_Stage1_SE1_PAN =3D 5 | ARM_MMU_IDX_NOTLB, /* * Not allocated a TLB: used only for second stage of an S12 page * table walk, or for descriptor loads during first stage of an S1 @@ -2995,7 +3003,8 @@ typedef enum ARMMMUIdx { * then various TLB flush insns which currently are no-ops or flush * only stage 1 MMU indexes will need to change to flush stage 2. */ - ARMMMUIdx_Stage2 =3D 3 | ARM_MMU_IDX_NOTLB, + ARMMMUIdx_Stage2 =3D 6 | ARM_MMU_IDX_NOTLB, + ARMMMUIdx_Stage2_S =3D 7 | ARM_MMU_IDX_NOTLB, =20 /* * M-profile. diff --git a/target/arm/helper.c b/target/arm/helper.c index 90967771b6..aae22847bb 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3429,7 +3429,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64= _t value, uint32_t syn, fsr, fsc; bool take_exc =3D false; =20 - if (fi.s1ptw && current_el =3D=3D 1 && !arm_is_secure(env) + if (fi.s1ptw && current_el =3D=3D 1 && arm_mmu_idx_is_stage1_of_2(mmu_idx, NULL)) { /* * Synchronous stage 2 fault on an access made as part of the @@ -3586,10 +3586,10 @@ static void ats_write(CPUARMState *env, const ARMCP= RegInfo *ri, uint64_t value) /* fall through */ case 1: if (ri->crm =3D=3D 9 && (env->uncached_cpsr & CPSR_PAN)) { - mmu_idx =3D (secure ? ARMMMUIdx_SE10_1_PAN + mmu_idx =3D (secure ? ARMMMUIdx_Stage1_SE1_PAN : ARMMMUIdx_Stage1_E1_PAN); } else { - mmu_idx =3D secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E= 1; + mmu_idx =3D secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stag= e1_E1; } break; default: @@ -3603,10 +3603,11 @@ static void ats_write(CPUARMState *env, const ARMCP= RegInfo *ri, uint64_t value) mmu_idx =3D ARMMMUIdx_SE10_0; break; case 2: + g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */ mmu_idx =3D ARMMMUIdx_Stage1_E0; break; case 1: - mmu_idx =3D secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_Stage1_E0; + mmu_idx =3D secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E= 0; break; default: g_assert_not_reached(); @@ -3671,10 +3672,10 @@ static void ats_write64(CPUARMState *env, const ARM= CPRegInfo *ri, switch (ri->opc1) { case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */ if (ri->crm =3D=3D 9 && (env->pstate & PSTATE_PAN)) { - mmu_idx =3D (secure ? ARMMMUIdx_SE10_1_PAN + mmu_idx =3D (secure ? ARMMMUIdx_Stage1_SE1_PAN : ARMMMUIdx_Stage1_E1_PAN); } else { - mmu_idx =3D secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E= 1; + mmu_idx =3D secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stag= e1_E1; } break; case 4: /* AT S1E2R, AT S1E2W */ @@ -3688,7 +3689,7 @@ static void ats_write64(CPUARMState *env, const ARMCP= RegInfo *ri, } break; case 2: /* AT S1E0R, AT S1E0W */ - mmu_idx =3D secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_Stage1_E0; + mmu_idx =3D secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E0; break; case 4: /* AT S12E1R, AT S12E1W */ mmu_idx =3D secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_E10_1; @@ -10049,7 +10050,7 @@ static inline bool regime_translation_disabled(CPUA= RMState *env, =20 hcr_el2 =3D arm_hcr_el2_eff(env); =20 - if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { + if (mmu_idx =3D=3D ARMMMUIdx_Stage2 || mmu_idx =3D=3D ARMMMUIdx_Stage2= _S) { /* HCR.DC means HCR.VM behaves as 1 */ return (hcr_el2 & (HCR_DC | HCR_VM)) =3D=3D 0; } @@ -10082,6 +10083,9 @@ static inline uint64_t regime_ttbr(CPUARMState *env= , ARMMMUIdx mmu_idx, if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { return env->cp15.vttbr_el2; } + if (mmu_idx =3D=3D ARMMMUIdx_Stage2_S) { + return env->cp15.vsttbr_el2; + } if (ttbrn =3D=3D 0) { return env->cp15.ttbr0_el[regime_el(env, mmu_idx)]; } else { @@ -10097,6 +10101,12 @@ static inline uint64_t regime_ttbr(CPUARMState *en= v, ARMMMUIdx mmu_idx, static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx) { switch (mmu_idx) { + case ARMMMUIdx_SE10_0: + return ARMMMUIdx_Stage1_SE0; + case ARMMMUIdx_SE10_1: + return ARMMMUIdx_Stage1_SE1; + case ARMMMUIdx_SE10_1_PAN: + return ARMMMUIdx_Stage1_SE1_PAN; case ARMMMUIdx_E10_0: return ARMMMUIdx_Stage1_E0; case ARMMMUIdx_E10_1: @@ -10141,6 +10151,7 @@ static inline bool regime_is_user(CPUARMState *env,= ARMMMUIdx mmu_idx) case ARMMMUIdx_E20_0: case ARMMMUIdx_SE20_0: case ARMMMUIdx_Stage1_E0: + case ARMMMUIdx_Stage1_SE0: case ARMMMUIdx_MUser: case ARMMMUIdx_MSUser: case ARMMMUIdx_MUserNegPri: @@ -10306,6 +10317,7 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx m= mu_idx, bool is_aa64, int wxn =3D 0; =20 assert(mmu_idx !=3D ARMMMUIdx_Stage2); + assert(mmu_idx !=3D ARMMMUIdx_Stage2_S); =20 user_rw =3D simple_ap_to_rw_prot_is_user(ap, true); if (is_user) { @@ -10405,7 +10417,21 @@ static hwaddr S1_ptw_translate(CPUARMState *env, A= RMMMUIdx mmu_idx, ARMCacheAttrs cacheattrs =3D {}; MemTxAttrs txattrs =3D {}; =20 - assert(!*is_secure); /* TODO: S-EL2 */ + if (s2_mmu_idx =3D=3D ARMMMUIdx_Stage2_S) { + /* Check if page table walk is to secure or non-secure PA spac= e. */ + if (*is_secure) { + *is_secure =3D !(env->cp15.vstcr_el2.raw_tcr & VSTCR_SW); + } else { + *is_secure =3D !(env->cp15.vtcr_el2.raw_tcr & VTCR_NSW); + } + if (*is_secure) { + txattrs.secure =3D true; + } else { + s2_mmu_idx =3D ARMMMUIdx_Stage2; + } + } else { + assert(!*is_secure); + } =20 ret =3D get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx, f= alse, &s2pa, &txattrs, &s2prot, &s2size, fi, @@ -10870,7 +10896,7 @@ static int aa64_va_parameter_tbi(uint64_t tcr, ARMM= MUIdx mmu_idx) { if (regime_has_2_ranges(mmu_idx)) { return extract64(tcr, 37, 2); - } else if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { + } else if (mmu_idx =3D=3D ARMMMUIdx_Stage2 || mmu_idx =3D=3D ARMMMUIdx= _Stage2_S) { return 0; /* VTCR_EL2 */ } else { /* Replicate the single TBI bit so we always have 2 bits. */ @@ -10882,7 +10908,7 @@ static int aa64_va_parameter_tbid(uint64_t tcr, ARM= MMUIdx mmu_idx) { if (regime_has_2_ranges(mmu_idx)) { return extract64(tcr, 51, 2); - } else if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { + } else if (mmu_idx =3D=3D ARMMMUIdx_Stage2 || mmu_idx =3D=3D ARMMMUIdx= _Stage2_S) { return 0; /* VTCR_EL2 */ } else { /* Replicate the single TBID bit so we always have 2 bits. */ @@ -10912,7 +10938,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env= , uint64_t va, tsz =3D extract32(tcr, 0, 6); using64k =3D extract32(tcr, 14, 1); using16k =3D extract32(tcr, 15, 1); - if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { + if (mmu_idx =3D=3D ARMMMUIdx_Stage2 || mmu_idx =3D=3D ARMMMUIdx_St= age2_S) { /* VTCR_EL2 */ hpd =3D false; } else { @@ -10970,6 +10996,8 @@ static ARMVAParameters aa32_va_parameters(CPUARMSta= te *env, uint32_t va, int select, tsz; bool epd, hpd; =20 + assert(mmu_idx !=3D ARMMMUIdx_Stage2_S); + if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { /* VTCR */ bool sext =3D extract32(tcr, 4, 1); @@ -11135,7 +11163,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, ta= rget_ulong address, goto do_fault; } =20 - if (mmu_idx !=3D ARMMMUIdx_Stage2) { + if (mmu_idx !=3D ARMMMUIdx_Stage2 && mmu_idx !=3D ARMMMUIdx_Stage2_S) { /* The starting level depends on the virtual address size (which c= an * be up to 48 bits) and the translation granule size. It indicates * the number of strides (stride bits at a time) needed to @@ -11239,7 +11267,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, ta= rget_ulong address, attrs =3D extract64(descriptor, 2, 10) | (extract64(descriptor, 52, 12) << 10); =20 - if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { + if (mmu_idx =3D=3D ARMMMUIdx_Stage2 || mmu_idx =3D=3D ARMMMUIdx_St= age2_S) { /* Stage 2 table descriptors do not include any attribute fiel= ds */ break; } @@ -11269,8 +11297,10 @@ static bool get_phys_addr_lpae(CPUARMState *env, t= arget_ulong address, =20 ap =3D extract32(attrs, 4, 2); =20 - if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { - ns =3D true; + if (mmu_idx =3D=3D ARMMMUIdx_Stage2 || mmu_idx =3D=3D ARMMMUIdx_Stage2= _S) { + if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { + ns =3D true; + } xn =3D extract32(attrs, 11, 2); *prot =3D get_S2prot(env, ap, xn, s1_is_el0); } else { @@ -11297,7 +11327,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, ta= rget_ulong address, arm_tlb_bti_gp(txattrs) =3D true; } =20 - if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { + if (mmu_idx =3D=3D ARMMMUIdx_Stage2 || mmu_idx =3D=3D ARMMMUIdx_Stage2= _S) { cacheattrs->attrs =3D convert_stage2_attrs(env, extract32(attrs, 0= , 4)); } else { /* Index into MAIR registers for cache attributes */ @@ -11316,7 +11346,8 @@ do_fault: fi->type =3D fault_type; fi->level =3D level; /* Tag the error as S2 for failed S1 PTW at S2 or ordinary S2. */ - fi->stage2 =3D fi->s1ptw || (mmu_idx =3D=3D ARMMMUIdx_Stage2); + fi->stage2 =3D fi->s1ptw || (mmu_idx =3D=3D ARMMMUIdx_Stage2 || + mmu_idx =3D=3D ARMMMUIdx_Stage2_S); return true; } =20 @@ -12132,7 +12163,10 @@ bool get_phys_addr(CPUARMState *env, target_ulong = address, { if (mmu_idx =3D=3D ARMMMUIdx_E10_0 || mmu_idx =3D=3D ARMMMUIdx_E10_1 || - mmu_idx =3D=3D ARMMMUIdx_E10_1_PAN) { + mmu_idx =3D=3D ARMMMUIdx_E10_1_PAN || + mmu_idx =3D=3D ARMMMUIdx_SE10_0 || + mmu_idx =3D=3D ARMMMUIdx_SE10_1 || + mmu_idx =3D=3D ARMMMUIdx_SE10_1_PAN) { /* Call ourselves recursively to do the stage 1 and then stage 2 * translations. */ @@ -12140,21 +12174,25 @@ bool get_phys_addr(CPUARMState *env, target_ulong= address, hwaddr ipa; int s2_prot; int ret; + ARMMMUIdx s2_mmu_idx; + bool is_el0; ARMCacheAttrs cacheattrs2 =3D {}; =20 ret =3D get_phys_addr(env, address, access_type, stage_1_mmu_idx(mmu_idx), &ipa, attrs, prot, page_size, fi, cacheattrs); =20 + s2_mmu_idx =3D attrs->secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_= Stage2; + is_el0 =3D mmu_idx =3D=3D ARMMMUIdx_SE10_0 || mmu_idx =3D=3D A= RMMMUIdx_E10_0; + /* If S1 fails or S2 is disabled, return early. */ - if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2))= { + if (ret || regime_translation_disabled(env, s2_mmu_idx)) { *phys_ptr =3D ipa; return ret; } =20 /* S1 is done. Now do S2 translation. */ - ret =3D get_phys_addr_lpae(env, ipa, access_type, ARMMMUIdx_St= age2, - mmu_idx =3D=3D ARMMMUIdx_E10_0, + ret =3D get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx, = is_el0, phys_ptr, attrs, &s2_prot, page_size, fi, &cacheattrs2); fi->s2addr =3D ipa; @@ -12166,6 +12204,18 @@ bool get_phys_addr(CPUARMState *env, target_ulong = address, return ret; } =20 + /* Check if IPA translates to secure or non-secure PA space. */ + if (arm_is_secure_below_el3(env)) { + if (attrs->secure) { + attrs->secure =3D + !(env->cp15.vstcr_el2.raw_tcr & (VSTCR_SA | VSTCR_= SW)); + } else { + attrs->secure =3D + !((env->cp15.vtcr_el2.raw_tcr & (VTCR_NSA | VTCR_N= SW)) + || (env->cp15.vstcr_el2.raw_tcr & VSTCR_SA)); + } + } + /* Combine the S1 and S2 cache attributes. */ if (arm_hcr_el2_eff(env) & HCR_DC) { /* @@ -12249,7 +12299,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong a= ddress, * MMU disabled. S1 addresses within aa64 translation regimes are * still checked for bounds -- see AArch64.TranslateAddressS1Off. */ - if (mmu_idx !=3D ARMMMUIdx_Stage2) { + if (mmu_idx !=3D ARMMMUIdx_Stage2 && mmu_idx !=3D ARMMMUIdx_Stage2= _S) { int r_el =3D regime_el(env, mmu_idx); if (arm_el_is_aa64(env, r_el)) { int pamax =3D arm_pamax(env_archcpu(env)); diff --git a/target/arm/internals.h b/target/arm/internals.h index ec6d6dd733..04f71e0601 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -851,6 +851,9 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_id= x) case ARMMMUIdx_Stage1_E0: case ARMMMUIdx_Stage1_E1: case ARMMMUIdx_Stage1_E1_PAN: + case ARMMMUIdx_Stage1_SE0: + case ARMMMUIdx_Stage1_SE1: + case ARMMMUIdx_Stage1_SE1_PAN: case ARMMMUIdx_E10_0: case ARMMMUIdx_E10_1: case ARMMMUIdx_E10_1_PAN: @@ -896,7 +899,11 @@ static inline bool regime_is_secure(CPUARMState *env, = ARMMMUIdx mmu_idx) case ARMMMUIdx_SE20_0: case ARMMMUIdx_SE20_2: case ARMMMUIdx_SE20_2_PAN: + case ARMMMUIdx_Stage1_SE0: + case ARMMMUIdx_Stage1_SE1: + case ARMMMUIdx_Stage1_SE1_PAN: case ARMMMUIdx_SE2: + case ARMMMUIdx_Stage2_S: case ARMMMUIdx_MSPrivNegPri: case ARMMMUIdx_MSUserNegPri: case ARMMMUIdx_MSPriv: @@ -911,6 +918,7 @@ static inline bool regime_is_pan(CPUARMState *env, ARMM= MUIdx mmu_idx) { switch (mmu_idx) { case ARMMMUIdx_Stage1_E1_PAN: + case ARMMMUIdx_Stage1_SE1_PAN: case ARMMMUIdx_E10_1_PAN: case ARMMMUIdx_E20_2_PAN: case ARMMMUIdx_SE10_1_PAN: @@ -932,6 +940,7 @@ static inline uint32_t regime_el(CPUARMState *env, ARMM= MUIdx mmu_idx) case ARMMMUIdx_E20_2: case ARMMMUIdx_E20_2_PAN: case ARMMMUIdx_Stage2: + case ARMMMUIdx_Stage2_S: case ARMMMUIdx_SE2: case ARMMMUIdx_E2: return 2; @@ -944,6 +953,9 @@ static inline uint32_t regime_el(CPUARMState *env, ARMM= MUIdx mmu_idx) case ARMMMUIdx_Stage1_E0: case ARMMMUIdx_Stage1_E1: case ARMMMUIdx_Stage1_E1_PAN: + case ARMMMUIdx_Stage1_SE0: + case ARMMMUIdx_Stage1_SE1: + case ARMMMUIdx_Stage1_SE1_PAN: case ARMMMUIdx_E10_0: case ARMMMUIdx_E10_1: case ARMMMUIdx_E10_1_PAN: @@ -967,6 +979,12 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMU= Idx mmu_idx) if (mmu_idx =3D=3D ARMMMUIdx_Stage2) { return &env->cp15.vtcr_el2; } + if (mmu_idx =3D=3D ARMMMUIdx_Stage2_S) { + /* Note: Secure stage 2 nominally shares fields from VTCR_EL2, but + * those are not currently used by QEMU, so just return VSTCR_EL2. + */ + return &env->cp15.vstcr_el2; + } return &env->cp15.tcr_el[regime_el(env, mmu_idx)]; } =20 @@ -1176,6 +1194,12 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMU= Idx s1_mmu_idx, *s2_mmu_idx =3D ARMMMUIdx_Stage2; } return true; + case ARMMMUIdx_Stage1_SE0: + case ARMMMUIdx_Stage1_SE1: + case ARMMMUIdx_Stage1_SE1_PAN: + if (s2_mmu_idx !=3D NULL) + *s2_mmu_idx =3D ARMMMUIdx_Stage2_S; + return true; default: return false; } --=20 2.29.2