diff options
Diffstat (limited to 'sys/arch/powerpc')
-rw-r--r-- | sys/arch/powerpc/include/bat.h | 7 | ||||
-rw-r--r-- | sys/arch/powerpc/include/cpu.h | 12 | ||||
-rw-r--r-- | sys/arch/powerpc/include/pmap.h | 3 | ||||
-rw-r--r-- | sys/arch/powerpc/powerpc/cpu_subr.c | 51 | ||||
-rw-r--r-- | sys/arch/powerpc/powerpc/pmap.c | 124 |
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. |