First attempt to spin up the secondary processor on 180MP and 200MP.
XXX Need more work.
This commit is contained in:
parent
f6f00e2615
commit
73db3f2b79
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: cpu.c,v 1.6 2000/02/08 12:49:06 tsubai Exp $ */
|
||||
/* $NetBSD: cpu.c,v 1.7 2000/07/05 16:02:38 tsubai Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (C) 1998, 1999 Internet Research Institute, Inc.
|
||||
|
@ -31,26 +31,55 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_multiprocessor.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <machine/autoconf.h>
|
||||
#include <machine/bat.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/pio.h>
|
||||
|
||||
static int cpumatch __P((struct device *, struct cfdata *, void *));
|
||||
static void cpuattach __P((struct device *, struct device *, void *));
|
||||
int cpumatch(struct device *, struct cfdata *, void *);
|
||||
void cpuattach(struct device *, struct device *, void *);
|
||||
|
||||
static void ohare_init __P((void));
|
||||
static void display_l2cr __P((void));
|
||||
void identifycpu(char *);
|
||||
static void ohare_init(void);
|
||||
static void display_l2cr(void);
|
||||
int cpu_spinup(void);
|
||||
void cpu_hatch(void);
|
||||
|
||||
void cpu_spinup_trampoline(void);
|
||||
|
||||
struct cfattach cpu_ca = {
|
||||
sizeof(struct device), cpumatch, cpuattach
|
||||
};
|
||||
|
||||
int ncpus;
|
||||
|
||||
extern struct cfdriver cpu_cd;
|
||||
extern int powersave;
|
||||
|
||||
#define HAMMERHEAD 0xf8000000
|
||||
#define HH_ARBCONF (HAMMERHEAD + 0x90)
|
||||
#define HH_INTR (HAMMERHEAD + 0xc0)
|
||||
|
||||
/* XXX for now */
|
||||
#undef cpu_number
|
||||
static inline int
|
||||
cpu_number()
|
||||
{
|
||||
int pir;
|
||||
|
||||
asm ("mfspr %0,1023" : "=r"(pir));
|
||||
return pir;
|
||||
}
|
||||
|
||||
int
|
||||
cpumatch(parent, cf, aux)
|
||||
struct device *parent;
|
||||
|
@ -58,11 +87,23 @@ cpumatch(parent, cf, aux)
|
|||
void *aux;
|
||||
{
|
||||
struct confargs *ca = aux;
|
||||
int *reg = ca->ca_reg;
|
||||
int hammerhead;
|
||||
|
||||
if (strcmp(ca->ca_name, cpu_cd.cd_name))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
switch (reg[0]) {
|
||||
case 0: /* master CPU */
|
||||
return 1;
|
||||
case 1: /* secondary CPU */
|
||||
hammerhead = OF_finddevice("/hammerhead");
|
||||
if (hammerhead == -1)
|
||||
return 0;
|
||||
if (in32rb(HH_ARBCONF) & 0x02)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MPC601 1
|
||||
|
@ -83,7 +124,29 @@ cpuattach(parent, self, aux)
|
|||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct confargs *ca = aux;
|
||||
int *reg = ca->ca_reg;
|
||||
int hid0, pvr;
|
||||
char model[80];
|
||||
|
||||
ncpus++;
|
||||
|
||||
switch (reg[0]) {
|
||||
case 0:
|
||||
asm volatile ("mtspr 1023,%0" :: "r"(0)); /* PIR */
|
||||
identifycpu(model);
|
||||
printf(": %s, ID %d (primary)", model, cpu_number());
|
||||
break;
|
||||
/* #ifdef MULTIPROCESSOR */
|
||||
case 1:
|
||||
cpu_spinup();
|
||||
printf("\n");
|
||||
return;
|
||||
/* #endif */
|
||||
default:
|
||||
printf(": more than 2 cpus?\n");
|
||||
panic("cpuattach");
|
||||
}
|
||||
|
||||
__asm __volatile ("mfpvr %0" : "=r"(pvr));
|
||||
switch (pvr >> 16) {
|
||||
|
@ -116,6 +179,47 @@ cpuattach(parent, self, aux)
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
struct cputab {
|
||||
int version;
|
||||
char *name;
|
||||
};
|
||||
static struct cputab models[] = {
|
||||
{ 1, "601" },
|
||||
{ 3, "603" },
|
||||
{ 4, "604" },
|
||||
{ 5, "602" },
|
||||
{ 6, "603e" },
|
||||
{ 7, "603ev" },
|
||||
{ 8, "750" },
|
||||
{ 9, "604ev" },
|
||||
{ 12, "7400" },
|
||||
{ 20, "620" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
void
|
||||
identifycpu(cpu_model)
|
||||
char *cpu_model;
|
||||
{
|
||||
int pvr, vers, rev;
|
||||
struct cputab *cp = models;
|
||||
|
||||
asm ("mfpvr %0" : "=r"(pvr));
|
||||
vers = pvr >> 16;
|
||||
rev = pvr & 0xffff;
|
||||
|
||||
while (cp->name) {
|
||||
if (cp->version == vers)
|
||||
break;
|
||||
cp++;
|
||||
}
|
||||
if (cp->name)
|
||||
strcpy(cpu_model, cp->name);
|
||||
else
|
||||
sprintf(cpu_model, "Version %x", vers);
|
||||
sprintf(cpu_model + strlen(cpu_model), " (Revision %x)", rev);
|
||||
}
|
||||
|
||||
#define CACHE_REG 0xf8000000
|
||||
|
||||
void
|
||||
|
@ -210,3 +314,162 @@ display_l2cr()
|
|||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* #ifdef MULTIPROCESSOR */
|
||||
struct cpu_hatch_data {
|
||||
int running;
|
||||
int pir;
|
||||
int hid0;
|
||||
int sdr1;
|
||||
int sr[16];
|
||||
int tbu, tbl;
|
||||
};
|
||||
|
||||
volatile struct cpu_hatch_data *cpu_hatch_data;
|
||||
volatile int cpu_hatchstack;
|
||||
|
||||
int
|
||||
cpu_spinup()
|
||||
{
|
||||
volatile struct cpu_hatch_data hatch_data, *h = &hatch_data;
|
||||
int i;
|
||||
struct pcb *pcb;
|
||||
struct pglist mlist;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Allocate UPAGES contiguous pages for the idle PCB and stack
|
||||
* from the lowest 256MB (because bat0 always maps it va == pa).
|
||||
*/
|
||||
TAILQ_INIT(&mlist);
|
||||
error = uvm_pglistalloc(USPACE, 0x0, 0x10000000, 0, 0, &mlist, 1, 1);
|
||||
if (error) {
|
||||
printf(": unable to allocate idle stack");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pcb = (void *)VM_PAGE_TO_PHYS(TAILQ_FIRST(&mlist));
|
||||
bzero(pcb, USPACE);
|
||||
|
||||
/*
|
||||
* Initialize the idle stack pointer, reserving space for an
|
||||
* (empty) trapframe (XXX is the trapframe really necessary?)
|
||||
*/
|
||||
pcb->pcb_sp = (paddr_t)pcb + USPACE - sizeof(struct trapframe);
|
||||
|
||||
cpu_hatch_data = h;
|
||||
h->running = 0;
|
||||
h->pir = 1;
|
||||
cpu_hatchstack = pcb->pcb_sp;
|
||||
|
||||
/* copy special registers */
|
||||
asm volatile ("mfspr %0,1008" : "=r"(h->hid0));
|
||||
asm volatile ("mfsdr1 %0" : "=r"(h->sdr1));
|
||||
for (i = 0; i < 16; i++)
|
||||
asm ("mfsrin %0,%1" : "=r"(h->sr[i]) : "r"(i << ADDR_SR_SHFT));
|
||||
|
||||
asm volatile ("sync; isync");
|
||||
|
||||
/* Start secondary cpu and stop timebase. */
|
||||
out32(0xf2800000, (int)cpu_spinup_trampoline);
|
||||
out32(HH_INTR, ~0);
|
||||
out32(HH_INTR, 0);
|
||||
|
||||
/* sync timebase (XXX shouldn't be zero'ed) */
|
||||
asm volatile ("mttbl %0; mttbu %0; mttbl %0" :: "r"(0));
|
||||
|
||||
/*
|
||||
* wait for secondary spin up (1.5ms @ 604/200MHz)
|
||||
* XXX we cannot use delay() here because timebase is not running.
|
||||
*/
|
||||
for (i = 0; i < 100000; i++)
|
||||
if (h->running)
|
||||
break;
|
||||
|
||||
/* Start timebase. */
|
||||
out32(0xf2800000, 0x100);
|
||||
out32(HH_INTR, ~0);
|
||||
out32(HH_INTR, 0);
|
||||
|
||||
delay(100000); /* wait for secondary printf */
|
||||
|
||||
if (h->running == 0) {
|
||||
printf(": secondary cpu didn't start");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cpu_hatch()
|
||||
{
|
||||
volatile struct cpu_hatch_data *h = cpu_hatch_data;
|
||||
u_int msr;
|
||||
int i;
|
||||
char model[80];
|
||||
|
||||
/* Initialize timebase. */
|
||||
asm ("mttbl %0; mttbu %0; mttbl %0" :: "r"(0));
|
||||
|
||||
/* Set PIR (Processor Identification Register). i.e. whoami */
|
||||
asm volatile ("mtspr 1023,%0" :: "r"(h->pir));
|
||||
|
||||
/* Initialize MMU. */
|
||||
asm ("mtibatu 0,%0" :: "r"(0));
|
||||
asm ("mtibatu 1,%0" :: "r"(0));
|
||||
asm ("mtibatu 2,%0" :: "r"(0));
|
||||
asm ("mtibatu 3,%0" :: "r"(0));
|
||||
asm ("mtdbatu 0,%0" :: "r"(0));
|
||||
asm ("mtdbatu 1,%0" :: "r"(0));
|
||||
asm ("mtdbatu 2,%0" :: "r"(0));
|
||||
asm ("mtdbatu 3,%0" :: "r"(0));
|
||||
|
||||
asm ("mtspr 1008,%0" :: "r"(h->hid0));
|
||||
|
||||
asm ("mtibatl 0,%0; mtibatu 0,%1;"
|
||||
"mtdbatl 0,%0; mtdbatu 0,%1;"
|
||||
:: "r"(battable[0].batl), "r"(battable[0].batu));
|
||||
|
||||
/* XXX obio (for now) */
|
||||
asm ("mtibatl 1,%0; mtibatu 1,%1;"
|
||||
"mtdbatl 1,%0; mtdbatu 1,%1;"
|
||||
:: "r"(battable[0xf].batl), "r"(battable[0xf].batu));
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
asm ("mtsrin %0,%1" :: "r"(h->sr[i]), "r"(i << ADDR_SR_SHFT));
|
||||
asm ("mtsdr1 %0" :: "r"(h->sdr1));
|
||||
|
||||
asm volatile ("isync");
|
||||
|
||||
/* Enable I/D address translations. */
|
||||
asm volatile ("mfmsr %0" : "=r"(msr));
|
||||
msr |= PSL_IR|PSL_DR|PSL_ME|PSL_RI;
|
||||
asm volatile ("mtmsr %0" :: "r"(msr));
|
||||
|
||||
asm volatile ("sync; isync");
|
||||
h->running = 1;
|
||||
|
||||
identifycpu(model);
|
||||
printf(": %s, ID %d", model, cpu_number());
|
||||
|
||||
/* XXX Enter power-saving mode and never return. */
|
||||
asm volatile ("
|
||||
1:
|
||||
sync
|
||||
mtmsr %0
|
||||
isync
|
||||
b 1b
|
||||
" :: "r"(PSL_POW));
|
||||
|
||||
for (;;);
|
||||
}
|
||||
/* #endif MULTIPROCESSOR */
|
||||
|
||||
#ifdef MULTIPROCESSOR
|
||||
void
|
||||
cpu_boot_secondary_processors()
|
||||
{
|
||||
/* currently noop */
|
||||
}
|
||||
#endif /* MULTIPROCESSOR */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */
|
||||
/* $NetBSD: locore.S,v 1.25 2000/07/05 16:02:39 tsubai Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
|
||||
|
@ -1486,3 +1486,25 @@ _C_LABEL(setfault):
|
|||
stmw 12,12(3)
|
||||
xor 3,3,3
|
||||
blr
|
||||
|
||||
/* #ifdef MULTIPROCESSOR */
|
||||
.globl _C_LABEL(cpu_spinup_trampoline)
|
||||
_C_LABEL(cpu_spinup_trampoline):
|
||||
li 0,0
|
||||
mtmsr 0
|
||||
isync
|
||||
|
||||
lis 3,cpu_hatchstack@ha
|
||||
lwz 1,cpu_hatchstack@l(3)
|
||||
|
||||
bl _C_LABEL(cpu_hatch)
|
||||
|
||||
1:
|
||||
sync
|
||||
mfmsr 3
|
||||
oris 3,3,PSL_POW@h
|
||||
mtmsr 3
|
||||
isync
|
||||
b 1b
|
||||
|
||||
/* #endif */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.77 2000/07/02 04:40:39 cgd Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.78 2000/07/05 16:02:39 tsubai Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
|
||||
|
@ -392,60 +392,10 @@ restore_ofw_mapping()
|
|||
/*
|
||||
* This should probably be in autoconf! XXX
|
||||
*/
|
||||
int cpu;
|
||||
char cpu_model[80];
|
||||
char machine[] = MACHINE; /* from <machine/param.h> */
|
||||
char machine_arch[] = MACHINE_ARCH; /* from <machine/param.h> */
|
||||
|
||||
void
|
||||
identifycpu()
|
||||
{
|
||||
int pvr;
|
||||
|
||||
/*
|
||||
* Find cpu type (Do it by OpenFirmware?)
|
||||
*/
|
||||
asm ("mfpvr %0" : "=r"(pvr));
|
||||
cpu = pvr >> 16;
|
||||
switch (cpu) {
|
||||
case 1:
|
||||
sprintf(cpu_model, "601");
|
||||
break;
|
||||
case 3:
|
||||
sprintf(cpu_model, "603");
|
||||
break;
|
||||
case 4:
|
||||
sprintf(cpu_model, "604");
|
||||
break;
|
||||
case 5:
|
||||
sprintf(cpu_model, "602");
|
||||
break;
|
||||
case 6:
|
||||
sprintf(cpu_model, "603e");
|
||||
break;
|
||||
case 7:
|
||||
sprintf(cpu_model, "603ev");
|
||||
break;
|
||||
case 8:
|
||||
sprintf(cpu_model, "750");
|
||||
break;
|
||||
case 9:
|
||||
sprintf(cpu_model, "604ev");
|
||||
break;
|
||||
case 12:
|
||||
sprintf(cpu_model, "7400");
|
||||
break;
|
||||
case 20:
|
||||
sprintf(cpu_model, "620");
|
||||
break;
|
||||
default:
|
||||
sprintf(cpu_model, "Version %x", cpu);
|
||||
break;
|
||||
}
|
||||
sprintf(cpu_model + strlen(cpu_model), " (Revision %x)", pvr & 0xffff);
|
||||
printf("CPU: %s\n", cpu_model);
|
||||
}
|
||||
|
||||
void
|
||||
install_extint(handler)
|
||||
void (*handler) __P((void));
|
||||
|
@ -486,7 +436,7 @@ cpu_startup()
|
|||
v = (caddr_t)proc0paddr + USPACE;
|
||||
|
||||
printf("%s", version);
|
||||
identifycpu();
|
||||
identifycpu(cpu_model);
|
||||
|
||||
format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
|
||||
printf("total memory = %s\n", pbuf);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mainbus.c,v 1.7 2000/02/03 19:27:45 tsubai Exp $ */
|
||||
/* $NetBSD: mainbus.c,v 1.8 2000/07/05 16:02:39 tsubai Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
|
||||
|
@ -69,12 +69,19 @@ mainbus_attach(parent, self, aux)
|
|||
{
|
||||
struct ofbus_attach_args oba;
|
||||
struct confargs ca;
|
||||
int node;
|
||||
int node, i;
|
||||
u_int32_t reg[4];
|
||||
char name[32];
|
||||
|
||||
printf("\n");
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
ca.ca_name = "cpu";
|
||||
ca.ca_reg = reg;
|
||||
reg[0] = i;
|
||||
config_found(self, &ca, NULL);
|
||||
}
|
||||
|
||||
node = OF_peer(0);
|
||||
if (node) {
|
||||
oba.oba_busname = "ofw";
|
||||
|
@ -82,9 +89,6 @@ mainbus_attach(parent, self, aux)
|
|||
config_found(self, &oba, NULL);
|
||||
}
|
||||
|
||||
ca.ca_name = "cpu";
|
||||
config_found(self, &ca, NULL);
|
||||
|
||||
for (node = OF_child(OF_finddevice("/")); node; node = OF_peer(node)) {
|
||||
bzero(name, sizeof(name));
|
||||
if (OF_getprop(node, "name", name, sizeof(name)) == -1)
|
||||
|
|
Loading…
Reference in New Issue