[POWERPC] Cleanup CPU inits
Cleanup CPU inits a bit more, Geoff Levand already did some earlier. * Move CPU state save to cpu_setup, since cpu_setup is only ever done on cpu 0 on 64-bit and save is never done more than once. * Rename __restore_cpu_setup to __restore_cpu_ppc970 and add function pointers to the cputable to use instead. Powermac always has 970 so no need to check there. * Rename __970_cpu_preinit to __cpu_preinit_ppc970 and check PVR before calling it instead of in it, it's too early to use cputable. * Rename pSeries_secondary_smp_init to generic_secondary_smp_init since everyone but powermac and iSeries use it. Signed-off-by: Olof Johansson <olof@lixom.net> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Родитель
2e97425197
Коммит
f39b7a55a8
|
@ -246,6 +246,7 @@ int main(void)
|
||||||
DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value));
|
DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value));
|
||||||
DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
|
DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
|
||||||
DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
|
DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
|
||||||
|
DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
|
||||||
|
|
||||||
#ifndef CONFIG_PPC64
|
#ifndef CONFIG_PPC64
|
||||||
DEFINE(pbe_address, offsetof(struct pbe, address));
|
DEFINE(pbe_address, offsetof(struct pbe, address));
|
||||||
|
|
|
@ -16,27 +16,12 @@
|
||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
|
|
||||||
_GLOBAL(__970_cpu_preinit)
|
_GLOBAL(__cpu_preinit_ppc970)
|
||||||
/*
|
/* Do nothing if not running in HV mode */
|
||||||
* Do nothing if not running in HV mode
|
|
||||||
*/
|
|
||||||
mfmsr r0
|
mfmsr r0
|
||||||
rldicl. r0,r0,4,63
|
rldicl. r0,r0,4,63
|
||||||
beqlr
|
beqlr
|
||||||
|
|
||||||
/*
|
|
||||||
* Deal only with PPC970 and PPC970FX.
|
|
||||||
*/
|
|
||||||
mfspr r0,SPRN_PVR
|
|
||||||
srwi r0,r0,16
|
|
||||||
cmpwi r0,0x39
|
|
||||||
beq 1f
|
|
||||||
cmpwi r0,0x3c
|
|
||||||
beq 1f
|
|
||||||
cmpwi r0,0x44
|
|
||||||
bnelr
|
|
||||||
1:
|
|
||||||
|
|
||||||
/* Make sure HID4:rm_ci is off before MMU is turned off, that large
|
/* Make sure HID4:rm_ci is off before MMU is turned off, that large
|
||||||
* pages are enabled with HID4:61 and clear HID5:DCBZ_size and
|
* pages are enabled with HID4:61 and clear HID5:DCBZ_size and
|
||||||
* HID5:DCBZ32_ill
|
* HID5:DCBZ32_ill
|
||||||
|
@ -72,21 +57,6 @@ _GLOBAL(__970_cpu_preinit)
|
||||||
isync
|
isync
|
||||||
blr
|
blr
|
||||||
|
|
||||||
_GLOBAL(__setup_cpu_ppc970)
|
|
||||||
mfspr r0,SPRN_HID0
|
|
||||||
li r11,5 /* clear DOZE and SLEEP */
|
|
||||||
rldimi r0,r11,52,8 /* set NAP and DPM */
|
|
||||||
mtspr SPRN_HID0,r0
|
|
||||||
mfspr r0,SPRN_HID0
|
|
||||||
mfspr r0,SPRN_HID0
|
|
||||||
mfspr r0,SPRN_HID0
|
|
||||||
mfspr r0,SPRN_HID0
|
|
||||||
mfspr r0,SPRN_HID0
|
|
||||||
mfspr r0,SPRN_HID0
|
|
||||||
sync
|
|
||||||
isync
|
|
||||||
blr
|
|
||||||
|
|
||||||
/* Definitions for the table use to save CPU states */
|
/* Definitions for the table use to save CPU states */
|
||||||
#define CS_HID0 0
|
#define CS_HID0 0
|
||||||
#define CS_HID1 8
|
#define CS_HID1 8
|
||||||
|
@ -101,33 +71,28 @@ cpu_state_storage:
|
||||||
.balign L1_CACHE_BYTES,0
|
.balign L1_CACHE_BYTES,0
|
||||||
.text
|
.text
|
||||||
|
|
||||||
/* Called in normal context to backup CPU 0 state. This
|
|
||||||
* does not include cache settings. This function is also
|
|
||||||
* called for machine sleep. This does not include the MMU
|
|
||||||
* setup, BATs, etc... but rather the "special" registers
|
|
||||||
* like HID0, HID1, HID4, etc...
|
|
||||||
*/
|
|
||||||
_GLOBAL(__save_cpu_setup)
|
|
||||||
/* Some CR fields are volatile, we back it up all */
|
|
||||||
mfcr r7
|
|
||||||
|
|
||||||
/* Get storage ptr */
|
_GLOBAL(__setup_cpu_ppc970)
|
||||||
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
|
/* Do nothing if not running in HV mode */
|
||||||
|
|
||||||
/* We only deal with 970 for now */
|
|
||||||
mfspr r0,SPRN_PVR
|
|
||||||
srwi r0,r0,16
|
|
||||||
cmpwi r0,0x39
|
|
||||||
beq 1f
|
|
||||||
cmpwi r0,0x3c
|
|
||||||
beq 1f
|
|
||||||
cmpwi r0,0x44
|
|
||||||
bne 2f
|
|
||||||
|
|
||||||
1: /* skip if not running in HV mode */
|
|
||||||
mfmsr r0
|
mfmsr r0
|
||||||
rldicl. r0,r0,4,63
|
rldicl. r0,r0,4,63
|
||||||
beq 2f
|
beqlr
|
||||||
|
|
||||||
|
mfspr r0,SPRN_HID0
|
||||||
|
li r11,5 /* clear DOZE and SLEEP */
|
||||||
|
rldimi r0,r11,52,8 /* set NAP and DPM */
|
||||||
|
mtspr SPRN_HID0,r0
|
||||||
|
mfspr r0,SPRN_HID0
|
||||||
|
mfspr r0,SPRN_HID0
|
||||||
|
mfspr r0,SPRN_HID0
|
||||||
|
mfspr r0,SPRN_HID0
|
||||||
|
mfspr r0,SPRN_HID0
|
||||||
|
mfspr r0,SPRN_HID0
|
||||||
|
sync
|
||||||
|
isync
|
||||||
|
|
||||||
|
/* Save away cpu state */
|
||||||
|
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
|
||||||
|
|
||||||
/* Save HID0,1,4 and 5 */
|
/* Save HID0,1,4 and 5 */
|
||||||
mfspr r3,SPRN_HID0
|
mfspr r3,SPRN_HID0
|
||||||
|
@ -139,35 +104,19 @@ _GLOBAL(__save_cpu_setup)
|
||||||
mfspr r3,SPRN_HID5
|
mfspr r3,SPRN_HID5
|
||||||
std r3,CS_HID5(r5)
|
std r3,CS_HID5(r5)
|
||||||
|
|
||||||
2:
|
|
||||||
mtcr r7
|
|
||||||
blr
|
blr
|
||||||
|
|
||||||
/* Called with no MMU context (typically MSR:IR/DR off) to
|
/* Called with no MMU context (typically MSR:IR/DR off) to
|
||||||
* restore CPU state as backed up by the previous
|
* restore CPU state as backed up by the previous
|
||||||
* function. This does not include cache setting
|
* function. This does not include cache setting
|
||||||
*/
|
*/
|
||||||
_GLOBAL(__restore_cpu_setup)
|
_GLOBAL(__restore_cpu_ppc970)
|
||||||
/* Get storage ptr (FIXME when using anton reloc as we
|
/* Do nothing if not running in HV mode */
|
||||||
* are running with translation disabled here
|
|
||||||
*/
|
|
||||||
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
|
|
||||||
|
|
||||||
/* We only deal with 970 for now */
|
|
||||||
mfspr r0,SPRN_PVR
|
|
||||||
srwi r0,r0,16
|
|
||||||
cmpwi r0,0x39
|
|
||||||
beq 1f
|
|
||||||
cmpwi r0,0x3c
|
|
||||||
beq 1f
|
|
||||||
cmpwi r0,0x44
|
|
||||||
bnelr
|
|
||||||
|
|
||||||
1: /* skip if not running in HV mode */
|
|
||||||
mfmsr r0
|
mfmsr r0
|
||||||
rldicl. r0,r0,4,63
|
rldicl. r0,r0,4,63
|
||||||
beqlr
|
beqlr
|
||||||
|
|
||||||
|
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
|
||||||
/* Before accessing memory, we make sure rm_ci is clear */
|
/* Before accessing memory, we make sure rm_ci is clear */
|
||||||
li r0,0
|
li r0,0
|
||||||
mfspr r3,SPRN_HID4
|
mfspr r3,SPRN_HID4
|
||||||
|
|
|
@ -39,7 +39,10 @@ extern void __setup_cpu_7400(unsigned long offset, struct cpu_spec* spec);
|
||||||
extern void __setup_cpu_7410(unsigned long offset, struct cpu_spec* spec);
|
extern void __setup_cpu_7410(unsigned long offset, struct cpu_spec* spec);
|
||||||
extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
|
extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
|
||||||
#endif /* CONFIG_PPC32 */
|
#endif /* CONFIG_PPC32 */
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
|
extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
|
||||||
|
extern void __restore_cpu_ppc970(void);
|
||||||
|
#endif /* CONFIG_PPC64 */
|
||||||
|
|
||||||
/* This table only contains "desktop" CPUs, it need to be filled with embedded
|
/* This table only contains "desktop" CPUs, it need to be filled with embedded
|
||||||
* ones as well...
|
* ones as well...
|
||||||
|
@ -184,6 +187,7 @@ struct cpu_spec cpu_specs[] = {
|
||||||
.dcache_bsize = 128,
|
.dcache_bsize = 128,
|
||||||
.num_pmcs = 8,
|
.num_pmcs = 8,
|
||||||
.cpu_setup = __setup_cpu_ppc970,
|
.cpu_setup = __setup_cpu_ppc970,
|
||||||
|
.cpu_restore = __restore_cpu_ppc970,
|
||||||
.oprofile_cpu_type = "ppc64/970",
|
.oprofile_cpu_type = "ppc64/970",
|
||||||
.oprofile_type = PPC_OPROFILE_POWER4,
|
.oprofile_type = PPC_OPROFILE_POWER4,
|
||||||
.platform = "ppc970",
|
.platform = "ppc970",
|
||||||
|
@ -199,6 +203,7 @@ struct cpu_spec cpu_specs[] = {
|
||||||
.dcache_bsize = 128,
|
.dcache_bsize = 128,
|
||||||
.num_pmcs = 8,
|
.num_pmcs = 8,
|
||||||
.cpu_setup = __setup_cpu_ppc970,
|
.cpu_setup = __setup_cpu_ppc970,
|
||||||
|
.cpu_restore = __restore_cpu_ppc970,
|
||||||
.oprofile_cpu_type = "ppc64/970",
|
.oprofile_cpu_type = "ppc64/970",
|
||||||
.oprofile_type = PPC_OPROFILE_POWER4,
|
.oprofile_type = PPC_OPROFILE_POWER4,
|
||||||
.platform = "ppc970",
|
.platform = "ppc970",
|
||||||
|
@ -214,6 +219,7 @@ struct cpu_spec cpu_specs[] = {
|
||||||
.dcache_bsize = 128,
|
.dcache_bsize = 128,
|
||||||
.num_pmcs = 8,
|
.num_pmcs = 8,
|
||||||
.cpu_setup = __setup_cpu_ppc970,
|
.cpu_setup = __setup_cpu_ppc970,
|
||||||
|
.cpu_restore = __restore_cpu_ppc970,
|
||||||
.oprofile_cpu_type = "ppc64/970",
|
.oprofile_cpu_type = "ppc64/970",
|
||||||
.oprofile_type = PPC_OPROFILE_POWER4,
|
.oprofile_type = PPC_OPROFILE_POWER4,
|
||||||
.platform = "ppc970",
|
.platform = "ppc970",
|
||||||
|
|
|
@ -132,7 +132,7 @@ _GLOBAL(__secondary_hold)
|
||||||
bne 100b
|
bne 100b
|
||||||
|
|
||||||
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
|
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
|
||||||
LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init)
|
LOAD_REG_IMMEDIATE(r4, .generic_secondary_smp_init)
|
||||||
mtctr r4
|
mtctr r4
|
||||||
mr r3,r24
|
mr r3,r24
|
||||||
bctr
|
bctr
|
||||||
|
@ -1484,19 +1484,17 @@ fwnmi_data_area:
|
||||||
. = 0x8000
|
. = 0x8000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On pSeries, secondary processors spin in the following code.
|
* On pSeries and most other platforms, secondary processors spin
|
||||||
|
* in the following code.
|
||||||
* At entry, r3 = this processor's number (physical cpu id)
|
* At entry, r3 = this processor's number (physical cpu id)
|
||||||
*/
|
*/
|
||||||
_GLOBAL(pSeries_secondary_smp_init)
|
_GLOBAL(generic_secondary_smp_init)
|
||||||
mr r24,r3
|
mr r24,r3
|
||||||
|
|
||||||
/* turn on 64-bit mode */
|
/* turn on 64-bit mode */
|
||||||
bl .enable_64b_mode
|
bl .enable_64b_mode
|
||||||
isync
|
isync
|
||||||
|
|
||||||
/* Copy some CPU settings from CPU 0 */
|
|
||||||
bl .__restore_cpu_setup
|
|
||||||
|
|
||||||
/* Set up a paca value for this processor. Since we have the
|
/* Set up a paca value for this processor. Since we have the
|
||||||
* physical cpu id in r24, we need to search the pacas to find
|
* physical cpu id in r24, we need to search the pacas to find
|
||||||
* which logical id maps to our physical one.
|
* which logical id maps to our physical one.
|
||||||
|
@ -1522,15 +1520,28 @@ _GLOBAL(pSeries_secondary_smp_init)
|
||||||
/* start. */
|
/* start. */
|
||||||
sync
|
sync
|
||||||
|
|
||||||
/* Create a temp kernel stack for use before relocation is on. */
|
#ifndef CONFIG_SMP
|
||||||
|
b 3b /* Never go on non-SMP */
|
||||||
|
#else
|
||||||
|
cmpwi 0,r23,0
|
||||||
|
beq 3b /* Loop until told to go */
|
||||||
|
|
||||||
|
/* See if we need to call a cpu state restore handler */
|
||||||
|
LOAD_REG_IMMEDIATE(r23, cur_cpu_spec)
|
||||||
|
ld r23,0(r23)
|
||||||
|
ld r23,CPU_SPEC_RESTORE(r23)
|
||||||
|
cmpdi 0,r23,0
|
||||||
|
beq 4f
|
||||||
|
ld r23,0(r23)
|
||||||
|
mtctr r23
|
||||||
|
bctrl
|
||||||
|
|
||||||
|
4: /* Create a temp kernel stack for use before relocation is on. */
|
||||||
ld r1,PACAEMERGSP(r13)
|
ld r1,PACAEMERGSP(r13)
|
||||||
subi r1,r1,STACK_FRAME_OVERHEAD
|
subi r1,r1,STACK_FRAME_OVERHEAD
|
||||||
|
|
||||||
cmpwi 0,r23,0
|
b .__secondary_start
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
bne .__secondary_start
|
|
||||||
#endif
|
#endif
|
||||||
b 3b /* Loop until told to go */
|
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_ISERIES
|
#ifdef CONFIG_PPC_ISERIES
|
||||||
_STATIC(__start_initialization_iSeries)
|
_STATIC(__start_initialization_iSeries)
|
||||||
|
@ -1611,7 +1622,16 @@ _GLOBAL(__start_initialization_multiplatform)
|
||||||
bl .enable_64b_mode
|
bl .enable_64b_mode
|
||||||
|
|
||||||
/* Setup some critical 970 SPRs before switching MMU off */
|
/* Setup some critical 970 SPRs before switching MMU off */
|
||||||
bl .__970_cpu_preinit
|
mfspr r0,SPRN_PVR
|
||||||
|
srwi r0,r0,16
|
||||||
|
cmpwi r0,0x39 /* 970 */
|
||||||
|
beq 1f
|
||||||
|
cmpwi r0,0x3c /* 970FX */
|
||||||
|
beq 1f
|
||||||
|
cmpwi r0,0x44 /* 970MP */
|
||||||
|
bne 2f
|
||||||
|
1: bl .__cpu_preinit_ppc970
|
||||||
|
2:
|
||||||
|
|
||||||
/* Switch off MMU if not already */
|
/* Switch off MMU if not already */
|
||||||
LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
|
LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
|
||||||
|
@ -1782,7 +1802,7 @@ _GLOBAL(pmac_secondary_start)
|
||||||
isync
|
isync
|
||||||
|
|
||||||
/* Copy some CPU settings from CPU 0 */
|
/* Copy some CPU settings from CPU 0 */
|
||||||
bl .__restore_cpu_setup
|
bl .__restore_cpu_ppc970
|
||||||
|
|
||||||
/* pSeries do that early though I don't think we really need it */
|
/* pSeries do that early though I don't think we really need it */
|
||||||
mfmsr r3
|
mfmsr r3
|
||||||
|
@ -1932,12 +1952,6 @@ _STATIC(start_here_multiplatform)
|
||||||
mr r5,r26
|
mr r5,r26
|
||||||
bl .identify_cpu
|
bl .identify_cpu
|
||||||
|
|
||||||
/* Save some low level config HIDs of CPU0 to be copied to
|
|
||||||
* other CPUs later on, or used for suspend/resume
|
|
||||||
*/
|
|
||||||
bl .__save_cpu_setup
|
|
||||||
sync
|
|
||||||
|
|
||||||
/* Do very early kernel initializations, including initial hash table,
|
/* Do very early kernel initializations, including initial hash table,
|
||||||
* stab and slb setup before we turn on relocation. */
|
* stab and slb setup before we turn on relocation. */
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
*/
|
*/
|
||||||
static cpumask_t of_spin_map;
|
static cpumask_t of_spin_map;
|
||||||
|
|
||||||
extern void pSeries_secondary_smp_init(unsigned long);
|
extern void generic_secondary_smp_init(unsigned long);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smp_startup_cpu() - start the given cpu
|
* smp_startup_cpu() - start the given cpu
|
||||||
|
@ -74,7 +74,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
unsigned long start_here = __pa((u32)*((unsigned long *)
|
unsigned long start_here = __pa((u32)*((unsigned long *)
|
||||||
pSeries_secondary_smp_init));
|
generic_secondary_smp_init));
|
||||||
unsigned int pcpu;
|
unsigned int pcpu;
|
||||||
int start_cpu;
|
int start_cpu;
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
*/
|
*/
|
||||||
static cpumask_t of_spin_map;
|
static cpumask_t of_spin_map;
|
||||||
|
|
||||||
extern void pSeries_secondary_smp_init(unsigned long);
|
extern void generic_secondary_smp_init(unsigned long);
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
unsigned long start_here = __pa((u32)*((unsigned long *)
|
unsigned long start_here = __pa((u32)*((unsigned long *)
|
||||||
pSeries_secondary_smp_init));
|
generic_secondary_smp_init));
|
||||||
unsigned int pcpu;
|
unsigned int pcpu;
|
||||||
int start_cpu;
|
int start_cpu;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
struct cpu_spec;
|
struct cpu_spec;
|
||||||
|
|
||||||
typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec);
|
typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec);
|
||||||
|
typedef void (*cpu_restore_t)(void);
|
||||||
|
|
||||||
enum powerpc_oprofile_type {
|
enum powerpc_oprofile_type {
|
||||||
PPC_OPROFILE_INVALID = 0,
|
PPC_OPROFILE_INVALID = 0,
|
||||||
|
@ -65,6 +66,8 @@ struct cpu_spec {
|
||||||
* BHT, SPD, etc... from head.S before branching to identify_machine
|
* BHT, SPD, etc... from head.S before branching to identify_machine
|
||||||
*/
|
*/
|
||||||
cpu_setup_t cpu_setup;
|
cpu_setup_t cpu_setup;
|
||||||
|
/* Used to restore cpu setup on secondary processors and at resume */
|
||||||
|
cpu_restore_t cpu_restore;
|
||||||
|
|
||||||
/* Used by oprofile userspace to select the right counters */
|
/* Used by oprofile userspace to select the right counters */
|
||||||
char *oprofile_cpu_type;
|
char *oprofile_cpu_type;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче