aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2009-02-22 11:25:45 -0500
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-03-11 02:10:14 -0400
commit2657dd4e301d4841ed67a4fac7d145ad8f3e1b28 (patch)
treecdf74a90364690fbf1daa71fbe5f09c07c6f5cb3 /arch/powerpc
parent666435bbf31bfc2aec2afccb2fb54951e573c5c1 (diff)
powerpc: Make sure we copy all cpu_spec features except PMC related ones
When identify_cpu() is called a second time with a logical PVR, it only copies a subset of the cpu_spec fields so as to avoid overwriting the performance monitor fields that were initialized based on the real PVR. However some of the other, non performance monitor related fields are also not copied: * pvr_mask * pvr_value * mmu_features * machine_check The fact that pvr_mask is not copied can result in show_cpuinfo() showing the cpu as "unknown", if we override an unknown PVR with a logical one - as reported by Shaggy. So change the logic to copy all fields, and then put back the PMC related ones in the case that we're overwriting a real PVR with a logical one. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Acked-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/cputable.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 401f973a74a0..638838691b20 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1788,22 +1788,27 @@ static struct cpu_spec the_cpu_spec;
1788static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s) 1788static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s)
1789{ 1789{
1790 struct cpu_spec *t = &the_cpu_spec; 1790 struct cpu_spec *t = &the_cpu_spec;
1791 struct cpu_spec old;
1792
1791 t = PTRRELOC(t); 1793 t = PTRRELOC(t);
1794 old = *t;
1795
1796 /* Copy everything, then do fixups */
1797 *t = *s;
1792 1798
1793 /* 1799 /*
1794 * If we are overriding a previous value derived from the real 1800 * If we are overriding a previous value derived from the real
1795 * PVR with a new value obtained using a logical PVR value, 1801 * PVR with a new value obtained using a logical PVR value,
1796 * don't modify the performance monitor fields. 1802 * don't modify the performance monitor fields.
1797 */ 1803 */
1798 if (t->num_pmcs && !s->num_pmcs) { 1804 if (old.num_pmcs && !s->num_pmcs) {
1799 t->cpu_name = s->cpu_name; 1805 t->num_pmcs = old.num_pmcs;
1800 t->cpu_features = s->cpu_features; 1806 t->pmc_type = old.pmc_type;
1801 t->cpu_user_features = s->cpu_user_features; 1807 t->oprofile_type = old.oprofile_type;
1802 t->icache_bsize = s->icache_bsize; 1808 t->oprofile_mmcra_sihv = old.oprofile_mmcra_sihv;
1803 t->dcache_bsize = s->dcache_bsize; 1809 t->oprofile_mmcra_sipr = old.oprofile_mmcra_sipr;
1804 t->cpu_setup = s->cpu_setup; 1810 t->oprofile_mmcra_clear = old.oprofile_mmcra_clear;
1805 t->cpu_restore = s->cpu_restore; 1811
1806 t->platform = s->platform;
1807 /* 1812 /*
1808 * If we have passed through this logic once before and 1813 * If we have passed through this logic once before and
1809 * have pulled the default case because the real PVR was 1814 * have pulled the default case because the real PVR was
@@ -1817,10 +1822,9 @@ static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s)
1817 * and, in that case, keep the current value for 1822 * and, in that case, keep the current value for
1818 * oprofile_cpu_type. 1823 * oprofile_cpu_type.
1819 */ 1824 */
1820 if (t->oprofile_cpu_type == NULL) 1825 if (old.oprofile_cpu_type == NULL)
1821 t->oprofile_cpu_type = s->oprofile_cpu_type; 1826 t->oprofile_cpu_type = s->oprofile_cpu_type;
1822 } else 1827 }
1823 *t = *s;
1824 1828
1825 *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; 1829 *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
1826 1830