On ARM64 Big/Little Platform, such as i.MX8QM,
there are two types of Cortex-A CPUs, Cortex-A53 and Cortex-A72.
A53 ID_AA64MMFR0_EL1 shows its physical address range supported is 40bits.
A72 ID_AA64MMFR0_EL1 shows its physical address range supported is 44bits.

The minimal value 40 needs to be used as cpu parange, if using 44,
A53 will be broken. So need to iterate the cpu parange of all the
CPUs to find out the smallest one.

Add a new percpu entry id_aa64mmfr0 whose low 4 bits holds parange.
Fill id_aa64mmfr0 before runs into entry
Move arm64 get_cpu_parange out to a new file
Use percpu id_aa64mmfr0 in get_cpu_parange and choose the smallest value

Then each time using get_cpu_parange, the smallest one will
be chosen.

Signed-off-by: Peng Fan <[email protected]>
---

V3:
 Use unsigned int in get_cpu_parange
 Use similar logic in gicv3_cell_init following Jan's comments.
 Add a comments to 0x10

V2:
 Refine commit log
 Use Jailhouse common header
 Use Doxygen format

 hypervisor/arch/arm64/Kbuild               |  2 +-
 hypervisor/arch/arm64/asm-defines.c        |  1 +
 hypervisor/arch/arm64/entry.S              |  3 ++
 hypervisor/arch/arm64/include/asm/paging.h | 27 +-------------
 hypervisor/arch/arm64/include/asm/percpu.h |  1 +
 hypervisor/arch/arm64/paging.c             | 60 ++++++++++++++++++++++++++++++
 6 files changed, 67 insertions(+), 27 deletions(-)
 create mode 100644 hypervisor/arch/arm64/paging.c

diff --git a/hypervisor/arch/arm64/Kbuild b/hypervisor/arch/arm64/Kbuild
index b0ef924e..7283a008 100644
--- a/hypervisor/arch/arm64/Kbuild
+++ b/hypervisor/arch/arm64/Kbuild
@@ -20,4 +20,4 @@ always := lib.a
 # irqchip (common-objs-y), <generic units>
 
 lib-y := $(common-objs-y)
-lib-y += entry.o setup.o control.o mmio.o caches.o traps.o
+lib-y += entry.o setup.o control.o mmio.o paging.o caches.o traps.o
diff --git a/hypervisor/arch/arm64/asm-defines.c 
b/hypervisor/arch/arm64/asm-defines.c
index 58669a4b..81141dc9 100644
--- a/hypervisor/arch/arm64/asm-defines.c
+++ b/hypervisor/arch/arm64/asm-defines.c
@@ -27,6 +27,7 @@ void common(void)
               debug_console.address);
        OFFSET(SYSCONFIG_HYPERVISOR_PHYS, jailhouse_system,
               hypervisor_memory.phys_start);
+       OFFSET(PERCPU_ID_AA64MMFR0, per_cpu, id_aa64mmfr0);
        BLANK();
 
        DEFINE(PERCPU_STACK_END,
diff --git a/hypervisor/arch/arm64/entry.S b/hypervisor/arch/arm64/entry.S
index 61c5dc49..d5b34f17 100644
--- a/hypervisor/arch/arm64/entry.S
+++ b/hypervisor/arch/arm64/entry.S
@@ -157,6 +157,9 @@ el2_entry:
         */
        sub     sp, sp, 20 * 8
 
+       mrs     x29, id_aa64mmfr0_el1
+       str     x29, [x1, #PERCPU_ID_AA64MMFR0]
+
        mov     x29, xzr        /* reset fp,lr */
        mov     x30, xzr
 
diff --git a/hypervisor/arch/arm64/include/asm/paging.h 
b/hypervisor/arch/arm64/include/asm/paging.h
index 0fe1429d..1a5ea0ed 100644
--- a/hypervisor/arch/arm64/include/asm/paging.h
+++ b/hypervisor/arch/arm64/include/asm/paging.h
@@ -178,32 +178,7 @@ typedef u64 *pt_entry_t;
 
 extern unsigned int cpu_parange;
 
-/* return the bits supported for the physical address range for this
- * machine; in arch_paging_init this value will be kept in
- * cpu_parange for later reference */
-static inline unsigned int get_cpu_parange(void)
-{
-       unsigned long id_aa64mmfr0;
-
-       arm_read_sysreg(ID_AA64MMFR0_EL1, id_aa64mmfr0);
-
-       switch (id_aa64mmfr0 & 0xf) {
-       case PARANGE_32B:
-               return 32;
-       case PARANGE_36B:
-               return 36;
-       case PARANGE_40B:
-               return 40;
-       case PARANGE_42B:
-               return 42;
-       case PARANGE_44B:
-               return 44;
-       case PARANGE_48B:
-               return 48;
-       default:
-               return 0;
-       }
-}
+unsigned int get_cpu_parange(void);
 
 /* The size of the cpu_parange, determines from which level we can
  * start from the S2 translations, and the size of the first level
diff --git a/hypervisor/arch/arm64/include/asm/percpu.h 
b/hypervisor/arch/arm64/include/asm/percpu.h
index a88ed477..f8b9f77b 100644
--- a/hypervisor/arch/arm64/include/asm/percpu.h
+++ b/hypervisor/arch/arm64/include/asm/percpu.h
@@ -34,6 +34,7 @@ struct per_cpu {
        u32 stats[JAILHOUSE_NUM_CPU_STATS];
        int shutdown_state;
        bool failed;
+       unsigned long id_aa64mmfr0;
 
        struct pending_irqs pending_irqs;
 
diff --git a/hypervisor/arch/arm64/paging.c b/hypervisor/arch/arm64/paging.c
new file mode 100644
index 00000000..d775ff9f
--- /dev/null
+++ b/hypervisor/arch/arm64/paging.c
@@ -0,0 +1,60 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright 2018 NXP
+ *
+ * Authors:
+ *   Peng Fan <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <jailhouse/control.h>
+#include <asm/percpu.h>
+#include <asm/paging.h>
+
+/**
+ * Return the physical address bits.
+ *
+ * In arch_paging_init this value will be kept in cpu_parange
+ * for later reference
+ *
+ * @return The physical address bits.
+ */
+unsigned int get_cpu_parange(void)
+{
+       /* Larger than any possible value */
+       unsigned int parange = 0x10;
+       unsigned int cpu;
+
+       /*
+        * early_init calls paging_init, which will indirectly call
+        * get_cpu_parange, prior to cell_init, we cannot use
+        * for_each_cpu yet. So we need to iterate over the configuration
+        * of the root cell.
+        */
+       for (cpu = 0; cpu < system_config->root_cell.cpu_set_size * 8; cpu++) {
+               if (!cpu_id_valid(cpu))
+                       continue;
+               if ((per_cpu(cpu)->id_aa64mmfr0 & 0xf) < parange)
+                       parange = per_cpu(cpu)->id_aa64mmfr0 & 0xf;
+       }
+
+       switch (parange) {
+       case PARANGE_32B:
+               return 32;
+       case PARANGE_36B:
+               return 36;
+       case PARANGE_40B:
+               return 40;
+       case PARANGE_42B:
+               return 42;
+       case PARANGE_44B:
+               return 44;
+       case PARANGE_48B:
+               return 48;
+       default:
+               return 0;
+       }
+}
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to