Message ID | 1446747358-18214-10-git-send-email-peter.maydell@linaro.org |
---|---|
State | Accepted |
Headers | show |
On 9 November 2015 at 10:51, Paolo Bonzini <pbonzini@redhat.com> wrote: > > > On 05/11/2015 19:15, Peter Maydell wrote: >> If we have a secure address space, use it in page table walks: >> * when doing the physical accesses to read descriptors, >> make them through the correct address space >> * when the final result indicates a secure access, pass the >> correct address space index to tlb_set_page_with_attrs() >> >> (The descriptor reads are the only direct physical accesses >> made in target-arm/ for CPUs which might have TrustZone.) > > What is the case where you have no secure address space and you have > TrustZone? KVM doesn't have TrustZone, so it should never be in a > secure regime, should it? You mean "what is the case where is_secure but cpu->num_ases == 1" ? That happens if you have a TrustZone CPU but the board has only connected up one address space, because there is no difference in the view from Secure and NonSecure. (vexpress is like this in hardware, and most of our board models for TZ CPUS are like that now even if the real h/w makes a distinction.) I could have handled that by making the CPU init code always register two ASes (using the same one twice if the board code only passes one or using system_address_space twice if the board code doesn't pass one at all), but that seemed a bit wasteful. thanks -- PMM
On 9 November 2015 at 11:03, Paolo Bonzini <pbonzini@redhat.com> wrote: > > > On 09/11/2015 11:58, Peter Maydell wrote: >> You mean "what is the case where is_secure but cpu->num_ases == 1" ? >> That happens if you have a TrustZone CPU but the board has only >> connected up one address space, because there is no difference >> in the view from Secure and NonSecure. (vexpress is like this >> in hardware, and most of our board models for TZ CPUS are like >> that now even if the real h/w makes a distinction.) >> >> I could have handled that by making the CPU init code always >> register two ASes (using the same one twice if the board code >> only passes one or using system_address_space twice if the >> board code doesn't pass one at all), but that seemed a bit wasteful. > > I think it's simpler though. Complicating the init code is better than > handling the condition throughout all the helpers... It was the overhead of having an extra AddressSpace that concerned me (plus it shows up in things like 'info mtree' somewhat confusingly if you didn't expect your board to really have 2 ASes). But I don't feel very strongly about it (or have anything solid to base an argument either way on). thanks -- PMM
On 9 November 2015 at 11:19, Paolo Bonzini <pbonzini@redhat.com> wrote: > > > On 09/11/2015 12:09, Peter Maydell wrote: >>>> >> I could have handled that by making the CPU init code always >>>> >> register two ASes (using the same one twice if the board code >>>> >> only passes one or using system_address_space twice if the >>>> >> board code doesn't pass one at all), but that seemed a bit wasteful. >>> > >>> > I think it's simpler though. Complicating the init code is better than >>> > handling the condition throughout all the helpers... >> It was the overhead of having an extra AddressSpace that concerned >> me (plus it shows up in things like 'info mtree' somewhat confusingly >> if you didn't expect your board to really have 2 ASes). > > I don't think it shows up twice with address_space_init_shareable, does it? Yes, looking at the code you're right. -- PMM
On 9 November 2015 at 10:58, Peter Maydell <peter.maydell@linaro.org> wrote: > On 9 November 2015 at 10:51, Paolo Bonzini <pbonzini@redhat.com> wrote: >> >> >> On 05/11/2015 19:15, Peter Maydell wrote: >>> If we have a secure address space, use it in page table walks: >>> * when doing the physical accesses to read descriptors, >>> make them through the correct address space >>> * when the final result indicates a secure access, pass the >>> correct address space index to tlb_set_page_with_attrs() >>> >>> (The descriptor reads are the only direct physical accesses >>> made in target-arm/ for CPUs which might have TrustZone.) >> >> What is the case where you have no secure address space and you have >> TrustZone? KVM doesn't have TrustZone, so it should never be in a >> secure regime, should it? > > You mean "what is the case where is_secure but cpu->num_ases == 1" ? > That happens if you have a TrustZone CPU but the board has only > connected up one address space, because there is no difference > in the view from Secure and NonSecure. (vexpress is like this > in hardware, and most of our board models for TZ CPUS are like > that now even if the real h/w makes a distinction.) Looking more closely at my own code I was wrong here. The case where you have only one AS is when the CPU is using KVM. In that case in theory we should never end up being asked to pick an AddressSpace for a set of MemTxAttrs that say "secure" [in the new design where we figure out the asidx from the txattrs], but it's a bit tricky to be absolutely certain that never happens... thanks -- PMM
diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 815fef8..8dbf4d4 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -1720,6 +1720,12 @@ static inline int cpu_mmu_index(CPUARMState *env, bool ifetch) return el; } +/* Indexes used when registering address spaces with cpu_address_space_init */ +typedef enum ARMASIdx { + ARMASIdx_NS = 0, + ARMASIdx_S = 1, +} ARMASIdx; + /* Return the Exception Level targeted by debug exceptions; * currently always EL1 since we don't implement EL2 or EL3. */ @@ -1991,4 +1997,27 @@ enum { QEMU_PSCI_CONDUIT_HVC = 2, }; +#ifndef CONFIG_USER_ONLY +/* Return the address space index to use for a memory access + * (which depends on whether the access is S or NS, and whether + * the board gave us a separate AddressSpace for S accesses). + */ +static inline int arm_asidx(CPUState *cs, bool is_secure) +{ + if (is_secure && cs->num_ases > 1) { + return ARMASIdx_S; + } + return ARMASIdx_NS; +} + +/* Return the AddressSpace to use for a memory access + * (which depends on whether the access is S or NS, and whether + * the board gave us a separate AddressSpace for S accesses). + */ +static inline AddressSpace *arm_addressspace(CPUState *cs, bool is_secure) +{ + return cpu_get_address_space(cs, arm_asidx(cs, is_secure)); +} +#endif + #endif diff --git a/target-arm/helper.c b/target-arm/helper.c index 174371b..242928d 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -6260,13 +6260,14 @@ static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure, ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; MemTxAttrs attrs = {}; + AddressSpace *as = arm_addressspace(cs, is_secure); attrs.secure = is_secure; addr = S1_ptw_translate(env, mmu_idx, addr, attrs, fsr, fi); if (fi->s1ptw) { return 0; } - return address_space_ldl(cs->as, addr, attrs, NULL); + return address_space_ldl(as, addr, attrs, NULL); } static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure, @@ -6276,13 +6277,14 @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure, ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; MemTxAttrs attrs = {}; + AddressSpace *as = arm_addressspace(cs, is_secure); attrs.secure = is_secure; addr = S1_ptw_translate(env, mmu_idx, addr, attrs, fsr, fi); if (fi->s1ptw) { return 0; } - return address_space_ldq(cs->as, addr, attrs, NULL); + return address_space_ldq(as, addr, attrs, NULL); } static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, @@ -7307,6 +7309,7 @@ bool arm_tlb_fill(CPUState *cs, vaddr address, target_ulong page_size; int prot; int ret; + int asidx; MemTxAttrs attrs = {}; ret = get_phys_addr(env, address, access_type, mmu_idx, &phys_addr, @@ -7315,7 +7318,8 @@ bool arm_tlb_fill(CPUState *cs, vaddr address, /* Map a single [sub]page. */ phys_addr &= TARGET_PAGE_MASK; address &= TARGET_PAGE_MASK; - tlb_set_page_with_attrs(cs, address, 0, phys_addr, attrs, + asidx = arm_asidx(cs, attrs.secure); + tlb_set_page_with_attrs(cs, address, asidx, phys_addr, attrs, prot, mmu_idx, page_size); return 0; }
If we have a secure address space, use it in page table walks: * when doing the physical accesses to read descriptors, make them through the correct address space * when the final result indicates a secure access, pass the correct address space index to tlb_set_page_with_attrs() (The descriptor reads are the only direct physical accesses made in target-arm/ for CPUs which might have TrustZone.) Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target-arm/cpu.h | 29 +++++++++++++++++++++++++++++ target-arm/helper.c | 10 +++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) -- 1.9.1