change PTE PG_* bit define to support SH4 PCMCIA space attribute fully.

for detail, see pte.h.
This commit is contained in:
uch 2002-02-11 18:06:06 +00:00
parent 32f2c6e61f
commit 9487e1d731
2 changed files with 139 additions and 205 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pte.h,v 1.4 2000/02/24 23:32:27 msaitoh Exp $ */
/* $NetBSD: pte.h,v 1.5 2002/02/11 18:06:06 uch Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@ -62,39 +62,63 @@ typedef int pt_entry_t; /* Mach page table entry */
#define PT_MASK 0x003ff000 /* page table address bits */
#define PTES_PER_PTP (NBPD / NBPG) /* # of PTEs in a PTP */
#define PG_AVAIL2 0x00000200 /* ignored by hardware */
#define PG_V 0x00000100 /* present */
#define PG_AVAIL1 0x00000080 /* ignored by hardware */
#define PG_RO 0x00000000 /* read-only by user */
#define PG_RW 0x00000020 /* read-write by user */
#define PG_u 0x00000040 /* accessible by user */
#define PG_PROT 0x00000060 /* all protection bits */
#define PG_N 0x00000008 /* 0=non-cacheable */
#define PG_M 0x00000004 /* has been modified */
#define PG_FRAME 0xfffff000 /* page frame mask */
/*
*
* NetBSD/sh3 PTE format.
*
* SH3
* PPN V PR SZ C D SH
* [28:10][8][6:5][4][3][2][1]
*
* SH4
* V SZ PR SZ C D SH WT
* [28:10][8][7][6:5][4][3][2][1][0]
*
* + NetBSD/sh3 page size is 4KB. [11:10] and [7] can be used as SW bit.
* + [31:29] should be available for SW bit...
* + SH4 WT bit is not stored in PTE. U0 is always write-back. and
* P3 is always write-thurogh. (see sh3/trap.c::__setup_pte_sh4())
* We use WT bit as SW bit.
*
* Software bit assign
* [11:9] - SH4 PCMCIA Assistant bit. (space attribute bit only)
* [7] - Wired page bit.
* [0] - PVlist bit.
*/
#ifdef SH4_PCMCIA
#define PG_PCMCIA_16 0x00000000 /* 16bit width */
#define PG_PCMCIA_8 0x00000080 /* 8 bit width */
#define PG_PCMCIA_NONE 0x00000000 /* Non PCMCIA space */
#define PG_PCMCIA 0x00000a00 /* PCMCIA space */
#define PG_PCMCIA_IO 0x00000200 /* PCMCIA IO space */
#define PG_PCMCIA_MEM 0x00000800 /* PCMCIA Memory space */
#define PG_PCMCIA_ATT 0x00000a00 /* PCMCIA Attribute space */
#endif
/*
* Hardware bits
*/
#define PG_FRAME 0xfffff000 /* page frame mask XXX */
#define PG_V 0x00000100 /* present */
#define PG_UW 0x00000060 /* kernel/user read/write */
#define PG_URKR 0x00000040 /* kernel/user read only */
#define PG_KW 0x00000020 /* kernel read/write */
#define PG_KR 0x00000000 /* kernel read only */
#define PG_4K 0x00000010 /* page size 4KB */
#define PG_N 0x00000008 /* 0=non-cacheable */
#define PG_M 0x00000004 /* has been modified */
#define PG_G 0x00000002 /* share status */
#define PG_WT 0x00000001 /* write through (SH4) */
#define PG_KR 0x00000000
#define PG_KW 0x00000020
#define PG_URKR 0x00000040
#define PG_UW 0x00000060
#define PG_HW_BITS 0x1ffff17e /* [28:12][8][6:1] */
#define PG_W 0x00000400 /* page is wired */
#define PG_4K 0x00000010
#define PG_G 0x00000002 /* share status */
#ifdef SH4
#define PG_WT 0x00000001 /* write through */
#endif
/*
* Software bits
*/
#define PG_W 0x00000080 /* page is wired */
#define PG_PVLIST 0x00000001 /* mapping has entry on pvlist */
/* SH4 PCMCIA MMU support bits */
/* PTEA SA (Space Attribute bit) */
#define _PG_PCMCIA 0x00000e00
#define _PG_PCMCIA_SHIFT 9
#define _PG_PCMCIA_NONE 0x00000000 /* Non PCMCIA space */
#define _PG_PCMCIA_IO 0x00000200 /* IOIS16 signal */
#define _PG_PCMCIA_IO8 0x00000400 /* 8 bit I/O */
#define _PG_PCMCIA_IO16 0x00000600 /* 16 bit I/O */
#define _PG_PCMCIA_MEM8 0x00000800 /* 8 bit common memory */
#define _PG_PCMCIA_MEM16 0x00000a00 /* 16 bit common memory */
#define _PG_PCMCIA_ATTR8 0x00000c00 /* 8 bit attribute */
#define _PG_PCMCIA_ATTR16 0x00000e00 /* 16 bit attribute */
#endif /* !_SH3_PTE_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.28 2001/08/10 18:27:08 msaitoh Exp $ */
/* $NetBSD: trap.c,v 1.29 2002/02/11 18:06:06 uch Exp $ */
/*-
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
@ -66,6 +66,7 @@
#include <uvm/uvm_extern.h>
#include <sh3/mmureg.h>
#include <sh3/trapreg.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
@ -80,26 +81,54 @@
#include <sys/kgdb.h>
#endif
extern int cpu_debug_mode;
char *trap_type[] = {
"power-on", /* 0x000 T_POWERON */
"manual reset", /* 0x020 T_RESET */
"TLB miss/invalid (load)", /* 0x040 T_TLBMISSR */
"TLB miss/invalid (store)", /* 0x060 T_TLBMISSW */
"initial page write", /* 0x080 T_INITPAGEWR */
"TLB protection violation (load)", /* 0x0a0 T_TLBPRIVR */
"TLB protection violation (store)", /* 0x0c0 T_TLBPRIVW */
"address error (load)", /* 0x0e0 T_ADDRESSERRR */
"address error (store)", /* 0x100 T_ADDRESSERRW */
"unknown trap (0x120)", /* 0x120 */
"unknown trap (0x140)", /* 0x140 */
"unconditional trap (TRAPA)", /* 0x160 T_TRAP */
"reserved instruction code exception", /* 0x180 T_INVALIDISN */
"illegal slot instruction exception", /* 0x1a0 T_INVALIDSLOT */
"nonmaskable interrupt", /* 0x1c0 T_NMI */
"user break point trap", /* 0x1e0 T_USERBREAK */
};
int trap_types = sizeof trap_type / sizeof trap_type[0];
static __inline void userret __P((struct proc *, int, u_quad_t));
void trap __P((int, int, int, int, struct trapframe));
int trapwrite __P((unsigned));
void syscall __P((struct trapframe *));
void
tlb_handler __P((
int p1, int p2, int p3, int p4, /* These four param is dummy */
struct trapframe frame));
extern int cpu_debug_mode;
int trapdebug = 1;
static __inline void userret(struct proc *, int, u_quad_t);
void trap(int, int, int, int /* dummy 4 param*/, struct trapframe);
int trapwrite(unsigned);
void syscall(struct trapframe *);
void tlb_handler(int, int, int, int /* dummy 4 param */, struct trapframe);
void __setup_pte_sh3(vaddr_t, u_int32_t);
void __setup_pte_sh4(vaddr_t, u_int32_t);
#ifdef SH4
#define __SETUP_PTE(v, pte) __setup_pte_sh4((v), (pte))
#define __PD_AREA(x) SH3_P1SEG_TO_P2SEG(x)
#else /* SH4 */
#define __SETUP_PTE(v, pte) __setup_pte_sh3((v), (pte))
#define __PD_AREA(x) (x)
#endif /* SH4 */
#define __PD_TOP() ((u_long *)__PD_AREA(SHREG_TTB))
#define __PDE(pd, i) ((u_long *)__PD_AREA((pd)[(i)]))
/*
* Define the code needed before returning to user mode, for
* trap and syscall.
*/
static __inline void
userret(p, pc, oticks)
register struct proc *p;
int pc;
u_quad_t oticks;
userret(struct proc *p, int pc, u_quad_t oticks)
{
int sig;
@ -128,30 +157,34 @@ userret(p, pc, oticks)
curcpu()->ci_schedstate.spc_curpriority = p->p_priority;
}
char *trap_type[] = {
"power-on", /* 0x000 T_POWERON */
"manual reset", /* 0x020 T_RESET */
"TLB miss/invalid (load)", /* 0x040 T_TLBMISSR */
"TLB miss/invalid (store)", /* 0x060 T_TLBMISSW */
"initial page write", /* 0x080 T_INITPAGEWR */
"TLB protection violation (load)", /* 0x0a0 T_TLBPRIVR */
"TLB protection violation (store)", /* 0x0c0 T_TLBPRIVW */
"address error (load)", /* 0x0e0 T_ADDRESSERRR */
"address error (store)", /* 0x100 T_ADDRESSERRW */
"unknown trap (0x120)", /* 0x120 */
"unknown trap (0x140)", /* 0x140 */
"unconditional trap (TRAPA)", /* 0x160 T_TRAP */
"reserved instruction code exception", /* 0x180 T_INVALIDISN */
"illegal slot instruction exception", /* 0x1a0 T_INVALIDSLOT */
"nonmaskable interrupt", /* 0x1c0 T_NMI */
"user break point trap", /* 0x1e0 T_USERBREAK */
};
int trap_types = sizeof trap_type / sizeof trap_type[0];
/*
* PTEL, PTEA
*/
void
__setup_pte_sh3(vaddr_t va, u_int32_t pte)
{
#define DEBUG 1
#ifdef DEBUG
int trapdebug = 1;
#endif
SHREG_PTEL = pte & PG_HW_BITS;
}
void
__setup_pte_sh4(vaddr_t va, u_int32_t pte)
{
u_int32_t ptel;
ptel = pte & PG_HW_BITS;
if (pte & _PG_PCMCIA) {
SHREG_PTEA = (pte >> _PG_PCMCIA_SHIFT) & SH4_PTEA_SA_MASK;
SHREG_PTEL = ptel & ~PG_N;
} else {
if (va >= SH3_P1SEG_BASE)
ptel |= PG_WT; /* P3SEG is always write-through */
SHREG_PTEL = ptel;
SHREG_PTEA = 0;
}
}
/*
* trap(frame):
@ -163,9 +196,7 @@ int trapdebug = 1;
*/
/*ARGSUSED*/
void
trap(p1, p2, p3, p4, frame)
int p1, p2, p3, p4; /* dummy param */
struct trapframe frame;
trap(int p1, int p2, int p3, int p4,/* dummy param */ struct trapframe frame)
{
register struct proc *p = curproc;
int type = frame.tf_trapno;
@ -409,8 +440,7 @@ trap(p1, p2, p3, p4, frame)
*/
/*ARGSUSED*/
void
syscall(frame)
struct trapframe *frame;
syscall(struct trapframe *frame)
{
register caddr_t params;
register const struct sysent *callp;
@ -567,8 +597,7 @@ syscall(frame)
}
void
child_return(arg)
void *arg;
child_return(void *arg)
{
struct proc *p = arg;
struct trapframe *tf = p->p_md.md_regs;
@ -588,9 +617,7 @@ child_return(arg)
* This is called from tlb_miss exception handler.
*/
void
tlb_handler(p1, p2, p3, p4, frame)
int p1, p2, p3, p4; /* These four params are dummy */
struct trapframe frame;
tlb_handler(int p1, int p2, int p3, int p4, struct trapframe frame)
{
vaddr_t va;
int pde_index, sig;
@ -617,82 +644,17 @@ tlb_handler(p1, p2, p3, p4, frame)
va = (vaddr_t)SHREG_TEA;
va = trunc_page(va);
pde_index = pdei(va);
#ifdef SH4
pd_top = (u_long *)(SH3_P1SEG_TO_P2SEG(SHREG_TTB));
pde = (u_long *)((u_long)SH3_P1SEG_TO_P2SEG(pd_top[pde_index]));
#else
pd_top = (u_long *)SHREG_TTB;
pde = (u_long *)pd_top[pde_index];
#endif
pd_top = __PD_TOP();
pde = __PDE(pd_top, pde_index);
exptype = SHREG_EXPEVT;
#if 0 /* def SH4 */
if (((u_long)pde & PG_V) != 0 &&
(incpuswitch || exptype != T_TLBPRIVW)) {
#else
if (((u_long)pde & PG_V) != 0 && exptype != T_TLBPRIVW) {
#endif
(u_long)pde &= ~PGOFSET;
pte_index = ptei(va);
#ifdef SH4
pte = SH3_P1SEG_TO_P2SEG(pde[pte_index]);
#else
pte = pde[pte_index];
#endif
pte = (u_int32_t)__PDE(pde, pte_index);
if ((pte & PG_V) != 0) {
#ifdef DEBUG_TLB
if (trapdebug)
printf("tlb_handler:va(0x%lx),pte(0x%lx)\n",
va, pte);
#endif
#ifdef SH4_PCMCIA
#define PTEL_VALIDBITS 0x1ffff17e
#else
#define PTEL_VALIDBITS 0x1ffffd7e
#endif
#ifdef SH4
#ifdef SH4_PCMCIA
if (pte & PG_PCMCIA) {
int pcmtype;
unsigned long ptea = 0;
pcmtype = pte & PG_PCMCIA;
/* printf("pcmtype = %lx,pte=%lx\n",
pcmtype,pte); */
if (pcmtype == PG_PCMCIA_IO) {
ptea = 0x03;
} else if (pcmtype == PG_PCMCIA_MEM) {
ptea = 0x05;
/* ptea = 0x03; */
} else if (pcmtype == PG_PCMCIA_ATT) {
ptea = 0x07;
}
SHREG_PTEL = (pte & PTEL_VALIDBITS)
& ~PG_N;
SHREG_PTEA = ptea;
} else
#endif
{
if ( /*1 ||*/ (va >= SH3_P1SEG_BASE)) {
SHREG_PTEL = (pte & PTEL_VALIDBITS)
| PG_WT;
} else {
SHREG_PTEL = pte & PTEL_VALIDBITS;
}
SHREG_PTEA = 0;
}
#else
SHREG_PTEL = pte & PTEL_VALIDBITS;
#endif
__SETUP_PTE(va, pte);
__asm __volatile ("ldtlb; nop");
return;
}
}
@ -780,67 +742,16 @@ tlb_handler(p1, p2, p3, p4, frame)
va = va_save;
SHREG_PTEH = pteh_save;
pde_index = pdei(va);
pd_top = (u_long *)SHREG_TTB;
#ifdef SH4
pde = (u_long *)
((u_long)SH3_P1SEG_TO_P2SEG(pd_top[pde_index]));
#else
pde = (u_long *)pd_top[pde_index];
#endif
pd_top = __PD_TOP();
pde = __PDE(pd_top, pde_index);
if (((u_long)pde & PG_V) != 0) {
(u_long)pde &= ~PGOFSET;
pte_index = ptei(va);
pte = pde[pte_index];
if ((pte & PG_V) != 0) {
#ifdef TRAP_DEBUG
if (trapdebug)
printf("tlb_handler#:va(0x%lx),pte(0x%lx)\n", va, pte);
#endif
#ifdef SH4
#ifdef SH4_PCMCIA
if (pte & PG_PCMCIA) {
int pcmtype;
unsigned long ptea = 0;
pcmtype = pte & PG_PCMCIA;
/* printf("pcmtype = %lx,pte=%lx\n",
pcmtype,pte); */
if (pcmtype == PG_PCMCIA_IO) {
ptea = 0x03;
} else if (pcmtype == PG_PCMCIA_MEM) {
ptea = 0x05;
/*ptea = 0x03; */
} else if (pcmtype == PG_PCMCIA_ATT) {
ptea = 0x07;
}
SHREG_PTEL = (pte & PTEL_VALIDBITS)
& ~PG_N;
SHREG_PTEA = ptea;
} else
#endif
{
if ( /*1 ||*/ (va >= SH3_P1SEG_BASE)) {
SHREG_PTEL =
(pte & PTEL_VALIDBITS)
| PG_WT;
} else {
SHREG_PTEL =
(pte & PTEL_VALIDBITS);
}
SHREG_PTEA = 0;
}
#else
SHREG_PTEL = pte & PTEL_VALIDBITS;
#endif
}
if ((pte & PG_V) != 0)
__SETUP_PTE(va, pte);
}
__asm __volatile("ldtlb; nop");
if (user)
@ -850,8 +761,7 @@ tlb_handler(p1, p2, p3, p4, frame)
if (user == 0) {
/* Check for copyin/copyout fault. */
if (p != NULL &&
p->p_addr->u_pcb.pcb_onfault != 0) {
if (p != NULL && p->p_addr->u_pcb.pcb_onfault != 0) {
frame.tf_spc = (int) p->p_addr->u_pcb.pcb_onfault;
return;
}