Move the pmap_setup to the start oea_init (no non-OFW ports can use it).

If PPC_OEA64_BRIDGE is defined, add code so that when OEACPU_64_BRIDGE is not
present, it replaces the rfid with rfi and mfmsr/rldicl/mtmsrd sequence
with NOPs.  This allows plain OEA kernels to work.  (tested on PMPPC with
PPC_OEA64_BRIDGE option added).
This commit is contained in:
matt 2013-08-31 07:33:15 +00:00
parent 378cec5a74
commit 310fbebba0
2 changed files with 79 additions and 24 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: oea_machdep.c,v 1.65 2013/07/04 22:59:27 joerg Exp $ */
/* $NetBSD: oea_machdep.c,v 1.66 2013/08/31 07:33:15 matt Exp $ */
/*
* Copyright (C) 2002 Matt Thomas
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: oea_machdep.c,v 1.65 2013/07/04 22:59:27 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: oea_machdep.c,v 1.66 2013/08/31 07:33:15 matt Exp $");
#include "opt_ppcarch.h"
#include "opt_compat_netbsd.h"
@ -147,6 +147,14 @@ oea_init(void (*handler)(void))
#endif
KASSERT(mfspr(SPR_SPRG0) == (uintptr_t)ci);
#if defined (PPC_OEA64_BRIDGE) && defined (PPC_OEA)
if (oeacpufeat & OEACPU_64_BRIDGE)
pmap_setup64bridge();
else
pmap_setup32();
#endif
cpuvers = mfpvr() >> 16;
/*
@ -298,6 +306,16 @@ oea_init(void (*handler)(void))
#define B 0x48000000
#define TLBSYNC 0x7c00046c
#define SYNC 0x7c0004ac
#ifdef PPC_OEA64_BRIDGE
#define MFMSR_MASK 0xfc1fffff
#define MFMSR 0x7c0000a6
#define MTMSRD_MASK 0xfc1effff
#define MTMSRD 0x7c000164
#define RLDICL_MASK 0xfc00001c
#define RLDICL 0x78000000
#define RFID 0x4c000024
#define RFI 0x4c000064
#endif
#ifdef ALTIVEC
#define MFSPR_VRSAVE 0x7c0042a6
@ -320,9 +338,7 @@ oea_init(void (*handler)(void))
if (scratch & PSL_VEC) {
cpu_altivec = 1;
} else {
int *ip = trapstart;
for (; ip < trapend; ip++) {
for (int *ip = trapstart; ip < trapend; ip++) {
if ((ip[0] & MxSPR_MASK) == MFSPR_VRSAVE) {
ip[0] = NOP; /* mfspr */
ip[1] = NOP; /* stw */
@ -343,9 +359,7 @@ oea_init(void (*handler)(void))
* sequences where we zap/restore BAT registers on kernel exit/entry.
*/
if (cpuvers != MPC601) {
int *ip = trapstart;
for (; ip < trapend; ip++) {
for (int *ip = trapstart; ip < trapend; ip++) {
if ((ip[0] & MxSPR_MASK) == MFSPR_MQ) {
ip[0] = NOP; /* mfspr */
ip[1] = NOP; /* stw */
@ -361,6 +375,37 @@ oea_init(void (*handler)(void))
}
}
#ifdef PPC_OEA64_BRIDGE
if ((oeacpufeat & OEACPU_64_BRIDGE) == 0) {
for (int *ip = (int *)exc_base;
(uintptr_t)ip <= exc_base + EXC_LAST;
ip++) {
if ((ip[0] & MFMSR_MASK) == MFMSR
&& (ip[1] & RLDICL_MASK) == RLDICL
&& (ip[2] & MTMSRD_MASK) == MTMSRD) {
*ip++ = NOP;
*ip++ = NOP;
ip[0] = NOP;
}
}
/*
* Now replace each rfid instruction with a rfi instruction.
*/
for (int *ip = trapstart; ip < trapend; ip++) {
if ((ip[0] & MFMSR_MASK) == MFMSR
&& (ip[1] & RLDICL_MASK) == RLDICL
&& (ip[2] & MTMSRD_MASK) == MTMSRD) {
*ip++ = NOP;
*ip++ = NOP;
ip[0] = NOP;
} else if (*ip == RFID) {
*ip = RFI;
}
}
}
#endif /* PPC_OEA64_BRIDGE */
/*
* Sync the changed instructions.
*/
@ -381,10 +426,11 @@ oea_init(void (*handler)(void))
extern int kernel_text[], etext[];
int *ip;
for (ip = kernel_text; ip < etext; ip++)
for (ip = kernel_text; ip < etext; ip++) {
if (*ip == TLBSYNC) {
*ip = SYNC;
__syncicache(ip, sizeof(*ip));
}
}
}
#endif /* PPC_OEA601 */
@ -830,6 +876,11 @@ oea_install_extint(void (*handler)(void))
extern int extint[], extsize[];
extern int extint_call[];
uintptr_t offset = (uintptr_t)handler - (uintptr_t)extint_call;
#ifdef PPC_HIGH_VEC
const uintptr_t exc_exi_base = EXC_HIGHVEC + EXC_EXI;
#else
const uintptr_t exc_exi_base = EXC_EXI;
#endif
int omsr, msr;
#ifdef DIAGNOSTIC
@ -842,13 +893,24 @@ oea_install_extint(void (*handler)(void))
: "K" ((u_short)~PSL_EE));
extint_call[0] = (extint_call[0] & 0xfc000003) | offset;
__syncicache((void *)extint_call, sizeof extint_call[0]);
#ifdef PPC_HIGH_VEC
memcpy((void *)(EXC_HIGHVEC + EXC_EXI), extint, (size_t)extsize);
__syncicache((void *)(EXC_HIGHVEC + EXC_EXI), (int)extsize);
#else
memcpy((void *)EXC_EXI, extint, (size_t)extsize);
__syncicache((void *)EXC_EXI, (int)extsize);
memcpy((void *)exc_exi_base, extint, (size_t)extsize);
#ifdef PPC_OEA64_BRIDGE
if ((oeacpufeat & OEACPU_64_BRIDGE) == 0) {
for (int *ip = (int *)exc_exi_base;
(uintptr_t)ip <= exc_exi_base + (size_t)extsize;
ip++) {
if ((ip[0] & MFMSR_MASK) == MFMSR
&& (ip[1] & RLDICL_MASK) == RLDICL
&& (ip[2] & MTMSRD_MASK) == MTMSRD) {
*ip++ = NOP;
*ip++ = NOP;
ip[0] = NOP;
}
}
}
#endif
__syncicache((void *)exc_exi_base, (int)extsize);
__asm volatile ("mtmsr %0" :: "r"(omsr));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ofwoea_machdep.c,v 1.33 2013/05/13 00:12:01 macallan Exp $ */
/* $NetBSD: ofwoea_machdep.c,v 1.34 2013/08/31 07:33:15 matt Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ofwoea_machdep.c,v 1.33 2013/05/13 00:12:01 macallan Exp $");
__KERNEL_RCSID(0, "$NetBSD: ofwoea_machdep.c,v 1.34 2013/08/31 07:33:15 matt Exp $");
#include "opt_ppcarch.h"
#include "opt_compat_netbsd.h"
@ -201,13 +201,6 @@ ofwoea_initppc(u_int startkernel, u_int endkernel, char *args)
}
#endif
#if defined (PPC_OEA64_BRIDGE) && defined (PPC_OEA)
if (oeacpufeat & OEACPU_64_BRIDGE)
pmap_setup64bridge();
else
pmap_setup32();
#endif
oea_init(pic_ext_intr);
ofmaplen = save_ofmap(NULL, 0);