Changeset View
Changeset View
Standalone View
Standalone View
head/sys/powerpc/powernv/platform_powernv.c
Show First 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | |||||
#ifdef SMP | #ifdef SMP | ||||
static int powernv_smp_start_cpu(platform_t, struct pcpu *cpu); | static int powernv_smp_start_cpu(platform_t, struct pcpu *cpu); | ||||
static void powernv_smp_probe_threads(platform_t); | static void powernv_smp_probe_threads(platform_t); | ||||
static struct cpu_group *powernv_smp_topo(platform_t plat); | static struct cpu_group *powernv_smp_topo(platform_t plat); | ||||
#endif | #endif | ||||
static void powernv_reset(platform_t); | static void powernv_reset(platform_t); | ||||
static void powernv_cpu_idle(sbintime_t sbt); | static void powernv_cpu_idle(sbintime_t sbt); | ||||
static int powernv_cpuref_init(void); | static int powernv_cpuref_init(void); | ||||
static int powernv_node_numa_domain(platform_t platform, phandle_t node); | |||||
static platform_method_t powernv_methods[] = { | static platform_method_t powernv_methods[] = { | ||||
PLATFORMMETHOD(platform_probe, powernv_probe), | PLATFORMMETHOD(platform_probe, powernv_probe), | ||||
PLATFORMMETHOD(platform_attach, powernv_attach), | PLATFORMMETHOD(platform_attach, powernv_attach), | ||||
PLATFORMMETHOD(platform_mem_regions, powernv_mem_regions), | PLATFORMMETHOD(platform_mem_regions, powernv_mem_regions), | ||||
PLATFORMMETHOD(platform_numa_mem_regions, powernv_numa_mem_regions), | PLATFORMMETHOD(platform_numa_mem_regions, powernv_numa_mem_regions), | ||||
PLATFORMMETHOD(platform_timebase_freq, powernv_timebase_freq), | PLATFORMMETHOD(platform_timebase_freq, powernv_timebase_freq), | ||||
PLATFORMMETHOD(platform_smp_ap_init, powernv_smp_ap_init), | PLATFORMMETHOD(platform_smp_ap_init, powernv_smp_ap_init), | ||||
PLATFORMMETHOD(platform_smp_first_cpu, powernv_smp_first_cpu), | PLATFORMMETHOD(platform_smp_first_cpu, powernv_smp_first_cpu), | ||||
PLATFORMMETHOD(platform_smp_next_cpu, powernv_smp_next_cpu), | PLATFORMMETHOD(platform_smp_next_cpu, powernv_smp_next_cpu), | ||||
PLATFORMMETHOD(platform_smp_get_bsp, powernv_smp_get_bsp), | PLATFORMMETHOD(platform_smp_get_bsp, powernv_smp_get_bsp), | ||||
#ifdef SMP | #ifdef SMP | ||||
PLATFORMMETHOD(platform_smp_start_cpu, powernv_smp_start_cpu), | PLATFORMMETHOD(platform_smp_start_cpu, powernv_smp_start_cpu), | ||||
PLATFORMMETHOD(platform_smp_probe_threads, powernv_smp_probe_threads), | PLATFORMMETHOD(platform_smp_probe_threads, powernv_smp_probe_threads), | ||||
PLATFORMMETHOD(platform_smp_topo, powernv_smp_topo), | PLATFORMMETHOD(platform_smp_topo, powernv_smp_topo), | ||||
#endif | #endif | ||||
PLATFORMMETHOD(platform_node_numa_domain, powernv_node_numa_domain), | |||||
PLATFORMMETHOD(platform_reset, powernv_reset), | PLATFORMMETHOD(platform_reset, powernv_reset), | ||||
{ 0, 0 } | { 0, 0 } | ||||
}; | }; | ||||
static platform_def_t powernv_platform = { | static platform_def_t powernv_platform = { | ||||
"powernv", | "powernv", | ||||
powernv_methods, | powernv_methods, | ||||
0 | 0 | ||||
}; | }; | ||||
static struct cpuref platform_cpuref[MAXCPU]; | static struct cpuref platform_cpuref[MAXCPU]; | ||||
static int platform_cpuref_cnt; | static int platform_cpuref_cnt; | ||||
static int platform_cpuref_valid; | static int platform_cpuref_valid; | ||||
static int platform_associativity; | |||||
PLATFORM_DEF(powernv_platform); | PLATFORM_DEF(powernv_platform); | ||||
static uint64_t powernv_boot_pir; | static uint64_t powernv_boot_pir; | ||||
static int | static int | ||||
powernv_probe(platform_t plat) | powernv_probe(platform_t plat) | ||||
{ | { | ||||
if (opal_check() == 0) | if (opal_check() == 0) | ||||
return (BUS_PROBE_SPECIFIC); | return (BUS_PROBE_SPECIFIC); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
static int | static int | ||||
powernv_attach(platform_t plat) | powernv_attach(platform_t plat) | ||||
{ | { | ||||
uint32_t nptlp, shift = 0, slb_encoding = 0; | uint32_t nptlp, shift = 0, slb_encoding = 0; | ||||
int32_t lp_size, lp_encoding; | int32_t lp_size, lp_encoding; | ||||
char buf[255]; | char buf[255]; | ||||
pcell_t refpoints[3]; | |||||
pcell_t prop; | pcell_t prop; | ||||
phandle_t cpu; | phandle_t cpu; | ||||
phandle_t opal; | |||||
int res, len, idx; | int res, len, idx; | ||||
register_t msr; | register_t msr; | ||||
/* Ping OPAL again just to make sure */ | /* Ping OPAL again just to make sure */ | ||||
opal_check(); | opal_check(); | ||||
#if BYTE_ORDER == LITTLE_ENDIAN | #if BYTE_ORDER == LITTLE_ENDIAN | ||||
opal_call(OPAL_REINIT_CPUS, 2 /* Little endian */); | opal_call(OPAL_REINIT_CPUS, 2 /* Little endian */); | ||||
#else | #else | ||||
opal_call(OPAL_REINIT_CPUS, 1 /* Big endian */); | opal_call(OPAL_REINIT_CPUS, 1 /* Big endian */); | ||||
#endif | #endif | ||||
opal = OF_finddevice("/ibm,opal"); | |||||
platform_associativity = 4; /* Skiboot default. */ | |||||
if (OF_getencprop(opal, "ibm,associativity-reference-points", refpoints, | |||||
sizeof(refpoints)) > 0) { | |||||
platform_associativity = refpoints[0]; | |||||
} | |||||
if (cpu_idle_hook == NULL) | if (cpu_idle_hook == NULL) | ||||
cpu_idle_hook = powernv_cpu_idle; | cpu_idle_hook = powernv_cpu_idle; | ||||
powernv_boot_pir = mfspr(SPR_PIR); | powernv_boot_pir = mfspr(SPR_PIR); | ||||
/* LPID must not be altered when PSL_DR or PSL_IR is set */ | /* LPID must not be altered when PSL_DR or PSL_IR is set */ | ||||
msr = mfmsr(); | msr = mfmsr(); | ||||
mtmsr(msr & ~(PSL_DR | PSL_IR)); | mtmsr(msr & ~(PSL_DR | PSL_IR)); | ||||
▲ Show 20 Lines • Show All 167 Lines • ▼ Show 20 Lines | if (res > 0 && strcmp(buf, "cpu") == 0) { | ||||
res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s"); | res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s"); | ||||
if (res > 0) { | if (res > 0) { | ||||
OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", | OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", | ||||
interrupt_servers, res); | interrupt_servers, res); | ||||
for (a = 0; a < res/sizeof(cell_t); a++) { | for (a = 0; a < res/sizeof(cell_t); a++) { | ||||
tmp_cpuref[tmp_cpuref_cnt].cr_hwref = interrupt_servers[a]; | tmp_cpuref[tmp_cpuref_cnt].cr_hwref = interrupt_servers[a]; | ||||
tmp_cpuref[tmp_cpuref_cnt].cr_cpuid = tmp_cpuref_cnt; | tmp_cpuref[tmp_cpuref_cnt].cr_cpuid = tmp_cpuref_cnt; | ||||
tmp_cpuref[tmp_cpuref_cnt].cr_domain = interrupt_servers[a] >> 11; | tmp_cpuref[tmp_cpuref_cnt].cr_domain = | ||||
powernv_node_numa_domain(NULL, cpu); | |||||
if (interrupt_servers[a] == (uint32_t)powernv_boot_pir) | if (interrupt_servers[a] == (uint32_t)powernv_boot_pir) | ||||
bsp = tmp_cpuref_cnt; | bsp = tmp_cpuref_cnt; | ||||
tmp_cpuref_cnt++; | tmp_cpuref_cnt++; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | powernv_smp_ap_init(platform_t platform) | ||||
if (powernv_smp_ap_extra_init != NULL) | if (powernv_smp_ap_extra_init != NULL) | ||||
powernv_smp_ap_extra_init(); | powernv_smp_ap_extra_init(); | ||||
} | } | ||||
static void | static void | ||||
powernv_cpu_idle(sbintime_t sbt) | powernv_cpu_idle(sbintime_t sbt) | ||||
{ | { | ||||
} | |||||
static int | |||||
powernv_node_numa_domain(platform_t platform, phandle_t node) | |||||
{ | |||||
/* XXX: Is locking necessary in here? */ | |||||
static int numa_domains[MAXMEMDOM]; | |||||
static int numa_max_domain; | |||||
cell_t associativity[5]; | |||||
int i, res; | |||||
res = OF_getproplen(node, "ibm,associativity"); | |||||
/* If already at the root, use default domain. */ | |||||
if (res == 0) | |||||
return (0); | |||||
else if (res < 0) | |||||
/* If this node doesn't have associativity, check its parent. */ | |||||
return (powernv_node_numa_domain(platform, OF_parent(node))); | |||||
OF_getencprop(node, "ibm,associativity", | |||||
associativity, res); | |||||
for (i = 0; i < numa_max_domain; i++) { | |||||
if (numa_domains[i] == associativity[platform_associativity]) | |||||
return (i); | |||||
} | |||||
if (i < MAXMEMDOM) | |||||
numa_domains[numa_max_domain++] = | |||||
associativity[platform_associativity]; | |||||
else | |||||
i = 0; | |||||
return (i); | |||||
} | } | ||||
/* Set up the Nest MMU on POWER9 relatively early, but after pmap is setup. */ | /* Set up the Nest MMU on POWER9 relatively early, but after pmap is setup. */ | ||||
static void | static void | ||||
powernv_setup_nmmu(void *unused) | powernv_setup_nmmu(void *unused) | ||||
{ | { | ||||
if (opal_check() != 0) | if (opal_check() != 0) | ||||
return; | return; | ||||
opal_call(OPAL_NMMU_SET_PTCR, -1, mfspr(SPR_PTCR)); | opal_call(OPAL_NMMU_SET_PTCR, -1, mfspr(SPR_PTCR)); | ||||
} | } | ||||
SYSINIT(powernv_setup_nmmu, SI_SUB_CPU, SI_ORDER_ANY, powernv_setup_nmmu, NULL); | SYSINIT(powernv_setup_nmmu, SI_SUB_CPU, SI_ORDER_ANY, powernv_setup_nmmu, NULL); |