From: Ben Gras Date: Wed, 3 Jun 2009 11:22:49 +0000 (+0000) Subject: state X-Git-Tag: v3.1.4~15 X-Git-Url: http://zhaoyanbai.com/repos/host.html?a=commitdiff_plain;h=eb2959a560968e57d1472bf1aaae47b90b49464b;p=minix.git state --- diff --git a/include/minix/com.h b/include/minix/com.h index 0c838685a..5e629aa99 100755 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -525,6 +525,7 @@ * and sys_fork */ #define PR_FORK_FLAGS m1_i3 +#define PR_FORK_MSGADDR m1_p1 /* Field names for SYS_INT86 */ #define INT86_REG86 m1_p1 /* pointer to registers */ diff --git a/include/minix/syslib.h b/include/minix/syslib.h index d4facdc2c..07b9975df 100755 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -35,7 +35,7 @@ _PROTOTYPE( int sys_enable_iop, (endpoint_t proc)); _PROTOTYPE( int sys_exec, (endpoint_t proc, char *ptr, char *aout, vir_bytes initpc)); _PROTOTYPE( int sys_fork, (endpoint_t parent, endpoint_t child, int *, - struct mem_map *ptr, u32_t vm)); + struct mem_map *ptr, u32_t vm, vir_bytes *)); _PROTOTYPE( int sys_newmap, (endpoint_t proc, struct mem_map *ptr)); _PROTOTYPE( int sys_exit, (endpoint_t proc)); _PROTOTYPE( int sys_trace, (int req, endpoint_t proc, long addr, long *data_p)); diff --git a/kernel/arch/i386/arch_do_vmctl.c b/kernel/arch/i386/arch_do_vmctl.c index 71a0469aa..5e0e9b350 100644 --- a/kernel/arch/i386/arch_do_vmctl.c +++ b/kernel/arch/i386/arch_do_vmctl.c @@ -53,22 +53,19 @@ struct proc *p; m_ptr->SVMCTL_PF_WHO = rp->p_endpoint; m_ptr->SVMCTL_PF_I386_CR2 = rp->p_pagefault.pf_virtual; m_ptr->SVMCTL_PF_I386_ERR = rp->p_pagefault.pf_flags; - printf("kernel: returning pagefault for %s / %d\n", - rp->p_name, rp->p_endpoint); return OK; } case VMCTL_I386_KERNELLIMIT: { + int r; /* VM wants kernel to increase its segment. */ - kprintf("kernel: increase limit to 0x%x\n", - m_ptr->SVMCTL_VALUE); - return prot_set_kern_seg_limit(m_ptr->SVMCTL_VALUE); + r = prot_set_kern_seg_limit(m_ptr->SVMCTL_VALUE); + return r; } case VMCTL_I386_PAGEDIRS: { int pde; vm_pagedirs = (u32_t *) m_ptr->SVMCTL_VALUE; - kprintf("kernel: pagedirs now 0x%lx\n", vm_pagedirs); return OK; } case VMCTL_I386_FREEPDE: @@ -83,6 +80,8 @@ struct proc *p; } } + + kprintf("arch_do_vmctl: strange param %d\n", m_ptr->SVMCTL_PARAM); return EINVAL; } diff --git a/kernel/arch/i386/do_sdevio.c b/kernel/arch/i386/do_sdevio.c index 1beefa499..2363a2c57 100644 --- a/kernel/arch/i386/do_sdevio.c +++ b/kernel/arch/i386/do_sdevio.c @@ -33,10 +33,6 @@ register message *m_ptr; /* pointer to request message */ struct priv *privp; struct io_range *iorp; - kprintf("kernel: no sdevio\n"); - return EIO; - -#if 0 /* Allow safe copies and accesses to SELF */ if ((m_ptr->DIO_REQUEST & _DIO_SAFEMASK) != _DIO_SAFE && proc_nr_e != SELF) @@ -85,6 +81,11 @@ register message *m_ptr; /* pointer to request message */ (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0) return(EFAULT); } + /* current process must be target for phys_* to be OK */ + if(proc_addr(proc_nr) != ptproc) { + kprintf("do_sdevio: wrong process\n"); + return EIO; + } switch (io_type) { @@ -145,7 +146,6 @@ register message *m_ptr; /* pointer to request message */ return(EINVAL); } return(OK); -#endif } #endif /* USE_SDEVIO */ diff --git a/kernel/arch/i386/exception.c b/kernel/arch/i386/exception.c index b28d7d03b..29ab505e2 100755 --- a/kernel/arch/i386/exception.c +++ b/kernel/arch/i386/exception.c @@ -10,12 +10,10 @@ #include #include #include "../../proc.h" +#include "../../proto.h" extern int vm_copy_in_progress, catch_pagefaults; extern struct proc *vm_copy_from, *vm_copy_to; -extern u32_t vm_copy_from_v, vm_copy_to_v; -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; @@ -26,6 +24,7 @@ void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno) vir_bytes ph; u32_t pte; int procok = 0, pcok = 0, rangeok = 0; + int in_memcpy = 0, in_physcopy = 0; vmassert(old_eip_ptr); vmassert(old_eax_ptr); @@ -35,33 +34,30 @@ void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno) vmassert(pagefault_count == 1); - if(catch_pagefaults && - (rangeok = (pagefault_cr2 >= catchrange_lo && - pagefault_cr2 < catchrange_hi))) { + if(catch_pagefaults) { 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"); + in_memcpy = (test_eip > (vir_bytes) _memcpy_k) && + (test_eip < (vir_bytes) _memcpy_k_fault); + in_physcopy = (test_eip > (vir_bytes) phys_copy) && + (test_eip < (vir_bytes) phys_copy_fault); + if((pcok = in_memcpy || in_physcopy)) { pagefault_count = 0; - *old_eip_ptr = _memcpy_k_fault; + if(in_memcpy) { + vmassert(!in_physcopy); + *old_eip_ptr = _memcpy_k_fault; + } + if(in_physcopy) { + vmassert(!in_memcpy); + *old_eip_ptr = phys_copy_fault; + } *old_eax_ptr = pagefault_cr2; return; } } - kprintf("kernel stacktrace in pagefault: "); - util_stacktrace(); - - if(catch_pagefaults) { - 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 * have page faults. VM does have its own page table but also * can't have page faults (because VM has to handle them). @@ -94,16 +90,11 @@ void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno) pr->p_pagefault.pf_flags = trap_errno; pr->p_nextpagefault = pagefaults; pagefaults = pr; - soft_notify(VM_PROC_NR); + + lock_notify(SYSTEM, VM_PROC_NR); pagefault_count = 0; -#if 0 - kprintf("pagefault for process %d ('%s'), pc = 0x%x\n", - pr->p_endpoint, pr->p_name, pr->p_reg.pc); - proc_stacktrace(pr); -#endif - return; } @@ -148,13 +139,6 @@ struct proc *t; 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; diff --git a/kernel/arch/i386/klib386.s b/kernel/arch/i386/klib386.s index fda2f3f39..18a602846 100755 --- a/kernel/arch/i386/klib386.s +++ b/kernel/arch/i386/klib386.s @@ -8,7 +8,6 @@ #include #include #include "../../const.h" -#include "vm.h" #include "sconst.h" ! This file contains a number of assembly code utility routines needed by the @@ -21,13 +20,14 @@ .define __exit ! dummy for library routines .define ___exit ! dummy for library routines .define ___main ! dummy for GCC -!.define _phys_insw ! transfer data from (disk controller) port to memory -!.define _phys_insb ! likewise byte by byte -!.define _phys_outsw ! transfer data from memory to (disk controller) port -!.define _phys_outsb ! likewise byte by byte +.define _phys_insw ! transfer data from (disk controller) port to memory +.define _phys_insb ! likewise byte by byte +.define _phys_outsw ! transfer data from memory to (disk controller) port +.define _phys_outsb ! likewise byte by byte .define _intr_unmask ! enable an irq at the 8259 controller .define _intr_mask ! disable an irq .define _phys_copy ! copy data from anywhere to anywhere in memory +.define _phys_copy_fault! phys_copy pagefault .define _phys_memset ! write pattern anywhere in memory .define _mem_rdw ! copy one word from [segment:offset] .define _reset ! reset the system @@ -35,9 +35,7 @@ .define _level0 ! call a function at level 0 .define _read_cpu_flags ! read the cpu flags .define _read_cr0 ! read cr0 -.define _write_cr3 ! write cr3 .define _getcr3val -.define _last_cr3 .define _write_cr0 ! write a value in cr0 .define _read_cr4 .define _thecr3 @@ -46,6 +44,7 @@ .define _i386_invlpg_level0 .define __memcpy_k .define __memcpy_k_fault +.define _catch_pagefaults ! The routines only guarantee to preserve the registers the C compiler ! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and @@ -183,52 +182,52 @@ ___main: !*===========================================================================* ! PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count); ! Input an array from an I/O port. Absolute address version of insw(). -! -!_phys_insw: -! push ebp -! mov ebp, esp -! cld -! push edi -! push es -! -! mov ecx, FLAT_DS_SELECTOR -! mov es, cx -! mov edx, 8(ebp) ! port to read from -! mov edi, 12(ebp) ! destination addr -! mov ecx, 16(ebp) ! byte count -! shr ecx, 1 ! word count -!rep o16 ins ! input many words -! pop es -! pop edi -! pop ebp -! ret -! + +_phys_insw: + push ebp + mov ebp, esp + cld + push edi + push es + + mov ecx, FLAT_DS_SELECTOR + mov es, cx + mov edx, 8(ebp) ! port to read from + mov edi, 12(ebp) ! destination addr + mov ecx, 16(ebp) ! byte count + shr ecx, 1 ! word count +rep o16 ins ! input many words + pop es + pop edi + pop ebp + ret + !*===========================================================================* !* phys_insb * !*===========================================================================* ! PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count); ! Input an array from an I/O port. Absolute address version of insb(). -! -!_phys_insb: -! push ebp -! mov ebp, esp -! cld -! push edi -! push es -! -! mov ecx, FLAT_DS_SELECTOR -! mov es, cx -! mov edx, 8(ebp) ! port to read from -! mov edi, 12(ebp) ! destination addr -! mov ecx, 16(ebp) ! byte count -!! shr ecx, 1 ! word count -! rep insb ! input many bytes -! pop es -! pop edi -! pop ebp -! ret -! + +_phys_insb: + push ebp + mov ebp, esp + cld + push edi + push es + + mov ecx, FLAT_DS_SELECTOR + mov es, cx + mov edx, 8(ebp) ! port to read from + mov edi, 12(ebp) ! destination addr + mov ecx, 16(ebp) ! byte count +! shr ecx, 1 ! word count + rep insb ! input many bytes + pop es + pop edi + pop ebp + ret + !*===========================================================================* !* phys_outsw * @@ -236,51 +235,51 @@ ___main: ! PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count); ! Output an array to an I/O port. Absolute address version of outsw(). -! .align 16 -!_phys_outsw: -! push ebp -! mov ebp, esp -! cld -! push esi -! push ds -! -! mov ecx, FLAT_DS_SELECTOR -! mov ds, cx -! mov edx, 8(ebp) ! port to write to -! mov esi, 12(ebp) ! source addr -! mov ecx, 16(ebp) ! byte count -! shr ecx, 1 ! word count -!rep o16 outs ! output many words -! pop ds -! pop esi -! pop ebp -! ret -! + .align 16 +_phys_outsw: + push ebp + mov ebp, esp + cld + push esi + push ds + + mov ecx, FLAT_DS_SELECTOR + mov ds, cx + mov edx, 8(ebp) ! port to write to + mov esi, 12(ebp) ! source addr + mov ecx, 16(ebp) ! byte count + shr ecx, 1 ! word count +rep o16 outs ! output many words + pop ds + pop esi + pop ebp + ret + !*===========================================================================* !* phys_outsb * !*===========================================================================* ! PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count); ! Output an array to an I/O port. Absolute address version of outsb(). -! -! .align 16 -!_phys_outsb: -! push ebp -! mov ebp, esp -! cld -! push esi -! push ds -! -! mov ecx, FLAT_DS_SELECTOR -! mov ds, cx -! mov edx, 8(ebp) ! port to write to -! mov esi, 12(ebp) ! source addr -! mov ecx, 16(ebp) ! byte count -! rep outsb ! output many bytes -! pop ds -! pop esi -! pop ebp -! ret + + .align 16 +_phys_outsb: + push ebp + mov ebp, esp + cld + push esi + push ds + + mov ecx, FLAT_DS_SELECTOR + mov ds, cx + mov edx, 8(ebp) ! port to write to + mov esi, 12(ebp) ! source addr + mov ecx, 16(ebp) ! byte count + rep outsb ! output many bytes + pop ds + pop esi + pop ebp + ret !*==========================================================================* @@ -363,7 +362,7 @@ dis_already: !*===========================================================================* !* phys_copy * !*===========================================================================* -! PUBLIC void phys_copy(phys_bytes source, phys_bytes destination, +! PUBLIC phys_bytes phys_copy(phys_bytes source, phys_bytes destination, ! phys_bytes bytecount); ! Copy a block of physical memory. @@ -384,6 +383,8 @@ _phys_copy: mov edi, PC_ARGS+4(esp) mov eax, PC_ARGS+4+4(esp) + mov (_catch_pagefaults), 1 + cmp eax, 10 ! avoid align overhead for small counts jb pc_small mov ecx, esi ! align source, hope target is too @@ -405,6 +406,9 @@ pc_small: pop es pop edi pop esi + mov eax, 0 ! 0 means: no fault +_phys_copy_fault: ! kernel can send us here + mov (_catch_pagefaults), 0 ret !*===========================================================================* @@ -576,17 +580,6 @@ _write_cr4: pop ebp ret -!*===========================================================================* -!* write_cr3 * -!*===========================================================================* -! PUBLIC void write_cr3(unsigned long value); -_write_cr3: - push ebp - mov ebp, esp - mov eax, 8(ebp) - mov cr3, eax - pop ebp - ret !*===========================================================================* !* getcr3val * @@ -602,9 +595,8 @@ _getcr3val: !*===========================================================================* ! PUBLIC void i386_invlpg(void); _i386_invlpg_level0: - push ebp - invlpg (_i386_invlpg_addr) - pop ebp + mov eax, (_i386_invlpg_addr) + invlpg (eax) ret diff --git a/kernel/arch/i386/memory.c b/kernel/arch/i386/memory.c index ea725e3a7..44896b90f 100644 --- a/kernel/arch/i386/memory.c +++ b/kernel/arch/i386/memory.c @@ -23,22 +23,14 @@ PRIVATE int psok = 0; +extern u32_t createpde, linlincopies, physzero; + #define PROCPDEPTR(pr, pi) ((u32_t *) ((u8_t *) vm_pagedirs +\ I386_PAGE_SIZE * pr->p_nr + \ I386_VM_PT_ENT_SIZE * pi)) /* Signal to exception handler that pagefaults can happen. */ int catch_pagefaults = 0; -u32_t catchrange_lo = 0; -u32_t catchrange_hi = 0; - -#if 0 -/* VM functions and data. */ -PUBLIC u32_t kernel_cr3; -#endif - -extern u32_t cswitch; -u32_t last_cr3 = 0; u8_t *vm_pagedirs = NULL; @@ -70,11 +62,6 @@ PUBLIC void vm_init(struct proc *newptproc) ptproc->p_seg.p_cr3); vmassert(newcr3); - kprintf("vm_init thinks cr3 0x%lx is loaded, proc %d, cr3 0x%lx, actual cr3 0x%lx\n", - last_cr3, ptproc->p_endpoint, ptproc->p_seg.p_cr3, read_cr3()); - - kprintf("vm_init: writing cr3 0x%lx\n", newcr3); - /* Set this cr3 now (not active until paging enabled). */ vm_set_cr3(newcr3); @@ -93,15 +80,6 @@ PUBLIC void vm_init(struct proc *newptproc) kprintf("vm_init done\n"); } -#if 0 -PRIVATE void phys_put32(addr, value) -phys_bytes addr; -u32_t value; -{ - phys_copy(vir2phys((vir_bytes)&value), addr, sizeof(value)); -} -#endif - PRIVATE u32_t phys_get32(addr) phys_bytes addr; { @@ -179,9 +157,6 @@ PRIVATE void vm_enable_paging(void) cr0= read_cr0(); cr4= read_cr4(); - kprintf("vm_enable_paging: cr0: %s cr4: %s; want to disable\n", - cr0_str(cr0), cr4_str(cr4)); - /* First clear PG and PGE flag, as PGE must be enabled after PG. */ write_cr0(cr0 & ~I386_CR0_PG); write_cr4(cr4 & ~(I386_CR4_PGE | I386_CR4_PSE)); @@ -189,9 +164,6 @@ PRIVATE void vm_enable_paging(void) cr0= read_cr0(); cr4= read_cr4(); - kprintf("vm_enable_paging: cr0: %s cr4: %s after disabling\n", - cr0_str(cr0), cr4_str(cr4)); - /* Our first page table contains 4MB entries. */ if(psok) cr4 |= I386_CR4_PSE; @@ -199,21 +171,15 @@ PRIVATE void vm_enable_paging(void) write_cr4(cr4); /* First enable paging, then enable global page flag. */ - kprintf("vm_enable_paging: write PG\n"); cr0 |= I386_CR0_PG; write_cr0(cr0 ); - kprintf("vm_enable_paging: writing WP\n"); cr0 |= I386_CR0_WP; write_cr0(cr0); - kprintf("vm_enable_paging: write WP done\n"); /* May we enable these features? */ if(pgeok) cr4 |= I386_CR4_PGE; - kprintf("vm_enable_paging: write cr4 0x%lx\n", cr4); - write_cr4(cr4); - kprintf("vm_enable_paging: write cr4 0x%lx done\n", cr4); write_cr4(cr4); } @@ -510,9 +476,8 @@ PUBLIC int vm_suspend(struct proc *caller, struct proc *target) /* Connect caller on vmrequest wait queue. */ caller->p_vmrequest.nextrequestor = vmrequest; vmrequest = caller; - if(!caller->p_vmrequest.nextrequestor) { - soft_notify(VM_PROC_NR); - } + if(!caller->p_vmrequest.nextrequestor) + lock_notify(SYSTEM, VM_PROC_NR); } /*===========================================================================* @@ -670,11 +635,7 @@ void invlpg_range(u32_t lin, u32_t bytes) limit = lin + bytes - 1; o = lin % I386_PAGE_SIZE; lin -= o; - limit += o; - limit &= I386_VM_PT_ENT_MASK; - FIXME("invlpg_range reloads cr3"); - cr3 = read_cr3(); - vm_set_cr3(cr3); + limit = (limit + o) & I386_VM_ADDR_MASK; for(i386_invlpg_addr = lin; i386_invlpg_addr <= limit; i386_invlpg_addr += I386_PAGE_SIZE) level0(i386_invlpg_level0); @@ -700,10 +661,12 @@ u32_t read_cr3(void) * It needs FREEPDE (available and addressable PDE within kernel * address space), SEG (hardware segment), VIRT (in-datasegment * address if known). - * - * TODO: don't re-make a pde that's already there. */ #define CREATEPDE(PROC, PTR, LINADDR, OFFSET, FREEPDE, VIRT, SEG, REMAIN, BYTES) { \ + FIXME("CREATEPDE: check if invlpg is necessary"); \ + if(PROC == ptproc) { \ + FIXME("CREATEPDE: use in-memory process"); \ + } \ if((PROC) && iskernelp(PROC) && SEG == D) { \ PTR = VIRT; \ OFFSET = 0; \ @@ -713,16 +676,13 @@ u32_t read_cr3(void) vmassert(psok); \ pde_index = I386_VM_PDE(LINADDR); \ vmassert(!iskernelp(PROC)); \ + createpde++; \ if(PROC) { \ u32_t *pdeptr; \ vmassert(!iskernelp(PROC)); \ vmassert(HASPT(PROC)); \ pdeptr = PROCPDEPTR(PROC, pde_index); \ pdeval = *pdeptr; \ - if(!(pdeval & I386_VM_PRESENT)) { \ - kprintf("kernel: pde %d 0x%lx for proc %d\n", \ - pde_index, pdeval, PROC->p_endpoint); \ - } \ } else { \ pdeval = (LINADDR & I386_VM_ADDR_MASK_4MB) | \ I386_VM_BIGPAGE | I386_VM_PRESENT | \ @@ -737,6 +697,20 @@ u32_t read_cr3(void) } \ } + +/*===========================================================================* + * arch_switch_copymsg * + *===========================================================================*/ +phys_bytes arch_switch_copymsg(struct proc *rp, message *m, phys_bytes lin) +{ + phys_bytes r; + if(rp->p_seg.p_cr3) { + vm_set_cr3(rp->p_seg.p_cr3); + ptproc = rp; + } + r = phys_copy(vir2phys(m), lin, sizeof(message)); +} + /*===========================================================================* * lin_lin_copy * *===========================================================================*/ @@ -748,9 +722,11 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc, { u32_t addr; int procslot; - u32_t catchrange_dst; + u32_t catchrange_dst, catchrange_lo, catchrange_hi; NOREC_ENTER(linlincopy); + linlincopies++; + if(srcproc && dstproc && iskernelp(srcproc) && iskernelp(dstproc)) { memcpy(vdst, vsrc, bytes); NOREC_RETURN(linlincopy, OK); @@ -795,14 +771,10 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc, catch_pagefaults = 0; if(addr) { - kprintf("kernel: lin_lin copy: returning EFAULT, addr 0x%lx\n", - addr); if(addr >= catchrange_lo && addr < catchrange_dst) { - kprintf("src\n"); NOREC_RETURN(linlincopy, EFAULT_SRC); } if(addr >= catchrange_dst && addr < catchrange_hi) { - kprintf("dst\n"); NOREC_RETURN(linlincopy, EFAULT_DST); } minix_panic("lin_lin_copy fault out of range", NO_NUM); @@ -831,6 +803,8 @@ int vm_phys_memset(phys_bytes ph, u8_t c, phys_bytes bytes) { char *v; + physzero++; + if(!vm_running) { u32_t p; p = c | (c << 8) | (c << 16) | (c << 24); @@ -857,6 +831,7 @@ int vm_phys_memset(phys_bytes ph, u8_t c, phys_bytes bytes) ph += chunk; } + return OK; } @@ -966,8 +941,7 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ caller = proc_addr(who_p); - printf("virtual_copy: suspending caller %d / %s\n", - caller->p_endpoint, caller->p_name); + vmassert(procs[_SRC_] && procs[_DST_]); if(r == EFAULT_SRC) { caller->p_vmrequest.start = phys_addr[_SRC_]; @@ -981,6 +955,12 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */ minix_panic("r strange", r); } +#if 0 + printf("virtual_copy: suspending caller %d / %s, target %d / %s\n", + caller->p_endpoint, caller->p_name, + target->p_endpoint, target->p_name); +#endif + caller->p_vmrequest.length = bytes; caller->p_vmrequest.who = target->p_endpoint; @@ -1068,5 +1048,4 @@ void i386_freepde(int pde) if(nfreepdes >= WANT_FREEPDES) return; freepdes[nfreepdes++] = pde; - printf("kernel: free pde: %d\n", pde); } diff --git a/kernel/arch/i386/mpx386.s b/kernel/arch/i386/mpx386.s index 61b849c8d..241df7330 100755 --- a/kernel/arch/i386/mpx386.s +++ b/kernel/arch/i386/mpx386.s @@ -60,7 +60,6 @@ begbss: #include #include #include "../../const.h" -#include "vm.h" #include "sconst.h" /* Selected 386 tss offsets. */ @@ -78,6 +77,9 @@ begbss: .define _pagefault_count .define _old_eip_ptr .define _old_eax_ptr +.define _cr3_test +.define _cr3_reload +.define _write_cr3 ! write cr3 .define errexception .define exception1 @@ -411,13 +413,15 @@ _restart: mov (_next_ptr), 0 0: mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0 lldt P_LDT_SEL(esp) ! enable process' segment descriptors + inc (_cr3_test) cmp P_CR3(esp), 0 ! process does not have its own PT jz noload mov eax, P_CR3(esp) - mov ebx, cr3 - cmp eax, ebx + cmp eax, (loadedcr3) jz noload + inc (_cr3_reload) mov cr3, eax + mov (loadedcr3), eax mov eax, (_proc_ptr) mov (_ptproc), eax noload: @@ -553,6 +557,20 @@ exception1: ! Common for all exceptions. add esp, 5*4 ret + +!*===========================================================================* +!* write_cr3 * +!*===========================================================================* +! PUBLIC void write_cr3(unsigned long value); +_write_cr3: + push ebp + mov ebp, esp + mov eax, 8(ebp) + mov cr3, eax + mov (loadedcr3), eax + pop ebp + ret + !*===========================================================================* !* level0_call * !*===========================================================================* @@ -576,4 +594,5 @@ k_stktop: ! top of kernel stack .comm old_eip, 4 .comm old_cs, 4 .comm old_eflags, 4 + .comm loadedcr3, 4 diff --git a/kernel/arch/i386/protect.c b/kernel/arch/i386/protect.c index 8e2408ee7..0d13d89e3 100755 --- a/kernel/arch/i386/protect.c +++ b/kernel/arch/i386/protect.c @@ -340,40 +340,25 @@ PUBLIC int prot_set_kern_seg_limit(vir_bytes limit) int orig_click; int incr_clicks; - kprintf("prot_set_kern_seg_limit: limit 0x%lx\n", limit); - if(limit <= kinfo.data_base) { kprintf("prot_set_kern_seg_limit: limit bogus\n"); return EINVAL; } - kprintf("size: 0x%lx -> ", kinfo.data_size); - /* Do actual increase. */ orig_click = kinfo.data_size / CLICK_SIZE; kinfo.data_size = limit - kinfo.data_base; incr_clicks = kinfo.data_size / CLICK_SIZE - orig_click; - kprintf("0x%lx\n", kinfo.data_size); - - kprintf("prot_set_kern_seg_limit: prot_init\n"); - prot_init(); - kprintf("prot_set_kern_seg_limit: prot_init done\n"); - /* Increase kernel processes too. */ for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; ++rp) { if (RTS_ISSET(rp, SLOT_FREE) || !iskernelp(rp)) continue; - kprintf("prot_set_kern_seg_limit: increase %d 0x%x ->\n", - rp->p_endpoint, rp->p_memmap[S].mem_len); rp->p_memmap[S].mem_len += incr_clicks; alloc_segments(rp); - kprintf("prot_set_kern_seg_limit: increase %d done -> 0x%x\n", - rp->p_endpoint, rp->p_memmap[S].mem_len); } - kprintf("prot_set_kern_seg_limit: done\n"); return OK; } diff --git a/kernel/arch/i386/system.c b/kernel/arch/i386/system.c index ca3fae394..a04cdd6fb 100644 --- a/kernel/arch/i386/system.c +++ b/kernel/arch/i386/system.c @@ -166,11 +166,12 @@ PRIVATE void printslot(struct proc *pp) level++; - kprintf("%*s %d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s ", + kprintf("%*s %d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s misc %s ", level, "", proc_nr(pp), pp->p_name, pp->p_endpoint, pp->p_priority, pp->p_max_priority, pp->p_user_time, - pp->p_sys_time, pp->p_seg.p_cr3, rtsflagstr(pp->p_rts_flags)); + pp->p_sys_time, pp->p_seg.p_cr3, + rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags)); if(pp->p_rts_flags & SENDING) { dep = pp->p_sendto_e; diff --git a/kernel/debug.c b/kernel/debug.c index 13a001dd7..9e4c78d46 100644 --- a/kernel/debug.c +++ b/kernel/debug.c @@ -25,6 +25,8 @@ check_runqueues_f(char *file, int line) minix_panic("check_runqueues called with interrupts enabled", NO_NUM); } + FIXME("check_runqueues being done"); + #define MYPANIC(msg) { \ kprintf("check_runqueues:%s:%d: %s\n", file, line, msg); \ minix_panic("check_runqueues failed", NO_NUM); \ @@ -128,3 +130,17 @@ rtsflagstr(int flags) return str; } +PUBLIC char * +miscflagstr(int flags) +{ + static char str[100]; + str[0] = '\0'; + + FLAG(MF_REPLY_PEND); + FLAG(MF_ASYNMSG); + FLAG(MF_FULLVM); + FLAG(MF_DELIVERMSG); + + return str; +} + diff --git a/kernel/debug.h b/kernel/debug.h index df6790cb9..67adacb26 100644 --- a/kernel/debug.h +++ b/kernel/debug.h @@ -25,8 +25,8 @@ #define DEBUG_TIME_LOCKS 1 /* Runtime sanity checking. */ -#define DEBUG_VMASSERT 1 -#define DEBUG_SCHED_CHECK 1 +#define DEBUG_VMASSERT 0 +#define DEBUG_SCHED_CHECK 0 #define NOREC_ENTER(varname) \ static int varname = 0; \ @@ -48,9 +48,9 @@ return v; \ } while(0) - #if DEBUG_VMASSERT #define vmassert(t) { \ + FIXME("vmassert on"); \ if(!(t)) { minix_panic("vm: assert " #t " failed\n", __LINE__); } } #else #define vmassert(t) { } diff --git a/kernel/glo.h b/kernel/glo.h index b7c1a19eb..db6706219 100755 --- a/kernel/glo.h +++ b/kernel/glo.h @@ -36,7 +36,6 @@ EXTERN struct proc *bill_ptr; /* process to bill for clock ticks */ EXTERN struct proc *vmrestart; /* first process on vmrestart queue */ EXTERN struct proc *vmrequest; /* first process on vmrequest queue */ EXTERN struct proc *pagefaults; /* first process on pagefault queue */ -EXTERN struct proc *softnotify; /* first process on softnotify queue */ EXTERN char k_reenter; /* kernel reentry count (entry count less 1) */ EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */ diff --git a/kernel/main.c b/kernel/main.c index 18b510d48..8ff9e1f70 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -195,6 +195,9 @@ PUBLIC void main() #endif #if DEBUG_VMASSERT FIXME("DEBUG_VMASSERT enabled"); +#endif +#if DEBUG_PROC_CHECK + FIXME("PROC check enabled"); #endif restart(); } diff --git a/kernel/proc.c b/kernel/proc.c index 2fee24eac..8009b5be6 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -67,8 +67,7 @@ FORWARD _PROTOTYPE( int try_one, (struct proc *src_ptr, struct proc *dst_ptr)); FORWARD _PROTOTYPE( void sched, (struct proc *rp, int *queue, int *front)); FORWARD _PROTOTYPE( void pick_proc, (void)); -#define BuildMess(m_ptr, src, dst_ptr) \ - (m_ptr)->m_source = proc_addr(src)->p_endpoint; \ +#define BuildNotifyMessage(m_ptr, src, dst_ptr) \ (m_ptr)->m_type = NOTIFY_FROM(src); \ (m_ptr)->NOTIFY_TIMESTAMP = get_uptime(); \ switch (src) { \ @@ -82,43 +81,41 @@ FORWARD _PROTOTYPE( void pick_proc, (void)); break; \ } -#define RETRYCOPY(sp, dp, sm, dm) {\ - if(r != EFAULT_DST) { \ - kprintf("error %d\n", r); \ - minix_panic("CopyMess: copy error", __LINE__); \ - } \ - 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__);\ - } \ +#define Deliver(rp) do { \ + vmassert(rp->p_misc_flags & MF_DELIVERMSG); \ + vmassert(rp->p_delivermsg_lin); \ + if(arch_switch_copymsg(rp, &rp->p_delivermsg, \ + rp->p_delivermsg_lin)) { \ + minix_panic("MF_DELIVERMSG copy failed", NO_NUM); \ + } \ + rp->p_delivermsg.m_source = NONE; \ + rp->p_delivermsg_lin = 0; \ + rp->p_misc_flags &= ~MF_DELIVERMSG; \ + } while(0) + +/*===========================================================================* + * QueueMess * + *===========================================================================*/ +PRIVATE int QueueMess(endpoint_t ep, vir_bytes msg_lin, struct proc *dst) +{ + /* Queue a message from the src process (in memory) to the dst + * process (using dst process table entry). Do actual copy here; + * it's an error if the copy fails. + */ + vmassert(!(dst->p_misc_flags & MF_DELIVERMSG)); + vmassert(dst->p_delivermsg_lin); + if(phys_copy(msg_lin, vir2phys(&dst->p_delivermsg), + sizeof(message))) { + return EFAULT; + } + dst->p_delivermsg.m_source = ep; + dst->p_misc_flags |= MF_DELIVERMSG; + if(iskernelp(dst) || ptproc == dst) { + Deliver(dst); } -#define CopyMess(s,sp,sm,dp,dm) do { \ - endpoint_t e = proc_addr(s)->p_endpoint; \ - struct vir_addr src, dst; \ - int r; \ - src.proc_nr_e = (sp)->p_endpoint; \ - dst.proc_nr_e = (dp)->p_endpoint; \ - src.segment = dst.segment = D; \ - src.offset = (vir_bytes) (sm); \ - dst.offset = (vir_bytes) (dm); \ - if((r=virtual_copy(&src, &dst, sizeof(message))) != OK) { \ - RETRYCOPY(sp, dp, sm, dm) \ - } else { \ - src.proc_nr_e = SYSTEM; \ - src.offset = (vir_bytes) &e; \ - if((r=virtual_copy(&src, &dst, sizeof(e))) != OK) { \ - RETRYCOPY(sp, dp, sm, dm) \ - } \ - } \ -} while(0) + return OK; +} /*===========================================================================* * sys_call * @@ -139,6 +136,15 @@ long bit_map; /* notification event set or flags */ int result; /* the system call's result */ int src_dst_p; /* Process slot number */ size_t msg_size; + phys_bytes linaddr = 0; + +#if DEBUG_SCHED_CHECK + if(caller_ptr->p_misc_flags & MF_DELIVERMSG) { + kprintf("sys_call: MF_DELIVERMSG on for %s / %d\n", + caller_ptr->p_name, caller_ptr->p_endpoint); + minix_panic("MF_DELIVERMSG on", NO_NUM); + } +#endif if (caller_ptr->p_endpoint == ipc_stats_target) ipc_stats.total= add64u(ipc_stats.total, 1); @@ -157,7 +163,7 @@ long bit_map; /* notification event set or flags */ } #endif -#if 1 +#if DEBUG_SCHED_CHECK if (RTS_ISSET(caller_ptr, SLOT_FREE)) { kprintf("called by the dead?!?\n"); @@ -239,7 +245,7 @@ long bit_map; /* notification event set or flags */ #if DEBUG_ENABLE_IPC_WARNINGS kprintf( "sys_call: ipc mask denied trap %d from %d to %d\n", - call_nr, proc_nr(caller_ptr), src_dst_p); + call_nr, caller_ptr->p_endpoint, src_dst_e); #endif if (caller_ptr->p_endpoint == ipc_stats_target) ipc_stats.dst_not_allowed++; @@ -301,61 +307,6 @@ long bit_map; /* notification event set or flags */ msg_size = sizeof(*m_ptr); } - /* If the call involves a message buffer, i.e., for SEND, SENDREC, - * or RECEIVE, check the message pointer. This check allows a message to be - * anywhere in data or stack or gap. It will have to be made more elaborate - * for machines which don't have the gap mapped. - * - * We use msg_size decided above. - */ - if (call_nr == SEND || call_nr == SENDREC || - call_nr == RECEIVE || call_nr == SENDA || call_nr == SENDNB) { - int r; - phys_bytes lin; - - /* Map to linear address. */ - if(msg_size > 0 && - (lin = umap_local(caller_ptr, D, (vir_bytes) m_ptr, msg_size)) == 0) { - kprintf("umap_local failed for %s / %d on 0x%lx size %d\n", - caller_ptr->p_name, caller_ptr->p_endpoint, - m_ptr, msg_size); - return EFAULT; - } - - /* Check if message pages in calling process are mapped. - * We don't have to check the recipient if this is a send, - * because this code will do that before its receive() starts. - * - * It is important the range is verified as _writable_, because - * the kernel will want to write to the SENDA buffer in the future, - * and those pages may not be shared between processes. - */ - - if(vm_running && msg_size > 0 && - (r=vm_checkrange(caller_ptr, caller_ptr, lin, msg_size, 1, 0)) != OK) { - if(r != VMSUSPEND) { - kprintf("SYSTEM:sys_call:vm_checkrange: err %d\n", r); - return r; - } - - /* We can't go ahead with this call. Caller is suspended - * and we have to save the state in its process struct. - */ - caller_ptr->p_vmrequest.saved.sys_call.call_nr = call_nr; - caller_ptr->p_vmrequest.saved.sys_call.m_ptr = m_ptr; - caller_ptr->p_vmrequest.saved.sys_call.src_dst_e = src_dst_e; - caller_ptr->p_vmrequest.saved.sys_call.bit_map = bit_map; - caller_ptr->p_vmrequest.type = VMSTYPE_SYS_CALL; - - kprintf("SYSTEM: %s:%d: suspending call 0x%lx on ipc buffer 0x%lx length 0x%lx\n", - caller_ptr->p_name, caller_ptr->p_endpoint, call_nr, m_ptr, msg_size); - - /* vm_checkrange() will have suspended caller with VMREQUEST. */ - return OK; - } - - } - /* Check for a possible deadlock for blocking SEND(REC) and RECEIVE. */ if (call_nr == SEND || call_nr == SENDREC || call_nr == RECEIVE) { if (group_size = deadlock(call_nr, caller_ptr, src_dst_p)) { @@ -380,7 +331,7 @@ long bit_map; /* notification event set or flags */ switch(call_nr) { case SENDREC: /* A flag is set so that notifications cannot interrupt SENDREC. */ - caller_ptr->p_misc_flags |= REPLY_PENDING; + caller_ptr->p_misc_flags |= MF_REPLY_PEND; /* fall through */ case SEND: result = mini_send(caller_ptr, src_dst_e, m_ptr, 0); @@ -389,7 +340,7 @@ long bit_map; /* notification event set or flags */ /* fall through for SENDREC */ case RECEIVE: if (call_nr == RECEIVE) - caller_ptr->p_misc_flags &= ~REPLY_PENDING; + caller_ptr->p_misc_flags &= ~MF_REPLY_PEND; result = mini_receive(caller_ptr, src_dst_e, m_ptr, 0); break; case NOTIFY: @@ -478,22 +429,6 @@ int src_dst; /* src or dst process */ return(0); /* not a deadlock */ } -/*===========================================================================* - * sys_call_restart * - *===========================================================================*/ -PUBLIC void sys_call_restart(caller) -struct proc *caller; -{ - int r; - kprintf("restarting sys_call code 0x%lx, " - "m_ptr 0x%lx, srcdst %d, bitmap 0x%lx, but not really\n", - caller->p_vmrequest.saved.sys_call.call_nr, - caller->p_vmrequest.saved.sys_call.m_ptr, - caller->p_vmrequest.saved.sys_call.src_dst_e, - caller->p_vmrequest.saved.sys_call.bit_map); - caller->p_reg.retreg = r; -} - /*===========================================================================* * mini_send * *===========================================================================*/ @@ -510,7 +445,13 @@ int flags; register struct proc *dst_ptr; register struct proc **xpp; int dst_p; + phys_bytes linaddr; + int r; + if(!(linaddr = umap_local(caller_ptr, D, (vir_bytes) m_ptr, + sizeof(message)))) { + return EFAULT; + } dst_p = _ENDPOINT_P(dst_e); dst_ptr = proc_addr(dst_p); @@ -526,8 +467,9 @@ int flags; */ if (WILLRECEIVE(dst_ptr, caller_ptr->p_endpoint)) { /* Destination is indeed waiting for this message. */ - CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr, - dst_ptr->p_messbuf); + vmassert(!(dst_ptr->p_misc_flags & MF_DELIVERMSG)); + if((r=QueueMess(caller_ptr->p_endpoint, linaddr, dst_ptr)) != OK) + return r; RTS_UNSET(dst_ptr, RECEIVING); } else { if(flags & NON_BLOCKING) { @@ -537,7 +479,9 @@ int flags; } /* Destination is not waiting. Block and dequeue caller. */ - caller_ptr->p_messbuf = m_ptr; + if(phys_copy(linaddr, vir2phys(&caller_ptr->p_sendmsg), sizeof(message))) { + return EFAULT; + } RTS_SET(caller_ptr, SENDING); caller_ptr->p_sendto_e = dst_e; @@ -570,6 +514,17 @@ int flags; sys_map_t *map; bitchunk_t *chunk; int i, r, src_id, src_proc_nr, src_p; + phys_bytes linaddr; + + vmassert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG)); + + if(!(linaddr = umap_local(caller_ptr, D, (vir_bytes) m_ptr, + sizeof(message)))) { + return EFAULT; + } + + /* This is where we want our message. */ + caller_ptr->p_delivermsg_lin = linaddr; if(src_e == ANY) src_p = ANY; else @@ -591,7 +546,7 @@ int flags; if (!RTS_ISSET(caller_ptr, SENDING)) { /* Check if there are pending notifications, except for SENDREC. */ - if (! (caller_ptr->p_misc_flags & REPLY_PENDING)) { + if (! (caller_ptr->p_misc_flags & MF_REPLY_PEND)) { map = &priv(caller_ptr)->s_notify_pending; for (chunk=&map->chunk[0]; chunk<&map->chunk[NR_SYS_CHUNKS]; chunk++) { @@ -611,8 +566,11 @@ int flags; *chunk &= ~(1 << i); /* no longer pending */ /* Found a suitable source, deliver the notification message. */ - BuildMess(&m, src_proc_nr, caller_ptr); /* assemble message */ - CopyMess(src_proc_nr, proc_addr(HARDWARE), &m, caller_ptr, m_ptr); + BuildNotifyMessage(&m, src_proc_nr, caller_ptr); /* assemble message */ + vmassert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG)); + if((r=QueueMess(src_proc_nr, vir2phys(&m), caller_ptr)) != OK) { + minix_panic("mini_receive: local QueueMess failed", NO_NUM); + } return(OK); /* report success */ } } @@ -621,7 +579,7 @@ int flags; xpp = &caller_ptr->p_caller_q; while (*xpp != NIL_PROC) { if (src_e == ANY || src_p == proc_nr(*xpp)) { -#if 1 +#if DEBUG_SCHED_CHECK if (RTS_ISSET(*xpp, SLOT_FREE) || RTS_ISSET(*xpp, NO_ENDPOINT)) { kprintf("%d: receive from %d; found dead %d (%s)?\n", @@ -634,7 +592,10 @@ int flags; #endif /* Found acceptable message. Copy it and update status. */ - CopyMess((*xpp)->p_nr, *xpp, (*xpp)->p_messbuf, caller_ptr, m_ptr); + FIXME("message copied twice here"); + vmassert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG)); + QueueMess((*xpp)->p_endpoint, + vir2phys(&(*xpp)->p_sendmsg), caller_ptr); RTS_UNSET(*xpp, SENDING); *xpp = (*xpp)->p_q_link; /* remove from queue */ return(OK); /* report success */ @@ -653,7 +614,6 @@ int flags; } else { - caller_ptr->p_messbuf = m_ptr; r= try_async(caller_ptr); } if (r == OK) @@ -666,7 +626,6 @@ int flags; */ if ( ! (flags & NON_BLOCKING)) { caller_ptr->p_getfrom_e = src_e; - caller_ptr->p_messbuf = m_ptr; RTS_SET(caller_ptr, RECEIVING); return(OK); } else { @@ -686,19 +645,22 @@ int dst; /* which process to notify */ register struct proc *dst_ptr = proc_addr(dst); int src_id; /* source id for late delivery */ message m; /* the notification message */ + int r; /* Check to see if target is blocked waiting for this message. A process * can be both sending and receiving during a SENDREC system call. */ if (WILLRECEIVE(dst_ptr, caller_ptr->p_endpoint) && - ! (dst_ptr->p_misc_flags & REPLY_PENDING)) { + ! (dst_ptr->p_misc_flags & MF_REPLY_PEND)) { /* Destination is indeed waiting for a message. Assemble a notification * message and deliver it. Copy from pseudo-source HARDWARE, since the * message is in the kernel's address space. */ - BuildMess(&m, proc_nr(caller_ptr), dst_ptr); - CopyMess(proc_nr(caller_ptr), proc_addr(HARDWARE), &m, - dst_ptr, dst_ptr->p_messbuf); + BuildNotifyMessage(&m, proc_nr(caller_ptr), dst_ptr); + vmassert(!(dst_ptr->p_misc_flags & MF_DELIVERMSG)); + if((r=QueueMess(caller_ptr->p_endpoint, vir2phys(&m), dst_ptr)) != OK) { + minix_panic("mini_notify: local QueueMess failed", NO_NUM); + } RTS_UNSET(dst_ptr, RECEIVING); return(OK); } @@ -743,13 +705,19 @@ struct proc *caller_ptr; asynmsg_t *table; size_t size; { - int i, dst_p, done, do_notify; + int i, dst_p, done, do_notify, r; unsigned flags; struct proc *dst_ptr; struct priv *privp; message *m_ptr; asynmsg_t tabent; vir_bytes table_v = (vir_bytes) table; + vir_bytes linaddr; + + if(!(linaddr = umap_local(caller_ptr, D, (vir_bytes) table, + size * sizeof(*table)))) { + return EFAULT; + } privp= priv(caller_ptr); if (!(privp->s_flags & SYS_PROC)) @@ -827,11 +795,6 @@ size_t size; continue; } -#if 0 - kprintf("mini_senda: entry[%d]: flags 0x%x dst %d/%d\n", - i, tabent.flags, tabent.dst, dst_p); -#endif - dst_ptr = proc_addr(dst_p); /* NO_ENDPOINT should be removed */ @@ -860,12 +823,13 @@ size_t size; m_ptr= &table[i].msg; /* Note: pointer in the * caller's address space. */ - CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr, - dst_ptr->p_messbuf); + /* Copy message from sender. */ + tabent.result= QueueMess(caller_ptr->p_endpoint, + linaddr + (vir_bytes) &table[i].msg - + (vir_bytes) table, dst_ptr); + if(tabent.result == OK) + RTS_UNSET(dst_ptr, RECEIVING); - RTS_UNSET(dst_ptr, RECEIVING); - - tabent.result= OK; A_INSERT(i, result); tabent.flags= flags | AMF_DONE; A_INSERT(i, flags); @@ -888,13 +852,6 @@ size_t size; { privp->s_asyntab= (vir_bytes)table; privp->s_asynsize= size; -#if 0 - if(caller_ptr->p_endpoint > INIT_PROC_NR) { - kprintf("kernel: %s (%d) asynsend table at 0x%lx, %d\n", - caller_ptr->p_name, caller_ptr->p_endpoint, - table, size); - } -#endif } return OK; } @@ -909,7 +866,7 @@ struct proc *caller_ptr; int r; struct priv *privp; struct proc *src_ptr; - + /* Try all privilege structures */ for (privp = BEG_PRIV_ADDR; privp < END_PRIV_ADDR; ++privp) { @@ -917,11 +874,8 @@ struct proc *caller_ptr; continue; if (privp->s_asynsize == 0) continue; -#if 0 - kprintf("try_async: found asyntable for proc %d\n", - privp->s_proc_nr); -#endif src_ptr= proc_addr(privp->s_proc_nr); + vmassert(!(caller_ptr->p_misc_flags & MF_DELIVERMSG)); r= try_one(src_ptr, caller_ptr); if (r == OK) return r; @@ -951,6 +905,7 @@ struct proc *dst_ptr; asynmsg_t tabent; vir_bytes table_v; struct proc *caller_ptr; + int r; privp= priv(src_ptr); size= privp->s_asynsize; @@ -1009,10 +964,11 @@ struct proc *dst_ptr; m_ptr= &table_ptr[i].msg; /* Note: pointer in the * caller's address space. */ - CopyMess(src_ptr->p_nr, src_ptr, m_ptr, dst_ptr, - dst_ptr->p_messbuf); + A_RETRIEVE(i, msg); + r = QueueMess(src_ptr->p_endpoint, vir2phys(&tabent.msg), + dst_ptr); - tabent.result= OK; + tabent.result= r; A_INSERT(i, result); tabent.flags= flags | AMF_DONE; A_INSERT(i, flags); @@ -1060,43 +1016,6 @@ int dst_e; /* (endpoint) who is to be notified */ return(result); } -/*===========================================================================* - * soft_notify * - *===========================================================================*/ -PUBLIC int soft_notify(dst_e) -int dst_e; /* (endpoint) who is to be notified */ -{ - int dst, u = 0; - struct proc *dstp, *sys = proc_addr(SYSTEM); - -/* Delayed interface to notify() from SYSTEM that is safe/easy to call - * from more places than notify(). - */ - if(!intr_disabled()) { lock; u = 1; } - - { - if(!isokendpt(dst_e, &dst)) - minix_panic("soft_notify to dead ep", dst_e); - - dstp = proc_addr(dst); - - if(!dstp->p_softnotified) { - dstp->next_soft_notify = softnotify; - softnotify = dstp; - dstp->p_softnotified = 1; - - if (RTS_ISSET(sys, RECEIVING)) { - sys->p_messbuf->m_source = SYSTEM; - RTS_UNSET(sys, RECEIVING); - } - } - } - - if(u) { unlock; } - - return OK; -} - /*===========================================================================* * enqueue * *===========================================================================*/ @@ -1251,6 +1170,13 @@ PRIVATE void pick_proc() */ for (q=0; q < NR_SCHED_QUEUES; q++) { if ( (rp = rdy_head[q]) != NIL_PROC) { + if(rp->p_misc_flags & MF_DELIVERMSG) { + /* Want to schedule process, but have to copy a message + * first. + */ + FIXME("MF_DELIVERMSG no callback"); + Deliver(rp); + } next_ptr = rp; /* run process 'rp' next */ #if 0 if(!iskernelp(rp)) @@ -1296,9 +1222,6 @@ timer_t *tp; /* watchdog timer pointer */ unlock; } } -#if DEBUG - kprintf("ticks_added: %d\n", ticks_added); -#endif /* Now schedule a new watchdog timer to balance the queues again. The * period depends on the total amount of quantum ticks added. @@ -1395,24 +1318,18 @@ int *p, fatalflag; *p = _ENDPOINT_P(e); if(!isokprocn(*p)) { #if DEBUG_ENABLE_IPC_WARNINGS -#if 0 kprintf("kernel:%s:%d: bad endpoint %d: proc %d out of range\n", file, line, e, *p); -#endif #endif } else if(isemptyn(*p)) { #if DEBUG_ENABLE_IPC_WARNINGS -#if 0 kprintf("kernel:%s:%d: bad endpoint %d: proc %d empty\n", file, line, e, *p); -#endif #endif } else if(proc_addr(*p)->p_endpoint != e) { #if DEBUG_ENABLE_IPC_WARNINGS -#if 0 kprintf("kernel:%s:%d: bad endpoint %d: proc %d has ept %d (generation %d vs. %d)\n", file, line, e, *p, proc_addr(*p)->p_endpoint, _ENDPOINT_G(e), _ENDPOINT_G(proc_addr(*p)->p_endpoint)); -#endif #endif } else ok = 1; if(!ok && fatalflag) { diff --git a/kernel/proc.h b/kernel/proc.h index 52a4612a8..f8956eb83 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -36,7 +36,6 @@ struct proc { struct proc *p_nextready; /* pointer to next ready process */ struct proc *p_caller_q; /* head of list of procs wishing to send */ struct proc *p_q_link; /* link to next proc wishing to send */ - message *p_messbuf; /* pointer to passed message buffer */ int p_getfrom_e; /* from whom does process want to receive? */ int p_sendto_e; /* to whom does process want to send? */ @@ -46,6 +45,10 @@ struct proc { endpoint_t p_endpoint; /* endpoint number, generation-aware */ + message p_sendmsg; /* Message from this process if SENDING */ + message p_delivermsg; /* Message for this process if MF_DELIVERMSG */ + vir_bytes p_delivermsg_lin; /* Linear addr this proc wants message at */ + /* If handler functions detect a process wants to do something with * memory that isn't present, VM has to fix it. Until it has asked * what needs to be done and fixed it, save necessary state here. @@ -58,27 +61,10 @@ struct proc { struct proc *nextrequestor; /* next in vmrequest chain */ #define VMSTYPE_SYS_NONE 0 #define VMSTYPE_SYS_MESSAGE 1 -#define VMSTYPE_SYS_CALL 2 -#define VMSTYPE_MSGCOPY 3 int type; /* suspended operation */ union { /* VMSTYPE_SYS_MESSAGE */ message reqmsg; /* suspended request message */ - - /* VMSTYPE_SYS_CALL */ - struct { - int call_nr; - message *m_ptr; - int src_dst_e; - long bit_map; - } sys_call; - - /* VMSTYPE_MSGCOPY */ - struct { - struct proc *dst; - vir_bytes dst_v; - message msgbuf; - } msgcopy; } saved; /* Parameters of request to VM */ @@ -107,7 +93,6 @@ struct proc { #define PMAGIC 0xC0FFEE1 int p_magic; /* check validity of proc pointers */ #endif - int verbose; }; /* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */ @@ -169,10 +154,10 @@ struct proc { } while(0) /* Misc flags */ -#define REPLY_PENDING 0x01 /* reply to IPC_REQUEST is pending */ -#define MF_VM 0x08 /* process uses VM */ +#define MF_REPLY_PEND 0x01 /* reply to IPC_REQUEST is pending */ #define MF_ASYNMSG 0x10 /* Asynchrous message pending */ #define MF_FULLVM 0x20 +#define MF_DELIVERMSG 0x40 /* Copy message for him before running */ /* Scheduling priorities for p_priority. Values must start at zero (highest * priority) and increment. Priorities of the processes in the boot image diff --git a/kernel/proto.h b/kernel/proto.h index 130900ebb..44bbbfefe 100755 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -33,7 +33,6 @@ _PROTOTYPE( int sys_call, (int call_nr, int src_dst, message *m_ptr, long bit_map) ); _PROTOTYPE( void sys_call_restart, (struct proc *caller) ); _PROTOTYPE( int lock_notify, (int src, int dst) ); -_PROTOTYPE( int soft_notify, (int dst) ); _PROTOTYPE( int lock_send, (int dst, message *m_ptr) ); _PROTOTYPE( void lock_enqueue, (struct proc *rp) ); _PROTOTYPE( void lock_dequeue, (struct proc *rp) ); @@ -88,6 +87,7 @@ _PROTOTYPE( void cons_seth, (int pos, int n) ); _PROTOTYPE( void check_runqueues_f, (char *file, int line) ); #endif _PROTOTYPE( char *rtsflagstr, (int flags) ); +_PROTOTYPE( char *miscflagstr, (int flags) ); /* system/do_safecopy.c */ _PROTOTYPE( int verify_grant, (endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes, @@ -103,8 +103,9 @@ _PROTOTYPE( void stop_profile_clock, (void) ); #endif /* functions defined in architecture-dependent files. */ -_PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest, +_PROTOTYPE( phys_bytes phys_copy, (phys_bytes source, phys_bytes dest, phys_bytes count) ); +_PROTOTYPE( void phys_copy_fault, (void)); #define virtual_copy(src, dst, bytes) virtual_copy_f(src, dst, bytes, 0) #define virtual_copy_vmcheck(src, dst, bytes) virtual_copy_f(src, dst, bytes, 1) _PROTOTYPE( int virtual_copy_f, (struct vir_addr *src, struct vir_addr *dst, @@ -162,5 +163,7 @@ _PROTOTYPE( int vm_checkrange, (struct proc *caller, struct proc *target, _PROTOTYPE( void proc_stacktrace, (struct proc *proc) ); _PROTOTYPE( int vm_lookup, (struct proc *proc, vir_bytes virtual, vir_bytes *result, u32_t *ptent)); _PROTOTYPE( int vm_suspend, (struct proc *caller, struct proc *target)); +_PROTOTYPE( phys_bytes arch_switch_copymsg, (struct proc *rp, message *m, + phys_bytes lin)); #endif /* PROTO_H */ diff --git a/kernel/system.c b/kernel/system.c index 148459ecc..8e27606de 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -56,9 +56,10 @@ char *callnames[NR_SYS_CALLS]; call_vec[(call_nr-KERNEL_CALL)] = (handler) FORWARD _PROTOTYPE( void initialize, (void)); -FORWARD _PROTOTYPE( void softnotify_check, (void)); FORWARD _PROTOTYPE( struct proc *vmrestart_check, (message *)); +u32_t cr3_test, cr3_reload, createpde, linlincopies, physzero; + /*===========================================================================* * sys_task * *===========================================================================*/ @@ -75,27 +76,35 @@ PUBLIC void sys_task() /* Initialize the system task. */ initialize(); + while (TRUE) { struct proc *restarting; restarting = vmrestart_check(&m); - softnotify_check(); - if(softnotify) - minix_panic("softnotify non-NULL before receive (1)", NO_NUM); if(!restarting) { int r; /* Get work. Block and wait until a request message arrives. */ - if(softnotify) - minix_panic("softnotify non-NULL before receive (2)", NO_NUM); if((r=receive(ANY, &m)) != OK) minix_panic("receive() failed", r); - if(m.m_source == SYSTEM) - continue; - if(softnotify) - minix_panic("softnotify non-NULL after receive", NO_NUM); } +#if 1 + { + static int prevu; + int u; + u = get_uptime(); + if(u/system_hz != prevu/system_hz) { + printf("cr3 tests: %5lu reloads: %5lu createpde: %5lu linlincopies: %5lu physzero: %5lu\n", + cr3_test, cr3_reload, createpde, linlincopies, physzero); + cr3_test = 1; + cr3_reload = 0; + createpde = linlincopies = physzero = 0; + } + prevu = u; + } +#endif + sys_call_code = (unsigned) m.m_type; call_nr = sys_call_code - KERNEL_CALL; who_e = m.m_source; @@ -310,7 +319,7 @@ PUBLIC void send_sig(int proc_nr, int sig_nr) rp = proc_addr(proc_nr); sigaddset(&priv(rp)->s_sig_pending, sig_nr); - soft_notify(rp->p_endpoint); + lock_notify(SYSTEM, rp->p_endpoint); } /*===========================================================================* @@ -429,7 +438,6 @@ register struct proc *rc; /* slot of process to clean up */ #if 0 if(rc->p_endpoint == PM_PROC_NR || rc->p_endpoint == VFS_PROC_NR) -#endif { /* This test is great for debugging system processes dying, * but as this happens normally on reboot, not good permanent code. @@ -438,10 +446,9 @@ register struct proc *rc; /* slot of process to clean up */ proc_stacktrace(rc); kprintf("kernel trace: "); util_stacktrace(); -#if 0 minix_panic("clear_proc: system process died", rc->p_endpoint); -#endif } +#endif /* Make sure that the exiting process is no longer scheduled. */ RTS_LOCK_SET(rc, NO_ENDPOINT); @@ -508,13 +515,6 @@ register struct proc *rc; /* slot of process to clean up */ #endif } } - - /* No pending soft notifies. */ - for(np = softnotify; np; np = np->next_soft_notify) { - if(np == rc) { - minix_panic("dying proc was on next_soft_notify", np->p_endpoint); - } - } } /*===========================================================================* @@ -548,28 +548,6 @@ int access; /* does grantee want to CPF_READ or _WRITE? */ return umap_virtual(proc_addr(proc_nr), D, v_offset, bytes); } -/*===========================================================================* - * softnotify_check * - *===========================================================================*/ -PRIVATE void softnotify_check(void) -{ - struct proc *np, *nextnp; - - if(!softnotify) - return; - - for(np = softnotify; np; np = nextnp) { - if(!np->p_softnotified) - minix_panic("softnotify but no p_softnotified", NO_NUM); - lock_notify(SYSTEM, np->p_endpoint); - nextnp = np->next_soft_notify; - np->next_soft_notify = NULL; - np->p_softnotified = 0; - } - - softnotify = NULL; -} - /*===========================================================================* * vmrestart_check * *===========================================================================*/ @@ -618,29 +596,6 @@ PRIVATE struct proc *vmrestart_check(message *m) } } return restarting; - case VMSTYPE_SYS_CALL: - kprintf("SYSTEM: restart sys_call\n"); - /* Restarting a kernel trap. */ - sys_call_restart(restarting); - - /* Handled; restart system loop. */ - return NULL; - case VMSTYPE_MSGCOPY: - /* Do delayed message copy. */ - printf("copying message into %d..\n", - restarting->p_vmrequest.saved.msgcopy.dst->p_endpoint); - if((r=data_copy(SYSTEM, - (vir_bytes) &restarting->p_vmrequest.saved.msgcopy.msgbuf, - restarting->p_vmrequest.saved.msgcopy.dst->p_endpoint, - (vir_bytes) restarting->p_vmrequest.saved.msgcopy.dst_v, - sizeof(message))) != OK) { - minix_panic("SYSTEM: delayed msgcopy failed", r); - } - printf("OK!\n"); - RTS_LOCK_UNSET(restarting, VMREQUEST); - - /* Handled; restart system loop. */ - return NULL; default: minix_panic("strange restart type", type); } diff --git a/kernel/system/do_exec.c b/kernel/system/do_exec.c index 4161bb088..0bffb7f64 100644 --- a/kernel/system/do_exec.c +++ b/kernel/system/do_exec.c @@ -31,6 +31,15 @@ register message *m_ptr; /* pointer to request message */ rp = proc_addr(proc); + if(rp->p_misc_flags & MF_DELIVERMSG) { + printf("%s / %d has MF_DELIVERMSG on during exec - clearing.\n", + rp->p_name, rp->p_endpoint); +#if 1 + rp->p_misc_flags &= ~MF_DELIVERMSG; + rp->p_delivermsg_lin = 0; +#endif + } + /* Save command name for debugging, ps(1) output, etc. */ if(data_copy(who_e, (vir_bytes) m_ptr->PR_NAME_PTR, SYSTEM, (vir_bytes) rp->p_name, (phys_bytes) P_NAME_LEN - 1) != OK) @@ -42,8 +51,6 @@ register message *m_ptr; /* pointer to request message */ /* No reply to EXEC call */ RTS_LOCK_UNSET(rp, RECEIVING); - printf("kernel: exec %d now %s\n", rp->p_endpoint, rp->p_name); - return(OK); } #endif /* USE_EXEC */ diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index e6e1ef5e5..3df76da50 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -31,10 +31,25 @@ register message *m_ptr; /* pointer to request message */ if(!isokendpt(m_ptr->PR_ENDPT, &p_proc)) return EINVAL; + rpp = proc_addr(p_proc); rpc = proc_addr(m_ptr->PR_SLOT); if (isemptyp(rpp) || ! isemptyp(rpc)) return(EINVAL); + vmassert(!(rpp->p_misc_flags & MF_DELIVERMSG)); + + /* needs to be receiving so we know where the message buffer is */ + if(!RTS_ISSET(rpp, RECEIVING)) { + printf("kernel: fork not done synchronously?\n"); + return EINVAL; + } + + /* memory becomes readonly */ + if (priv(rpp)->s_asynsize > 0) { + printf("kernel: process with waiting asynsend table can't fork\n"); + return EINVAL; + } + map_ptr= (struct mem_map *) m_ptr->PR_MEM_PTR; /* Copy parent 'proc' struct to child. And reinitialize some fields. */ @@ -75,6 +90,7 @@ register message *m_ptr; /* pointer to request message */ /* Calculate endpoint identifier, so caller knows what it is. */ m_ptr->PR_ENDPT = rpc->p_endpoint; + m_ptr->PR_FORK_MSGADDR = (char *) rpp->p_delivermsg_lin; /* Install new map */ r = newmap(rpc, map_ptr); @@ -88,9 +104,6 @@ register message *m_ptr; /* pointer to request message */ RTS_LOCK_UNSET(rpc, (SIGNALED | SIG_PENDING | P_STOP)); sigemptyset(&rpc->p_pending); - printf("kernel: %d / %s forked into %d\n", - rpp->p_endpoint, rpp->p_name, rpc->p_endpoint); - return r; } diff --git a/kernel/system/do_vmctl.c b/kernel/system/do_vmctl.c index fa2a30dfc..f766ba853 100644 --- a/kernel/system/do_vmctl.c +++ b/kernel/system/do_vmctl.c @@ -43,11 +43,13 @@ register message *m_ptr; /* pointer to request message */ if(!RTS_ISSET(rp, VMREQUEST)) minix_panic("do_vmctl: no VMREQUEST set", NO_NUM); +#if 0 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); +#endif /* Reply with request fields. */ m_ptr->SVMCTL_MRG_ADDR = (char *) rp->p_vmrequest.start; @@ -77,7 +79,6 @@ register message *m_ptr; /* pointer to request message */ rp->p_vmrequest.vmresult); /* Put on restart chain. */ - printf("kernel: vm reply received for %d\n", rp->p_endpoint); rp->p_vmrequest.nextrestart = vmrestart; vmrestart = rp; @@ -94,7 +95,7 @@ kprintf("SYSTEM: request %d:0x%lx-0x%lx, wrflag %d, failed\n", rp->p_vmrequest.writeflag); minix_panic("SYSTEM: fail but VM said OK", NO_NUM); - } + } } #endif return OK; diff --git a/kernel/utility.c b/kernel/utility.c index 03bc8cfce..a061f6f4f 100755 --- a/kernel/utility.c +++ b/kernel/utility.c @@ -46,6 +46,7 @@ if (!minix_panicing++) { kprintf("\n"); } + kprintf("proc_ptr %s / %d\n", proc_ptr->p_name, proc_ptr->p_endpoint); kprintf("kernel stacktrace: "); util_stacktrace(); } diff --git a/kernel/vm.h b/kernel/vm.h index e94645eed..8a618d6bf 100644 --- a/kernel/vm.h +++ b/kernel/vm.h @@ -3,6 +3,7 @@ #define _VM_H 1 #define CHECKRANGE_OR_SUSPEND(pr, start, length, wr) { int mr; \ + FIXME("CHECKRANGE_OR_SUSPEND exists"); \ if(vm_running && (mr=vm_checkrange(proc_addr(who_p), pr, start, length, wr, 0)) != OK) { \ return mr; \ } } diff --git a/lib/syslib/sys_fork.c b/lib/syslib/sys_fork.c index 8aef1b8ca..1aa4c9034 100755 --- a/lib/syslib/sys_fork.c +++ b/lib/syslib/sys_fork.c @@ -1,11 +1,12 @@ #include "syslib.h" -PUBLIC int sys_fork(parent, child, child_endpoint, map_ptr, flags) +PUBLIC int sys_fork(parent, child, child_endpoint, map_ptr, flags, msgaddr) endpoint_t parent; /* process doing the fork */ endpoint_t child; /* which proc has been created by the fork */ int *child_endpoint; struct mem_map *map_ptr; u32_t flags; +vir_bytes *msgaddr; { /* A process has forked. Tell the kernel. */ @@ -18,5 +19,6 @@ u32_t flags; m.PR_FORK_FLAGS = flags; r = _taskcall(SYSTASK, SYS_FORK, &m); *child_endpoint = m.PR_ENDPT; + *msgaddr = m.PR_FORK_MSGADDR; return r; } diff --git a/lib/sysutil/Makefile.in b/lib/sysutil/Makefile.in index a44addf98..cd9f53252 100644 --- a/lib/sysutil/Makefile.in +++ b/lib/sysutil/Makefile.in @@ -6,7 +6,6 @@ LIBRARIES=libsys libsys_FILES=" \ asynsend.c \ - kmalloc.c \ kprintf.c \ kputc.c \ tickdelay.c \ diff --git a/servers/init/init.c b/servers/init/init.c index 5e5cb5832..5fd15fd3e 100644 --- a/servers/init/init.c +++ b/servers/init/init.c @@ -99,7 +99,6 @@ int main(void) /* Execute the /etc/rc file. */ if ((pid = fork()) != 0) { - printf("init: parent (%d)\n", getpid()); /* Parent just waits. */ while (wait(NULL) != pid) { if (gotabrt) reboot(RBT_HALT); @@ -112,7 +111,6 @@ int main(void) static char *rc_command[] = { "sh", "/etc/rc", NULL, NULL, NULL }; char **rcp = rc_command + 2; - printf("init: child (%d)\n", getpid()); /* Get the boot options from the boot environment. */ sysgetenv.key = "bootopts"; sysgetenv.keylen = 8+1; @@ -121,9 +119,7 @@ int main(void) if (svrctl(MMGETPARAM, &sysgetenv) == 0) *rcp++ = bootopts; *rcp = "start"; - printf("init: %d: exec /etc/rc..\n", getpid()); execute(rc_command); - printf("init: %d: exec /etc/rc fail..\n", getpid()); report(2, "sh /etc/rc"); _exit(1); /* impossible, we hope */ } diff --git a/servers/pm/main.c b/servers/pm/main.c index b57e87626..6ed92614e 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -452,13 +452,9 @@ PRIVATE void send_work() rmp->mp_fs_call= PM_IDLE; /* Wakeup the newly created process */ - printf("PM: replying fork OK to child %d\n", - rmp->mp_endpoint); setreply(rmp-mproc, OK); /* Wakeup the parent */ - printf("PM: replying fork %d to parent %d\n", - rmp->mp_pid, parent_mp->mp_endpoint); setreply(parent_mp-mproc, rmp->mp_pid); break; } diff --git a/servers/vfs/fs.h b/servers/vfs/fs.h index 40a22b472..9bd2058ac 100644 --- a/servers/vfs/fs.h +++ b/servers/vfs/fs.h @@ -5,7 +5,7 @@ #define _MINIX 1 /* tell headers to include MINIX stuff */ #define _SYSTEM 1 /* tell headers that this is the kernel */ -#define DO_SANITYCHECKS 1 +#define DO_SANITYCHECKS 0 #if DO_SANITYCHECKS #define SANITYCHECK do { \ diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 0d9161792..e1e5ed217 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -292,7 +292,9 @@ PRIVATE void get_work() if(who_p >= 0 && fproc[who_p].fp_endpoint != who_e) { printf("FS: receive endpoint inconsistent (%d, %d, %d).\n", who_e, fproc[who_p].fp_endpoint, who_e); +#if 0 panic(__FILE__, "FS: inconsistent endpoint ", NO_NUM); +#endif continue; } call_nr = m_in.m_type; diff --git a/servers/vm/alloc.c b/servers/vm/alloc.c index 7ab0fd488..96331e099 100644 --- a/servers/vm/alloc.c +++ b/servers/vm/alloc.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -423,6 +424,8 @@ struct memory *chunks; /* list of free memory chunks */ } CHECKHOLES; + + FIXME("below 16MB allocation not done"); } /*===========================================================================* diff --git a/servers/vm/exit.c b/servers/vm/exit.c index 99151c087..c311e17e0 100644 --- a/servers/vm/exit.c +++ b/servers/vm/exit.c @@ -55,8 +55,6 @@ PUBLIC int do_exit(message *msg) SANITYCHECK(SCL_FUNCTIONS); - printf("VM: %d exiting\n", msg->VME_ENDPOINT); - if(vm_isokendpt(msg->VME_ENDPOINT, &proc) != OK) { printf("VM: bogus endpoint VM_EXIT %d\n", msg->VME_ENDPOINT); return EINVAL; diff --git a/servers/vm/fork.c b/servers/vm/fork.c index caef81c36..a0af18811 100644 --- a/servers/vm/fork.c +++ b/servers/vm/fork.c @@ -33,6 +33,7 @@ PUBLIC int do_fork(message *msg) int r, proc, s, childproc, fullvm; struct vmproc *vmp, *vmc; pt_t origpt; + vir_bytes msgaddr; SANITYCHECK(SCL_FUNCTIONS); @@ -139,11 +140,15 @@ PUBLIC int do_fork(message *msg) /* Tell kernel about the (now successful) FORK. */ if((r=sys_fork(vmp->vm_endpoint, childproc, &vmc->vm_endpoint, vmc->vm_arch.vm_seg, - fullvm ? PFF_VMINHIBIT : 0)) != OK) { + fullvm ? PFF_VMINHIBIT : 0, &msgaddr)) != OK) { vm_panic("do_fork can't sys_fork", r); } if(fullvm) { + if(handle_memory(vmc, msgaddr, sizeof(message), 1) != OK) + vm_panic("can't make message writable (child)", NO_NUM); + if(handle_memory(vmp, msgaddr, sizeof(message), 1) != OK) + vm_panic("can't make message writable (parent)", NO_NUM); if((r=pt_bind(&vmc->vm_pt, vmc)) != OK) vm_panic("fork can't pt_bind", r); } diff --git a/servers/vm/i386/pagetable.c b/servers/vm/i386/pagetable.c index cc0e6b9de..947ff5141 100644 --- a/servers/vm/i386/pagetable.c +++ b/servers/vm/i386/pagetable.c @@ -647,8 +647,6 @@ PUBLIC void pt_init(void) 1, VMP_PAGETABLE))) vm_panic("no virt addr for vm mappings", NO_NUM); - printf("VM: pt made\n"); - memset(page_directories, 0, I386_PAGE_SIZE); /* Increase our hardware data segment to create virtual address @@ -684,8 +682,6 @@ PUBLIC void pt_init(void) } varmap = (unsigned char *) arch_map2vir(vmp, varmap_loc); - printf("VM: setting pagedir_pde\n"); - /* Find a PDE below processes available for mapping in the * page directories (readonly). */ @@ -705,8 +701,6 @@ PUBLIC void pt_init(void) kernlimit = free_pde*I386_BIG_PAGE_SIZE; - printf("VM: set limit to 0x%x\n", kernlimit); - /* Increase kernel segment to address this memory. */ if((r=sys_vmctl(SELF, VMCTL_I386_KERNELLIMIT, kernlimit)) != OK) { vm_panic("VMCTL_I386_KERNELLIMIT failed", r); @@ -714,8 +708,6 @@ PUBLIC void pt_init(void) kpagedir = arch_map2vir(&vmproc[VMP_SYSTEM], pagedir_pde*I386_BIG_PAGE_SIZE); - printf("VM: pagedir linear 0x%x, in kernel 0x%x\n", - pagedir_pde*I386_BIG_PAGE_SIZE, kpagedir); /* Tell kernel how to get at the page directories. */ if((r=sys_vmctl(SELF, VMCTL_I386_PAGEDIRS, kpagedir)) != OK) { @@ -723,20 +715,15 @@ PUBLIC void pt_init(void) } /* Give our process the new, copied, private page table. */ - printf("VM: pt_bind for VM\n"); pt_mapkernel(newpt); /* didn't know about vm_dir pages earlier */ pt_bind(newpt, vmp); - printf("VM: enable paging\n"); - /* Now actually enable paging. */ if((r=sys_vmctl(SELF, VMCTL_ENABLE_PAGING, vmp->vm_arch.vm_seg)) != OK) { vm_panic("VMCTL_ENABLE_PAGING failed", r); } - printf("VM: enable paging done\n"); - /* Back to reality - this is where the stack actually is. */ vmp->vm_arch.vm_seg[S].mem_len -= extra_clicks; @@ -747,8 +734,6 @@ PUBLIC void pt_init(void) vm_panic("pt_init: pt_writemap failed", NO_NUM); } - printf("VM: pt_init done\n"); - /* All OK. */ return; } @@ -843,8 +828,6 @@ PUBLIC int pt_mapkernel(pt_t *pt) if(pagedir_pde >= 0) { /* Kernel also wants to know about all page directories. */ pt->pt_dir[pagedir_pde] = pagedir_pde_val; - } else { - printf("VM: pagedir pde not set\n"); } return OK; diff --git a/servers/vm/pagefaults.c b/servers/vm/pagefaults.c index fcf84c558..60987118b 100644 --- a/servers/vm/pagefaults.c +++ b/servers/vm/pagefaults.c @@ -106,8 +106,10 @@ PUBLIC void do_pagefaults(void) } +#if 0 printf("VM: handling pagefault OK: %d addr 0x%lx %s\n", ep, arch_map2vir(vmp, addr), pf_errstr(err)); +#endif /* Pagefault is handled, so now reactivate the process. */ if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK) @@ -131,55 +133,64 @@ PUBLIC void do_memory(void) while((r=sys_vmctl_get_memreq(&who, &mem, &len, &wrflag)) == OK) { int p, r = OK; - struct vir_region *region; struct vmproc *vmp; - vir_bytes o; if(vm_isokendpt(who, &p) != OK) vm_panic("do_memory: endpoint wrong", who); vmp = &vmproc[p]; - printf("VM: handling memory request: %d, 0x%lx-0x%lx, wr %d\n", - who, mem, mem+len, wrflag); - - /* Page-align memory and length. */ - o = mem % VM_PAGE_SIZE; - mem -= o; - len += o; - o = len % VM_PAGE_SIZE; - if(o > 0) len += VM_PAGE_SIZE - o; - - if(!(region = map_lookup(vmp, mem))) { - printf("VM: do_memory: memory doesn't exist\n"); - r = EFAULT; - } else if(mem + len > region->vaddr + region->length) { - vm_assert(region->vaddr <= mem); - vm_panic("do_memory: not contained", NO_NUM); - } else if(!(region->flags & VR_WRITABLE) && wrflag) { - printf("VM: do_memory: write to unwritable map\n"); - r = EFAULT; - } else { - vir_bytes offset; - vm_assert(region->vaddr <= mem); - vm_assert(!(region->flags & VR_NOPF)); - vm_assert(!(region->vaddr % VM_PAGE_SIZE)); - offset = mem - region->vaddr; - - r = map_handle_memory(vmp, region, offset, len, wrflag); - } - - if(r != OK) { - printf("VM: memory range 0x%lx-0x%lx not available in %d\n", - arch_map2vir(vmp, mem), arch_map2vir(vmp, mem+len), - vmp->vm_endpoint); - } - + r = handle_memory(vmp, mem, len, wrflag); if(sys_vmctl(who, VMCTL_MEMREQ_REPLY, r) != OK) vm_panic("do_memory: sys_vmctl failed", r); +#if 0 printf("VM: handling memory request %d done OK\n", who); +#endif } } +int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag) +{ + struct vir_region *region; + vir_bytes o; + int r; + +#if 0 + printf("VM: handling memory request: %d, 0x%lx-0x%lx, wr %d\n", + vmp->vm_endpoint, mem, mem+len, wrflag); +#endif + + /* Page-align memory and length. */ + o = mem % VM_PAGE_SIZE; + mem -= o; + len += o; + o = len % VM_PAGE_SIZE; + if(o > 0) len += VM_PAGE_SIZE - o; + + if(!(region = map_lookup(vmp, mem))) { + printf("VM: do_memory: memory doesn't exist\n"); + r = EFAULT; + } else if(mem + len > region->vaddr + region->length) { + vm_assert(region->vaddr <= mem); + vm_panic("do_memory: not contained", NO_NUM); + } else if(!(region->flags & VR_WRITABLE) && wrflag) { + printf("VM: do_memory: write to unwritable map\n"); + r = EFAULT; + } else { + vir_bytes offset; + vm_assert(region->vaddr <= mem); + vm_assert(!(region->flags & VR_NOPF)); + vm_assert(!(region->vaddr % VM_PAGE_SIZE)); + offset = mem - region->vaddr; + + r = map_handle_memory(vmp, region, offset, len, wrflag); + } + + if(r != OK) { + printf("VM: memory range 0x%lx-0x%lx not available in %d\n", + arch_map2vir(vmp, mem), arch_map2vir(vmp, mem+len), + vmp->vm_endpoint); + } +} diff --git a/servers/vm/proto.h b/servers/vm/proto.h index f4e860834..91a0ac1a4 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -81,6 +81,8 @@ _PROTOTYPE(int do_unmap_phys, (message *msg) ); _PROTOTYPE( void do_pagefaults, (void) ); _PROTOTYPE( void do_memory, (void) ); _PROTOTYPE( char *pf_errstr, (u32_t err)); +_PROTOTYPE( int handle_memory, (struct vmproc *vmp, vir_bytes mem, + vir_bytes len, int wrflag)); /* $(ARCH)/pagetable.c */ _PROTOTYPE( void pt_init, (void) ); diff --git a/servers/vm/region.c b/servers/vm/region.c index ac25ced45..cad352388 100644 --- a/servers/vm/region.c +++ b/servers/vm/region.c @@ -718,8 +718,9 @@ int write; if(ph->ph->refcount == 1) r = map_ph_writept(vmp, region, ph->ph, NULL, NULL); - else + else { r = map_copy_ph_block(vmp, region, ph); + } } else { /* Pagefault in non-existing block. Map in new block. */ #if 0 diff --git a/servers/vm/vm.h b/servers/vm/vm.h index fb3b14c8e..8ac80f4ce 100644 --- a/servers/vm/vm.h +++ b/servers/vm/vm.h @@ -13,8 +13,8 @@ #define ABS2CLICK(a) ((a) >> CLICK_SHIFT) /* Compile in asserts and custom sanity checks at all? */ -#define SANITYCHECKS 1 -#define VMSTATS 1 +#define SANITYCHECKS 0 +#define VMSTATS 0 /* If so, this level: */ #define SCL_NONE 0 /* No sanity checks - vm_assert()s only. */