Changeset View
Changeset View
Standalone View
Standalone View
sys/mips/mips/trap.c
Show First 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | |||||
#include <machine/trap.h> | #include <machine/trap.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <machine/pte.h> | #include <machine/pte.h> | ||||
#include <machine/pmap.h> | #include <machine/pmap.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/mips_opcode.h> | #include <machine/mips_opcode.h> | ||||
#include <machine/frame.h> | #include <machine/frame.h> | ||||
#include <machine/regnum.h> | #include <machine/regnum.h> | ||||
#include <machine/tlb.h> | |||||
#include <machine/tls.h> | #include <machine/tls.h> | ||||
#ifdef DDB | #ifdef DDB | ||||
#include <machine/db_machdep.h> | #include <machine/db_machdep.h> | ||||
#include <ddb/db_sym.h> | #include <ddb/db_sym.h> | ||||
#include <ddb/ddb.h> | #include <ddb/ddb.h> | ||||
#include <sys/kdb.h> | #include <sys/kdb.h> | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 167 Lines • ▼ Show 20 Lines | char *trap_type[] = { | ||||
"reserved 16", | "reserved 16", | ||||
"reserved 17", | "reserved 17", | ||||
"reserved 18", | "reserved 18", | ||||
"reserved 19", | "reserved 19", | ||||
"reserved 20", | "reserved 20", | ||||
"reserved 21", | "reserved 21", | ||||
"reserved 22", | "reserved 22", | ||||
"watch", | "watch", | ||||
"reserved 24", | "machine check", | ||||
"reserved 25", | "reserved 25", | ||||
"reserved 26", | "reserved 26", | ||||
"reserved 27", | "reserved 27", | ||||
"reserved 28", | "reserved 28", | ||||
"reserved 29", | "reserved 29", | ||||
"reserved 30", | "reserved 30", | ||||
"virtual coherency data", | "virtual coherency data", | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 351 Lines • ▼ Show 20 Lines | #endif | ||||
switch (type) { | switch (type) { | ||||
case T_MCHECK: | case T_MCHECK: | ||||
#ifdef DDB | #ifdef DDB | ||||
kdb_trap(type, 0, trapframe); | kdb_trap(type, 0, trapframe); | ||||
#endif | #endif | ||||
panic("MCHECK\n"); | panic("MCHECK\n"); | ||||
break; | break; | ||||
case T_MCHECK + T_USER: | |||||
{ | |||||
uint32_t status = mips_rd_status(); | |||||
if (status & MIPS_SR_TS) { | |||||
/* | |||||
* Machine Check exception caused by TLB | |||||
* detecting a match for multiple entries. | |||||
* | |||||
* Attempt to recover by flushing the user TLB | |||||
* and resetting the status bit. | |||||
jmallett: Can you explain to me why this happens with the new pmap? Is it related to superpages somehow? | |||||
*/ | |||||
printf("Machine Check in User - Dup TLB entry. " | |||||
"Recovering...\n"); | |||||
pmap = &p->p_vmspace->vm_pmap; | |||||
tlb_invalidate_all_user(pmap); | |||||
mips_wr_status(status & ~MIPS_SR_TS); | |||||
return (trapframe->pc); | |||||
} else { | |||||
#ifdef DDB | |||||
kdb_trap(type, 0, trapframe); | |||||
#endif | |||||
panic("MCHECK\n"); | |||||
} | |||||
} | |||||
break; | |||||
case T_TLB_MOD: | case T_TLB_MOD: | ||||
/* check for kernel address */ | /* check for kernel address */ | ||||
if (KERNLAND(trapframe->badvaddr)) { | if (KERNLAND(trapframe->badvaddr)) { | ||||
if (pmap_emulate_modified(kernel_pmap, | if (pmap_emulate_modified(kernel_pmap, | ||||
trapframe->badvaddr) != 0) { | trapframe->badvaddr) != 0) { | ||||
ftype = VM_PROT_WRITE; | ftype = VM_PROT_WRITE; | ||||
goto kernel_fault; | goto kernel_fault; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | if (td->td_pcb->pcb_onfault == fswintrberr) { | ||||
td->td_pcb->pcb_onfault = NULL; | td->td_pcb->pcb_onfault = NULL; | ||||
return (pc); | return (pc); | ||||
} | } | ||||
goto dofault; | goto dofault; | ||||
case T_TLB_LD_MISS + T_USER: | case T_TLB_LD_MISS + T_USER: | ||||
ftype = VM_PROT_READ; | ftype = VM_PROT_READ; | ||||
goto dofault; | goto checkrefbit; | ||||
case T_TLB_ST_MISS + T_USER: | case T_TLB_ST_MISS + T_USER: | ||||
ftype = VM_PROT_WRITE; | ftype = VM_PROT_WRITE; | ||||
checkrefbit: | |||||
/* | |||||
* Was this trap caused by the PTE_VR bit not being set? | |||||
*/ | |||||
if (pmap_emulate_referenced(&p->p_vmspace->vm_pmap, | |||||
trapframe->badvaddr) == 0) { | |||||
if (!usermode) { | |||||
return (trapframe->pc); | |||||
} | |||||
goto out; | |||||
} | |||||
dofault: | dofault: | ||||
{ | { | ||||
vm_offset_t va; | vm_offset_t va; | ||||
struct vmspace *vm; | struct vmspace *vm; | ||||
vm_map_t map; | vm_map_t map; | ||||
int rv = 0; | int rv = 0; | ||||
vm = p->p_vmspace; | vm = p->p_vmspace; | ||||
▲ Show 20 Lines • Show All 697 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp) | get_mapping_info(vm_offset_t va, pd_entry_t **pdepp, pt_entry_t **ptepp) | ||||
{ | { | ||||
pt_entry_t *ptep; | pt_entry_t *ptep; | ||||
pd_entry_t *pdep; | pd_entry_t *pdep; | ||||
struct proc *p = curproc; | struct proc *p = curproc; | ||||
pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)])); | pdep = (&(p->p_vmspace->vm_pmap.pm_segtab[(va >> SEGSHIFT) & (NPDEPG - 1)])); | ||||
if (*pdep) | if (*pdep) { | ||||
ptep = pmap_pte(&p->p_vmspace->vm_pmap, va); | #if VM_NRESERVLEVEL > 0 | ||||
pd_entry_t *pde = &pdep[(va >> PDRSHIFT) & (NPDEPG - 1)]; | |||||
if (pde_is_superpage(pde)) | |||||
ptep = (pt_entry_t *)pde; | |||||
else | else | ||||
#endif /* VM_NRESERVLEVEL > 0 */ | |||||
ptep = pmap_pte(&p->p_vmspace->vm_pmap, va); | |||||
} else | |||||
ptep = (pt_entry_t *)0; | ptep = (pt_entry_t *)0; | ||||
*pdepp = pdep; | *pdepp = pdep; | ||||
*ptepp = ptep; | *ptepp = ptep; | ||||
} | } | ||||
static void | static void | ||||
log_illegal_instruction(const char *msg, struct trapframe *frame) | log_illegal_instruction(const char *msg, struct trapframe *frame) | ||||
▲ Show 20 Lines • Show All 305 Lines • Show Last 20 Lines |
Can you explain to me why this happens with the new pmap? Is it related to superpages somehow? It seems worrying. Again, I must be missing something?