diff options
author | Anton Blanchard <anton@samba.org> | 2006-03-25 01:25:17 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-03-26 22:48:48 -0500 |
commit | 4df20460a3ff0d60280738b094945c56cb5567a5 (patch) | |
tree | 39f831cf5f778b14a08b3453a8f798b2b8be8813 /arch/powerpc/kernel/prom.c | |
parent | b4f382a3e5e20ba867e7aa5b01189a3fd40eea2c (diff) |
[PATCH] powerpc: Allow non zero boot cpuids
We currently have a hack to flip the boot cpu and its secondary thread
to logical cpuid 0 and 1. This means the logical - physical mapping will
differ depending on which cpu is boot cpu. This is most apparent on
kexec, where we might kexec on any cpu and therefore change the mapping
from boot to boot.
The patch below does a first pass early on to work out the logical cpuid
of the boot thread. We then fix up some paca structures to match.
Ive also removed the boot_cpuid_phys variable for ppc64, to be
consistent we use get_hard_smp_processor_id(boot_cpuid) everywhere.
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 83 |
1 files changed, 56 insertions, 27 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index d63cd562d9d5..5a24415a2e3c 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -854,35 +854,70 @@ void __init unflatten_device_tree(void) | |||
854 | DBG(" <- unflatten_device_tree()\n"); | 854 | DBG(" <- unflatten_device_tree()\n"); |
855 | } | 855 | } |
856 | 856 | ||
857 | |||
858 | static int __init early_init_dt_scan_cpus(unsigned long node, | 857 | static int __init early_init_dt_scan_cpus(unsigned long node, |
859 | const char *uname, int depth, void *data) | 858 | const char *uname, int depth, |
859 | void *data) | ||
860 | { | 860 | { |
861 | u32 *prop; | 861 | static int logical_cpuid = 0; |
862 | unsigned long size; | 862 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
863 | char *type = of_get_flat_dt_prop(node, "device_type", &size); | 863 | u32 *prop, *intserv; |
864 | int i, nthreads; | ||
865 | unsigned long len; | ||
866 | int found = 0; | ||
864 | 867 | ||
865 | /* We are scanning "cpu" nodes only */ | 868 | /* We are scanning "cpu" nodes only */ |
866 | if (type == NULL || strcmp(type, "cpu") != 0) | 869 | if (type == NULL || strcmp(type, "cpu") != 0) |
867 | return 0; | 870 | return 0; |
868 | 871 | ||
869 | boot_cpuid = 0; | 872 | /* Get physical cpuid */ |
870 | boot_cpuid_phys = 0; | 873 | intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len); |
871 | if (initial_boot_params && initial_boot_params->version >= 2) { | 874 | if (intserv) { |
872 | /* version 2 of the kexec param format adds the phys cpuid | 875 | nthreads = len / sizeof(int); |
873 | * of booted proc. | ||
874 | */ | ||
875 | boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; | ||
876 | } else { | 876 | } else { |
877 | /* Check if it's the boot-cpu, set it's hw index now */ | 877 | intserv = of_get_flat_dt_prop(node, "reg", NULL); |
878 | if (of_get_flat_dt_prop(node, | 878 | nthreads = 1; |
879 | } | ||
880 | |||
881 | /* | ||
882 | * Now see if any of these threads match our boot cpu. | ||
883 | * NOTE: This must match the parsing done in smp_setup_cpu_maps. | ||
884 | */ | ||
885 | for (i = 0; i < nthreads; i++) { | ||
886 | /* | ||
887 | * version 2 of the kexec param format adds the phys cpuid of | ||
888 | * booted proc. | ||
889 | */ | ||
890 | if (initial_boot_params && initial_boot_params->version >= 2) { | ||
891 | if (intserv[i] == | ||
892 | initial_boot_params->boot_cpuid_phys) { | ||
893 | found = 1; | ||
894 | break; | ||
895 | } | ||
896 | } else { | ||
897 | /* | ||
898 | * Check if it's the boot-cpu, set it's hw index now, | ||
899 | * unfortunately this format did not support booting | ||
900 | * off secondary threads. | ||
901 | */ | ||
902 | if (of_get_flat_dt_prop(node, | ||
879 | "linux,boot-cpu", NULL) != NULL) { | 903 | "linux,boot-cpu", NULL) != NULL) { |
880 | prop = of_get_flat_dt_prop(node, "reg", NULL); | 904 | found = 1; |
881 | if (prop != NULL) | 905 | break; |
882 | boot_cpuid_phys = *prop; | 906 | } |
883 | } | 907 | } |
908 | |||
909 | #ifdef CONFIG_SMP | ||
910 | /* logical cpu id is always 0 on UP kernels */ | ||
911 | logical_cpuid++; | ||
912 | #endif | ||
913 | } | ||
914 | |||
915 | if (found) { | ||
916 | DBG("boot cpu: logical %d physical %d\n", logical_cpuid, | ||
917 | intserv[i]); | ||
918 | boot_cpuid = logical_cpuid; | ||
919 | set_hard_smp_processor_id(boot_cpuid, intserv[i]); | ||
884 | } | 920 | } |
885 | set_hard_smp_processor_id(0, boot_cpuid_phys); | ||
886 | 921 | ||
887 | #ifdef CONFIG_ALTIVEC | 922 | #ifdef CONFIG_ALTIVEC |
888 | /* Check if we have a VMX and eventually update CPU features */ | 923 | /* Check if we have a VMX and eventually update CPU features */ |
@@ -901,16 +936,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
901 | #endif /* CONFIG_ALTIVEC */ | 936 | #endif /* CONFIG_ALTIVEC */ |
902 | 937 | ||
903 | #ifdef CONFIG_PPC_PSERIES | 938 | #ifdef CONFIG_PPC_PSERIES |
904 | /* | 939 | if (nthreads > 1) |
905 | * Check for an SMT capable CPU and set the CPU feature. We do | ||
906 | * this by looking at the size of the ibm,ppc-interrupt-server#s | ||
907 | * property | ||
908 | */ | ||
909 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", | ||
910 | &size); | ||
911 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | ||
912 | if (prop && ((size / sizeof(u32)) > 1)) | ||
913 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; | 940 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; |
941 | else | ||
942 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | ||
914 | #endif | 943 | #endif |
915 | 944 | ||
916 | return 0; | 945 | return 0; |