[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 20/27] target-arm: Add computation of starting level
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 20/27] target-arm: Add computation of starting level for S2 PTW |
Date: |
Tue, 27 Oct 2015 14:33:22 +0000 |
From: "Edgar E. Iglesias" <address@hidden>
The starting level for S2 pagetable walks is computed
differently from the S1 starting level. Implement the S2
variant.
Signed-off-by: Edgar E. Iglesias <address@hidden>
Message-id: address@hidden
Reviewed-by: Peter Maydell <address@hidden>
Signed-off-by: Peter Maydell <address@hidden>
---
target-arm/helper.c | 114 +++++++++++++++++++++++++++++++++++++++++++------
target-arm/internals.h | 25 +++++++++++
2 files changed, 126 insertions(+), 13 deletions(-)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 2af126f..8714724 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -6470,12 +6470,72 @@ typedef enum {
permission_fault = 3,
} MMUFaultType;
+/*
+ * check_s2_startlevel
+ * @cpu: ARMCPU
+ * @is_aa64: True if the translation regime is in AArch64 state
+ * @startlevel: Suggested starting level
+ * @inputsize: Bitsize of IPAs
+ * @stride: Page-table stride (See the ARM ARM)
+ *
+ * Returns true if the suggested starting level is OK and false otherwise.
+ */
+static bool check_s2_startlevel(ARMCPU *cpu, bool is_aa64, int level,
+ int inputsize, int stride)
+{
+ /* Negative levels are never allowed. */
+ if (level < 0) {
+ return false;
+ }
+
+ if (is_aa64) {
+ unsigned int pamax = arm_pamax(cpu);
+
+ switch (stride) {
+ case 13: /* 64KB Pages. */
+ if (level == 0 || (level == 1 && pamax <= 42)) {
+ return false;
+ }
+ break;
+ case 11: /* 16KB Pages. */
+ if (level == 0 || (level == 1 && pamax <= 40)) {
+ return false;
+ }
+ break;
+ case 9: /* 4KB Pages. */
+ if (level == 0 && pamax <= 42) {
+ return false;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ } else {
+ const int grainsize = stride + 3;
+ int startsizecheck;
+
+ /* AArch32 only supports 4KB pages. Assert on that. */
+ assert(stride == 9);
+
+ if (level == 0) {
+ return false;
+ }
+
+ startsizecheck = inputsize - ((3 - level) * stride + grainsize);
+ if (startsizecheck < 1 || startsizecheck > stride + 4) {
+ return false;
+ }
+ }
+ return true;
+}
+
static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address,
int access_type, ARMMMUIdx mmu_idx,
hwaddr *phys_ptr, MemTxAttrs *txattrs, int
*prot,
target_ulong *page_size_ptr, uint32_t *fsr)
{
- CPUState *cs = CPU(arm_env_get_cpu(env));
+ ARMCPU *cpu = arm_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
/* Read an LPAE long-descriptor translation table. */
MMUFaultType fault_type = translation_fault;
uint32_t level = 1;
@@ -6630,18 +6690,46 @@ static bool get_phys_addr_lpae(CPUARMState *env,
target_ulong address,
goto do_fault;
}
- /* The starting level depends on the virtual address size (which can be
- * up to 48 bits) and the translation granule size. It indicates the number
- * of strides (stride bits at a time) needed to consume the bits
- * of the input address. In the pseudocode this is:
- * level = 4 - RoundUp((inputsize - grainsize) / stride)
- * where their 'inputsize' is our 'inputsize', 'grainsize' is
- * our 'stride + 3' and 'stride' is our 'stride'.
- * Applying the usual "rounded up m/n is (m+n-1)/n" and simplifying:
- * = 4 - (inputsize - stride - 3 + stride - 1) / stride
- * = 4 - (inputsize - 4) / stride;
- */
- level = 4 - (inputsize - 4) / stride;
+ if (mmu_idx != ARMMMUIdx_S2NS) {
+ /* The starting level depends on the virtual address size (which can
+ * be up to 48 bits) and the translation granule size. It indicates
+ * the number of strides (stride bits at a time) needed to
+ * consume the bits of the input address. In the pseudocode this is:
+ * level = 4 - RoundUp((inputsize - grainsize) / stride)
+ * where their 'inputsize' is our 'inputsize', 'grainsize' is
+ * our 'stride + 3' and 'stride' is our 'stride'.
+ * Applying the usual "rounded up m/n is (m+n-1)/n" and simplifying:
+ * = 4 - (inputsize - stride - 3 + stride - 1) / stride
+ * = 4 - (inputsize - 4) / stride;
+ */
+ level = 4 - (inputsize - 4) / stride;
+ } else {
+ /* For stage 2 translations the starting level is specified by the
+ * VTCR_EL2.SL0 field (whose interpretation depends on the page size)
+ */
+ int startlevel = extract32(tcr->raw_tcr, 6, 2);
+ bool ok;
+
+ if (va_size == 32 || stride == 9) {
+ /* AArch32 or 4KB pages */
+ level = 2 - startlevel;
+ } else {
+ /* 16KB or 64KB pages */
+ level = 3 - startlevel;
+ }
+
+ /* Check that the starting level is valid. */
+ ok = check_s2_startlevel(cpu, va_size == 64, level,
+ inputsize, stride);
+ if (!ok) {
+ /* AArch64 reports these as level 0 faults.
+ * AArch32 reports these as level 1 faults.
+ */
+ level = va_size == 64 ? 0 : 1;
+ fault_type = translation_fault;
+ goto do_fault;
+ }
+ }
/* 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
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 36a56aa..8bd37eb 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -152,6 +152,31 @@ static inline void update_spsel(CPUARMState *env, uint32_t
imm)
aarch64_restore_sp(env, cur_el);
}
+/*
+ * arm_pamax
+ * @cpu: ARMCPU
+ *
+ * Returns the implementation defined bit-width of physical addresses.
+ * The ARMv8 reference manuals refer to this as PAMax().
+ */
+static inline unsigned int arm_pamax(ARMCPU *cpu)
+{
+ static const unsigned int pamax_map[] = {
+ [0] = 32,
+ [1] = 36,
+ [2] = 40,
+ [3] = 42,
+ [4] = 44,
+ [5] = 48,
+ };
+ unsigned int parange = extract32(cpu->id_aa64mmfr0, 0, 4);
+
+ /* id_aa64mmfr0 is a read-only register so values outside of the
+ * supported mappings can be considered an implementation error. */
+ assert(parange < ARRAY_SIZE(pamax_map));
+ return pamax_map[parange];
+}
+
/* Return true if extended addresses are enabled.
* This is always the case if our translation regime is 64 bit,
* but depends on TTBCR.EAE for 32 bit.
--
1.9.1
- [Qemu-devel] [PULL 25/27] target-arm: Add S2 translation to 32bit S1 PTWs, (continued)
- [Qemu-devel] [PULL 25/27] target-arm: Add S2 translation to 32bit S1 PTWs, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 17/27] target-arm: Add support for AArch32 S2 negative t0sz, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 26/27] target-arm: Route S2 MMU faults to EL2, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 14/27] target-arm: Add HPFAR_EL2, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 13/27] i.MX: Standardize i.MX GPT debug, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 19/27] target-arm: lpae: Rename granule_sz to stride, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 23/27] target-arm: Add ARMMMUFaultInfo, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 24/27] target-arm: Add S2 translation to 64bit S1 PTWs, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 16/27] target-arm: lpae: Move declaration of t0sz and t1sz, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 21/27] target-arm: Add support for S2 page-table protection bits, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 20/27] target-arm: Add computation of starting level for S2 PTW,
Peter Maydell <=
- [Qemu-devel] [PULL 01/27] target-arm: Fix "no 64-bit EL2" assumption in arm_excp_unmasked(), Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 07/27] i.MX: Standardize i.MX GPIO debug, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 10/27] i.MX: Standardize i.MX CCM debug, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 05/27] hw/arm/virt: don't use a15memmap directly, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 03/27] target-arm: Add support for SPSR_(ABT|UND|IRQ|FIQ), Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 04/27] arm_gic_kvm: Disable live migration if not supported, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 15/27] target-arm: lpae: Make t0sz and t1sz signed integers, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 12/27] i.MX: Standardize i.MX EPIT debug, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 18/27] target-arm: lpae: Replace tsz with computed inputsize, Peter Maydell, 2015/10/27
- [Qemu-devel] [PULL 06/27] i.MX: Standardize i.MX serial debug., Peter Maydell, 2015/10/27