beng work in progress, to be explained in a future commit message :).

This commit is contained in:
Ben Gras 2009-05-28 13:47:20 +00:00
parent 78e5d6d4eb
commit 9b73964f6d
50 changed files with 1096 additions and 834 deletions

View File

@ -403,7 +403,8 @@ int safe;
#endif #endif
/* Try to allocate a piece of memory for the RAM disk. */ /* Try to allocate a piece of memory for the RAM disk. */
if((mem = mmap(0, ramdev_size, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0)) == MAP_FAILED) { if((mem = mmap(0, ramdev_size, PROT_READ|PROT_WRITE,
MAP_PREALLOC|MAP_ANON, -1, 0)) == MAP_FAILED) {
printf("MEM: failed to get memory for ramdisk\n"); printf("MEM: failed to get memory for ramdisk\n");
return(ENOMEM); return(ENOMEM);
} }

View File

@ -766,8 +766,22 @@ int scode; /* scan code of key just struck or released */
return -1; return -1;
if(ch) if(ch)
return ch; return ch;
printf("tty: ignoring unrecognized %s scancode 0x%x\n", {
escape ? "escaped" : "straight", scode); static char seen[2][NR_SCAN_CODES];
int notseen = 0, ei;
ei = escape ? 1 : 0;
if(scode >= 0 && scode < NR_SCAN_CODES) {
notseen = !seen[ei][scode];
seen[ei][scode] = 1;
} else {
printf("tty: scode %d makes no sense\n", scode);
}
if(notseen) {
printf("tty: ignoring unrecognized %s "
"scancode 0x%x\n",
escape ? "escaped" : "straight", scode);
}
}
return -1; return -1;
} }

View File

@ -311,7 +311,6 @@
# define SYS_GETINFO (KERNEL_CALL + 26) /* sys_getinfo() */ # define SYS_GETINFO (KERNEL_CALL + 26) /* sys_getinfo() */
# define SYS_ABORT (KERNEL_CALL + 27) /* sys_abort() */ # define SYS_ABORT (KERNEL_CALL + 27) /* sys_abort() */
# define SYS_IOPENABLE (KERNEL_CALL + 28) /* sys_enable_iop() */ # define SYS_IOPENABLE (KERNEL_CALL + 28) /* sys_enable_iop() */
# define SYS_VM_SETBUF (KERNEL_CALL + 29) /* sys_vm_setbuf() */
# define SYS_SAFECOPYFROM (KERNEL_CALL + 31) /* sys_safecopyfrom() */ # define SYS_SAFECOPYFROM (KERNEL_CALL + 31) /* sys_safecopyfrom() */
# define SYS_SAFECOPYTO (KERNEL_CALL + 32) /* sys_safecopyto() */ # define SYS_SAFECOPYTO (KERNEL_CALL + 32) /* sys_safecopyto() */
# define SYS_VSAFECOPY (KERNEL_CALL + 33) /* sys_vsafecopy() */ # define SYS_VSAFECOPY (KERNEL_CALL + 33) /* sys_vsafecopy() */
@ -605,9 +604,9 @@
#define VMCTL_NOPAGEZERO 18 #define VMCTL_NOPAGEZERO 18
#define VMCTL_I386_KERNELLIMIT 19 #define VMCTL_I386_KERNELLIMIT 19
#define VMCTL_I386_PAGEDIRS 20 #define VMCTL_I386_PAGEDIRS 20
#define VMCTL_I386_PDE 21
#define VMCTL_I386_PDEVAL 22
#define VMCTL_I386_FREEPDE 23 #define VMCTL_I386_FREEPDE 23
#define VMCTL_ENABLE_PAGING 24
#define VMCTL_I386_INVLPG 25
/*===========================================================================* /*===========================================================================*
* Messages for the Reincarnation Server * * Messages for the Reincarnation Server *

View File

@ -95,7 +95,4 @@
#define SPROFILE 1 /* statistical profiling */ #define SPROFILE 1 /* statistical profiling */
#define CPROFILE 0 /* call profiling */ #define CPROFILE 0 /* call profiling */
/* Compile kernel so that first page of code and data can be unmapped. */
#define VM_KERN_NOPAGEZERO 0
#endif /* _CONFIG_H */ #endif /* _CONFIG_H */

13
include/minix/debug.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef _MINIX_DEBUG_H
#define _MINIX_DEBUG_H 1
/* For reminders of things to be fixed. */
#define FIXME(str) { static int fixme_warned = 0; \
if(!fixme_warned) { \
printf("FIXME: %s:%d: %s\n", __FILE__, __LINE__, str);\
fixme_warned = 1; \
} \
}
#endif /* _MINIX_DEBUG_H */

View File

@ -97,9 +97,6 @@ struct kinfo {
int nr_tasks; /* number of kernel tasks */ int nr_tasks; /* number of kernel tasks */
char release[6]; /* kernel release number */ char release[6]; /* kernel release number */
char version[6]; /* kernel version number */ char version[6]; /* kernel version number */
#if DEBUG_LOCK_CHECK
int relocking; /* interrupt locking depth (should be 0) */
#endif
}; };
/* Load data accounted every this no. of seconds. */ /* Load data accounted every this no. of seconds. */

View File

@ -36,6 +36,12 @@ sys/vm_i386.h
#define I386_VM_PFA_SHIFT 22 /* Page frame address shift */ #define I386_VM_PFA_SHIFT 22 /* Page frame address shift */
/* CR0 bits */ /* CR0 bits */
#define I386_CR0_PE 0x00000001 /* Protected mode */
#define I386_CR0_MP 0x00000002 /* Monitor Coprocessor */
#define I386_CR0_EM 0x00000004 /* Emulate */
#define I386_CR0_TS 0x00000008 /* Task Switched */
#define I386_CR0_ET 0x00000010 /* Extension Type */
#define I386_CR0_WP 0x00010000 /* Enable paging */
#define I386_CR0_PG 0x80000000 /* Enable paging */ #define I386_CR0_PG 0x80000000 /* Enable paging */
/* some CR4 bits */ /* some CR4 bits */

View File

@ -12,7 +12,6 @@
#include "proto.h" #include "proto.h"
extern u32_t kernel_cr3;
extern u32_t *vm_pagedirs; extern u32_t *vm_pagedirs;
/*===========================================================================* /*===========================================================================*
@ -22,10 +21,6 @@ PUBLIC int arch_do_vmctl(m_ptr, p)
register message *m_ptr; /* pointer to request message */ register message *m_ptr; /* pointer to request message */
struct proc *p; struct proc *p;
{ {
static int vmpde = -1;
static u32_t pdeval = -1;
switch(m_ptr->SVMCTL_PARAM) { switch(m_ptr->SVMCTL_PARAM) {
case VMCTL_I386_GETCR3: case VMCTL_I386_GETCR3:
/* Get process CR3. */ /* Get process CR3. */
@ -37,7 +32,7 @@ struct proc *p;
p->p_seg.p_cr3 = m_ptr->SVMCTL_VALUE; p->p_seg.p_cr3 = m_ptr->SVMCTL_VALUE;
p->p_misc_flags |= MF_FULLVM; p->p_misc_flags |= MF_FULLVM;
} else { } else {
p->p_seg.p_cr3 = kernel_cr3; p->p_seg.p_cr3 = 0;
p->p_misc_flags &= ~MF_FULLVM; p->p_misc_flags &= ~MF_FULLVM;
} }
RTS_LOCK_UNSET(p, VMINHIBIT); RTS_LOCK_UNSET(p, VMINHIBIT);
@ -58,6 +53,8 @@ struct proc *p;
m_ptr->SVMCTL_PF_WHO = rp->p_endpoint; m_ptr->SVMCTL_PF_WHO = rp->p_endpoint;
m_ptr->SVMCTL_PF_I386_CR2 = rp->p_pagefault.pf_virtual; m_ptr->SVMCTL_PF_I386_CR2 = rp->p_pagefault.pf_virtual;
m_ptr->SVMCTL_PF_I386_ERR = rp->p_pagefault.pf_flags; 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; return OK;
} }
case VMCTL_I386_KERNELLIMIT: case VMCTL_I386_KERNELLIMIT:
@ -74,27 +71,16 @@ struct proc *p;
kprintf("kernel: pagedirs now 0x%lx\n", vm_pagedirs); kprintf("kernel: pagedirs now 0x%lx\n", vm_pagedirs);
return OK; return OK;
} }
case VMCTL_I386_PDE:
{
vmpde = m_ptr->SVMCTL_VALUE;
kprintf("kernel: HACK: vmpde %d\n", vmpde);
return OK;
}
case VMCTL_I386_PDEVAL:
{
pdeval = m_ptr->SVMCTL_VALUE;
kprintf("kernel: HACK: vmpde %d, set val 0x%x\n",
vmpde, pdeval);
i386_updatepde(vmpde, pdeval);
kprintf("kernel: HACK: vmpde %d, set val 0x%x done\n",
vmpde, pdeval);
return OK;
}
case VMCTL_I386_FREEPDE: case VMCTL_I386_FREEPDE:
{ {
i386_freepde(m_ptr->SVMCTL_VALUE); i386_freepde(m_ptr->SVMCTL_VALUE);
return OK; return OK;
} }
case VMCTL_I386_INVLPG:
{
invlpg_range(m_ptr->SVMCTL_VALUE, 1);
return OK;
}
} }
kprintf("arch_do_vmctl: strange param %d\n", m_ptr->SVMCTL_PARAM); kprintf("arch_do_vmctl: strange param %d\n", m_ptr->SVMCTL_PARAM);

View File

@ -33,6 +33,10 @@ register message *m_ptr; /* pointer to request message */
struct priv *privp; struct priv *privp;
struct io_range *iorp; struct io_range *iorp;
kprintf("kernel: no sdevio\n");
return EIO;
#if 0
/* Allow safe copies and accesses to SELF */ /* Allow safe copies and accesses to SELF */
if ((m_ptr->DIO_REQUEST & _DIO_SAFEMASK) != _DIO_SAFE && if ((m_ptr->DIO_REQUEST & _DIO_SAFEMASK) != _DIO_SAFE &&
proc_nr_e != SELF) proc_nr_e != SELF)
@ -141,6 +145,7 @@ register message *m_ptr; /* pointer to request message */
return(EINVAL); return(EINVAL);
} }
return(OK); return(OK);
#endif
} }
#endif /* USE_SDEVIO */ #endif /* USE_SDEVIO */

View File

