summaryrefslogtreecommitdiff
path: root/sys/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/powerpc')
-rw-r--r--sys/arch/powerpc/include/bat.h7
-rw-r--r--sys/arch/powerpc/include/cpu.h12
-rw-r--r--sys/arch/powerpc/include/pmap.h3
-rw-r--r--sys/arch/powerpc/powerpc/cpu_subr.c51
-rw-r--r--sys/arch/powerpc/powerpc/pmap.c124
5 files changed, 148 insertions, 49 deletions
diff --git a/sys/arch/powerpc/include/bat.h b/sys/arch/powerpc/include/bat.h
index d2601d9a2bd..030cc56a330 100644
--- a/sys/arch/powerpc/include/bat.h
+++ b/sys/arch/powerpc/include/bat.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bat.h,v 1.5 2014/10/27 21:56:57 kettenis Exp $ */
+/* $OpenBSD: bat.h,v 1.6 2015/03/31 16:00:38 mpi Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -59,6 +59,11 @@ struct bat {
#define BAT_BL_64M 0x000007fc
#define BAT_BL_128M 0x00000ffc
#define BAT_BL_256M 0x00001ffc
+/* Extended Block Lengths (7455+) */
+#define BAT_BL_512M 0x00003ffc
+#define BAT_BL_1G 0x00007ffc
+#define BAT_BL_2G 0x0000fffc
+#define BAT_BL_4G 0x0001fffc
#ifdef _KERNEL
extern struct bat battable[16];
diff --git a/sys/arch/powerpc/include/cpu.h b/sys/arch/powerpc/include/cpu.h
index 11cc4cc5670..b41167ceefa 100644
--- a/sys/arch/powerpc/include/cpu.h
+++ b/sys/arch/powerpc/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.60 2015/02/11 07:05:39 dlg Exp $ */
+/* $OpenBSD: cpu.h,v 1.61 2015/03/31 16:00:38 mpi Exp $ */
/* $NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $ */
/*
@@ -150,7 +150,12 @@ extern struct cpu_info cpu_info[PPC_MAXPROCS];
#define CLKF_PC(frame) ((frame)->srr0)
#define CLKF_INTR(frame) ((frame)->depth != 0)
-extern int ppc_cpuidle;
+extern int ppc_cpuidle;
+extern int ppc_proc_is_64b;
+extern int ppc_nobat;
+
+void cpu_bootstrap(void);
+
/*
* This is used during profiling to integrate system time.
*/
@@ -385,8 +390,6 @@ ppc_intr_disable(void)
}
int ppc_cpuspeed(int *);
-void ppc_check_procid(void);
-extern int ppc_proc_is_64b;
/*
* PowerPC CPU types
@@ -409,6 +412,7 @@ extern int ppc_proc_is_64b;
#define PPC_CPU_MPC7450 0x8000
#define PPC_CPU_MPC7455 0x8001
#define PPC_CPU_MPC7457 0x8002
+#define PPC_CPU_MPC83xx 0x8083
/*
* This needs to be included late since it relies on definitions higher
diff --git a/sys/arch/powerpc/include/pmap.h b/sys/arch/powerpc/include/pmap.h
index ba66701637c..d422f56c249 100644
--- a/sys/arch/powerpc/include/pmap.h
+++ b/sys/arch/powerpc/include/pmap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.h,v 1.55 2015/02/15 21:34:33 miod Exp $ */
+/* $OpenBSD: pmap.h,v 1.56 2015/03/31 16:00:38 mpi Exp $ */
/* $NetBSD: pmap.h,v 1.1 1996/09/30 16:34:29 ws Exp $ */
/*-
@@ -134,6 +134,7 @@ boolean_t pteclrbits(struct vm_page *pg, u_int mask, u_int clear);
#define __HAVE_PMAP_DIRECT
void pmap_bootstrap(u_int kernelstart, u_int kernelend);
+void pmap_enable_mmu();
void pmap_pinit(struct pmap *);
void pmap_release(struct pmap *);
diff --git a/sys/arch/powerpc/powerpc/cpu_subr.c b/sys/arch/powerpc/powerpc/cpu_subr.c
index d6198aa6a40..5f8235270c6 100644
--- a/sys/arch/powerpc/powerpc/cpu_subr.c
+++ b/sys/arch/powerpc/powerpc/cpu_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu_subr.c,v 1.6 2015/03/31 15:51:05 mpi Exp $ */
+/* $OpenBSD: cpu_subr.c,v 1.7 2015/03/31 16:00:38 mpi Exp $ */
/*
* Copyright (c) 2013 Martin Pieuchot
@@ -19,21 +19,22 @@
#include <sys/param.h>
-#include <machine/cpu.h>
+#include <powerpc/cpu.h>
+
+int ppc_cpuidle; /* Support DOZE, NAP or DEEP NAP? */
+int ppc_altivec; /* CPU has altivec support. */
+int ppc_proc_is_64b; /* CPU is 64bit */
+int ppc_nobat; /* Do not use BAT registers. */
struct patch {
uint32_t *s;
uint32_t *e;
};
-extern struct patch rfi_start, nop32_start, nop64_start;
-extern uint32_t rfi_inst, rfid_inst, nop_inst;
-
-int ppc_cpuidle; /* Support DOZE, NAP or DEEP NAP? */
-int ppc_altivec;
-int ppc_proc_is_64b;
+extern struct patch rfi_start, nop32_start, nopbat_start;
+extern uint32_t rfid_inst, nop_inst;
void
-ppc_check_procid(void)
+cpu_bootstrap(void)
{
uint32_t cpu;
uint32_t *inst;
@@ -45,22 +46,44 @@ ppc_check_procid(void)
case PPC_CPU_IBM970:
case PPC_CPU_IBM970FX:
case PPC_CPU_IBM970MP:
+ ppc_nobat = 1;
ppc_proc_is_64b = 1;
+
for (p = &rfi_start; p->s; p++) {
for (inst = p->s; inst < p->e; inst++)
*inst = rfid_inst;
syncicache(p->s, (p->e - p->s) * sizeof(*p->e));
}
- for (p = &nop64_start; p->s; p++) {
+ break;
+ case PPC_CPU_MPC83xx:
+ ppc_mtibat4u(0);
+ ppc_mtibat5u(0);
+ ppc_mtibat6u(0);
+ ppc_mtibat7u(0);
+ ppc_mtdbat4u(0);
+ ppc_mtdbat5u(0);
+ ppc_mtdbat6u(0);
+ ppc_mtdbat7u(0);
+ /* FALLTHROUGH */
+ default:
+ ppc_mtibat0u(0);
+ ppc_mtibat1u(0);
+ ppc_mtibat2u(0);
+ ppc_mtibat3u(0);
+ ppc_mtdbat0u(0);
+ ppc_mtdbat1u(0);
+ ppc_mtdbat2u(0);
+ ppc_mtdbat3u(0);
+
+ for (p = &nop32_start; p->s; p++) {
for (inst = p->s; inst < p->e; inst++)
*inst = nop_inst;
syncicache(p->s, (p->e - p->s) * sizeof(*p->e));
}
+ }
- break;
- default:
- ppc_proc_is_64b = 0;
- for (p = &nop32_start; p->s; p++) {
+ if (ppc_nobat) {
+ for (p = &nopbat_start; p->s; p++) {
for (inst = p->s; inst < p->e; inst++)
*inst = nop_inst;
syncicache(p->s, (p->e - p->s) * sizeof(*p->e));
diff --git a/sys/arch/powerpc/powerpc/pmap.c b/sys/arch/powerpc/powerpc/pmap.c
index bde7f17c1ac..622002ee4ce 100644
--- a/sys/arch/powerpc/powerpc/pmap.c
+++ b/sys/arch/powerpc/powerpc/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.143 2015/03/31 15:51:05 mpi Exp $ */
+/* $OpenBSD: pmap.c,v 1.144 2015/03/31 16:00:38 mpi Exp $ */
/*
* Copyright (c) 2001, 2002, 2007 Dale Rahn.
@@ -85,12 +85,15 @@
#include <machine/pcb.h>
#include <powerpc/powerpc.h>
+#include <powerpc/bat.h>
#include <machine/pmap.h>
#include <machine/db_machdep.h>
#include <ddb/db_extern.h>
#include <ddb/db_output.h>
+struct bat battable[16];
+
struct dumpmem dumpmem[VM_PHYSSEG_MAX];
u_int ndumpmem;
@@ -1566,6 +1569,11 @@ pmap_bootstrap(u_int kernelstart, u_int kernelend)
struct pmapvp *vp2;
/*
+ * set the page size (default value is 4K which is ok)
+ */
+ uvm_setpagesize();
+
+ /*
* Get memory.
*/
pmap_avail_setup();
@@ -1630,7 +1638,17 @@ pmap_bootstrap(u_int kernelstart, u_int kernelend)
}
}
- if (ppc_proc_is_64b) {
+ /*
+ * Initialize kernel pmap and hardware.
+ */
+#if NPMAPS >= PPC_KERNEL_SEGMENT / 16
+ usedsr[PPC_KERNEL_SEGMENT / 16 / (sizeof usedsr[0] * 8)]
+ |= 1 << ((PPC_KERNEL_SEGMENT / 16) % (sizeof usedsr[0] * 8));
+#endif
+ for (i = 0; i < 16; i++)
+ pmap_kernel()->pm_sr[i] = (PPC_KERNEL_SEG0 + i) | SR_NOEXEC;
+
+ if (ppc_nobat) {
vp1 = pmap_steal_avail(sizeof (struct pmapvp), 4);
bzero (vp1, sizeof(struct pmapvp));
pmap_kernel()->pm_vp[0] = vp1;
@@ -1645,39 +1663,56 @@ pmap_bootstrap(u_int kernelstart, u_int kernelend)
vp2->vp[k] = pted;
}
}
- }
- ppc_kvm_stolen += reserve_dumppages( (caddr_t)(VM_MIN_KERNEL_ADDRESS +
- ppc_kvm_stolen));
-
-
- /*
- * Initialize kernel pmap and hardware.
- */
-#if NPMAPS >= PPC_KERNEL_SEGMENT / 16
- usedsr[PPC_KERNEL_SEGMENT / 16 / (sizeof usedsr[0] * 8)]
- |= 1 << ((PPC_KERNEL_SEGMENT / 16) % (sizeof usedsr[0] * 8));
-#endif
- for (i = 0; i < 16; i++) {
- pmap_kernel()->pm_sr[i] = (PPC_KERNEL_SEG0 + i) | SR_NOEXEC;
- ppc_mtsrin(PPC_KERNEL_SEG0 + i, i << ADDR_SR_SHIFT);
- }
-
- if (ppc_proc_is_64b) {
/* first segment contains executable pages */
pmap_kernel()->pm_exec[0]++;
pmap_kernel()->pm_sr[0] &= ~SR_NOEXEC;
+ } else {
+ /*
+ * Setup fixed BAT registers.
+ *
+ * Note that we still run in real mode, and the BAT
+ * registers were cleared in cpu_bootstrap().
+ */
+ battable[0].batl = BATL(0x00000000, BAT_M);
+ if (physmem > atop(0x08000000))
+ battable[0].batu = BATU(0x00000000, BAT_BL_256M);
+ else
+ battable[0].batu = BATU(0x00000000, BAT_BL_128M);
- asm volatile ("sync; mtsdr1 %0; isync"
- :: "r"((u_int)pmap_ptable64 | HTABSIZE_64));
- } else
- asm volatile ("sync; mtsdr1 %0; isync"
- :: "r"((u_int)pmap_ptable32 | (pmap_ptab_mask >> 10)));
-
- pmap_avail_fixup();
-
+ /* Map physical memory with BATs. */
+ if (physmem > atop(0x10000000)) {
+ battable[0x1].batl = BATL(0x10000000, BAT_M);
+ battable[0x1].batu = BATU(0x10000000, BAT_BL_256M);
+ }
+ if (physmem > atop(0x20000000)) {
+ battable[0x2].batl = BATL(0x20000000, BAT_M);
+ battable[0x2].batu = BATU(0x20000000, BAT_BL_256M);
+ }
+ if (physmem > atop(0x30000000)) {
+ battable[0x3].batl = BATL(0x30000000, BAT_M);
+ battable[0x3].batu = BATU(0x30000000, BAT_BL_256M);
+ }
+ if (physmem > atop(0x40000000)) {
+ battable[0x4].batl = BATL(0x40000000, BAT_M);
+ battable[0x4].batu = BATU(0x40000000, BAT_BL_256M);
+ }
+ if (physmem > atop(0x50000000)) {
+ battable[0x5].batl = BATL(0x50000000, BAT_M);
+ battable[0x5].batu = BATU(0x50000000, BAT_BL_256M);
+ }
+ if (physmem > atop(0x60000000)) {
+ battable[0x6].batl = BATL(0x60000000, BAT_M);
+ battable[0x6].batu = BATU(0x60000000, BAT_BL_256M);
+ }
+ if (physmem > atop(0x70000000)) {
+ battable[0x7].batl = BATL(0x70000000, BAT_M);
+ battable[0x7].batu = BATU(0x70000000, BAT_BL_256M);
+ }
+ }
- tlbia();
+ ppc_kvm_stolen += reserve_dumppages( (caddr_t)(VM_MIN_KERNEL_ADDRESS +
+ ppc_kvm_stolen));
pmap_avail_fixup();
for (mp = pmap_avail; mp->size; mp++) {
@@ -1690,6 +1725,37 @@ pmap_bootstrap(u_int kernelstart, u_int kernelend)
}
}
+void
+pmap_enable_mmu(void)
+{
+ uint32_t scratch, sdr1;
+ int i;
+
+ if (!ppc_nobat) {
+ /* DBAT0 used for initial segment */
+ ppc_mtdbat0l(battable[0].batl);
+ ppc_mtdbat0u(battable[0].batu);
+
+ /* IBAT0 only covering the kernel .text */
+ ppc_mtibat0l(battable[0].batl);
+ ppc_mtibat0u(BATU(0x00000000, BAT_BL_8M));
+ }
+
+ for (i = 0; i < 16; i++)
+ ppc_mtsrin(PPC_KERNEL_SEG0 + i, i << ADDR_SR_SHIFT);
+
+ if (ppc_proc_is_64b)
+ sdr1 = (uint32_t)pmap_ptable64 | HTABSIZE_64;
+ else
+ sdr1 = (uint32_t)pmap_ptable32 | (pmap_ptab_mask >> 10);
+
+ asm volatile ("sync; mtsdr1 %0; isync" :: "r"(sdr1));
+ tlbia();
+
+ asm volatile ("eieio; mfmsr %0; ori %0,%0,%1; mtmsr %0; sync; isync"
+ : "=r"(scratch) : "K"(PSL_IR|PSL_DR|PSL_ME|PSL_RI));
+}
+
/*
* activate a pmap entry
* NOOP on powerpc, all PTE entries exist in the same hash table.