summaryrefslogtreecommitdiff
path: root/sys/arch/mips64
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-01-09 20:33:17 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-01-09 20:33:17 +0000
commit87b483e2a7df54e7ed2f12b9849b2536d55e9082 (patch)
treed6b24a614c2a0c15bad70eed78b911b2ef109148 /sys/arch/mips64
parent1c2dbae3782a9af621a9d39b2388249f24e4a16f (diff)
Define struct cpu_hwinfo, to hold hardware specific information about each
processor (instead of sys_config.cpu[]), and pass it in the attach_args when attaching cpu devices. This allows per-cpu information to be gathered late in the bootstrap process, and not be limited by an arbitrary MAX_CPUS limit; this will suit IP27 and IP35 systems better. While there, use this information to make sure delay() uses the speed information from the cpu it is invoked on.
Diffstat (limited to 'sys/arch/mips64')
-rw-r--r--sys/arch/mips64/include/autoconf.h35
-rw-r--r--sys/arch/mips64/include/cpu.h25
-rw-r--r--sys/arch/mips64/mips64/clock.c73
-rw-r--r--sys/arch/mips64/mips64/cpu.c50
-rw-r--r--sys/arch/mips64/mips64/db_machdep.c16
-rw-r--r--sys/arch/mips64/mips64/pmap.c7
6 files changed, 133 insertions, 73 deletions
diff --git a/sys/arch/mips64/include/autoconf.h b/sys/arch/mips64/include/autoconf.h
new file mode 100644
index 00000000000..1a1519f9971
--- /dev/null
+++ b/sys/arch/mips64/include/autoconf.h
@@ -0,0 +1,35 @@
+/* $OpenBSD: autoconf.h,v 1.1 2010/01/09 20:33:16 miod Exp $ */
+
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Common defines used by autoconf on all mips64-based platforms.
+ */
+
+#ifndef _MIPS64_AUTOCONF_H_
+#define _MIPS64_AUTOCONF_H_
+
+#include <machine/cpu.h> /* for struct cpu_hwinfo */
+
+struct cpu_attach_args {
+ struct mainbus_attach_args caa_maa;
+ struct cpu_hwinfo *caa_hw;
+};
+
+extern struct cpu_hwinfo bootcpu_hwinfo;
+
+#endif /* _MIPS64_AUTOCONF_H_ */
diff --git a/sys/arch/mips64/include/cpu.h b/sys/arch/mips64/include/cpu.h
index cb2d70e10d1..e60cd3f65d1 100644
--- a/sys/arch/mips64/include/cpu.h
+++ b/sys/arch/mips64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.51 2010/01/08 01:35:52 syuu Exp $ */
+/* $OpenBSD: cpu.h,v 1.52 2010/01/09 20:33:16 miod Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -364,21 +364,30 @@ extern vaddr_t uncached_base;
#include <machine/intr.h>
+struct cpu_hwinfo {
+ uint32_t c0prid;
+ uint32_t c1prid;
+ uint32_t clock; /* Hz */
+ uint32_t tlbsize;
+ uint type;
+};
+
struct cpu_info {
- struct device *ci_dev; /* our device */
- struct cpu_info *ci_self; /* pointer to this structure */
- struct cpu_info *ci_next; /* next cpu */
+ struct device *ci_dev; /* our device */
+ struct cpu_info *ci_self; /* pointer to this structure */
+ struct cpu_info *ci_next; /* next cpu */
struct proc *ci_curproc;
struct user *ci_curprocpaddr;
struct proc *ci_fpuproc; /* pointer to last proc to use FP */
-
+ struct cpu_hwinfo
+ ci_hw;
struct schedstate_percpu
ci_schedstate;
int ci_want_resched; /* need_resched() invoked */
- cpuid_t ci_cpuid; /* our CPU ID */
+ cpuid_t ci_cpuid; /* our CPU ID */
uint32_t ci_randseed; /* per cpu random seed */
- int ci_ipl; /* software IPL */
- uint32_t ci_softpending; /* pending soft interrupts */
+ int ci_ipl; /* software IPL */
+ uint32_t ci_softpending; /* pending soft interrupts */
int ci_clock_started;
u_int32_t ci_cpu_counter_last;
u_int32_t ci_cpu_counter_interval;
diff --git a/sys/arch/mips64/mips64/clock.c b/sys/arch/mips64/mips64/clock.c
index 02c7de179dc..a0f7f530d06 100644
--- a/sys/arch/mips64/mips64/clock.c
+++ b/sys/arch/mips64/mips64/clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clock.c,v 1.31 2009/12/28 06:55:27 syuu Exp $ */
+/* $OpenBSD: clock.c,v 1.32 2010/01/09 20:33:16 miod Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -52,6 +52,7 @@ struct cfattach clock_ca = {
sizeof(struct device), clockmatch, clockattach
};
+void clock_calibrate(struct cpu_info *);
uint32_t clock_int5(uint32_t, struct trap_frame *);
u_int cp0_get_timecount(struct timecounter *);
@@ -188,9 +189,10 @@ delay(int n)
{
int dly;
int p, c;
+ struct cpu_info *ci = curcpu();
p = cp0_get_count();
- dly = (sys_config.cpu[0].clock / 1000000) * n / 2;
+ dly = (ci->ci_hw.clock / 1000000) * n / 2;
while (dly > 0) {
c = cp0_get_count();
dly -= c - p;
@@ -205,49 +207,57 @@ delay(int n)
struct tod_desc sys_tod;
/*
- * Start the real-time and statistics clocks. Leave stathz 0 since there
- * are no other timers available.
+ * Calibrate cpu clock against the TOD clock if available.
*/
void
-cpu_initclocks()
+clock_calibrate(struct cpu_info *ci)
{
struct tod_desc *cd = &sys_tod;
struct tod_time ct;
u_int first_cp0, second_cp0, cycles_per_sec;
int first_sec;
+
+ if (cd->tod_get == NULL)
+ return;
+
+ (*cd->tod_get)(cd->tod_cookie, 0, &ct);
+ first_sec = ct.sec;
+
+ /* Let the clock tick one second. */
+ do {
+ first_cp0 = cp0_get_count();
+ (*cd->tod_get)(cd->tod_cookie, 0, &ct);
+ } while (ct.sec == first_sec);
+ first_sec = ct.sec;
+ /* Let the clock tick one more second. */
+ do {
+ second_cp0 = cp0_get_count();
+ (*cd->tod_get)(cd->tod_cookie, 0, &ct);
+ } while (ct.sec == first_sec);
+
+ cycles_per_sec = second_cp0 - first_cp0;
+ ci->ci_hw.clock = cycles_per_sec * 2;
+}
+
+/*
+ * Start the real-time and statistics clocks. Leave stathz 0 since there
+ * are no other timers available.
+ */
+void
+cpu_initclocks()
+{
struct cpu_info *ci = curcpu();
hz = 100;
profhz = 100;
stathz = 0; /* XXX no stat clock yet */
- /*
- * Calibrate the cycle counter frequency.
- */
- if (cd->tod_get != NULL) {
- (*cd->tod_get)(cd->tod_cookie, 0, &ct);
- first_sec = ct.sec;
-
- /* Let the clock tick one second. */
- do {
- first_cp0 = cp0_get_count();
- (*cd->tod_get)(cd->tod_cookie, 0, &ct);
- } while (ct.sec == first_sec);
- first_sec = ct.sec;
- /* Let the clock tick one more second. */
- do {
- second_cp0 = cp0_get_count();
- (*cd->tod_get)(cd->tod_cookie, 0, &ct);
- } while (ct.sec == first_sec);
-
- cycles_per_sec = second_cp0 - first_cp0;
- sys_config.cpu[0].clock = cycles_per_sec * 2;
- }
+ clock_calibrate(ci);
tick = 1000000 / hz; /* number of micro-seconds between interrupts */
tickadj = 240000 / (60 * hz); /* can adjust 240ms in 60s */
- cp0_timecounter.tc_frequency = sys_config.cpu[0].clock / 2;
+ cp0_timecounter.tc_frequency = (uint64_t)ci->ci_hw.clock / 2;
tc_init(&cp0_timecounter);
cpu_startclock(ci);
}
@@ -264,11 +274,13 @@ cpu_startclock(struct cpu_info *ci)
/* try to avoid getting clock interrupts early */
cp0_set_compare(cp0_get_count() - 1);
+
+ clock_calibrate(ci);
}
/* Start the clock. */
s = splclock();
- ci->ci_cpu_counter_interval = cp0_timecounter.tc_frequency / hz;
+ ci->ci_cpu_counter_interval = (ci->ci_hw.clock / 2) / hz;
ci->ci_cpu_counter_last = cp0_get_count() + ci->ci_cpu_counter_interval;
cp0_set_compare(ci->ci_cpu_counter_last);
ci->ci_clock_started++;
@@ -309,7 +321,7 @@ inittodr(time_t base)
if (base < 35 * SECYR) {
printf("WARNING: preposterous time in file system");
/* read the system clock anyway */
- base = 38 * SECYR; /* 2008 */
+ base = 40 * SECYR; /* 2010 */
}
/*
@@ -414,5 +426,6 @@ resettodr()
u_int
cp0_get_timecount(struct timecounter *tc)
{
+ /* XXX SMP */
return (cp0_get_count());
}
diff --git a/sys/arch/mips64/mips64/cpu.c b/sys/arch/mips64/mips64/cpu.c
index 0dd44178805..5c7a6e5d2e3 100644
--- a/sys/arch/mips64/mips64/cpu.c
+++ b/sys/arch/mips64/mips64/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.23 2010/01/08 01:35:52 syuu Exp $ */
+/* $OpenBSD: cpu.c,v 1.24 2010/01/09 20:33:16 miod Exp $ */
/*
* Copyright (c) 1997-2004 Opsycon AB (www.opsycon.se)
@@ -80,13 +80,10 @@ struct cfdriver cpu_cd = {
int
cpumatch(struct device *parent, void *match, void *aux)
{
- struct cfdata *cf = match;
- struct mainbus_attach_args *maa = aux;
+ struct cpu_attach_args *caa = aux;
/* make sure that we're looking for a CPU. */
- if (strcmp(maa->maa_name, cpu_cd.cd_name) != 0)
- return 0;
- if (cf->cf_unit >= MAX_CPUS)
+ if (strcmp(caa->caa_maa.maa_name, cpu_cd.cd_name) != 0)
return 0;
return 20; /* Make CPU probe first */
@@ -95,9 +92,12 @@ cpumatch(struct device *parent, void *match, void *aux)
void
cpuattach(struct device *parent, struct device *dev, void *aux)
{
+ struct cpu_attach_args *caa = aux;
+ struct cpu_hwinfo *ch = caa->caa_hw;
struct cpu_info *ci;
int cpuno = dev->dv_unit;
int isr16k = 0;
+ int fptype, vers_maj, vers_min;
int displayver;
if (cpuno == 0) {
@@ -122,11 +122,14 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
ci->ci_self = ci;
ci->ci_cpuid = cpuno;
ci->ci_dev = dev;
+ bcopy(ch, &ci->ci_hw, sizeof(struct cpu_hwinfo));
printf(": ");
displayver = 1;
- switch (sys_config.cpu[cpuno].type) {
+ vers_maj = (ch->c0prid >> 4) & 0x0f;
+ vers_min = ch->c0prid & 0x0f;
+ switch (ch->type) {
case MIPS_R4000:
if (CpuPrimaryInstCacheSize == 16384)
printf("MIPS R4400 CPU");
@@ -143,8 +146,8 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
printf("MIPS R12000 CPU");
break;
case MIPS_R14000:
- if (sys_config.cpu[cpuno].vers_maj > 2) {
- sys_config.cpu[cpuno].vers_maj -= 2;
+ if (vers_maj > 2) {
+ vers_maj -= 2;
isr16k = 1;
}
printf("R1%d000 CPU", isr16k ? 6 : 4);
@@ -168,7 +171,7 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
printf("PMC-Sierra RM52X0 CPU");
break;
case MIPS_RM7000:
- if (sys_config.cpu[cpuno].vers_maj < 2)
+ if (vers_maj < 2)
printf("PMC-Sierra RM7000 CPU");
else
printf("PMC-Sierra RM7000A CPU");
@@ -178,21 +181,22 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
printf("PMC-Sierra RM9000 CPU");
break;
case MIPS_LOONGSON2:
- printf("STC Loongson2%c CPU",
- 'C' + sys_config.cpu[cpuno].vers_min);
+ printf("STC Loongson2%c CPU", 'C' + vers_min);
displayver = 0;
break;
default:
- printf("Unknown CPU type (0x%x)",sys_config.cpu[cpuno].type);
+ printf("Unknown CPU type (0x%x)", ch->type);
break;
}
if (displayver != 0)
- printf(" rev %d.%d", sys_config.cpu[cpuno].vers_maj,
- sys_config.cpu[cpuno].vers_min);
- printf(" %d MHz, ", sys_config.cpu[cpuno].clock / 1000000);
+ printf(" rev %d.%d", vers_maj, vers_min);
+ printf(" %d MHz, ", ch->clock / 1000000);
displayver = 1;
- switch (sys_config.cpu[cpuno].fptype) {
+ fptype = (ch->c1prid >> 8) & 0xff;
+ vers_maj = (ch->c1prid >> 4) & 0x0f;
+ vers_min = ch->c1prid & 0x0f;
+ switch (fptype) {
case MIPS_SOFT:
printf("Software FP emulation");
break;
@@ -230,17 +234,15 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
printf("RM9000 FPC");
break;
case MIPS_LOONGSON2:
- printf("STC Loongson2%c FPU",
- 'C' + sys_config.cpu[cpuno].fpvers_min);
+ printf("STC Loongson2%c FPU", 'C' + vers_min);
displayver = 0;
break;
default:
- printf("Unknown FPU type (0x%x)", sys_config.cpu[cpuno].fptype);
+ printf("Unknown FPU type (0x%x)", fptype);
break;
}
if (displayver != 0)
- printf(" rev %d.%d", sys_config.cpu[cpuno].fpvers_maj,
- sys_config.cpu[cpuno].fpvers_min);
+ printf(" rev %d.%d", vers_maj, vers_min);
printf("\n");
printf("cpu%d: cache L1-I %dKB", cpuno, CpuPrimaryInstCacheSize / 1024);
@@ -259,7 +261,7 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
}
if (CpuSecondaryCacheSize != 0) {
- switch (sys_config.cpu[cpuno].type) {
+ switch (ch->type) {
case MIPS_R10000:
case MIPS_R12000:
case MIPS_R14000:
@@ -285,7 +287,7 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
printf("cpu%d: Alias mask 0x%x\n", cpuno, CpuCacheAliasMask);
printf("cpu%d: Config Register %x\n", cpuno, CpuConfigRegister);
printf("cpu%d: Cache type %x\n", cpuno, CpuCacheType);
- if (sys_config.cpu[cpuno].fptype == MIPS_RM7000) {
+ if (ch->type == MIPS_RM7000) {
u_int tmp = CpuConfigRegister;
printf("cpu%d: ", cpuno);
diff --git a/sys/arch/mips64/mips64/db_machdep.c b/sys/arch/mips64/mips64/db_machdep.c
index 4dc4e3b8f80..9cd02ddadf2 100644
--- a/sys/arch/mips64/mips64/db_machdep.c
+++ b/sys/arch/mips64/mips64/db_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_machdep.c,v 1.21 2009/12/25 21:02:15 miod Exp $ */
+/* $OpenBSD: db_machdep.c,v 1.22 2010/01/09 20:33:16 miod Exp $ */
/*
* Copyright (c) 1998-2003 Opsycon AB (www.opsycon.se)
@@ -552,6 +552,7 @@ db_dump_tlb_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *m)
{
int tlbno, last, check, pid;
struct tlb_entry tlb, tlbp;
+ struct cpu_info *ci = curcpu();
char *attr[] = {
"WTNA", "WTA ", "UCBL", "CWB ", "RES ", "RES ", "UCNB", "BPAS"
};
@@ -562,10 +563,10 @@ char *attr[] = {
if (have_addr && addr < 256) {
pid = addr;
tlbno = 0;
- count = sys_config.cpu[0].tlbsize;
+ count = ci->ci_hw.tlbsize;
}
} else if (m[0] == 'c') {
- last = sys_config.cpu[0].tlbsize;
+ last = ci->ci_hw.tlbsize;
for (tlbno = 0; tlbno < last; tlbno++) {
tlb_read(tlbno, &tlb);
for (check = tlbno + 1; check < last; check++) {
@@ -581,17 +582,16 @@ if ((tlbp.tlb_hi == tlb.tlb_hi && (tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V)) ||
}
return;
} else {
- if (have_addr && addr < sys_config.cpu[0].tlbsize) {
+ if (have_addr && addr < ci->ci_hw.tlbsize) {
tlbno = addr;
- }
- else {
+ } else {
tlbno = 0;
- count = sys_config.cpu[0].tlbsize;
+ count = ci->ci_hw.tlbsize;
}
}
last = tlbno + count;
- for (; tlbno < sys_config.cpu[0].tlbsize && tlbno < last; tlbno++) {
+ for (; tlbno < ci->ci_hw.tlbsize && tlbno < last; tlbno++) {
tlb_read(tlbno, &tlb);
if (pid >= 0 && (tlb.tlb_hi & 0xff) != pid)
diff --git a/sys/arch/mips64/mips64/pmap.c b/sys/arch/mips64/mips64/pmap.c
index e3d3bb607ed..6f274949350 100644
--- a/sys/arch/mips64/mips64/pmap.c
+++ b/sys/arch/mips64/mips64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.46 2010/01/05 06:44:58 syuu Exp $ */
+/* $OpenBSD: pmap.c,v 1.47 2010/01/09 20:33:16 miod Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -1385,14 +1385,15 @@ pmap_alloc_tlbpid(struct proc *p)
{
pmap_t pmap;
uint id;
- u_long cpuid = cpu_number();
+ struct cpu_info *ci = curcpu();
+ u_long cpuid = ci->ci_cpuid;
pmap = p->p_vmspace->vm_map.pmap;
if (pmap->pm_asid[cpuid].pma_asidgen !=
pmap_asid_info[cpuid].pma_asidgen) {
id = pmap_asid_info[cpuid].pma_asid;
if (id >= VMNUM_PIDS) {
- tlb_flush(sys_config.cpu[0].tlbsize);
+ tlb_flush(ci->ci_hw.tlbsize);
/* reserve tlbpid_gen == 0 to alway mean invalid */
if (++pmap_asid_info[cpuid].pma_asidgen == 0)
pmap_asid_info[cpuid].pma_asidgen = 1;