@ -11,10 +11,11 @@
#include <minix/sysutil.h> #include <minix/sysutil.h>
#include "../../proc.h" #include "../../proc.h"
extern int vm_copy_in_progress; extern int vm_copy_in_progress, catch_pagefaults;
extern struct proc *vm_copy_from, *vm_copy_to; 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_v, vm_copy_to_v;
extern u32_t vm_copy_from_p, vm_copy_to_p, vm_copy_cr3; 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; u32_t pagefault_cr2, pagefault_count = 0;
@ -24,15 +25,33 @@ void pagefault(struct proc *pr, int trap_errno)
vir_bytes ph; vir_bytes ph;
u32_t pte; u32_t pte;
if(pagefault_count != 1) vmassert(pagefault_count == 1);
minix_panic("recursive pagefault", pagefault_count);
/* Don't schedule this process until pagefault is handled. */ if((iskernelp(pr) || k_reenter) && catch_pagefaults
if(RTS_ISSET(pr, PAGEFAULT)) && (pr->p_reg.pc > (vir_bytes) _memcpy_k &&
minix_panic("PAGEFAULT set", pr->p_endpoint); pr->p_reg.pc < (vir_bytes) _memcpy_k_fault) &&
RTS_LOCK_SET(pr, PAGEFAULT); pagefault_cr2 >= catchrange_lo &&
pagefault_cr2 < catchrange_hi) {
kprintf("handling pagefault during copy\n");
pr->p_reg.pc = (vir_bytes) _memcpy_k_fault;
pr->p_reg.retreg = pagefault_cr2;
pagefault_count = 0;
return;
}
if(pr->p_endpoint <= INIT_PROC_NR && !(pr->p_misc_flags & MF_FULLVM)) { proc_stacktrace(pr);
if(catch_pagefaults) {
printf("k_reenter: %d addr: 0x%lx range: 0x%lx-0x%lx\n",
k_reenter, pagefault_cr2, catchrange_lo, catchrange_hi);
}
/* 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).
*/
if(k_reenter || (pr->p_endpoint <= INIT_PROC_NR &&
!(pr->p_misc_flags & MF_FULLVM)) || pr->p_endpoint == VM_PROC_NR) {
/* Page fault we can't / don't want to /* Page fault we can't / don't want to
* handle. * handle.
*/ */
@ -45,6 +64,11 @@ void pagefault(struct proc *pr, int trap_errno)
return; return;
} }
/* Don't schedule this process until pagefault is handled. */
vmassert(pr->p_seg.p_cr3 == read_cr3());
vmassert(!RTS_ISSET(pr, PAGEFAULT));
RTS_LOCK_SET(pr, PAGEFAULT);
/* Save pagefault details, suspend process, /* Save pagefault details, suspend process,
* add process to pagefault chain, * add process to pagefault chain,
* and tell VM there is a pagefault to be * and tell VM there is a pagefault to be
@ -54,7 +78,7 @@ void pagefault(struct proc *pr, int trap_errno)
pr->p_pagefault.pf_flags = trap_errno; pr->p_pagefault.pf_flags = trap_errno;
pr->p_nextpagefault = pagefaults; pr->p_nextpagefault = pagefaults;
pagefaults = pr; pagefaults = pr;
lock_notify(HARDWARE, VM_PROC_NR); soft_notify(VM_PROC_NR);
pagefault_count = 0; pagefault_count = 0;
@ -184,17 +208,20 @@ PUBLIC void proc_stacktrace(struct proc *proc)
v_bp = proc->p_reg.fp; v_bp = proc->p_reg.fp;
kprintf("%8.8s %6d 0x%lx ", kprintf("%-8.8s %6d 0x%lx ",
proc->p_name, proc->p_endpoint, proc->p_reg.pc); proc->p_name, proc->p_endpoint, proc->p_reg.pc);
while(v_bp) { while(v_bp) {
if(data_copy(proc->p_endpoint, v_bp,
SYSTEM, (vir_bytes) &v_hbp, sizeof(v_hbp)) != OK) { #define PRCOPY(pr, pv, v, n) \
(iskernelp(pr) ? (memcpy(v, pv, n), OK) : \
data_copy(pr->p_endpoint, pv, SYSTEM, (vir_bytes) (v), n))
if(PRCOPY(proc, v_bp, &v_hbp, sizeof(v_hbp)) != OK) {
kprintf("(v_bp 0x%lx ?)", v_bp); kprintf("(v_bp 0x%lx ?)", v_bp);
break; break;
} }
if(data_copy(proc->p_endpoint, v_bp + sizeof(v_pc), if(PRCOPY(proc, v_bp + sizeof(v_pc), &v_pc, sizeof(v_pc)) != OK) {
SYSTEM, (vir_bytes) &v_pc, sizeof(v_pc)) != OK) {
kprintf("(v_pc 0x%lx ?)", v_pc); kprintf("(v_pc 0x%lx ?)", v_pc);
break; break;
} }

View File

@ -21,10 +21,10 @@
.define __exit ! dummy for library routines .define __exit ! dummy for library routines
.define ___exit ! dummy for library routines .define ___exit ! dummy for library routines
.define ___main ! dummy for GCC .define ___main ! dummy for GCC
.define _phys_insw ! transfer data from (disk controller) port to memory !.define _phys_insw ! transfer data from (disk controller) port to memory
.define _phys_insb ! likewise byte by byte !.define _phys_insb ! likewise byte by byte
.define _phys_outsw ! transfer data from memory to (disk controller) port !.define _phys_outsw ! transfer data from memory to (disk controller) port
.define _phys_outsb ! likewise byte by byte !.define _phys_outsb ! likewise byte by byte
.define _intr_unmask ! enable an irq at the 8259 controller .define _intr_unmask ! enable an irq at the 8259 controller
.define _intr_mask ! disable an irq .define _intr_mask ! disable an irq
.define _phys_copy ! copy data from anywhere to anywhere in memory .define _phys_copy ! copy data from anywhere to anywhere in memory
@ -36,14 +36,16 @@
.define _read_cpu_flags ! read the cpu flags .define _read_cpu_flags ! read the cpu flags
.define _read_cr0 ! read cr0 .define _read_cr0 ! read cr0
.define _write_cr3 ! write cr3 .define _write_cr3 ! write cr3
.define _getcr3val
.define _last_cr3 .define _last_cr3
.define _write_cr0 ! write a value in cr0 .define _write_cr0 ! write a value in cr0
.define _read_cr4 .define _read_cr4
.define _thecr3
.define _write_cr4 .define _write_cr4
.define _i386_invlpg_addr .define _i386_invlpg_addr
.define _i386_invlpg_level0 .define _i386_invlpg_level0
.define __memcpy_k
.define _kernel_cr3 .define __memcpy_k_fault
! The routines only guarantee to preserve the registers the C compiler ! The routines only guarantee to preserve the registers the C compiler
! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and ! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
@ -158,55 +160,6 @@ csinit: mov eax, DS_SELECTOR
ret ret
!*===========================================================================*
!* cp_mess *
!*===========================================================================*
! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
! phys_clicks dst_clicks, vir_bytes dst_offset);
! This routine makes a fast copy of a message from anywhere in the address
! space to anywhere else. It also copies the source address provided as a
! parameter to the call into the first word of the destination message.
!
! Note that the message size, "Msize" is in DWORDS (not bytes) and must be set
! correctly. Changing the definition of message in the type file and not
! changing it here will lead to total disaster.
!
!CM_ARGS = 4 + 4 + 4 + 4 + 4 ! 4 + 4 + 4 + 4 + 4
!! es ds edi esi eip proc scl sof dcl dof
!
! .align 16
!_cp_mess:
! cld
! push esi
! push edi
! push ds
! push es
!
! mov eax, FLAT_DS_SELECTOR
! mov ds, ax
! mov es, ax
!
! mov esi, CM_ARGS+4(esp) ! src clicks
! shl esi, CLICK_SHIFT
! add esi, CM_ARGS+4+4(esp) ! src offset
! mov edi, CM_ARGS+4+4+4(esp) ! dst clicks
! shl edi, CLICK_SHIFT
! add edi, CM_ARGS+4+4+4+4(esp) ! dst offset
!
! mov eax, CM_ARGS(esp) ! process number of sender
! stos ! copy number of sender to dest message
! add esi, 4 ! do not copy first word
! mov ecx, Msize - 1 ! remember, first word does not count
! rep
! movs ! copy the message
!
! pop es
! pop ds
! pop edi
! pop esi
! ret ! that is all folks!
!
!*===========================================================================* !*===========================================================================*
!* exit * !* exit *
!*===========================================================================* !*===========================================================================*
@ -230,56 +183,52 @@ ___main:
!*===========================================================================* !*===========================================================================*
! PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count); ! 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(). ! Input an array from an I/O port. Absolute address version of insw().
!
_phys_insw: !_phys_insw:
push ebp ! push ebp
mov ebp, esp ! mov ebp, esp
cld ! cld
push edi ! push edi
push es ! push es
!
LOADKERNELCR3 ! mov ecx, FLAT_DS_SELECTOR
! mov es, cx
mov ecx, FLAT_DS_SELECTOR ! mov edx, 8(ebp) ! port to read from
mov es, cx ! mov edi, 12(ebp) ! destination addr
mov edx, 8(ebp) ! port to read from ! mov ecx, 16(ebp) ! byte count
mov edi, 12(ebp) ! destination addr ! shr ecx, 1 ! word count
mov ecx, 16(ebp) ! byte count !rep o16 ins ! input many words
shr ecx, 1 ! word count ! pop es
rep o16 ins ! input many words ! pop edi
pop es ! pop ebp
pop edi ! ret
pop ebp !
ret
!*===========================================================================* !*===========================================================================*
!* phys_insb * !* phys_insb *
!*===========================================================================* !*===========================================================================*
! PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count); ! 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(). ! Input an array from an I/O port. Absolute address version of insb().
!
_phys_insb: !_phys_insb:
push ebp ! push ebp
mov ebp, esp ! mov ebp, esp
cld ! cld
push edi ! push edi
push es ! push es
!
LOADKERNELCR3 ! mov ecx, FLAT_DS_SELECTOR
! mov es, cx
mov ecx, FLAT_DS_SELECTOR ! mov edx, 8(ebp) ! port to read from
mov es, cx ! mov edi, 12(ebp) ! destination addr
mov edx, 8(ebp) ! port to read from ! mov ecx, 16(ebp) ! byte count
mov edi, 12(ebp) ! destination addr !! shr ecx, 1 ! word count
mov ecx, 16(ebp) ! byte count ! rep insb ! input many bytes
! shr ecx, 1 ! word count ! pop es
rep insb ! input many bytes ! pop edi
pop es ! pop ebp
pop edi ! ret
pop ebp !
ret
!*===========================================================================* !*===========================================================================*
!* phys_outsw * !* phys_outsw *
@ -287,55 +236,51 @@ _phys_insb:
! PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count); ! 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(). ! Output an array to an I/O port. Absolute address version of outsw().
.align 16 ! .align 16
_phys_outsw: !_phys_outsw:
push ebp ! push ebp
mov ebp, esp ! mov ebp, esp
cld ! cld
push esi ! push esi
push ds ! push ds
!
LOADKERNELCR3 ! mov ecx, FLAT_DS_SELECTOR
! mov ds, cx
mov ecx, FLAT_DS_SELECTOR ! mov edx, 8(ebp) ! port to write to
mov ds, cx ! mov esi, 12(ebp) ! source addr
mov edx, 8(ebp) ! port to write to ! mov ecx, 16(ebp) ! byte count
mov esi, 12(ebp) ! source addr ! shr ecx, 1 ! word count
mov ecx, 16(ebp) ! byte count !rep o16 outs ! output many words
shr ecx, 1 ! word count ! pop ds
rep o16 outs ! output many words ! pop esi
pop ds ! pop ebp
pop esi ! ret
pop ebp !
ret
!*===========================================================================* !*===========================================================================*
!* phys_outsb * !* phys_outsb *
!*===========================================================================* !*===========================================================================*
! PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count); ! 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(). ! Output an array to an I/O port. Absolute address version of outsb().
!
.align 16 ! .align 16
_phys_outsb: !_phys_outsb:
push ebp ! push ebp
mov ebp, esp ! mov ebp, esp
cld ! cld
push esi ! push esi
push ds ! push ds
!
LOADKERNELCR3 ! mov ecx, FLAT_DS_SELECTOR
! mov ds, cx
mov ecx, FLAT_DS_SELECTOR ! mov edx, 8(ebp) ! port to write to
mov ds, cx ! mov esi, 12(ebp) ! source addr
mov edx, 8(ebp) ! port to write to ! mov ecx, 16(ebp) ! byte count
mov esi, 12(ebp) ! source addr ! rep outsb ! output many bytes
mov ecx, 16(ebp) ! byte count ! pop ds
rep outsb ! output many bytes ! pop esi
pop ds ! pop ebp
pop esi ! ret
pop ebp
ret
!*==========================================================================* !*==========================================================================*
@ -432,8 +377,6 @@ _phys_copy:
push edi push edi
push es push es
LOADKERNELCR3
mov eax, FLAT_DS_SELECTOR mov eax, FLAT_DS_SELECTOR
mov es, ax mov es, ax
@ -479,8 +422,6 @@ _phys_memset:
push ebx push ebx
push ds push ds
LOADKERNELCR3
mov esi, 8(ebp) mov esi, 8(ebp)
mov eax, 16(ebp) mov eax, 16(ebp)
mov ebx, FLAT_DS_SELECTOR mov ebx, FLAT_DS_SELECTOR
@ -494,7 +435,7 @@ fill_start:
jnz fill_start jnz fill_start
! Any remaining bytes? ! Any remaining bytes?
mov eax, 16(ebp) mov eax, 16(ebp)
and eax, 3 ! and eax, 3
remain_fill: remain_fill:
cmp eax, 0 cmp eax, 0
jz fill_done jz fill_done
@ -642,10 +583,20 @@ _write_cr4:
_write_cr3: _write_cr3:
push ebp push ebp
mov ebp, esp mov ebp, esp
LOADCR3WITHEAX(0x22, 8(ebp)) mov eax, 8(ebp)
mov cr3, eax
pop ebp pop ebp
ret ret
!*===========================================================================*
!* getcr3val *
!*===========================================================================*
! PUBLIC unsigned long getcr3val(void);
_getcr3val:
mov eax, cr3
mov (_thecr3), eax
ret
!*===========================================================================* !*===========================================================================*
!* i386_invlpg * !* i386_invlpg *
!*===========================================================================* !*===========================================================================*
@ -657,4 +608,47 @@ _i386_invlpg_level0:
ret ret
!*===========================================================================*
!* _memcpy_k *
!*===========================================================================*
! _memcpy_k() Original Author: Kees J. Bot
! 2 Jan 1994
! void *_memcpy_k(void *s1, const void *s2, size_t n)
! Copy a chunk of memory that the kernel can use to trap pagefaults.
.define __memcpy_k
.define __memcpy_k_fault
.align 16
__memcpy_k:
push ebp
mov ebp, esp
push esi
push edi
mov edi, 8(ebp) ! String s1
mov esi, 12(ebp) ! String s2
mov ecx, 16(ebp) ! Length
cld ! Clear direction bit: upwards
cmp ecx, 16
jb upbyte ! Don't bother being smart with short arrays
mov eax, esi
or eax, edi
testb al, 1
jnz upbyte ! Bit 0 set, use byte copy
testb al, 2
jnz upword ! Bit 1 set, use word copy
uplword:shrd eax, ecx, 2 ! Save low 2 bits of ecx in eax
shr ecx, 2
rep
movs ! Copy longwords.
shld ecx, eax, 2 ! Restore excess count
upword: shr ecx, 1
rep
o16 movs ! Copy words
adc ecx, ecx ! One more byte?
upbyte: rep
movsb ! Copy bytes
done: mov eax, 0
__memcpy_k_fault: ! Kernel can send us here with pf cr2 in eax
pop edi
pop esi
pop ebp
ret

File diff suppressed because it is too large Load Diff

View File

@ -74,7 +74,6 @@ begbss:
.define _restart .define _restart
.define save .define save
.define _kernel_cr3
.define _pagefault_cr2 .define _pagefault_cr2
.define _pagefault_count .define _pagefault_count
@ -218,12 +217,6 @@ csinit:
ltr ax ltr ax
push 0 ! set flags to known good state push 0 ! set flags to known good state
popf ! esp, clear nested task and int enable popf ! esp, clear nested task and int enable
#if VM_KERN_NOPAGEZERO
jmp laststep
.align I386_PAGE_SIZE
laststep:
#endif
jmp _main ! main() jmp _main ! main()
@ -239,7 +232,6 @@ laststep:
#define hwint_master(irq) \ #define hwint_master(irq) \
call save /* save interrupted process state */;\ call save /* save interrupted process state */;\
push (_irq_handlers+4*irq) /* irq_handlers[irq] */;\ push (_irq_handlers+4*irq) /* irq_handlers[irq] */;\
LOADCR3WITHEAX(irq, (_kernel_cr3)) /* switch to kernel page table */;\
call _intr_handle /* intr_handle(irq_handlers[irq]) */;\ call _intr_handle /* intr_handle(irq_handlers[irq]) */;\
pop ecx ;\ pop ecx ;\
cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\ cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\
@ -291,7 +283,6 @@ _hwint07: ! Interrupt routine for irq 7 (printer)
#define hwint_slave(irq) \ #define hwint_slave(irq) \
call save /* save interrupted process state */;\ call save /* save interrupted process state */;\
push (_irq_handlers+4*irq) /* irq_handlers[irq] */;\ push (_irq_handlers+4*irq) /* irq_handlers[irq] */;\
LOADCR3WITHEAX(irq, (_kernel_cr3)) /* switch to kernel page table */;\
call _intr_handle /* intr_handle(irq_handlers[irq]) */;\ call _intr_handle /* intr_handle(irq_handlers[irq]) */;\
pop ecx ;\ pop ecx ;\
cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\ cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\
@ -398,8 +389,6 @@ _p_s_call:
push eax ! source / destination push eax ! source / destination
push ecx ! call number (ipc primitive to use) push ecx ! call number (ipc primitive to use)
! LOADCR3WITHEAX(0x20, (_kernel_cr3))
call _sys_call ! sys_call(call_nr, src_dst, m_ptr, bit_map) call _sys_call ! sys_call(call_nr, src_dst, m_ptr, bit_map)
! caller is now explicitly in proc_ptr ! caller is now explicitly in proc_ptr
mov AXREG(esi), eax ! sys_call MUST PRESERVE si mov AXREG(esi), eax ! sys_call MUST PRESERVE si
@ -420,7 +409,16 @@ _restart:
mov (_next_ptr), 0 mov (_next_ptr), 0
0: mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0 0: mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0
lldt P_LDT_SEL(esp) ! enable process' segment descriptors lldt P_LDT_SEL(esp) ! enable process' segment descriptors
LOADCR3WITHEAX(0x21, P_CR3(esp)) ! switch to process page table 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
jz noload
mov cr3, eax
mov eax, (_proc_ptr)
mov (_ptproc), eax
noload:
lea eax, P_STACKTOP(esp) ! arrange for next interrupt lea eax, P_STACKTOP(esp) ! arrange for next interrupt
mov (_tss+TSS3_S_SP0), eax ! to save state in process table mov (_tss+TSS3_S_SP0), eax ! to save state in process table
restart1: restart1:
@ -535,8 +533,6 @@ exception1: ! Common for all exceptions.
mov eax, 8+4(esp) ! old eflags mov eax, 8+4(esp) ! old eflags
sseg mov (old_eflags), eax sseg mov (old_eflags), eax
LOADCR3WITHEAX(0x24, (_kernel_cr3))
pop eax pop eax
call save call save
push (old_eflags) push (old_eflags)
@ -556,24 +552,12 @@ _level0_call:
call save call save
jmp (_level0_func) jmp (_level0_func)
!*===========================================================================*
!* load_kernel_cr3 *
!*===========================================================================*
.align 16
_load_kernel_cr3:
mov eax, (_kernel_cr3)
mov cr3, eax
ret
!*===========================================================================* !*===========================================================================*
!* data * !* data *
!*===========================================================================* !*===========================================================================*
.sect .rom ! Before the string table please .sect .rom ! Before the string table please
.data2 0x526F ! this must be the first data entry (magic #) .data2 0x526F ! this must be the first data entry (magic #)
#if VM_KERN_NOPAGEZERO
.align I386_PAGE_SIZE
#endif
.sect .bss .sect .bss
k_stack: k_stack:

View File

@ -51,6 +51,7 @@ _PROTOTYPE( void vir_insw, (u16_t port, struct proc *proc, u32_t vir, size_t cou
_PROTOTYPE( void vir_outsw, (u16_t port, struct proc *proc, u32_t vir, size_t count)); _PROTOTYPE( void vir_outsw, (u16_t port, struct proc *proc, u32_t vir, size_t count));
_PROTOTYPE( void i386_updatepde, (int pde, u32_t val)); _PROTOTYPE( void i386_updatepde, (int pde, u32_t val));
_PROTOTYPE( void i386_freepde, (int pde)); _PROTOTYPE( void i386_freepde, (int pde));
_PROTOTYPE( void getcr3val, (void));
/* exception.c */ /* exception.c */
@ -73,6 +74,8 @@ _PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) ); _PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) ); _PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void i386_invlpg_level0, (void) ); _PROTOTYPE( void i386_invlpg_level0, (void) );
_PROTOTYPE( int _memcpy_k, (void *dst, void *src, size_t n) );
_PROTOTYPE( int _memcpy_k_fault, (void) );
/* protect.c */ /* protect.c */
_PROTOTYPE( void prot_init, (void) ); _PROTOTYPE( void prot_init, (void) );

