state
This commit is contained in:
parent
f16eb59bbf
commit
eb2959a560
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -10,12 +10,10 @@
|
|||
#include <string.h>
|
||||
#include <minix/sysutil.h>
|
||||
#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;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include <ibm/interrupt.h>
|
||||
#include <archconst.h>
|
||||
#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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ begbss:
|
|||
#include <ibm/interrupt.h>
|
||||
#include <archconst.h>
|
||||
#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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) { }
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
313
kernel/proc.c
313
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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; \
|
||||
} }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ LIBRARIES=libsys
|
|||
|
||||
libsys_FILES=" \
|
||||
asynsend.c \
|
||||
kmalloc.c \
|
||||
kprintf.c \
|
||||
kputc.c \
|
||||
tickdelay.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 */
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 { \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <minix/const.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/debug.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
|
@ -423,6 +424,8 @@ struct memory *chunks; /* list of free memory chunks */
|
|||
}
|
||||
|
||||
CHECKHOLES;
|
||||
|
||||
FIXME("below 16MB allocation not done");
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) );
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user