From f16eb59bbf63fb600507cb59a3949353183499b5 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Fri, 29 May 2009 18:47:31 +0000 Subject: [PATCH] further messing with page fault handling --- kernel/arch/i386/exception.c | 48 ++++++++++++++++++++++++------------ kernel/arch/i386/memory.c | 28 ++------------------- kernel/arch/i386/mpx386.s | 8 ++++++ kernel/arch/i386/proto.h | 1 + kernel/proc.c | 6 ++--- kernel/system/do_vmctl.c | 7 ++++-- servers/vm/i386/vm.c | 8 +++--- 7 files changed, 56 insertions(+), 50 deletions(-) diff --git a/kernel/arch/i386/exception.c b/kernel/arch/i386/exception.c index 0e137755d..b28d7d03b 100755 --- a/kernel/arch/i386/exception.c +++ b/kernel/arch/i386/exception.c @@ -18,32 +18,48 @@ extern u32_t vm_copy_from_p, vm_copy_to_p, vm_copy_cr3; extern u32_t catchrange_lo, catchrange_hi; u32_t pagefault_cr2, pagefault_count = 0; +vir_bytes *old_eip_ptr = NULL, *old_eax_ptr = NULL; -void pagefault(struct proc *pr, int trap_errno) +void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno) { int s; vir_bytes ph; u32_t pte; + int procok = 0, pcok = 0, rangeok = 0; + + vmassert(old_eip_ptr); + vmassert(old_eax_ptr); + + vmassert(*old_eip_ptr == old_eip); + vmassert(old_eip_ptr != &old_eip); vmassert(pagefault_count == 1); - if((iskernelp(pr) || k_reenter) && catch_pagefaults - && (pr->p_reg.pc > (vir_bytes) _memcpy_k && - pr->p_reg.pc < (vir_bytes) _memcpy_k_fault) && - pagefault_cr2 >= catchrange_lo && - pagefault_cr2 < catchrange_hi) { - kprintf("handling pagefault during copy\n"); - pr->p_reg.pc = (vir_bytes) _memcpy_k_fault; - pr->p_reg.retreg = pagefault_cr2; - pagefault_count = 0; - return; + if(catch_pagefaults && + (rangeok = (pagefault_cr2 >= catchrange_lo && + pagefault_cr2 < catchrange_hi))) { + vir_bytes test_eip; + test_eip = k_reenter ? old_eip : pr->p_reg.pc; + if((pcok = ((test_eip > (vir_bytes) _memcpy_k) && + (test_eip < (vir_bytes) _memcpy_k_fault)))) { + kprintf("handling pagefault during copy\n"); + pagefault_count = 0; + + *old_eip_ptr = _memcpy_k_fault; + *old_eax_ptr = pagefault_cr2; + + return; + } } - proc_stacktrace(pr); + kprintf("kernel stacktrace in pagefault: "); + util_stacktrace(); if(catch_pagefaults) { - printf("k_reenter: %d addr: 0x%lx range: 0x%lx-0x%lx\n", - k_reenter, pagefault_cr2, catchrange_lo, catchrange_hi); + kprintf("procok: %d pcok: %d rangeok: %d\n", + procok, pcok, rangeok); + printf("k_reenter: %d addr: 0x%lx range: 0x%lx-0x%lx pc: 0x%lx\n", + k_reenter, pagefault_cr2, catchrange_lo, catchrange_hi, pr->p_reg.pc); } /* System processes that don't have their own page table can't @@ -150,7 +166,7 @@ struct proc *t; } if(vec_nr == PAGE_FAULT_VECTOR) { - pagefault(saved_proc, trap_errno); + pagefault(old_eip, saved_proc, trap_errno); return; } @@ -214,7 +230,7 @@ PUBLIC void proc_stacktrace(struct proc *proc) while(v_bp) { #define PRCOPY(pr, pv, v, n) \ - (iskernelp(pr) ? (memcpy(v, pv, n), OK) : \ + (iskernelp(pr) ? (memcpy((char *) v, (char *) pv, n), OK) : \ data_copy(pr->p_endpoint, pv, SYSTEM, (vir_bytes) (v), n)) if(PRCOPY(proc, v_bp, &v_hbp, sizeof(v_hbp)) != OK) { diff --git a/kernel/arch/i386/memory.c b/kernel/arch/i386/memory.c index c747932d6..ea725e3a7 100644 --- a/kernel/arch/i386/memory.c +++ b/kernel/arch/i386/memory.c @@ -723,7 +723,6 @@ u32_t read_cr3(void) kprintf("kernel: pde %d 0x%lx for proc %d\n", \ pde_index, pdeval, PROC->p_endpoint); \ } \ - if(copyverbose) { kprintf("installing pde val 0x%lx from pde index %d of proc %d into my pde\n", pdeval, pde_index, PROC->p_endpoint); } \ } else { \ pdeval = (LINADDR & I386_VM_ADDR_MASK_4MB) | \ I386_VM_BIGPAGE | I386_VM_PRESENT | \ @@ -745,7 +744,7 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc, int srcseg, struct proc *dstproc, vir_bytes dstlinaddr, u8_t *vdst, int dstseg, - vir_bytes bytes, int copyverbose) + vir_bytes bytes) { u32_t addr; int procslot; @@ -780,8 +779,6 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc, vir_bytes srcoffset, dstoffset; vir_bytes chunk = bytes; - FIXME("copyverbose"); - /* Set up 4MB ranges. */ CREATEPDE(srcproc, srcptr, srclinaddr, srcoffset, freepdes[FREEPDE_SRC], vsrc, srcseg, chunk, bytes); @@ -850,7 +847,6 @@ int vm_phys_memset(phys_bytes ph, u8_t c, phys_bytes bytes) vir_bytes chunk = bytes; u8_t *ptr; u32_t offset; - int copyverbose = 0; CREATEPDE(((struct proc *) NULL), ptr, ph, offset, freepdes[FREEPDE_MEMSET], 0, 0, chunk, bytes); /* We can memset as many bytes as we have remaining, @@ -957,20 +953,11 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ if(vm_running) { int r; struct proc *target, *caller; - int verbose = 0; - - if(procs[_SRC_] && procs[_DST_] && - procs[_SRC_]->p_endpoint == PM_PROC_NR && - (procs[_DST_]->p_endpoint == INIT_PROC_NR || - procs[_DST_]->p_endpoint == 35549) && - bytes == sizeof(message)) { - verbose = 1; - } if((r=lin_lin_copy(procs[_SRC_], phys_addr[_SRC_], (u8_t *) src_addr->offset, src_addr->segment, procs[_DST_], phys_addr[_DST_], (u8_t *) dst_addr->offset, - dst_addr->segment, bytes, verbose)) != OK) { + dst_addr->segment, bytes)) != OK) { if(r != EFAULT_SRC && r != EFAULT_DST) minix_panic("lin_lin_copy failed", r); if(!vmcheck) { @@ -1002,17 +989,6 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ NOREC_RETURN(virtualcopy, VMSUSPEND); } - if(verbose) { - static int count = 0; - message *m; - kprintf("lin_lin_copy: PM to %d: %d bytes copy OK\n", - procs[_DST_]->p_endpoint, bytes); - if(count++ < 10) { - vm_print(procs[_SRC_]->p_seg.p_cr3); - vm_print(procs[_DST_]->p_seg.p_cr3); - } - } - NOREC_RETURN(virtualcopy, OK); } diff --git a/kernel/arch/i386/mpx386.s b/kernel/arch/i386/mpx386.s index 844d93d87..61b849c8d 100755 --- a/kernel/arch/i386/mpx386.s +++ b/kernel/arch/i386/mpx386.s @@ -76,6 +76,8 @@ begbss: .define save .define _pagefault_cr2 .define _pagefault_count +.define _old_eip_ptr +.define _old_eax_ptr .define errexception .define exception1 @@ -524,10 +526,16 @@ errexception: sseg pop (ex_number) sseg pop (trap_errno) exception1: ! Common for all exceptions. + sseg mov (_old_eax_ptr), esp ! where will eax be saved? + sseg sub (_old_eax_ptr), PCREG-AXREG ! here + push eax ! eax is scratch register mov eax, 0+4(esp) ! old eip sseg mov (old_eip), eax + mov eax, esp + add eax, 4 + sseg mov (_old_eip_ptr), eax movzx eax, 4+4(esp) ! old cs sseg mov (old_cs), eax mov eax, 8+4(esp) ! old eflags diff --git a/kernel/arch/i386/proto.h b/kernel/arch/i386/proto.h index ccb90ff86..3c9a0f36a 100644 --- a/kernel/arch/i386/proto.h +++ b/kernel/arch/i386/proto.h @@ -76,6 +76,7 @@ _PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) ); _PROTOTYPE( void i386_invlpg_level0, (void) ); _PROTOTYPE( int _memcpy_k, (void *dst, void *src, size_t n) ); _PROTOTYPE( int _memcpy_k_fault, (void) ); +_PROTOTYPE( u32_t read_cr3, (void) ); /* protect.c */ _PROTOTYPE( void prot_init, (void) ); diff --git a/kernel/proc.c b/kernel/proc.c index 02b1ade1d..2fee24eac 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -87,17 +87,17 @@ FORWARD _PROTOTYPE( void pick_proc, (void)); kprintf("error %d\n", r); \ minix_panic("CopyMess: copy error", __LINE__); \ } \ - vm_suspend(dp, dp); \ + minix_panic("parameters unknown", NO_NUM); \ (dp)->p_vmrequest.saved.msgcopy.dst = (dp); \ (dp)->p_vmrequest.saved.msgcopy.dst_v = (vir_bytes) dm; \ + (dp)->p_vmrequest.saved.msgcopy.msgbuf.m_source = e; \ + (dp)->p_vmrequest.type = VMSTYPE_MSGCOPY; \ if(data_copy((sp)->p_endpoint, \ (vir_bytes) (sm), SYSTEM, \ (vir_bytes) &(dp)->p_vmrequest.saved.msgcopy.msgbuf, \ sizeof(message)) != OK) { \ minix_panic("CopyMess: data_copy failed", __LINE__);\ } \ - (dp)->p_vmrequest.saved.msgcopy.msgbuf.m_source = e; \ - (dp)->p_vmrequest.type = VMSTYPE_MSGCOPY; \ } #define CopyMess(s,sp,sm,dp,dm) do { \ diff --git a/kernel/system/do_vmctl.c b/kernel/system/do_vmctl.c index 9fa261827..fa2a30dfc 100644 --- a/kernel/system/do_vmctl.c +++ b/kernel/system/do_vmctl.c @@ -43,8 +43,11 @@ register message *m_ptr; /* pointer to request message */ if(!RTS_ISSET(rp, VMREQUEST)) minix_panic("do_vmctl: no VMREQUEST set", NO_NUM); - printf("kernel: vm request sent by: %s / %d about %d\n", - rp->p_name, rp->p_endpoint, rp->p_vmrequest.who); + printf("kernel: vm request sent by: %s / %d about %d; 0x%lx-0x%lx, wr %d\n", + rp->p_name, rp->p_endpoint, rp->p_vmrequest.who, + rp->p_vmrequest.start, + rp->p_vmrequest.start + rp->p_vmrequest.length, + rp->p_vmrequest.writeflag); /* Reply with request fields. */ m_ptr->SVMCTL_MRG_ADDR = (char *) rp->p_vmrequest.start; diff --git a/servers/vm/i386/vm.c b/servers/vm/i386/vm.c index 43d6db1c3..6ff14ddb3 100644 --- a/servers/vm/i386/vm.c +++ b/servers/vm/i386/vm.c @@ -30,11 +30,13 @@ *===========================================================================*/ PUBLIC vir_bytes arch_map2vir(struct vmproc *vmp, vir_bytes addr) { - vir_bytes bottom = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys); + vir_bytes textstart = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys); + vir_bytes datastart = CLICK2ABS(vmp->vm_arch.vm_seg[D].mem_phys); - vm_assert(bottom <= addr); + /* Could be a text address. */ + vm_assert(datastart <= addr || textstart <= addr); - return addr - bottom; + return addr - datastart; } /*===========================================================================* -- 2.44.0