View File

@ -153,6 +153,60 @@ PRIVATE void ser_debug(int c)
do_serial_debug--; do_serial_debug--;
} }
PRIVATE void printslot(struct proc *pp)
{
static int level = 0;
struct proc *depproc = NULL;
int dep = NONE;
if(level >= NR_PROCS) {
kprintf("loop??\n");
return;
}
level++;
kprintf("%*s %d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %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));
if(pp->p_rts_flags & SENDING) {
dep = pp->p_sendto_e;
kprintf(" to: ");
} else if(pp->p_rts_flags & RECEIVING) {
dep = pp->p_getfrom_e;
kprintf(" from: ");
}
if(dep != NONE) {
if(dep == ANY) {
kprintf(" ANY\n");
} else {
int procno;
if(!isokendpt(dep, &procno)) {
kprintf(" ??? %d\n", dep);
} else {
depproc = proc_addr(procno);
if(depproc->p_rts_flags & SLOT_FREE) {
kprintf(" empty slot %d???\n", procno);
depproc = NULL;
} else {
kprintf(" %s\n", depproc->p_name);
}
}
}
} else {
kprintf("\n");
}
kprintf("%*s ", level, "");
proc_stacktrace(pp);
if(depproc)
printslot(depproc);
level--;
}
PUBLIC void ser_dump_proc() PUBLIC void ser_dump_proc()
{ {
struct proc *pp; struct proc *pp;
@ -165,15 +219,7 @@ PUBLIC void ser_dump_proc()
{ {
if (pp->p_rts_flags & SLOT_FREE) if (pp->p_rts_flags & SLOT_FREE)
continue; continue;
kprintf( printslot(pp);
"%d: 0x%02x %s e %d src %d dst %d prio %d/%d time %d/%d EIP 0x%x\n",
proc_nr(pp),
pp->p_rts_flags, pp->p_name,
pp->p_endpoint, pp->p_getfrom_e, pp->p_sendto_e,
pp->p_priority, pp->p_max_priority,
pp->p_user_time, pp->p_sys_time,
pp->p_reg.pc);
proc_stacktrace(pp);
} }
if(u) { unlock; } if(u) { unlock; }

View File

@ -1,21 +1,7 @@
.define _load_kernel_cr3
.define _last_cr3 .define _last_cr3
#define LOADKERNELCR3 ;\ #define LOADCR3WITHEAX(type, newcr3, ptproc) ;\
inc (_cr3switch) ;\
mov eax, (_kernel_cr3) ;\
cmp (_last_cr3), eax ;\
jz 9f ;\
push _load_kernel_cr3 ;\
call _level0 ;\
pop eax ;\
mov eax, (_kernel_cr3) ;\
mov (_last_cr3), eax ;\
inc (_cr3reload) ;\
9:
#define LOADCR3WITHEAX(type, newcr3) ;\
sseg inc (_cr3switch) ;\ sseg inc (_cr3switch) ;\
sseg mov eax, newcr3 ;\ sseg mov eax, newcr3 ;\
sseg cmp (_last_cr3), eax ;\ sseg cmp (_last_cr3), eax ;\
@ -23,5 +9,7 @@ sseg cmp (_last_cr3), eax ;\
mov cr3, eax ;\ mov cr3, eax ;\
sseg inc (_cr3reload) ;\ sseg inc (_cr3reload) ;\
sseg mov (_last_cr3), eax ;\ sseg mov (_last_cr3), eax ;\
sseg mov eax, (ptproc) ;\
sseg mov (_ptproc), eax ;\
8: 8:

View File

@ -103,3 +103,28 @@ check_runqueues_f(char *file, int line)
} }
#endif /* DEBUG_SCHED_CHECK */ #endif /* DEBUG_SCHED_CHECK */
PUBLIC char *
rtsflagstr(int flags)
{
static char str[100];
str[0] = '\0';
#define FLAG(n) if(flags & n) { strcat(str, #n " "); }
FLAG(SLOT_FREE);
FLAG(NO_PRIORITY);
FLAG(SENDING);
FLAG(RECEIVING);
FLAG(SIGNALED);
FLAG(SIG_PENDING);
FLAG(P_STOP);
FLAG(NO_PRIV);
FLAG(NO_ENDPOINT);
FLAG(VMINHIBIT);
FLAG(PAGEFAULT);
FLAG(VMREQUEST);
return str;
}

View File

@ -8,6 +8,7 @@
*/ */
#include <ansi.h> #include <ansi.h>
#include <minix/debug.h>
#include "config.h" #include "config.h"
/* Enable prints such as /* Enable prints such as
@ -25,6 +26,34 @@
/* Runtime sanity checking. */ /* Runtime sanity checking. */
#define DEBUG_VMASSERT 1 #define DEBUG_VMASSERT 1
#define DEBUG_SCHED_CHECK 0 #define DEBUG_SCHED_CHECK 1
#define NOREC_ENTER(varname) \
static int varname = 0; \
int mustunlock = 0; \
if(!intr_disabled()) { lock; mustunlock = 1; } \
if(varname) { \
minix_panic(#varname " recursive enter", __LINE__); \
} \
varname = 1; \
FIXME(#varname " recursion check enabled");
#define NOREC_RETURN(varname, v) do { \
if(!varname) \
minix_panic(#varname " flag off", __LINE__); \
if(!intr_disabled()) \
minix_panic(#varname " interrupts on", __LINE__); \
varname = 0; \
if(mustunlock) { unlock; } \
return v; \
} while(0)
#if DEBUG_VMASSERT
#define vmassert(t) { \
if(!(t)) { minix_panic("vm: assert " #t " failed\n", __LINE__); } }
#else
#define vmassert(t) { }
#endif
#endif /* DEBUG_H */ #endif /* DEBUG_H */

View File

@ -89,11 +89,9 @@ EXTERN unsigned long cr3switch;
EXTERN unsigned long cr3reload; EXTERN unsigned long cr3reload;
/* VM */ /* VM */
EXTERN phys_bytes vm_base;
EXTERN phys_bytes vm_size;
EXTERN phys_bytes vm_mem_high;
EXTERN int vm_running; EXTERN int vm_running;
EXTERN int must_notify_vm; EXTERN int must_notify_vm;
EXTERN struct proc *ptproc;
/* Verbose flags (debugging). */ /* Verbose flags (debugging). */
EXTERN int verbose_vm; EXTERN int verbose_vm;

View File

@ -17,6 +17,7 @@
#include <minix/com.h> #include <minix/com.h>
#include <minix/endpoint.h> #include <minix/endpoint.h>
#include "proc.h" #include "proc.h"
#include "debug.h"
/* Prototype declarations for PRIVATE functions. */ /* Prototype declarations for PRIVATE functions. */
FORWARD _PROTOTYPE( void announce, (void)); FORWARD _PROTOTYPE( void announce, (void));
@ -185,6 +186,16 @@ PUBLIC void main()
*/ */
bill_ptr = proc_addr(IDLE); /* it has to point somewhere */ bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
announce(); /* print MINIX startup banner */ announce(); /* print MINIX startup banner */
/* Warnings for sanity checks that take time. These warnings are printed
* so it's a clear warning no full release should be done with them
* enabled.
*/
#if DEBUG_SCHED_CHECK
FIXME("DEBUG_SCHED_CHECK enabled");
#endif
#if DEBUG_VMASSERT
FIXME("DEBUG_VMASSERT enabled");
#endif
restart(); restart();
} }

View File

@ -82,19 +82,12 @@ FORWARD _PROTOTYPE( void pick_proc, (void));
break; \ break; \
} }
#define CopyMess(s,sp,sm,dp,dm) do { \ #define RETRYCOPY(sp, dp, sm, dm) {\
vir_bytes dstlin; \ if(r != EFAULT_DST) { \
endpoint_t e = proc_addr(s)->p_endpoint; \ kprintf("error %d\n", r); \
struct vir_addr src, dst; \ minix_panic("CopyMess: copy error", __LINE__); \
int r; \ } \
if((dstlin = umap_local((dp), D, (vir_bytes) dm, sizeof(message))) == 0){\ vm_suspend(dp, dp); \
minix_panic("CopyMess: umap_local failed", __LINE__); \
} \
\
if(vm_running && \
(r=vm_checkrange((dp), (dp), dstlin, sizeof(message), 1, 0)) != OK) { \
if(r != VMSUSPEND) \
minix_panic("CopyMess: vm_checkrange error", __LINE__); \
(dp)->p_vmrequest.saved.msgcopy.dst = (dp); \ (dp)->p_vmrequest.saved.msgcopy.dst = (dp); \
(dp)->p_vmrequest.saved.msgcopy.dst_v = (vir_bytes) dm; \ (dp)->p_vmrequest.saved.msgcopy.dst_v = (vir_bytes) dm; \
if(data_copy((sp)->p_endpoint, \ if(data_copy((sp)->p_endpoint, \
@ -105,25 +98,26 @@ FORWARD _PROTOTYPE( void pick_proc, (void));
} \ } \
(dp)->p_vmrequest.saved.msgcopy.msgbuf.m_source = e; \ (dp)->p_vmrequest.saved.msgcopy.msgbuf.m_source = e; \
(dp)->p_vmrequest.type = VMSTYPE_MSGCOPY; \ (dp)->p_vmrequest.type = VMSTYPE_MSGCOPY; \
} else { \ }
src.proc_nr_e = (sp)->p_endpoint; \
dst.proc_nr_e = (dp)->p_endpoint; \ #define CopyMess(s,sp,sm,dp,dm) do { \
src.segment = dst.segment = D; \ endpoint_t e = proc_addr(s)->p_endpoint; \
src.offset = (vir_bytes) (sm); \ struct vir_addr src, dst; \
dst.offset = (vir_bytes) (dm); \ int r; \
if(virtual_copy(&src, &dst, sizeof(message)) != OK) { \ src.proc_nr_e = (sp)->p_endpoint; \
kprintf("copymess: copy %d:%lx to %d:%lx failed\n",\ dst.proc_nr_e = (dp)->p_endpoint; \
(sp)->p_endpoint, (sm), (dp)->p_endpoint, dm);\ src.segment = dst.segment = D; \
minix_panic("CopyMess: virtual_copy (1) failed", __LINE__); \ 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.proc_nr_e = SYSTEM; \
src.offset = (vir_bytes) &e; \ src.offset = (vir_bytes) &e; \
if(virtual_copy(&src, &dst, sizeof(e)) != OK) { \ if((r=virtual_copy(&src, &dst, sizeof(e))) != OK) { \
kprintf("copymess: copy %d:%lx to %d:%lx\n", \ RETRYCOPY(sp, dp, sm, dm) \
(sp)->p_endpoint, (sm), (dp)->p_endpoint, dm);\
minix_panic("CopyMess: virtual_copy (2) failed", __LINE__); \
} \ } \
} \ } \
} while(0) } while(0)
/*===========================================================================* /*===========================================================================*
@ -1259,8 +1253,8 @@ PRIVATE void pick_proc()
if ( (rp = rdy_head[q]) != NIL_PROC) { if ( (rp = rdy_head[q]) != NIL_PROC) {
next_ptr = rp; /* run process 'rp' next */ next_ptr = rp; /* run process 'rp' next */
#if 0 #if 0
if(rp->p_endpoint != 4 && rp->p_endpoint != 5 && rp->p_endpoint != IDLE && rp->p_endpoint != SYSTEM) if(!iskernelp(rp))
kprintf("[run %s]", rp->p_name); kprintf("[run %s/%d]", rp->p_name, rp->p_endpoint);
#endif #endif
if (priv(rp)->s_flags & BILLABLE) if (priv(rp)->s_flags & BILLABLE)
bill_ptr = rp; /* bill for system time */ bill_ptr = rp; /* bill for system time */

View File

@ -107,6 +107,7 @@ struct proc {
#define PMAGIC 0xC0FFEE1 #define PMAGIC 0xC0FFEE1
int p_magic; /* check validity of proc pointers */ int p_magic; /* check validity of proc pointers */
#endif #endif
int verbose;
}; };
/* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */ /* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */

