powerpc: prom_init exception when updating core value
authorLaurent Dufour <ldufour@linux.vnet.ibm.com>
Tue, 17 Sep 2013 09:52:48 +0000 (11:52 +0200)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 11 Oct 2013 05:53:16 +0000 (16:53 +1100)
Since the CPU is generating an exception when accessing unaligned word, and
as this exception is not yet handled when running prom_init, data should be
copied from the architecture vector byte per byte.

Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/kernel/prom_init.c

index 5fe2842e8bab7cc4013c987c74791c00005c51ee..cb64a6e1dc5186918b4d2052e52e961cfb14eedb 100644 (file)
@@ -858,7 +858,8 @@ static void __init prom_send_capabilities(void)
 {
        ihandle root;
        prom_arg_t ret;
-       __be32 *cores;
+       u32 cores;
+       unsigned char *ptcores;
 
        root = call_prom("open", 1, 1, ADDR("/"));
        if (root != 0) {
@@ -868,15 +869,30 @@ static void __init prom_send_capabilities(void)
                 * (we assume this is the same for all cores) and use it to
                 * divide NR_CPUS.
                 */
-               cores = (__be32 *)&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
-               if (be32_to_cpup(cores) != NR_CPUS) {
+
+               /* The core value may start at an odd address. If such a word
+                * access is made at a cache line boundary, this leads to an
+                * exception which may not be handled at this time.
+                * Forcing a per byte access to avoid exception.
+                */
+               ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
+               cores = 0;
+               cores |= ptcores[0] << 24;
+               cores |= ptcores[1] << 16;
+               cores |= ptcores[2] << 8;
+               cores |= ptcores[3];
+               if (cores != NR_CPUS) {
                        prom_printf("WARNING ! "
                                    "ibm_architecture_vec structure inconsistent: %lu!\n",
-                                   be32_to_cpup(cores));
+                                   cores);
                } else {
-                       *cores = cpu_to_be32(DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()));
+                       cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
                        prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
-                                   be32_to_cpup(cores), NR_CPUS);
+                                   cores, NR_CPUS);
+                       ptcores[0] = (cores >> 24) & 0xff;
+                       ptcores[1] = (cores >> 16) & 0xff;
+                       ptcores[2] = (cores >> 8) & 0xff;
+                       ptcores[3] = cores & 0xff;
                }
 
                /* try calling the ibm,client-architecture-support method */