All of lore.kernel.org
 help / color / mirror / Atom feed
* [XEN/ARM PATCH v1 1/1] Unbreak Arndale XEN boot
@ 2014-09-11 17:25 Suriyan Ramasami
  2014-09-11 18:49 ` Julien Grall
  0 siblings, 1 reply; 11+ messages in thread
From: Suriyan Ramasami @ 2014-09-11 17:25 UTC (permalink / raw)
  To: xen-devel
  Cc: keir, ian.campbell, Suriyan Ramasami, tim, jbeulich, ian.jackson,
	julien.grall

XEN/ARM: Unbreak Arndale XEN boot

   For the Arndale board the secondary CPU kick address is in secure
   sysram and at offset 0. The Linux code differentiates by the existence
   of "secure-firmware". Arndale does not have one, and boards which use
   secure sysram at offset 0 as smp init address should not have one either.

   For other boards which do have a "secure-firmware" node, use sysram-ns
   at offset +0x1c as the smp init address.

   Have tested this on the Odroid XU. I have also tested the other code path
   on the Odroid XU by removing "secure-firmware" from its DT. I could see
   that the other code path was exercised with correct smp init address
   values.

---

Changes between versions as follows:
   v1:
       Unbreak Arndale XEN boot.

       Remove BUG_ON for checking the address offsets that we poke with.
       Instead use the size field from the DT to make valid comparisons.

       This patch is based off of the staging area as suggested by Ian.

Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>
---
 xen/arch/arm/platforms/exynos5.c | 113 ++++++++++++++++++++++++++++++---------
 1 file changed, 88 insertions(+), 25 deletions(-)

diff --git a/xen/arch/arm/platforms/exynos5.c b/xen/arch/arm/platforms/exynos5.c
index bc9ae15..334650c 100644
--- a/xen/arch/arm/platforms/exynos5.c
+++ b/xen/arch/arm/platforms/exynos5.c
@@ -28,6 +28,9 @@
 #include <asm/platform.h>
 #include <asm/io.h>
 
+/* This corresponds to CONFIG_NR_CPUS in linux config */
+#define EXYNOS_CONFIG_NR_CPUS       0x08
+
 #define EXYNOS_ARM_CORE0_CONFIG     0x2000
 #define EXYNOS_ARM_CORE_CONFIG(_nr) (0x80 * (_nr))
 #define EXYNOS_ARM_CORE_STATUS(_nr) (EXYNOS_ARM_CORE_CONFIG(_nr) + 0x4)
@@ -42,8 +45,6 @@ static int exynos5_init_time(void)
     u64 mct_base_addr;
     u64 size;
 
-    BUILD_BUG_ON(EXYNOS5_MCT_G_TCON >= PAGE_SIZE);
-
     node = dt_find_compatible_node(NULL, NULL, "samsung,exynos4210-mct");
     if ( !node )
     {
@@ -61,7 +62,14 @@ static int exynos5_init_time(void)
     dprintk(XENLOG_INFO, "mct_base_addr: %016llx size: %016llx\n",
             mct_base_addr, size);
 
-    mct = ioremap_attr(mct_base_addr, PAGE_SIZE, PAGE_HYPERVISOR_NOCACHE);
+    if ( size <= EXYNOS5_MCT_G_TCON )
+    {
+        dprintk(XENLOG_ERR, "EXYNOS5_MCT_G_TCON: %d is >= size\n",
+                EXYNOS5_MCT_G_TCON);
+        return -EINVAL;
+    }
+
+    mct = ioremap_attr(mct_base_addr, size, PAGE_HYPERVISOR_NOCACHE);
     if ( !mct )
     {
         dprintk(XENLOG_ERR, "Unable to map MCT\n");
@@ -91,14 +99,36 @@ static int exynos5250_specific_mapping(struct domain *d)
     return 0;
 }
 
-static int __init exynos5_smp_init(void)
+static int exynos_smp_init_getbaseandoffset(u64 *sysram_addr,
+                                            u64 *sysram_offset)
 {
-    void __iomem *sysram;
     struct dt_device_node *node;
-    u64 sysram_ns_base_addr;
     u64 size;
     int rc;
 
+    node = dt_find_compatible_node(NULL, NULL, "samsung,secure-firmware");
+    if ( !node )
+    {
+        /* Have to use sysram_base_addr + offset 0 for boot address */
+        node = dt_find_compatible_node(NULL, NULL, "samsung,exynos4210-sysram");
+        if ( !node )
+        {
+            dprintk(XENLOG_ERR, "samsung,exynos4210-sysram missing in DT\n");
+            return -ENXIO;
+        }
+
+        rc = dt_device_get_address(node, 0, sysram_addr, &size);
+        if ( rc )
+        {
+            dprintk(XENLOG_ERR, "Error in \"samsung,exynos4210-sysram\"\n");
+            return -ENXIO;
+        }
+
+        *sysram_offset = 0;
+        return 0;
+    }
+
+    /* Have to use sysram_ns_base_addr + 0x1c for boot address */
     node = dt_find_compatible_node(NULL, NULL, "samsung,exynos4210-sysram-ns");
     if ( !node )
     {
@@ -106,17 +136,38 @@ static int __init exynos5_smp_init(void)
         return -ENXIO;
     }
 
-    rc = dt_device_get_address(node, 0, &sysram_ns_base_addr, &size);
+    rc = dt_device_get_address(node, 0, sysram_addr, &size);
     if ( rc )
     {
         dprintk(XENLOG_ERR, "Error in \"samsung,exynos4210-sysram-ns\"\n");
         return -ENXIO;
     }
 
-    dprintk(XENLOG_INFO, "sysram_ns_base_addr: %016llx size: %016llx\n",
-            sysram_ns_base_addr, size);
+    *sysram_offset = 0x1c;
+    return 0;
+}
+
+static int __init exynos5_smp_init(void)
+{
+    void __iomem *sysram;
+    u64 sysram_addr;
+    u64 sysram_offset;
+    int rc;
+
+    rc = exynos_smp_init_getbaseandoffset(&sysram_addr, &sysram_offset);
+    if ( rc )
+        return rc;
 
-    sysram = ioremap_nocache(sysram_ns_base_addr, PAGE_SIZE);
+    dprintk(XENLOG_INFO, "sysram_addr: %016llx offset: %016llx\n",
+            sysram_addr, sysram_offset);
+
+    if ( sysram_offset >= PAGE_SIZE )
+    {
+        dprintk(XENLOG_ERR, "sysram_offset is >= PAGE_SIZE\n");
+        return -EINVAL;
+    }
+
+    sysram = ioremap_nocache(sysram_addr, PAGE_SIZE);
     if ( !sysram )
     {
         dprintk(XENLOG_ERR, "Unable to map exynos5 MMIO\n");
@@ -125,7 +176,7 @@ static int __init exynos5_smp_init(void)
 
     printk("Set SYSRAM to %"PRIpaddr" (%p)\n",
            __pa(init_secondary), init_secondary);
-    writel(__pa(init_secondary), sysram + 0x1c);
+    writel(__pa(init_secondary), sysram + sysram_offset);
 
     iounmap(sysram);
 
@@ -134,14 +185,14 @@ static int __init exynos5_smp_init(void)
 
 static int exynos_cpu_power_state(void __iomem *power, int cpu)
 {
-    return __raw_readl(power + EXYNOS_ARM_CORE_STATUS(cpu)) &
-                       S5P_CORE_LOCAL_PWR_EN;
+    return __raw_readl(power + EXYNOS_ARM_CORE0_CONFIG +
+                       EXYNOS_ARM_CORE_STATUS(cpu)) & S5P_CORE_LOCAL_PWR_EN;
 }
 
 static void exynos_cpu_power_up(void __iomem *power, int cpu)
 {
     __raw_writel(S5P_CORE_LOCAL_PWR_EN,
-                 power + EXYNOS_ARM_CORE_CONFIG(cpu));
+                 power + EXYNOS_ARM_CORE0_CONFIG + EXYNOS_ARM_CORE_CONFIG(cpu));
 }
 
 static int exynos5_cpu_power_up(void __iomem *power, int cpu)
@@ -171,8 +222,7 @@ static int exynos5_cpu_power_up(void __iomem *power, int cpu)
     return 0;
 }
 
-static int exynos5_get_pmu_base_addr(u64 *power_base_addr) {
-    u64 size;
+static int exynos5_get_pmu_baseandsize(u64 *power_base_addr, u64 *size) {
     struct dt_device_node *node;
     int rc;
     static const struct dt_device_match exynos_dt_pmu_matches[] __initconst =
@@ -190,7 +240,7 @@ static int exynos5_get_pmu_base_addr(u64 *power_base_addr) {
         return -ENXIO;
     }
 
-    rc = dt_device_get_address(node, 0, power_base_addr, &size);
+    rc = dt_device_get_address(node, 0, power_base_addr, size);
     if ( rc )
     {
         dprintk(XENLOG_ERR, "Error in \"samsung,exynos5XXX-pmu\"\n");
@@ -198,7 +248,7 @@ static int exynos5_get_pmu_base_addr(u64 *power_base_addr) {
     }
 
     dprintk(XENLOG_DEBUG, "power_base_addr: %016llx size: %016llx\n",
-            *power_base_addr, size);
+            *power_base_addr, *size);
 
     return 0;
 }
@@ -206,15 +256,22 @@ static int exynos5_get_pmu_base_addr(u64 *power_base_addr) {
 static int exynos5_cpu_up(int cpu)
 {
     u64 power_base_addr;
+    u64 size;
     void __iomem *power;
     int rc;
 
-    rc = exynos5_get_pmu_base_addr(&power_base_addr);
+    rc = exynos5_get_pmu_baseandsize(&power_base_addr, &size);
     if ( rc )
         return rc;
 
-    power = ioremap_nocache(power_base_addr +
-                            EXYNOS_ARM_CORE0_CONFIG, PAGE_SIZE);
+    if ( size <= EXYNOS_ARM_CORE0_CONFIG +
+                 EXYNOS_ARM_CORE_STATUS(EXYNOS_CONFIG_NR_CPUS) )
+    {
+        dprintk(XENLOG_ERR, "CORE registers fall outside of pmu range.\n");
+        return -EINVAL;
+    }
+
+    power = ioremap_nocache(power_base_addr, size);
     if ( !power )
     {
         dprintk(XENLOG_ERR, "Unable to map power MMIO\n");
@@ -236,16 +293,22 @@ static int exynos5_cpu_up(int cpu)
 static void exynos5_reset(void)
 {
     u64 power_base_addr;
+    u64 size;
     void __iomem *pmu;
     int rc;
 
-    BUILD_BUG_ON(EXYNOS5_SWRESET >= PAGE_SIZE);
-
-    rc = exynos5_get_pmu_base_addr(&power_base_addr);
+    rc = exynos5_get_pmu_baseandsize(&power_base_addr, &size);
     if ( rc )
         return;
 
-    pmu = ioremap_nocache(power_base_addr, PAGE_SIZE);
+    if ( size <= EXYNOS5_SWRESET )
+    {
+        dprintk(XENLOG_ERR, "EXYNOS5_SWRESET: %d is >= size\n",
+                EXYNOS5_SWRESET);
+        return;
+    }
+
+    pmu = ioremap_nocache(power_base_addr, size);
     if ( !pmu )
     {
         dprintk(XENLOG_ERR, "Unable to map PMU\n");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-09-12 21:07 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-11 17:25 [XEN/ARM PATCH v1 1/1] Unbreak Arndale XEN boot Suriyan Ramasami
2014-09-11 18:49 ` Julien Grall
2014-09-11 21:01   ` Suriyan Ramasami
2014-09-12 10:08     ` Ian Campbell
2014-09-12 17:50       ` Suriyan Ramasami
2014-09-12 18:39         ` Julien Grall
2014-09-12 18:47           ` Suriyan Ramasami
2014-09-12 18:58     ` Julien Grall
2014-09-12 19:34       ` Suriyan Ramasami
2014-09-12 21:03         ` Suriyan Ramasami
2014-09-12 21:07           ` Julien Grall

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.