View File

@ -33,7 +33,7 @@ _PROTOTYPE( int sys_call, (int call_nr, int src_dst,
message *m_ptr, long bit_map) ); message *m_ptr, long bit_map) );
_PROTOTYPE( void sys_call_restart, (struct proc *caller) ); _PROTOTYPE( void sys_call_restart, (struct proc *caller) );
_PROTOTYPE( int lock_notify, (int src, int dst) ); _PROTOTYPE( int lock_notify, (int src, int dst) );
_PROTOTYPE( int soft_notify, (int dst) ); _PROTOTYPE( int soft_notify, (int dst) );
_PROTOTYPE( int lock_send, (int dst, message *m_ptr) ); _PROTOTYPE( int lock_send, (int dst, message *m_ptr) );
_PROTOTYPE( void lock_enqueue, (struct proc *rp) ); _PROTOTYPE( void lock_enqueue, (struct proc *rp) );
_PROTOTYPE( void lock_dequeue, (struct proc *rp) ); _PROTOTYPE( void lock_dequeue, (struct proc *rp) );
@ -87,6 +87,7 @@ _PROTOTYPE( void cons_seth, (int pos, int n) );
#define CHECK_RUNQUEUES check_runqueues_f(__FILE__, __LINE__) #define CHECK_RUNQUEUES check_runqueues_f(__FILE__, __LINE__)
_PROTOTYPE( void check_runqueues_f, (char *file, int line) ); _PROTOTYPE( void check_runqueues_f, (char *file, int line) );
#endif #endif
_PROTOTYPE( char *rtsflagstr, (int flags) );
/* system/do_safecopy.c */ /* system/do_safecopy.c */
_PROTOTYPE( int verify_grant, (endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes, _PROTOTYPE( int verify_grant, (endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes,
@ -113,7 +114,7 @@ _PROTOTYPE( int data_copy, (endpoint_t from, vir_bytes from_addr,
#define data_copy_to(d, p, v, n) data_copy(SYSTEM, (d), (p), (v), (n)); #define data_copy_to(d, p, v, n) data_copy(SYSTEM, (d), (p), (v), (n));
#define data_copy_from(d, p, v, n) data_copy((p), (v), SYSTEM, (d), (n)); #define data_copy_from(d, p, v, n) data_copy((p), (v), SYSTEM, (d), (n));
_PROTOTYPE( void alloc_segments, (struct proc *rp) ); _PROTOTYPE( void alloc_segments, (struct proc *rp) );
_PROTOTYPE( void vm_init, (void) ); _PROTOTYPE( void vm_init, (struct proc *first) );
_PROTOTYPE( void vm_map_range, (u32_t base, u32_t size, u32_t offset) ); _PROTOTYPE( void vm_map_range, (u32_t base, u32_t size, u32_t offset) );
_PROTOTYPE( int vm_copy, (vir_bytes src, struct proc *srcproc, _PROTOTYPE( int vm_copy, (vir_bytes src, struct proc *srcproc,
vir_bytes dst, struct proc *dstproc, phys_bytes bytes)); vir_bytes dst, struct proc *dstproc, phys_bytes bytes));
@ -126,7 +127,7 @@ _PROTOTYPE( phys_bytes umap_remote, (struct proc* rp, int seg,
_PROTOTYPE( phys_bytes umap_virtual, (struct proc* rp, int seg, _PROTOTYPE( phys_bytes umap_virtual, (struct proc* rp, int seg,
vir_bytes vir_addr, vir_bytes bytes) ); vir_bytes vir_addr, vir_bytes bytes) );
_PROTOTYPE( phys_bytes seg2phys, (U16_t) ); _PROTOTYPE( phys_bytes seg2phys, (U16_t) );
_PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern, _PROTOTYPE( int vm_phys_memset, (phys_bytes source, u8_t pattern,
phys_bytes count) ); phys_bytes count) );
_PROTOTYPE( vir_bytes alloc_remote_segment, (u32_t *, segframe_t *, _PROTOTYPE( vir_bytes alloc_remote_segment, (u32_t *, segframe_t *,
int, phys_bytes, vir_bytes, int)); int, phys_bytes, vir_bytes, int));
@ -160,5 +161,6 @@ _PROTOTYPE( int vm_checkrange, (struct proc *caller, struct proc *target,
vir_bytes start, vir_bytes length, int writeflag, int checkonly)); vir_bytes start, vir_bytes length, int writeflag, int checkonly));
_PROTOTYPE( void proc_stacktrace, (struct proc *proc) ); _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_lookup, (struct proc *proc, vir_bytes virtual, vir_bytes *result, u32_t *ptent));
_PROTOTYPE( int vm_suspend, (struct proc *caller, struct proc *target));
#endif /* PROTO_H */ #endif /* PROTO_H */

View File

@ -121,8 +121,12 @@ PUBLIC void sys_task()
if (curr < limit+extra) if (curr < limit+extra)
{ {
#if 0
kprintf("SYSTEM: request %d from %d denied.\n", kprintf("SYSTEM: request %d from %d denied.\n",
call_nr, m.m_source); call_nr, m.m_source);
#else
FIXME("privileges bypassed");
#endif
} else if (curr == limit+extra) } else if (curr == limit+extra)
{ {
kprintf("sys_task: no debug output for a while\n"); kprintf("sys_task: no debug output for a while\n");
@ -220,7 +224,6 @@ PRIVATE void initialize(void)
map(SYS_NEWMAP, do_newmap); /* set up a process memory map */ map(SYS_NEWMAP, do_newmap); /* set up a process memory map */
map(SYS_SEGCTL, do_segctl); /* add segment and get selector */ map(SYS_SEGCTL, do_segctl); /* add segment and get selector */
map(SYS_MEMSET, do_memset); /* write char to memory area */ map(SYS_MEMSET, do_memset); /* write char to memory area */
map(SYS_VM_SETBUF, do_vm_setbuf); /* PM passes buffer for page tables */
map(SYS_VMCTL, do_vmctl); /* various VM process settings */ map(SYS_VMCTL, do_vmctl); /* various VM process settings */
/* Copying. */ /* Copying. */
@ -424,7 +427,10 @@ register struct proc *rc; /* slot of process to clean up */
if(isemptyp(rc)) minix_panic("clear_proc: empty process", rc->p_endpoint); if(isemptyp(rc)) minix_panic("clear_proc: empty process", rc->p_endpoint);
if(rc->p_endpoint == PM_PROC_NR || rc->p_endpoint == VFS_PROC_NR) { #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, /* This test is great for debugging system processes dying,
* but as this happens normally on reboot, not good permanent code. * but as this happens normally on reboot, not good permanent code.
*/ */
@ -432,7 +438,9 @@ register struct proc *rc; /* slot of process to clean up */
proc_stacktrace(rc); proc_stacktrace(rc);
kprintf("kernel trace: "); kprintf("kernel trace: ");
util_stacktrace(); util_stacktrace();
#if 0
minix_panic("clear_proc: system process died", rc->p_endpoint); minix_panic("clear_proc: system process died", rc->p_endpoint);
#endif
} }
/* Make sure that the exiting process is no longer scheduled. */ /* Make sure that the exiting process is no longer scheduled. */
@ -619,6 +627,8 @@ PRIVATE struct proc *vmrestart_check(message *m)
return NULL; return NULL;
case VMSTYPE_MSGCOPY: case VMSTYPE_MSGCOPY:
/* Do delayed message copy. */ /* Do delayed message copy. */
printf("copying message into %d..\n",
restarting->p_vmrequest.saved.msgcopy.dst->p_endpoint);
if((r=data_copy(SYSTEM, if((r=data_copy(SYSTEM,
(vir_bytes) &restarting->p_vmrequest.saved.msgcopy.msgbuf, (vir_bytes) &restarting->p_vmrequest.saved.msgcopy.msgbuf,
restarting->p_vmrequest.saved.msgcopy.dst->p_endpoint, restarting->p_vmrequest.saved.msgcopy.dst->p_endpoint,
@ -626,6 +636,7 @@ PRIVATE struct proc *vmrestart_check(message *m)
sizeof(message))) != OK) { sizeof(message))) != OK) {
minix_panic("SYSTEM: delayed msgcopy failed", r); minix_panic("SYSTEM: delayed msgcopy failed", r);
} }
printf("OK!\n");
RTS_LOCK_UNSET(restarting, VMREQUEST); RTS_LOCK_UNSET(restarting, VMREQUEST);
/* Handled; restart system loop. */ /* Handled; restart system loop. */

View File

@ -91,9 +91,6 @@ _PROTOTYPE( int do_memset, (message *m_ptr) );
#define do_memset do_unused #define do_memset do_unused
#endif #endif
_PROTOTYPE( int do_vm_setbuf, (message *m_ptr) );
_PROTOTYPE( int do_vm_map, (message *m_ptr) );
_PROTOTYPE( int do_abort, (message *m_ptr) ); _PROTOTYPE( int do_abort, (message *m_ptr) );
#if ! USE_ABORT #if ! USE_ABORT
#define do_abort do_unused #define do_abort do_unused

View File

@ -42,6 +42,8 @@ register message *m_ptr; /* pointer to request message */
/* No reply to EXEC call */ /* No reply to EXEC call */
RTS_LOCK_UNSET(rp, RECEIVING); RTS_LOCK_UNSET(rp, RECEIVING);
printf("kernel: exec %d now %s\n", rp->p_endpoint, rp->p_name);
return(OK); return(OK);
} }
#endif /* USE_EXEC */ #endif /* USE_EXEC */

View File

@ -88,6 +88,9 @@ register message *m_ptr; /* pointer to request message */
RTS_LOCK_UNSET(rpc, (SIGNALED | SIG_PENDING | P_STOP)); RTS_LOCK_UNSET(rpc, (SIGNALED | SIG_PENDING | P_STOP));
sigemptyset(&rpc->p_pending); sigemptyset(&rpc->p_pending);
printf("kernel: %d / %s forked into %d\n",
rpp->p_endpoint, rpp->p_name, rpc->p_endpoint);
return r; return r;
} }

