more sanity checking. sanity checking disabled by default.

give every process a full pagetable by default now.

first step to disabling kernel page table code (processes
might not have page tables -> no address translation).
This commit is contained in:
Ben Gras 2009-05-12 11:35:01 +00:00
parent ebe050dbe2
commit e3ca89c0be
7 changed files with 87 additions and 40 deletions

View file

@ -36,8 +36,9 @@ void pagefault(struct proc *pr, int trap_errno)
/* Page fault we can't / don't want to
* handle.
*/
kprintf("pagefault for process %d ('%s'), pc = 0x%x\n",
pr->p_endpoint, pr->p_name, pr->p_reg.pc);
kprintf("pagefault for process %d ('%s'), pc = 0x%x, addr = 0x%x, flags = 0x%x\n",
pr->p_endpoint, pr->p_name, pr->p_reg.pc,
pagefault_cr2, trap_errno);
proc_stacktrace(pr);
minix_panic("page fault in system process", pr->p_endpoint);
@ -78,6 +79,8 @@ u32_t old_eflags;
{
/* An exception or unexpected interrupt has occurred. */
struct proc *t;
struct ex_s {
char *msg;
int signum;
@ -105,6 +108,13 @@ u32_t old_eflags;
register struct ex_s *ep;
struct proc *saved_proc;
#if DEBUG_SCHED_CHECK
for (t = BEG_PROC_ADDR; t < END_PROC_ADDR; ++t) {
if(t->p_magic != PMAGIC)
kprintf("entry %d broken\n", t->p_nr);
}
#endif
/* Save proc_ptr, because it may be changed by debug statements. */
saved_proc = proc_ptr;
@ -115,17 +125,17 @@ u32_t old_eflags;
return;
}
if(vec_nr == PAGE_FAULT_VECTOR) {
pagefault(saved_proc, trap_errno);
return;
}
/* If an exception occurs while running a process, the k_reenter variable
* will be zero. Exceptions in interrupt handlers or system traps will make
* k_reenter larger than zero.
*/
if (k_reenter == 0 && ! iskernelp(saved_proc)) {
{
switch(vec_nr) {
case PAGE_FAULT_VECTOR:
pagefault(saved_proc, trap_errno);
return;
}
kprintf(
"exception for process %d, endpoint %d ('%s'), pc = 0x%x:0x%x, sp = 0x%x:0x%x\n",

View file

@ -22,6 +22,8 @@ PUBLIC u32_t kernel_cr3;
extern u32_t cswitch;
u32_t last_cr3 = 0;
#define HASPT(procptr) ((procptr)->p_seg.p_cr3 != 0)
FORWARD _PROTOTYPE( void phys_put32, (phys_bytes addr, u32_t value) );
FORWARD _PROTOTYPE( u32_t phys_get32, (phys_bytes addr) );
FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value) );
@ -46,11 +48,12 @@ PUBLIC void vm_init(void)
unsigned pages;
struct proc* rp;
struct proc *sys = proc_addr(SYSTEM);
static int init_done = 0;
if (!vm_size)
minix_panic("i386_vm_init: no space for page tables", NO_NUM);
if(vm_running)
if(init_done)
return;
/* Align page directory */
@ -97,14 +100,15 @@ PUBLIC void vm_init(void)
phys_put32(vm_dir_base + p*I386_VM_PT_ENT_SIZE, entry);
}
/* Set this cr3 in all currently running processes for
* future context switches.
*/
for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
u32_t mycr3;
if(isemptyp(rp)) continue;
rp->p_seg.p_cr3 = vm_dir_base;
}
/* Set this cr3 in all currently running processes for
* future context switches.
*/
for (rp=BEG_PROC_ADDR; rp<END_PROC_ADDR; rp++) {
u32_t mycr3;
if(isemptyp(rp)) continue;
rp->p_seg.p_cr3 = vm_dir_base;
}
kernel_cr3 = vm_dir_base;
@ -115,6 +119,7 @@ PUBLIC void vm_init(void)
level0(vm_enable_paging);
/* Don't do this init in the future. */
init_done = 1;
vm_running = 1;
}
@ -312,6 +317,11 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
vmassert(physical);
vmassert(!(proc->p_rts_flags & SLOT_FREE));
if(!HASPT(proc)) {
*physical = virtual;
return OK;
}
/* Retrieve page directory entry. */
root = (u32_t *) proc->p_seg.p_cr3;
vmassert(!((u32_t) root % I386_PAGE_SIZE));
@ -428,7 +438,9 @@ PUBLIC int vm_contiguous(struct proc *targetproc, u32_t vir_buf, size_t bytes)
vmassert(targetproc);
vmassert(bytes > 0);
vmassert(vm_running);
if(!HASPT(targetproc))
return 1;
/* Start and end at page boundary to make logic simpler. */
po = vir_buf % I386_PAGE_SIZE;
@ -488,8 +500,8 @@ PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
u32_t flags, po, v;
int r;
vmassert(vm_running);
if(!HASPT(target))
return OK;
/* If caller has had a reply to this request, return it. */
if(RTS_ISSET(caller, VMREQUEST)) {
@ -760,8 +772,9 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */
if(vmcheck && procs[_DST_])
CHECKRANGE_OR_SUSPEND(procs[_DST_], phys_addr[_DST_], bytes, 1);
#define NOPT(p) (!(p) || !HASPT(p))
/* Now copy bytes between physical addresseses. */
if(!vm_running || (procs[_SRC_] == NULL && procs[_DST_] == NULL)) {
if(NOPT(procs[_SRC_]) && NOPT(procs[_DST_])) {
/* Without vm, address ranges actually are physical. */
phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes);
r = OK;

View file

@ -20,14 +20,14 @@ check_runqueues_f(char *file, int line)
{
int q, l = 0;
register struct proc *xp;
if(!intr_disabled()) {
minix_panic("check_runqueues called with interrupts enabled", NO_NUM);
}
#define MYPANIC(msg) { \
static char buf[100]; \
strcpy(buf, file); \
strcat(buf, ": "); \
util_nstrcat(buf, line);\
strcat(buf, ": "); \
strcat(buf, msg); \
minix_panic(buf, NO_NUM); \
kprintf("check_runqueues:%s:%d: %s\n", file, line, msg); \
minix_panic("check_runqueues failed", NO_NUM); \
}
for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
@ -49,14 +49,30 @@ check_runqueues_f(char *file, int line)
MYPANIC("scheduling error");
}
for(xp = rdy_head[q]; xp != NIL_PROC; xp = xp->p_nextready) {
vir_bytes vxp = (vir_bytes) xp, dxp;
if(vxp < (vir_bytes) BEG_PROC_ADDR || vxp >= (vir_bytes) END_PROC_ADDR) {
MYPANIC("xp out of range");
}
dxp = vxp - (vir_bytes) BEG_PROC_ADDR;
if(dxp % sizeof(struct proc)) {
MYPANIC("xp not a real pointer");
}
if(xp->p_magic != PMAGIC) {
MYPANIC("magic wrong in xp");
}
if (RTS_ISSET(xp, SLOT_FREE)) {
kprintf("scheduling error: dead proc q %d %d\n",
q, xp->p_endpoint);
MYPANIC("dead proc on run queue");
}
if (!xp->p_ready) {
kprintf("scheduling error: unready on runq %d proc %d\n",
q, xp->p_nr);
MYPANIC("found unready process on run queue");
}
if (xp->p_priority != q) {
kprintf("scheduling error: wrong priority q %d proc %d\n",
q, xp->p_nr);
kprintf("scheduling error: wrong priority q %d proc %d ep %d name %s\n",
q, xp->p_nr, xp->p_endpoint, xp->p_name);
MYPANIC("wrong priority");
}
if (xp->p_found) {
@ -76,6 +92,8 @@ check_runqueues_f(char *file, int line)
l = 0;
for (xp = BEG_PROC_ADDR; xp < END_PROC_ADDR; ++xp) {
if(xp->p_magic != PMAGIC)
MYPANIC("p_magic wrong in proc table");
if (! isemptyp(xp) && xp->p_ready && ! xp->p_found) {
kprintf("sched error: ready proc %d not on queue\n", xp->p_nr);
MYPANIC("ready proc not on scheduling queue");

View file

@ -21,8 +21,10 @@
*/
#define DEBUG_ENABLE_IPC_WARNINGS 1
#define DEBUG_STACKTRACE 1
#define DEBUG_VMASSERT 1
#define DEBUG_SCHED_CHECK 1
#define DEBUG_TIME_LOCKS 1
/* Runtime sanity checking. */
#define DEBUG_VMASSERT 0
#define DEBUG_SCHED_CHECK 0
#endif /* DEBUG_H */

View file

@ -43,6 +43,9 @@ PUBLIC void main()
*/
for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) {
rp->p_rts_flags = SLOT_FREE; /* initialize free slot */
#if DEBUG_SCHED_CHECK
rp->p_magic = PMAGIC;
#endif
rp->p_nr = i; /* proc number from ptr */
rp->p_endpoint = _ENDPOINT(0, rp->p_nr); /* generation no. 0 */
(pproc_addr + NR_TASKS)[i] = rp; /* proc ptr from number */
@ -67,6 +70,7 @@ PUBLIC void main()
for (i=0; i < NR_BOOT_PROCS; ++i) {
int ci;
bitchunk_t fv;
ip = &image[i]; /* process' attributes */
rp = proc_addr(ip->proc_nr); /* get process pointer */
ip->endpoint = rp->p_endpoint; /* ipc endpoint */
@ -164,8 +168,6 @@ PUBLIC void main()
/* Set ready. The HARDWARE task is never ready. */
if (rp->p_nr == HARDWARE) RTS_SET(rp, NO_PRIORITY);
RTS_UNSET(rp, SLOT_FREE); /* remove SLOT_FREE and schedule */
/* Code and data segments must be allocated in protected mode. */
alloc_segments(rp);
}

View file

@ -104,6 +104,8 @@ struct proc {
#if DEBUG_SCHED_CHECK
int p_ready, p_found;
#define PMAGIC 0xC0FFEE1
int p_magic; /* check validity of proc pointers */
#endif
};

View file

@ -48,7 +48,7 @@ PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
#define IDL_F (SYS_PROC | PREEMPTIBLE | BILLABLE) /* idle task */
#define TSK_F (SYS_PROC) /* kernel tasks */
#define SRV_F (SYS_PROC | PREEMPTIBLE) /* system services */
#define USR_F (BILLABLE | PREEMPTIBLE) /* user processes */
#define USR_F (BILLABLE | PREEMPTIBLE | PROC_FULLVM) /* user processes */
#define SVM_F (SRV_F | PROC_FULLVM) /* servers with VM */
/* Define system call traps for the various process types. These call masks
@ -117,13 +117,13 @@ PUBLIC struct boot_image image[] = {
{CLOCK,clock_task,TSK_F, 8, TASK_Q, TSK_S, TSK_T, 0, no_c,"clock" },
{SYSTEM, sys_task,TSK_F, 8, TASK_Q, TSK_S, TSK_T, 0, no_c,"system"},
{HARDWARE, 0,TSK_F, 8, TASK_Q, HRD_S, 0, 0, no_c,"kernel"},
{PM_PROC_NR, 0,SRV_F, 32, 4, 0, SRV_T, SRV_M, c(pm_c),"pm" },
{FS_PROC_NR, 0,SRV_F, 32, 5, 0, SRV_T, SRV_M, c(fs_c),"vfs" },
{RS_PROC_NR, 0,SRV_F, 4, 4, 0, SRV_T, SYS_M, c(rs_c),"rs" },
{DS_PROC_NR, 0,SRV_F, 4, 4, 0, SRV_T, SYS_M, c(ds_c),"ds" },
{TTY_PROC_NR, 0,SRV_F, 4, 1, 0, SRV_T, SYS_M,c(tty_c),"tty" },
{PM_PROC_NR, 0,SVM_F, 32, 4, 0, SRV_T, SRV_M, c(pm_c),"pm" },
{FS_PROC_NR, 0,SVM_F, 32, 5, 0, SRV_T, SRV_M, c(fs_c),"vfs" },
{RS_PROC_NR, 0,SVM_F, 4, 4, 0, SRV_T, SYS_M, c(rs_c),"rs" },
{DS_PROC_NR, 0,SVM_F, 4, 4, 0, SRV_T, SYS_M, c(ds_c),"ds" },
{TTY_PROC_NR, 0,SVM_F, 4, 1, 0, SRV_T, SYS_M,c(tty_c),"tty" },
{MEM_PROC_NR, 0,SVM_F, 4, 3, 0, SRV_T, SYS_M,c(mem_c),"memory"},
{LOG_PROC_NR, 0,SRV_F, 4, 2, 0, SRV_T, SYS_M,c(drv_c),"log" },
{LOG_PROC_NR, 0,SVM_F, 4, 2, 0, SRV_T, SYS_M,c(drv_c),"log" },
{MFS_PROC_NR, 0,SVM_F, 32, 5, 0, SRV_T, SRV_M, c(fs_c),"mfs" },
{VM_PROC_NR, 0,SRV_F, 32, 2, 0, SRV_T, SRV_M, c(vm_c),"vm" },
{INIT_PROC_NR, 0,USR_F, 8, USER_Q, 0, USR_T, USR_M, no_c,"init" },