diff options
author | Laurent Dufour <ldufour@linux.vnet.ibm.com> | 2013-09-17 05:52:48 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-10-11 01:53:16 -0400 |
commit | dbd0c5d5296f291a5c3affee4fbdde254632ffca (patch) | |
tree | 9b622a06c6dcd9150b24b27435ce5fe000b71749 /arch/powerpc/kernel/prom_init.c | |
parent | e48673360b8b113ca83dc3a45e02ad37fdf9f2d0 (diff) |
powerpc: prom_init exception when updating core value
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>
Diffstat (limited to 'arch/powerpc/kernel/prom_init.c')
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 5fe2842e8bab..cb64a6e1dc51 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -858,7 +858,8 @@ static void __init prom_send_capabilities(void) | |||
858 | { | 858 | { |
859 | ihandle root; | 859 | ihandle root; |
860 | prom_arg_t ret; | 860 | prom_arg_t ret; |
861 | __be32 *cores; | 861 | u32 cores; |
862 | unsigned char *ptcores; | ||
862 | 863 | ||
863 | root = call_prom("open", 1, 1, ADDR("/")); | 864 | root = call_prom("open", 1, 1, ADDR("/")); |
864 | if (root != 0) { | 865 | if (root != 0) { |
@@ -868,15 +869,30 @@ static void __init prom_send_capabilities(void) | |||
868 | * (we assume this is the same for all cores) and use it to | 869 | * (we assume this is the same for all cores) and use it to |
869 | * divide NR_CPUS. | 870 | * divide NR_CPUS. |
870 | */ | 871 | */ |
871 | cores = (__be32 *)&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]; | 872 | |
872 | if (be32_to_cpup(cores) != NR_CPUS) { | 873 | /* The core value may start at an odd address. If such a word |
874 | * access is made at a cache line boundary, this leads to an | ||
875 | * exception which may not be handled at this time. | ||
876 | * Forcing a per byte access to avoid exception. | ||
877 | */ | ||
878 | ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]; | ||
879 | cores = 0; | ||
880 | cores |= ptcores[0] << 24; | ||
881 | cores |= ptcores[1] << 16; | ||
882 | cores |= ptcores[2] << 8; | ||
883 | cores |= ptcores[3]; | ||
884 | if (cores != NR_CPUS) { | ||
873 | prom_printf("WARNING ! " | 885 | prom_printf("WARNING ! " |
874 | "ibm_architecture_vec structure inconsistent: %lu!\n", | 886 | "ibm_architecture_vec structure inconsistent: %lu!\n", |
875 | be32_to_cpup(cores)); | 887 | cores); |
876 | } else { | 888 | } else { |
877 | *cores = cpu_to_be32(DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads())); | 889 | cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()); |
878 | prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n", | 890 | prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n", |
879 | be32_to_cpup(cores), NR_CPUS); | 891 | cores, NR_CPUS); |
892 | ptcores[0] = (cores >> 24) & 0xff; | ||
893 | ptcores[1] = (cores >> 16) & 0xff; | ||
894 | ptcores[2] = (cores >> 8) & 0xff; | ||
895 | ptcores[3] = cores & 0xff; | ||
880 | } | 896 | } |
881 | 897 | ||
882 | /* try calling the ibm,client-architecture-support method */ | 898 | /* try calling the ibm,client-architecture-support method */ |