View File

@ -18,10 +18,8 @@ PUBLIC int do_memset(m_ptr)
register message *m_ptr; register message *m_ptr;
{ {
/* Handle sys_memset(). This writes a pattern into the specified memory. */ /* Handle sys_memset(). This writes a pattern into the specified memory. */
unsigned long p;
unsigned char c = m_ptr->MEM_PATTERN; unsigned char c = m_ptr->MEM_PATTERN;
p = c | (c << 8) | (c << 16) | (c << 24); vm_phys_memset((phys_bytes) m_ptr->MEM_PTR, c, (phys_bytes) m_ptr->MEM_COUNT);
phys_memset((phys_bytes) m_ptr->MEM_PTR, p, (phys_bytes) m_ptr->MEM_COUNT);
return(OK); return(OK);
} }

View File

@ -8,6 +8,8 @@
*/ */
#include "../system.h" #include "../system.h"
#if 0
#define VM_DEBUG 0 /* enable/ disable debug output */ #define VM_DEBUG 0 /* enable/ disable debug output */
/*===========================================================================* /*===========================================================================*
@ -27,3 +29,5 @@ message *m_ptr; /* pointer to request message */
return OK; return OK;
} }
#endif

View File

@ -25,8 +25,6 @@ register message *m_ptr; /* pointer to request message */
if(ep == SELF) { ep = m_ptr->m_source; } if(ep == SELF) { ep = m_ptr->m_source; }
vm_init();
if(!isokendpt(ep, &proc_nr)) { if(!isokendpt(ep, &proc_nr)) {
kprintf("do_vmctl: unexpected endpoint %d from VM\n", ep); kprintf("do_vmctl: unexpected endpoint %d from VM\n", ep);
return EINVAL; return EINVAL;
@ -45,6 +43,9 @@ register message *m_ptr; /* pointer to request message */
if(!RTS_ISSET(rp, VMREQUEST)) if(!RTS_ISSET(rp, VMREQUEST))
minix_panic("do_vmctl: no VMREQUEST set", NO_NUM); minix_panic("do_vmctl: no VMREQUEST set", NO_NUM);
printf("kernel: vm request sent by: %s / %d about %d\n",
rp->p_name, rp->p_endpoint, rp->p_vmrequest.who);
/* Reply with request fields. */ /* Reply with request fields. */
m_ptr->SVMCTL_MRG_ADDR = (char *) rp->p_vmrequest.start; m_ptr->SVMCTL_MRG_ADDR = (char *) rp->p_vmrequest.start;
m_ptr->SVMCTL_MRG_LEN = rp->p_vmrequest.length; m_ptr->SVMCTL_MRG_LEN = rp->p_vmrequest.length;
@ -73,6 +74,7 @@ register message *m_ptr; /* pointer to request message */
rp->p_vmrequest.vmresult); rp->p_vmrequest.vmresult);
/* Put on restart chain. */ /* Put on restart chain. */
printf("kernel: vm reply received for %d\n", rp->p_endpoint);
rp->p_vmrequest.nextrestart = vmrestart; rp->p_vmrequest.nextrestart = vmrestart;
vmrestart = rp; vmrestart = rp;
@ -93,10 +95,15 @@ kprintf("SYSTEM: request %d:0x%lx-0x%lx, wrflag %d, failed\n",
} }
#endif #endif
return OK; return OK;
#if VM_KERN_NOPAGEZERO case VMCTL_ENABLE_PAGING:
case VMCTL_NOPAGEZERO: if(vm_running)
minix_panic("do_vmctl: paging already enabled", NO_NUM);
vm_init(p);
if(!vm_running)
minix_panic("do_vmctl: paging enabling failed", NO_NUM);
if(newmap(p, m_ptr->SVMCTL_VALUE) != OK)
minix_panic("do_vmctl: newmap failed", NO_NUM);
return OK; return OK;
#endif
} }
/* Try architecture-specific vmctls. */ /* Try architecture-specific vmctls. */

View File

@ -96,7 +96,8 @@ PRIVATE int
drv_c[] = { DRV_C }, drv_c[] = { DRV_C },
tty_c[] = { DRV_C, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE, tty_c[] = { DRV_C, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
SYS_READBIOS }, SYS_READBIOS },
mem_c[] = { DRV_C, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_IOPENABLE }; mem_c[] = { DRV_C, SYS_PHYSCOPY, SYS_PHYSVCOPY, SYS_IOPENABLE },
usr_c[] = { SYS_SYSCTL };
/* The system image table lists all programs that are part of the boot image. /* The system image table lists all programs that are part of the boot image.
* The order of the entries here MUST agree with the order of the programs * The order of the entries here MUST agree with the order of the programs
@ -126,7 +127,7 @@ PUBLIC struct boot_image image[] = {
{LOG_PROC_NR, 0,SVM_F, 4, 2, 0, SRV_T, SYS_M,c(drv_c),"log" }, {LOG_PROC_NR, 0,SVM_F, 4, 2, 0, SRV_T, SYS_M,c(drv_c),"log" },
{MFS_PROC_NR, 0,SVM_F, 32, 5, 0, SRV_T, SRV_M, c(fs_c),"mfs" }, {MFS_PROC_NR, 0,SVM_F, 32, 5, 0, SRV_T, SRV_M, c(fs_c),"mfs" },
{VM_PROC_NR, 0,SRV_F, 32, 2, 0, SRV_T, SRV_M, c(vm_c),"vm" }, {VM_PROC_NR, 0,SRV_F, 32, 2, 0, SRV_T, SRV_M, c(vm_c),"vm" },
{INIT_PROC_NR, 0,USR_F, 8, USER_Q, 0, USR_T, USR_M, no_c,"init" }, {INIT_PROC_NR, 0,USR_F, 8, USER_Q, 0, USR_T, USR_M, c(usr_c),"init" },
}; };
/* Verify the size of the system image table at compile time. Also verify that /* Verify the size of the system image table at compile time. Also verify that

View File

@ -37,7 +37,7 @@ char *mess;
int nr; int nr;
{ {
/* The system has run aground of a fatal kernel error. Terminate execution. */ /* The system has run aground of a fatal kernel error. Terminate execution. */
if (minix_panicing ++) return; /* prevent recursive panics */ if (!minix_panicing++) {
if (mess != NULL) { if (mess != NULL) {
kprintf("kernel panic: %s", mess); kprintf("kernel panic: %s", mess);
@ -48,6 +48,7 @@ int nr;
kprintf("kernel stacktrace: "); kprintf("kernel stacktrace: ");
util_stacktrace(); util_stacktrace();
}
/* Abort MINIX. */ /* Abort MINIX. */
minix_shutdown(NULL); minix_shutdown(NULL);
@ -80,12 +81,13 @@ int c; /* character to append */
kmess.km_next = (kmess.km_next + 1) % _KMESS_BUF_SIZE; kmess.km_next = (kmess.km_next + 1) % _KMESS_BUF_SIZE;
} else { } else {
int p, outprocs[] = OUTPUT_PROCS_ARRAY; int p, outprocs[] = OUTPUT_PROCS_ARRAY;
if(do_serial_debug) return; if(!(minix_panicing || do_serial_debug)) {
if(minix_panicing || do_serial_debug) return; for(p = 0; outprocs[p] != NONE; p++) {
for(p = 0; outprocs[p] != NONE; p++) { if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) { send_sig(outprocs[p], SIGKMESS);
send_sig(outprocs[p], SIGKMESS); }
} }
} }
} }
return;
} }

View File

@ -10,10 +10,10 @@
#define CHECKRANGE(pr, start, length, wr) \ #define CHECKRANGE(pr, start, length, wr) \
vm_checkrange(proc_addr(who_p), pr, start, length, wr, 1) vm_checkrange(proc_addr(who_p), pr, start, length, wr, 1)
/* Pseudo error code indicating a process request has to be /* Pseudo error codes */
* restarted after an OK from VM.
*/
#define VMSUSPEND -996 #define VMSUSPEND -996
#define EFAULT_SRC -995
#define EFAULT_DST -994
#endif #endif

View File

@ -6,6 +6,7 @@ LIBRARIES=libsys
libsys_FILES=" \ libsys_FILES=" \
asynsend.c \ asynsend.c \
kmalloc.c \
kprintf.c \ kprintf.c \
kputc.c \ kputc.c \
tickdelay.c \ tickdelay.c \

View File

@ -99,6 +99,7 @@ int main(void)
/* Execute the /etc/rc file. */ /* Execute the /etc/rc file. */
if ((pid = fork()) != 0) { if ((pid = fork()) != 0) {
printf("init: parent (%d)\n", getpid());
/* Parent just waits. */ /* Parent just waits. */
while (wait(NULL) != pid) { while (wait(NULL) != pid) {
if (gotabrt) reboot(RBT_HALT); if (gotabrt) reboot(RBT_HALT);
@ -111,6 +112,7 @@ int main(void)
static char *rc_command[] = { "sh", "/etc/rc", NULL, NULL, NULL }; static char *rc_command[] = { "sh", "/etc/rc", NULL, NULL, NULL };
char **rcp = rc_command + 2; char **rcp = rc_command + 2;
printf("init: child (%d)\n", getpid());
/* Get the boot options from the boot environment. */ /* Get the boot options from the boot environment. */
sysgetenv.key = "bootopts"; sysgetenv.key = "bootopts";
sysgetenv.keylen = 8+1; sysgetenv.keylen = 8+1;
@ -119,7 +121,9 @@ int main(void)
if (svrctl(MMGETPARAM, &sysgetenv) == 0) *rcp++ = bootopts; if (svrctl(MMGETPARAM, &sysgetenv) == 0) *rcp++ = bootopts;
*rcp = "start"; *rcp = "start";
printf("init: %d: exec /etc/rc..\n", getpid());
execute(rc_command); execute(rc_command);
printf("init: %d: exec /etc/rc fail..\n", getpid());
report(2, "sh /etc/rc"); report(2, "sh /etc/rc");
_exit(1); /* impossible, we hope */ _exit(1); /* impossible, we hope */
} }

View File

@ -17,6 +17,7 @@
#include "fs.h" #include "fs.h"
#include <minix/com.h> #include <minix/com.h>
#include <minix/u64.h> #include <minix/u64.h>
#include <string.h>
#include "buf.h" #include "buf.h"
#include "super.h" #include "super.h"
#include "inode.h" #include "inode.h"
@ -24,6 +25,9 @@
FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) ); FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
FORWARD _PROTOTYPE( int rw_block, (struct buf *, int) ); FORWARD _PROTOTYPE( int rw_block, (struct buf *, int) );
char saved[100];
char *savedptr;
/*===========================================================================* /*===========================================================================*
* get_block * * get_block *
*===========================================================================*/ *===========================================================================*/
@ -48,10 +52,19 @@ int only_search; /* if NO_READ, don't read, else act normal */
*/ */
int b; int b;
register struct buf *bp, *prev_ptr; static struct buf *bp, *prev_ptr;
savedptr = (vir_bytes) &b + sizeof(b);
memcpy(saved, savedptr, sizeof(saved));
#define CHECK \
if(memcmp(saved, savedptr, sizeof(saved))) \
panic(__FILE__,"memory corruption", __LINE__);
ASSERT(fs_block_size > 0); ASSERT(fs_block_size > 0);
CHECK;
/* Search the hash chain for (dev, block). Do_read() can use /* Search the hash chain for (dev, block). Do_read() can use
* get_block(NO_DEV ...) to get an unnamed block to fill with zeros when * get_block(NO_DEV ...) to get an unnamed block to fill with zeros when
* someone wants to read from a hole in a file, in which case this search * someone wants to read from a hole in a file, in which case this search
@ -60,8 +73,11 @@ int only_search; /* if NO_READ, don't read, else act normal */
if (dev != NO_DEV) { if (dev != NO_DEV) {
b = BUFHASH(block); b = BUFHASH(block);
bp = buf_hash[b]; bp = buf_hash[b];
CHECK;
while (bp != NIL_BUF) { while (bp != NIL_BUF) {
CHECK;
if (bp->b_blocknr == block && bp->b_dev == dev) { if (bp->b_blocknr == block && bp->b_dev == dev) {
CHECK;
/* Block needed has been found. */ /* Block needed has been found. */
if (bp->b_count == 0) rm_lru(bp); if (bp->b_count == 0) rm_lru(bp);
bp->b_count++; /* record that block is in use */ bp->b_count++; /* record that block is in use */
@ -69,6 +85,7 @@ int only_search; /* if NO_READ, don't read, else act normal */
ASSERT(bp->b_dev == dev); ASSERT(bp->b_dev == dev);
ASSERT(bp->b_dev != NO_DEV); ASSERT(bp->b_dev != NO_DEV);
ASSERT(bp->bp); ASSERT(bp->bp);
CHECK;
return(bp); return(bp);
} else { } else {
/* This block is not the one sought. */ /* This block is not the one sought. */
@ -137,6 +154,7 @@ int only_search; /* if NO_READ, don't read, else act normal */
ASSERT(bp->bp); ASSERT(bp->bp);
CHECK;
return(bp); /* return the newly acquired block */ return(bp); /* return the newly acquired block */
} }

View File

@ -452,9 +452,13 @@ PRIVATE void send_work()
rmp->mp_fs_call= PM_IDLE; rmp->mp_fs_call= PM_IDLE;
/* Wakeup the newly created process */ /* Wakeup the newly created process */
printf("PM: replying fork OK to child %d\n",
rmp->mp_endpoint);
setreply(rmp-mproc, OK); setreply(rmp-mproc, OK);
/* Wakeup the parent */ /* 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); setreply(parent_mp-mproc, rmp->mp_pid);
break; break;
} }

View File

@ -5,7 +5,7 @@
#define _MINIX 1 /* tell headers to include MINIX stuff */ #define _MINIX 1 /* tell headers to include MINIX stuff */
#define _SYSTEM 1 /* tell headers that this is the kernel */ #define _SYSTEM 1 /* tell headers that this is the kernel */
#define DO_SANITYCHECKS 0 #define DO_SANITYCHECKS 1
#if DO_SANITYCHECKS #if DO_SANITYCHECKS
#define SANITYCHECK do { \ #define SANITYCHECK do { \

View File

@ -26,6 +26,7 @@
#include <minix/const.h> #include <minix/const.h>
#include <minix/endpoint.h> #include <minix/endpoint.h>
#include <minix/safecopies.h> #include <minix/safecopies.h>
#include <minix/debug.h>
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
@ -59,6 +60,10 @@ PUBLIC int main()
SANITYCHECK; SANITYCHECK;
#if DO_SANITYCHECKS
FIXME("VFS: DO_SANITYCHECKS is on");
#endif
/* This is the main loop that gets work, processes it, and sends replies. */ /* This is the main loop that gets work, processes it, and sends replies. */
while (TRUE) { while (TRUE) {
SANITYCHECK; SANITYCHECK;

View File

@ -55,6 +55,8 @@ PUBLIC int do_exit(message *msg)
SANITYCHECK(SCL_FUNCTIONS); SANITYCHECK(SCL_FUNCTIONS);
printf("VM: %d exiting\n", msg->VME_ENDPOINT);
if(vm_isokendpt(msg->VME_ENDPOINT, &proc) != OK) { if(vm_isokendpt(msg->VME_ENDPOINT, &proc) != OK) {
printf("VM: bogus endpoint VM_EXIT %d\n", msg->VME_ENDPOINT); printf("VM: bogus endpoint VM_EXIT %d\n", msg->VME_ENDPOINT);
return EINVAL; return EINVAL;

View File

@ -13,6 +13,7 @@
#include <minix/ipc.h> #include <minix/ipc.h>
#include <minix/sysutil.h> #include <minix/sysutil.h>
#include <minix/syslib.h> #include <minix/syslib.h>
#include <minix/debug.h>
#include <errno.h> #include <errno.h>
#include <env.h> #include <env.h>
@ -31,6 +32,7 @@ PUBLIC int do_fork(message *msg)
{ {
int r, proc, s, childproc, fullvm; int r, proc, s, childproc, fullvm;
struct vmproc *vmp, *vmc; struct vmproc *vmp, *vmc;
pt_t origpt;
SANITYCHECK(SCL_FUNCTIONS); SANITYCHECK(SCL_FUNCTIONS);
@ -49,6 +51,7 @@ PUBLIC int do_fork(message *msg)
vmp = &vmproc[proc]; /* parent */ vmp = &vmproc[proc]; /* parent */
vmc = &vmproc[childproc]; /* child */ vmc = &vmproc[childproc]; /* child */
vm_assert(vmc->vm_slot == childproc);
if(vmp->vm_flags & VMF_HAS_DMA) { if(vmp->vm_flags & VMF_HAS_DMA) {
printf("VM: %d has DMA memory and may not fork\n", msg->VMF_ENDPOINT); printf("VM: %d has DMA memory and may not fork\n", msg->VMF_ENDPOINT);
@ -58,14 +61,20 @@ PUBLIC int do_fork(message *msg)
fullvm = vmp->vm_flags & VMF_HASPT; fullvm = vmp->vm_flags & VMF_HASPT;
/* The child is basically a copy of the parent. */ /* The child is basically a copy of the parent. */
origpt = vmc->vm_pt;
*vmc = *vmp; *vmc = *vmp;
vmc->vm_slot = childproc;
vmc->vm_regions = NULL; vmc->vm_regions = NULL;
vmc->vm_endpoint = NONE; /* In case someone tries to use it. */ vmc->vm_endpoint = NONE; /* In case someone tries to use it. */
vmc->vm_pt = origpt;
vmc->vm_flags &= ~VMF_HASPT;
#if VMSTATS #if VMSTATS
vmc->vm_bytecopies = 0; vmc->vm_bytecopies = 0;
#endif #endif
SANITYCHECK(SCL_DETAIL);
if(fullvm) { if(fullvm) {
SANITYCHECK(SCL_DETAIL); SANITYCHECK(SCL_DETAIL);
@ -74,6 +83,8 @@ PUBLIC int do_fork(message *msg)
return ENOMEM; return ENOMEM;
} }
vmc->vm_flags |= VMF_HASPT;
SANITYCHECK(SCL_DETAIL); SANITYCHECK(SCL_DETAIL);
if(map_proc_copy(vmc, vmp) != OK) { if(map_proc_copy(vmc, vmp) != OK) {
@ -108,6 +119,7 @@ PUBLIC int do_fork(message *msg)
/* Create a copy of the parent's core image for the child. */ /* Create a copy of the parent's core image for the child. */
child_abs = (phys_bytes) child_base << CLICK_SHIFT; child_abs = (phys_bytes) child_base << CLICK_SHIFT;
parent_abs = (phys_bytes) vmp->vm_arch.vm_seg[D].mem_phys << CLICK_SHIFT; parent_abs = (phys_bytes) vmp->vm_arch.vm_seg[D].mem_phys << CLICK_SHIFT;
FIXME("VM uses kernel for abscopy");
s = sys_abscopy(parent_abs, child_abs, prog_bytes); s = sys_abscopy(parent_abs, child_abs, prog_bytes);
if (s < 0) vm_panic("do_fork can't copy", s); if (s < 0) vm_panic("do_fork can't copy", s);

View File

@ -44,6 +44,8 @@ PRIVATE u32_t varmap_loc; /* Our page table. */
PRIVATE int kernel_pde = -1, pagedir_pde = -1; PRIVATE int kernel_pde = -1, pagedir_pde = -1;
PRIVATE u32_t kern_pde_val = 0, global_bit = 0, pagedir_pde_val; PRIVATE u32_t kern_pde_val = 0, global_bit = 0, pagedir_pde_val;
PRIVATE int proc_pde = 0;
/* 4MB page size available in hardware? */ /* 4MB page size available in hardware? */
PRIVATE int bigpage_ok = 0; PRIVATE int bigpage_ok = 0;
@ -82,7 +84,6 @@ PRIVATE struct {
u32_t page_directories_phys, *page_directories = NULL; u32_t page_directories_phys, *page_directories = NULL;
#if SANITYCHECKS #if SANITYCHECKS
#define PT_SANE(p) { pt_sanitycheck((p), __FILE__, __LINE__); SANITYCHECK(SCL_DETAIL); }
/*===========================================================================* /*===========================================================================*
* pt_sanitycheck * * pt_sanitycheck *
*===========================================================================*/ *===========================================================================*/
@ -90,21 +91,33 @@ PUBLIC void pt_sanitycheck(pt_t *pt, char *file, int line)
{ {
/* Basic pt sanity check. */ /* Basic pt sanity check. */
int i; int i;
int slot;
MYASSERT(pt); MYASSERT(pt);
MYASSERT(pt->pt_dir); MYASSERT(pt->pt_dir);
MYASSERT(pt->pt_dir_phys); MYASSERT(pt->pt_dir_phys);
for(i = 0; i < I386_VM_DIR_ENTRIES; i++) { for(slot = 0; slot < ELEMENTS(vmproc); slot++) {
if(pt == &vmproc[slot].vm_pt)
break;
}
if(slot >= ELEMENTS(vmproc)) {
vm_panic("pt_sanitycheck: passed pt not in any proc", NO_NUM);
}
for(i = proc_pde; i < I386_VM_DIR_ENTRIES; i++) {
if(pt->pt_pt[i]) { if(pt->pt_pt[i]) {
if(!(pt->pt_dir[i] & I386_VM_PRESENT)) {
printf("slot %d: pt->pt_pt[%d] = 0x%lx, but pt_dir entry 0x%lx\n",
slot, i, pt->pt_pt[i], pt->pt_dir[i]);
}
MYASSERT(pt->pt_dir[i] & I386_VM_PRESENT); MYASSERT(pt->pt_dir[i] & I386_VM_PRESENT);
} else { } else {
MYASSERT(!(pt->pt_dir[i] & I386_VM_PRESENT)); MYASSERT(!(pt->pt_dir[i] & I386_VM_PRESENT));
} }
} }
} }
#else
#define PT_SANE(p)
#endif #endif
/*===========================================================================* /*===========================================================================*
@ -348,7 +361,7 @@ PRIVATE int pt_ptalloc(pt_t *pt, int pde, u32_t flags)
/* Argument must make sense. */ /* Argument must make sense. */
vm_assert(pde >= 0 && pde < I386_VM_DIR_ENTRIES); vm_assert(pde >= 0 && pde < I386_VM_DIR_ENTRIES);
vm_assert(!(flags & ~(PTF_ALLFLAGS | PTF_MAPALLOC))); vm_assert(!(flags & ~(PTF_ALLFLAGS)));
/* We don't expect to overwrite page directory entry, nor /* We don't expect to overwrite page directory entry, nor
* storage for the page table. * storage for the page table.
@ -386,10 +399,9 @@ PUBLIC int pt_writemap(pt_t *pt, vir_bytes v, phys_bytes physaddr,
/* Page directory and table entries for this virtual address. */ /* Page directory and table entries for this virtual address. */
int p, pages, pde; int p, pages, pde;
int finalpde; int finalpde;
SANITYCHECK(SCL_FUNCTIONS);
vm_assert(!(bytes % I386_PAGE_SIZE)); vm_assert(!(bytes % I386_PAGE_SIZE));
vm_assert(!(flags & ~(PTF_ALLFLAGS | PTF_MAPALLOC))); vm_assert(!(flags & ~(PTF_ALLFLAGS)));
pages = bytes / I386_PAGE_SIZE; pages = bytes / I386_PAGE_SIZE;
@ -471,7 +483,7 @@ PUBLIC int pt_writemap(pt_t *pt, vir_bytes v, phys_bytes physaddr,
v += I386_PAGE_SIZE; v += I386_PAGE_SIZE;
PT_SANE(pt); PT_SANE(pt);
} }
SANITYCHECK(SCL_FUNCTIONS);
PT_SANE(pt); PT_SANE(pt);
return OK; return OK;
@ -489,7 +501,14 @@ PUBLIC int pt_new(pt_t *pt)
*/ */
int i; int i;
if(!(pt->pt_dir = vm_allocpages(&pt->pt_dir_phys, 1, VMP_PAGEDIR))) { /* Don't ever re-allocate/re-move a certain process slot's
* page directory once it's been created. This is a fraction
* faster, but also avoids having to invalidate the page
* mappings from in-kernel page tables pointing to
* the page directories (the page_directories data).
*/
if(!pt->pt_dir &&
!(pt->pt_dir = vm_allocpages(&pt->pt_dir_phys, 1, VMP_PAGEDIR))) {
return ENOMEM; return ENOMEM;
} }
@ -501,10 +520,14 @@ PUBLIC int pt_new(pt_t *pt)
/* Where to start looking for free virtual address space? */ /* Where to start looking for free virtual address space? */
pt->pt_virtop = 0; pt->pt_virtop = 0;
PT_SANE(pt);
/* Map in kernel. */ /* Map in kernel. */
if(pt_mapkernel(pt) != OK) if(pt_mapkernel(pt) != OK)
vm_panic("pt_new: pt_mapkernel failed", NO_NUM); vm_panic("pt_new: pt_mapkernel failed", NO_NUM);
PT_SANE(pt);
return OK; return OK;
} }
@ -565,17 +588,15 @@ PUBLIC void pt_init(void)
*/ */
kern_pde_val = (KERNEL_TEXT & I386_VM_ADDR_MASK_4MB) | kern_pde_val = (KERNEL_TEXT & I386_VM_ADDR_MASK_4MB) |
I386_VM_BIGPAGE| I386_VM_BIGPAGE|
I386_VM_USER|
I386_VM_PRESENT|I386_VM_WRITE|global_bit; I386_VM_PRESENT|I386_VM_WRITE|global_bit;
kernel_pde = pde1; kernel_pde = pde1;
vm_assert(kernel_pde >= 0); vm_assert(kernel_pde >= 0);
free_pde = kernel_pde+1; free_pde = kernel_pde+1;
} }
/* Make new page table for ourselves, partly copied /* First unused pde. */
* from the current one. proc_pde = free_pde;
*/
if(pt_new(newpt) != OK)
vm_panic("pt_init: pt_new failed", NO_NUM);
/* Initial (current) range of our virtual address space. */ /* Initial (current) range of our virtual address space. */
lo = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys); lo = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys);
@ -592,6 +613,12 @@ PUBLIC void pt_init(void)
vm_assert(!(moveup % I386_PAGE_SIZE)); vm_assert(!(moveup % I386_PAGE_SIZE));
} }
/* Make new page table for ourselves, partly copied
* from the current one.
*/
if(pt_new(newpt) != OK)
vm_panic("pt_init: pt_new failed", NO_NUM);
/* Set up mappings for VM process. */ /* Set up mappings for VM process. */
for(v = lo; v < hi; v += I386_PAGE_SIZE) { for(v = lo; v < hi; v += I386_PAGE_SIZE) {
phys_bytes addr; phys_bytes addr;
@ -620,10 +647,9 @@ PUBLIC void pt_init(void)
1, VMP_PAGETABLE))) 1, VMP_PAGETABLE)))
vm_panic("no virt addr for vm mappings", NO_NUM); vm_panic("no virt addr for vm mappings", NO_NUM);
memset(page_directories, 0, I386_PAGE_SIZE); printf("VM: pt made\n");
/* Give our process the new, copied, private page table. */ memset(page_directories, 0, I386_PAGE_SIZE);
pt_bind(newpt, vmp);
/* Increase our hardware data segment to create virtual address /* Increase our hardware data segment to create virtual address
* space above our stack. We want to increase it to VM_DATATOP, * space above our stack. We want to increase it to VM_DATATOP,
@ -639,19 +665,6 @@ PUBLIC void pt_init(void)
(vmp->vm_arch.vm_seg[S].mem_vir + (vmp->vm_arch.vm_seg[S].mem_vir +
vmp->vm_arch.vm_seg[S].mem_len) << CLICK_SHIFT; vmp->vm_arch.vm_seg[S].mem_len) << CLICK_SHIFT;
if((s=sys_newmap(VM_PROC_NR, vmp->vm_arch.vm_seg)) != OK)
vm_panic("VM: pt_init: sys_newmap failed", s);
/* Back to reality - this is where the stack actually is. */
vmp->vm_arch.vm_seg[S].mem_len -= extra_clicks;
/* Wipe old mappings from VM. */
for(v = lo; v < hi; v += I386_PAGE_SIZE) {
if(pt_writemap(newpt, v, MAP_NONE, I386_PAGE_SIZE,
0, WMF_OVERWRITE) != OK)
vm_panic("pt_init: pt_writemap failed", NO_NUM);
}
/* Where our free virtual address space starts. /* Where our free virtual address space starts.
* This is only a hint to the VM system. * This is only a hint to the VM system.
*/ */
@ -671,36 +684,25 @@ PUBLIC void pt_init(void)
} }
varmap = (unsigned char *) arch_map2vir(vmp, varmap_loc); varmap = (unsigned char *) arch_map2vir(vmp, varmap_loc);
printf("VM: setting pagedir_pde\n");
/* Find a PDE below processes available for mapping in the /* Find a PDE below processes available for mapping in the
* page directories (readonly). * page directories (readonly).
*/ */
pagedir_pde = free_pde++; pagedir_pde = free_pde++;
pagedir_pde_val = (page_directories_phys & I386_VM_ADDR_MASK) | pagedir_pde_val = (page_directories_phys & I386_VM_ADDR_MASK) |
I386_VM_PRESENT | I386_VM_USER; I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE;
printf("VM: HACK: pagedir pde val is 0x%x (phys 0x%x)\n",
pagedir_pde_val, page_directories_phys);
/* Temporary hack while kernel still maintains own pagetable */
if((r=sys_vmctl(SELF, VMCTL_I386_PDE, pagedir_pde)) != OK) {
vm_panic("VMCTL_I386_PDE failed", r);
}
printf("VM: HACK: pagedir pde val is 0x%x\n", pagedir_pde_val);
/* Temporary hack while kernel still maintains own pagetable */
if((r=sys_vmctl(SELF, VMCTL_I386_PDEVAL, pagedir_pde_val)) != OK) {
vm_panic("VMCTL_I386_PDEVAL failed", r);
}
/* Tell kernel about free pde's. */ /* Tell kernel about free pde's. */
while(free_pde*I386_BIG_PAGE_SIZE < VM_PROCSTART) { while(free_pde*I386_BIG_PAGE_SIZE < VM_PROCSTART) {
printf("VM: telling kernel about free pde %d\n", free_pde);
if((r=sys_vmctl(SELF, VMCTL_I386_FREEPDE, free_pde++)) != OK) { if((r=sys_vmctl(SELF, VMCTL_I386_FREEPDE, free_pde++)) != OK) {
vm_panic("VMCTL_I386_FREEPDE failed", r); vm_panic("VMCTL_I386_FREEPDE failed", r);
} }
} }
/* first pde in use by process. */
proc_pde = free_pde;
kernlimit = free_pde*I386_BIG_PAGE_SIZE; kernlimit = free_pde*I386_BIG_PAGE_SIZE;
printf("VM: set limit to 0x%x\n", kernlimit); printf("VM: set limit to 0x%x\n", kernlimit);
@ -720,6 +722,33 @@ PUBLIC void pt_init(void)
vm_panic("VMCTL_I386_KERNELLIMIT failed", r); vm_panic("VMCTL_I386_KERNELLIMIT failed", r);
} }
/* 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;
/* Wipe old mappings from VM. */
for(v = lo; v < hi; v += I386_PAGE_SIZE) {
if(pt_writemap(newpt, v, MAP_NONE, I386_PAGE_SIZE,
0, WMF_OVERWRITE) != OK)
vm_panic("pt_init: pt_writemap failed", NO_NUM);
}
printf("VM: pt_init done\n");
/* All OK. */ /* All OK. */
return; return;
} }
@ -750,6 +779,10 @@ PUBLIC int pt_bind(pt_t *pt, struct vmproc *who)
/* Update "page directory pagetable." */ /* Update "page directory pagetable." */
page_directories[slot] = phys | I386_VM_PRESENT|I386_VM_WRITE; page_directories[slot] = phys | I386_VM_PRESENT|I386_VM_WRITE;
#if 0
printf("VM: slot %d has pde val 0x%lx\n", slot, page_directories[slot]);
#endif
/* Tell kernel about new page table root. */ /* Tell kernel about new page table root. */
return sys_vmctl(who->vm_endpoint, VMCTL_I386_SETCR3, return sys_vmctl(who->vm_endpoint, VMCTL_I386_SETCR3,
pt ? pt->pt_dir_phys : 0); pt ? pt->pt_dir_phys : 0);
@ -765,22 +798,14 @@ PUBLIC void pt_free(pt_t *pt)
PT_SANE(pt); PT_SANE(pt);
for(i = 0; i < I386_VM_DIR_ENTRIES; i++) { for(i = 0; i < I386_VM_DIR_ENTRIES; i++)
int p; if(pt->pt_pt[i])
if(pt->pt_pt[i]) { vm_freepages((vir_bytes) pt->pt_pt[i],
for(p = 0; p < I386_VM_PT_ENTRIES; p++) { I386_VM_PFA(pt->pt_dir[i]), 1, VMP_PAGETABLE);
if((pt->pt_pt[i][p] & (PTF_MAPALLOC | I386_VM_PRESENT))
== (PTF_MAPALLOC | I386_VM_PRESENT)) {
u32_t pa = I386_VM_PFA(pt->pt_pt[i][p]);
FREE_MEM(ABS2CLICK(pa), CLICKSPERPAGE);
}
}
vm_freepages((vir_bytes) pt->pt_pt[i],
I386_VM_PFA(pt->pt_dir[i]), 1, VMP_PAGETABLE);
}
}
#if 0
vm_freepages((vir_bytes) pt->pt_dir, pt->pt_dir_phys, 1, VMP_PAGEDIR); vm_freepages((vir_bytes) pt->pt_dir, pt->pt_dir_phys, 1, VMP_PAGEDIR);
#endif
return; return;
} }
@ -797,8 +822,13 @@ PUBLIC int pt_mapkernel(pt_t *pt)
vm_assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE); vm_assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE);
if(bigpage_ok) { if(bigpage_ok) {
pt->pt_dir[kernel_pde] = kern_pde_val; if(kernel_pde >= 0) {
pt->pt_dir[kernel_pde] = kern_pde_val;
} else
vm_panic("VM: pt_mapkernel: no kernel pde", NO_NUM);
} else { } else {
vm_panic("VM: pt_mapkernel: no bigpage", NO_NUM);
/* Map in text. flags: don't write, supervisor only */ /* Map in text. flags: don't write, supervisor only */
if((r=pt_writemap(pt, KERNEL_TEXT, KERNEL_TEXT, KERNEL_TEXT_LEN, if((r=pt_writemap(pt, KERNEL_TEXT, KERNEL_TEXT, KERNEL_TEXT_LEN,
I386_VM_PRESENT|global_bit, 0)) != OK) I386_VM_PRESENT|global_bit, 0)) != OK)
@ -810,40 +840,14 @@ PUBLIC int pt_mapkernel(pt_t *pt)
return r; return r;
} }
/* Kernel also wants to know about all page directories. */ if(pagedir_pde >= 0) {
pt->pt_dir[pagedir_pde] = pagedir_pde_val; /* Kernel also wants to know about all page directories. */
pt->pt_dir[pagedir_pde] = pagedir_pde_val;
return OK; } else {
} printf("VM: pagedir pde not set\n");
/*===========================================================================*
* pt_freerange *
*===========================================================================*/
PUBLIC void pt_freerange(pt_t *pt, vir_bytes low, vir_bytes high)
{
/* Free memory allocated by pagetable functions in this range. */
int pde;
u32_t v;
PT_SANE(pt);
for(v = low; v < high; v += I386_PAGE_SIZE) {
int pte;
pde = I386_VM_PDE(v);
pte = I386_VM_PTE(v);
if(!(pt->pt_dir[pde] & I386_VM_PRESENT))
continue;
if((pt->pt_pt[pde][pte] & (PTF_MAPALLOC | I386_VM_PRESENT))
== (PTF_MAPALLOC | I386_VM_PRESENT)) {
u32_t pa = I386_VM_PFA(pt->pt_pt[pde][pte]);
FREE_MEM(ABS2CLICK(pa), CLICKSPERPAGE);
pt->pt_pt[pde][pte] = 0;
}
} }
PT_SANE(pt); return OK;
return;
} }
/*===========================================================================* /*===========================================================================*
@ -881,8 +885,10 @@ static u32_t ismapped = MAP_NONE;
if(r != OK) \ if(r != OK) \
vm_panic("PHYS_MAP: pt_writemap", NO_NUM); \ vm_panic("PHYS_MAP: pt_writemap", NO_NUM); \
ismapped = wantmapped; \ ismapped = wantmapped; \
/* pt_bind() flushes TLB. */ \ /* Invalidate TLB for this page. */ \
pt_bind(&vmp->vm_pt, vmp); \ if((r=sys_vmctl(SELF, VMCTL_I386_INVLPG, varmap_loc)) != OK) { \
vm_panic("VM: vmctl failed", r); \
} \
} \ } \
} }
@ -891,7 +897,7 @@ static u32_t ismapped = MAP_NONE;
#if SANITYCHECKS #if SANITYCHECKS
#define PHYS_UNMAP if(OK != pt_writemap(&vmp->vm_pt, varmap_loc, MAP_NONE,\ #define PHYS_UNMAP if(OK != pt_writemap(&vmp->vm_pt, varmap_loc, MAP_NONE,\
I386_PAGE_SIZE, 0, WMF_OVERWRITE)) { \ I386_PAGE_SIZE, 0, WMF_OVERWRITE)) { \
vm_panic("PHYS_UNMAP: pt_writemap failed", NO_NUM); } vm_panic("PHYS_UNMAP: pt_writemap failed", NO_NUM); } \
ismapped = MAP_NONE; ismapped = MAP_NONE;
#endif #endif

View File

@ -5,6 +5,8 @@
#include <stdint.h> #include <stdint.h>
#include <sys/vm_i386.h> #include <sys/vm_i386.h>
#include "../vm.h"
/* An i386 pagetable. */ /* An i386 pagetable. */
typedef struct { typedef struct {
/* Directory entries in VM addr space - root of page table. */ /* Directory entries in VM addr space - root of page table. */
@ -34,5 +36,12 @@ typedef struct {
*/ */
#define PTF_ALLFLAGS (PTF_WRITE|PTF_PRESENT|PTF_USER|PTF_GLOBAL) #define PTF_ALLFLAGS (PTF_WRITE|PTF_PRESENT|PTF_USER|PTF_GLOBAL)
#if SANITYCHECKS
#define PT_SANE(p) { pt_sanitycheck((p), __FILE__, __LINE__); }
#else
#define PT_SANE(p)
#endif #endif
#endif

View File

@ -25,73 +25,6 @@
#include "memory.h" #include "memory.h"
#define PAGE_SIZE 4096
#define PAGE_DIR_SIZE (1024*PAGE_SIZE)
#define PAGE_TABLE_COVER (1024*PAGE_SIZE)
/*=========================================================================*
* arch_init_vm *
*=========================================================================*/
PUBLIC void arch_init_vm(mem_chunks)
struct memory mem_chunks[NR_MEMS];
{
phys_bytes high, bytes;
phys_clicks clicks, base_click;
unsigned pages;
int i, r;
/* Compute the highest memory location */
high= 0;
for (i= 0; i<NR_MEMS; i++)
{
if (mem_chunks[i].size == 0)
continue;
if (mem_chunks[i].base + mem_chunks[i].size > high)
high= mem_chunks[i].base + mem_chunks[i].size;
}
high <<= CLICK_SHIFT;
#if VERBOSE_VM
printf("do_x86_vm: found high 0x%x\n", high);
#endif
/* Rounding up */
high= (high-1+PAGE_DIR_SIZE) & ~(PAGE_DIR_SIZE-1);
/* The number of pages we need is one for the page directory, enough
* page tables to cover the memory, and one page for alignement.
*/
pages= 1 + (high + PAGE_TABLE_COVER-1)/PAGE_TABLE_COVER + 1;
bytes= pages*PAGE_SIZE;
clicks= (bytes + CLICK_SIZE-1) >> CLICK_SHIFT;
#if VERBOSE_VM
printf("do_x86_vm: need %d pages\n", pages);
printf("do_x86_vm: need %d bytes\n", bytes);
printf("do_x86_vm: need %d clicks\n", clicks);
#endif
for (i= 0; i<NR_MEMS; i++)
{
if (mem_chunks[i].size <= clicks)
continue;
break;
}
if (i >= NR_MEMS)
panic("VM", "not enough memory for VM page tables?", NO_NUM);
base_click= mem_chunks[i].base;
mem_chunks[i].base += clicks;
mem_chunks[i].size -= clicks;
#if VERBOSE_VM
printf("do_x86_vm: using 0x%x clicks @ 0x%x\n", clicks, base_click);
#endif
r= sys_vm_setbuf(base_click << CLICK_SHIFT, clicks << CLICK_SHIFT,
high);
if (r != 0)
printf("do_x86_vm: sys_vm_setbuf failed: %d\n", r);
}
/*===========================================================================* /*===========================================================================*
* arch_map2vir * * arch_map2vir *
*===========================================================================*/ *===========================================================================*/

View File

@ -77,6 +77,7 @@ PUBLIC int main(void)
#if SANITYCHECKS #if SANITYCHECKS
nocheck = 0; nocheck = 0;
FIXME("VM SANITYCHECKS are on");
memcpy(data1, CHECKADDR, sizeof(data1)); memcpy(data1, CHECKADDR, sizeof(data1));
#endif #endif
SANITYCHECK(SCL_TOP); SANITYCHECK(SCL_TOP);
@ -114,21 +115,16 @@ PUBLIC int main(void)
switch(msg.m_source) { switch(msg.m_source) {
case SYSTEM: case SYSTEM:
/* Kernel wants to have memory ranges /* Kernel wants to have memory ranges
* verified. * verified, and/or pagefaults handled.
*/ */
do_memory(); do_memory();
do_pagefaults();
break; break;
case PM_PROC_NR: case PM_PROC_NR:
/* PM sends a notify() on shutdown, which /* PM sends a notify() on shutdown, which
* is OK and we ignore. * is OK and we ignore.
*/ */
break; break;
case HARDWARE:
/* This indicates a page fault has happened,
* which we have to handle.
*/
do_pagefaults();
break;
default: default:
/* No-one else should send us notifies. */ /* No-one else should send us notifies. */
printf("VM: ignoring notify() from %d\n", printf("VM: ignoring notify() from %d\n",
@ -242,10 +238,6 @@ PRIVATE void vm_init(void)
vmp->vm_flags |= VMF_SEPARATE; vmp->vm_flags |= VMF_SEPARATE;
} }
/* Let architecture-dependent VM initialization use some memory. */
arch_init_vm(mem_chunks);
/* Architecture-dependent initialization. */ /* Architecture-dependent initialization. */
pt_init(); pt_init();
@ -316,13 +308,6 @@ PRIVATE void vm_init(void)
VM_STACKTOP); VM_STACKTOP);
} }
/* Temporary hack; throw away all lower memory. */
while((click=ALLOC_MEM(1, 0)) <= ABS2CLICK(VM_PROCSTART)) {
clicksforgotten++;
}
printf("VM: HACK: clicks forgotten: %d last one: 0x%x\n", clicksforgotten, click);
/* Set up table of calls. */ /* Set up table of calls. */
#define CALLMAP(code, func, thecaller) { int i; \ #define CALLMAP(code, func, thecaller) { int i; \
if((i=CALLNUMBER(code)) < 0) { vm_panic(#code " invalid", (code)); } \ if((i=CALLNUMBER(code)) < 0) { vm_panic(#code " invalid", (code)); } \

View File

@ -106,9 +106,13 @@ PUBLIC void do_pagefaults(void)
} }
printf("VM: handling pagefault OK: %d addr 0x%lx %s\n",
ep, arch_map2vir(vmp, addr), pf_errstr(err));
/* Pagefault is handled, so now reactivate the process. */ /* Pagefault is handled, so now reactivate the process. */
if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK) if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
vm_panic("do_pagefaults: sys_vmctl failed", ep); vm_panic("do_pagefaults: sys_vmctl failed", ep);
} }
return; return;
@ -135,6 +139,9 @@ PUBLIC void do_memory(void)
vm_panic("do_memory: endpoint wrong", who); vm_panic("do_memory: endpoint wrong", who);
vmp = &vmproc[p]; 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. */ /* Page-align memory and length. */
o = mem % VM_PAGE_SIZE; o = mem % VM_PAGE_SIZE;
mem -= o; mem -= o;
@ -167,8 +174,12 @@ PUBLIC void do_memory(void)
vmp->vm_endpoint); vmp->vm_endpoint);
} }
if(sys_vmctl(who, VMCTL_MEMREQ_REPLY, r) != OK) if(sys_vmctl(who, VMCTL_MEMREQ_REPLY, r) != OK)
vm_panic("do_memory: sys_vmctl failed", r); vm_panic("do_memory: sys_vmctl failed", r);
printf("VM: handling memory request %d done OK\n",
who);
} }
} }

View File

@ -135,6 +135,7 @@ _PROTOTYPE(int map_pf,(struct vmproc *vmp,
struct vir_region *region, vir_bytes offset, int write)); struct vir_region *region, vir_bytes offset, int write));
_PROTOTYPE(int map_handle_memory,(struct vmproc *vmp, _PROTOTYPE(int map_handle_memory,(struct vmproc *vmp,
struct vir_region *region, vir_bytes offset, vir_bytes len, int write)); struct vir_region *region, vir_bytes offset, vir_bytes len, int write));
_PROTOTYPE(void map_printmap, (struct vmproc *vmp));
_PROTOTYPE(struct vir_region * map_region_lookup_tag, (struct vmproc *vmp, u32_t tag)); _PROTOTYPE(struct vir_region * map_region_lookup_tag, (struct vmproc *vmp, u32_t tag));
_PROTOTYPE(void map_region_set_tag, (struct vir_region *vr, u32_t tag)); _PROTOTYPE(void map_region_set_tag, (struct vir_region *vr, u32_t tag));

View File

@ -32,8 +32,6 @@ FORWARD _PROTOTYPE(int map_new_physblock, (struct vmproc *vmp,
FORWARD _PROTOTYPE(int map_copy_ph_block, (struct vmproc *vmp, struct vir_region *region, struct phys_region *ph)); FORWARD _PROTOTYPE(int map_copy_ph_block, (struct vmproc *vmp, struct vir_region *region, struct phys_region *ph));
FORWARD _PROTOTYPE(struct vir_region *map_copy_region, (struct vir_region *)); FORWARD _PROTOTYPE(struct vir_region *map_copy_region, (struct vir_region *));
FORWARD _PROTOTYPE(void map_printmap, (struct vmproc *vmp));
PRIVATE char *map_name(struct vir_region *vr) PRIVATE char *map_name(struct vir_region *vr)
{ {
int type = vr->flags & (VR_ANON|VR_DIRECT); int type = vr->flags & (VR_ANON|VR_DIRECT);
@ -52,7 +50,7 @@ PRIVATE char *map_name(struct vir_region *vr)
/*===========================================================================* /*===========================================================================*
* map_printmap * * map_printmap *
*===========================================================================*/ *===========================================================================*/
PRIVATE void map_printmap(vmp) PUBLIC void map_printmap(vmp)
struct vmproc *vmp; struct vmproc *vmp;
{ {
struct vir_region *vr; struct vir_region *vr;
@ -60,9 +58,10 @@ struct vmproc *vmp;
for(vr = vmp->vm_regions; vr; vr = vr->next) { for(vr = vmp->vm_regions; vr; vr = vr->next) {
struct phys_region *ph; struct phys_region *ph;
int nph = 0; int nph = 0;
printf("map_printmap: map_name: %s\n", map_name(vr));
printf("\t0x%lx - 0x%lx (len 0x%lx), %s\n", printf("\t0x%lx - 0x%lx (len 0x%lx), %s\n",
vr->vaddr, vr->vaddr + vr->length, vr->length, vr->vaddr, vr->vaddr + vr->length, vr->length,
vr->vaddr + vr->length, map_name(vr)); map_name(vr));
printf("\t\tphysical: "); printf("\t\tphysical: ");
for(ph = vr->first; ph; ph = ph->next) { for(ph = vr->first; ph; ph = ph->next) {
printf("0x%lx-0x%lx (refs %d): phys 0x%lx ", printf("0x%lx-0x%lx (refs %d): phys 0x%lx ",
@ -912,6 +911,9 @@ struct vmproc *src;
dst->vm_regions = NULL; dst->vm_regions = NULL;
SANITYCHECK(SCL_FUNCTIONS); SANITYCHECK(SCL_FUNCTIONS);
PT_SANE(&src->vm_pt);
for(vr = src->vm_regions; vr; vr = vr->next) { for(vr = src->vm_regions; vr; vr = vr->next) {
struct vir_region *newvr; struct vir_region *newvr;
struct phys_region *orig_ph, *new_ph; struct phys_region *orig_ph, *new_ph;
@ -958,8 +960,12 @@ struct vmproc *src;
} }
SANITYCHECK(SCL_DETAIL); SANITYCHECK(SCL_DETAIL);
PT_SANE(&src->vm_pt);
map_writept(src); map_writept(src);
PT_SANE(&src->vm_pt);
map_writept(dst); map_writept(dst);
PT_SANE(&dst->vm_pt);
SANITYCHECK(SCL_FUNCTIONS); SANITYCHECK(SCL_FUNCTIONS);
return OK; return OK;

View File

@ -34,7 +34,7 @@
for(vmp = vmproc; vmp <= &vmproc[_NR_PROCS]; vmp++) { \ for(vmp = vmproc; vmp <= &vmproc[_NR_PROCS]; vmp++) { \
if((vmp->vm_flags & (VMF_INUSE | VMF_HASPT)) == \ if((vmp->vm_flags & (VMF_INUSE | VMF_HASPT)) == \
(VMF_INUSE | VMF_HASPT)) { \ (VMF_INUSE | VMF_HASPT)) { \
pt_sanitycheck(&vmp->vm_pt, __FILE__, __LINE__); \ PT_SANE(&vmp->vm_pt); \
} \ } \
} \ } \
map_sanitycheck(__FILE__, __LINE__); \ map_sanitycheck(__FILE__, __LINE__); \

View File

@ -13,7 +13,7 @@
#define ABS2CLICK(a) ((a) >> CLICK_SHIFT) #define ABS2CLICK(a) ((a) >> CLICK_SHIFT)
/* Compile in asserts and custom sanity checks at all? */ /* Compile in asserts and custom sanity checks at all? */
#define SANITYCHECKS 0 #define SANITYCHECKS 1
#define VMSTATS 1 #define VMSTATS 1
/* If so, this level: */ /* If so, this level: */