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>
This commit is contained in:
Родитель
666435bbf3
Коммит
2657dd4e30
|
@ -1788,22 +1788,27 @@ static struct cpu_spec the_cpu_spec;
|
||||||
static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s)
|
static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s)
|
||||||
{
|
{
|
||||||
struct cpu_spec *t = &the_cpu_spec;
|
struct cpu_spec *t = &the_cpu_spec;
|
||||||
|
struct cpu_spec old;
|
||||||
|
|
||||||
t = PTRRELOC(t);
|
t = PTRRELOC(t);
|
||||||
|
old = *t;
|
||||||
|
|
||||||
|
/* Copy everything, then do fixups */
|
||||||
|
*t = *s;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are overriding a previous value derived from the real
|
* If we are overriding a previous value derived from the real
|
||||||
* PVR with a new value obtained using a logical PVR value,
|
* PVR with a new value obtained using a logical PVR value,
|
||||||
* don't modify the performance monitor fields.
|
* don't modify the performance monitor fields.
|
||||||
*/
|
*/
|
||||||
if (t->num_pmcs && !s->num_pmcs) {
|
if (old.num_pmcs && !s->num_pmcs) {
|
||||||
t->cpu_name = s->cpu_name;
|
t->num_pmcs = old.num_pmcs;
|
||||||
t->cpu_features = s->cpu_features;
|
t->pmc_type = old.pmc_type;
|
||||||
t->cpu_user_features = s->cpu_user_features;
|
t->oprofile_type = old.oprofile_type;
|
||||||
t->icache_bsize = s->icache_bsize;
|
t->oprofile_mmcra_sihv = old.oprofile_mmcra_sihv;
|
||||||
t->dcache_bsize = s->dcache_bsize;
|
t->oprofile_mmcra_sipr = old.oprofile_mmcra_sipr;
|
||||||
t->cpu_setup = s->cpu_setup;
|
t->oprofile_mmcra_clear = old.oprofile_mmcra_clear;
|
||||||
t->cpu_restore = s->cpu_restore;
|
|
||||||
t->platform = s->platform;
|
|
||||||
/*
|
/*
|
||||||
* If we have passed through this logic once before and
|
* If we have passed through this logic once before and
|
||||||
* have pulled the default case because the real PVR was
|
* 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)
|
||||||
* and, in that case, keep the current value for
|
* and, in that case, keep the current value for
|
||||||
* oprofile_cpu_type.
|
* oprofile_cpu_type.
|
||||||
*/
|
*/
|
||||||
if (t->oprofile_cpu_type == NULL)
|
if (old.oprofile_cpu_type == NULL)
|
||||||
t->oprofile_cpu_type = s->oprofile_cpu_type;
|
t->oprofile_cpu_type = s->oprofile_cpu_type;
|
||||||
} else
|
}
|
||||||
*t = *s;
|
|
||||||
|
|
||||||
*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
|
*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче