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
/* 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");
return(ENOMEM);
}

View File

@@ -766,8 +766,22 @@ int scode; /* scan code of key just struck or released */
return -1;
if(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;
}

View File

@@ -311,7 +311,6 @@
# define SYS_GETINFO (KERNEL_CALL + 26) /* sys_getinfo() */
# define SYS_ABORT (KERNEL_CALL + 27) /* sys_abort() */
# 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_SAFECOPYTO (KERNEL_CALL + 32) /* sys_safecopyto() */
# define SYS_VSAFECOPY (KERNEL_CALL + 33) /* sys_vsafecopy() */
@@ -605,9 +604,9 @@
#define VMCTL_NOPAGEZERO 18
#define VMCTL_I386_KERNELLIMIT 19
#define VMCTL_I386_PAGEDIRS 20
#define VMCTL_I386_PDE 21
#define VMCTL_I386_PDEVAL 22
#define VMCTL_I386_FREEPDE 23
#define VMCTL_ENABLE_PAGING 24
#define VMCTL_I386_INVLPG 25
/*===========================================================================*
* Messages for the Reincarnation Server *

View File

@@ -95,7 +95,4 @@
#define SPROFILE 1 /* statistical 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 */

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 */
char release[6]; /* kernel release 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. */

View File

@@ -36,6 +36,12 @@ sys/vm_i386.h
#define I386_VM_PFA_SHIFT 22 /* Page frame address shift */
/* 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 */
/* some CR4 bits */

View File

@@ -12,7 +12,6 @@
#include "proto.h"
extern u32_t kernel_cr3;
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 */
struct proc *p;
{
static int vmpde = -1;
static u32_t pdeval = -1;
switch(m_ptr->SVMCTL_PARAM) {
case VMCTL_I386_GETCR3:
/* Get process CR3. */
@@ -37,7 +32,7 @@ struct proc *p;
p->p_seg.p_cr3 = m_ptr->SVMCTL_VALUE;
p->p_misc_flags |= MF_FULLVM;
} else {
p->p_seg.p_cr3 = kernel_cr3;
p->p_seg.p_cr3 = 0;
p->p_misc_flags &= ~MF_FULLVM;
}
RTS_LOCK_UNSET(p, VMINHIBIT);
@@ -58,6 +53,8 @@ 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:
@@ -74,27 +71,16 @@ struct proc *p;
kprintf("kernel: pagedirs now 0x%lx\n", vm_pagedirs);
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:
{
i386_freepde(m_ptr->SVMCTL_VALUE);
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);

View File

@@ -33,6 +33,10 @@ 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)
@@ -141,6 +145,7 @@ register message *m_ptr; /* pointer to request message */
return(EINVAL);
}
return(OK);
#endif
}
#endif /* USE_SDEVIO */

View File

@@ -11,10 +11,11 @@
#include <minix/sysutil.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 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;
@@ -24,15 +25,33 @@ void pagefault(struct proc *pr, int trap_errno)
vir_bytes ph;
u32_t pte;
if(pagefault_count != 1)
minix_panic("recursive pagefault", pagefault_count);
vmassert(pagefault_count == 1);
/* Don't schedule this process until pagefault is handled. */
if(RTS_ISSET(pr, PAGEFAULT))
minix_panic("PAGEFAULT set", pr->p_endpoint);
RTS_LOCK_SET(pr, PAGEFAULT);
if((iskernelp(pr) || k_reenter) && catch_pagefaults
&& (pr->p_reg.pc > (vir_bytes) _memcpy_k &&
pr->p_reg.pc < (vir_bytes) _memcpy_k_fault) &&
pagefault_cr2 >= catchrange_lo &&
pagefault_cr2 < catchrange_hi) {
kprintf("handling pagefault during copy\n");
pr->p_reg.pc = (vir_bytes) _memcpy_k_fault;
pr->p_reg.retreg = pagefault_cr2;
pagefault_count = 0;
return;
}
if(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
* handle.
*/
@@ -45,6 +64,11 @@ void pagefault(struct proc *pr, int trap_errno)
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,
* add process to pagefault chain,
* 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_nextpagefault = pagefaults;
pagefaults = pr;
lock_notify(HARDWARE, VM_PROC_NR);
soft_notify(VM_PROC_NR);
pagefault_count = 0;
@@ -184,17 +208,20 @@ PUBLIC void proc_stacktrace(struct proc *proc)
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);
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);
break;
}
if(data_copy(proc->p_endpoint, v_bp + sizeof(v_pc),
SYSTEM, (vir_bytes) &v_pc, sizeof(v_pc)) != OK) {
if(PRCOPY(proc, v_bp + sizeof(v_pc), &v_pc, sizeof(v_pc)) != OK) {
kprintf("(v_pc 0x%lx ?)", v_pc);
break;
}

View File

@@ -21,10 +21,10 @@
.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
@@ -36,14 +36,16 @@
.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
.define _write_cr4
.define _i386_invlpg_addr
.define _i386_invlpg_level0
.define _kernel_cr3
.define __memcpy_k
.define __memcpy_k_fault
! The routines only guarantee to preserve the registers the C compiler
! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and
@@ -158,55 +160,6 @@ csinit: mov eax, DS_SELECTOR
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 *
!*===========================================================================*
@@ -230,56 +183,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
LOADKERNELCR3
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
LOADKERNELCR3
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 *
@@ -287,55 +236,51 @@ _phys_insb:
! 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
LOADKERNELCR3
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
LOADKERNELCR3
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
!*==========================================================================*
@@ -432,8 +377,6 @@ _phys_copy:
push edi
push es
LOADKERNELCR3
mov eax, FLAT_DS_SELECTOR
mov es, ax
@@ -479,8 +422,6 @@ _phys_memset:
push ebx
push ds
LOADKERNELCR3
mov esi, 8(ebp)
mov eax, 16(ebp)
mov ebx, FLAT_DS_SELECTOR
@@ -494,7 +435,7 @@ fill_start:
jnz fill_start
! Any remaining bytes?
mov eax, 16(ebp)
and eax, 3
! and eax, 3
remain_fill:
cmp eax, 0
jz fill_done
@@ -642,10 +583,20 @@ _write_cr4:
_write_cr3:
push ebp
mov ebp, esp
LOADCR3WITHEAX(0x22, 8(ebp))
mov eax, 8(ebp)
mov cr3, eax
pop ebp
ret
!*===========================================================================*
!* getcr3val *
!*===========================================================================*
! PUBLIC unsigned long getcr3val(void);
_getcr3val:
mov eax, cr3
mov (_thecr3), eax
ret
!*===========================================================================*
!* i386_invlpg *
!*===========================================================================*
@@ -657,4 +608,47 @@ _i386_invlpg_level0:
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 save
.define _kernel_cr3
.define _pagefault_cr2
.define _pagefault_count
@@ -218,12 +217,6 @@ csinit:
ltr ax
push 0 ! set flags to known good state
popf ! esp, clear nested task and int enable
#if VM_KERN_NOPAGEZERO
jmp laststep
.align I386_PAGE_SIZE
laststep:
#endif
jmp _main ! main()
@@ -239,7 +232,6 @@ laststep:
#define hwint_master(irq) \
call save /* save interrupted process state */;\
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]) */;\
pop ecx ;\
cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\
@@ -291,7 +283,6 @@ _hwint07: ! Interrupt routine for irq 7 (printer)
#define hwint_slave(irq) \
call save /* save interrupted process state */;\
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]) */;\
pop ecx ;\
cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\
@@ -398,8 +389,6 @@ _p_s_call:
push eax ! source / destination
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)
! caller is now explicitly in proc_ptr
mov AXREG(esi), eax ! sys_call MUST PRESERVE si
@@ -420,7 +409,16 @@ _restart:
mov (_next_ptr), 0
0: mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0
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
mov (_tss+TSS3_S_SP0), eax ! to save state in process table
restart1:
@@ -535,8 +533,6 @@ exception1: ! Common for all exceptions.
mov eax, 8+4(esp) ! old eflags
sseg mov (old_eflags), eax
LOADCR3WITHEAX(0x24, (_kernel_cr3))
pop eax
call save
push (old_eflags)
@@ -556,24 +552,12 @@ _level0_call:
call save
jmp (_level0_func)
!*===========================================================================*
!* load_kernel_cr3 *
!*===========================================================================*
.align 16
_load_kernel_cr3:
mov eax, (_kernel_cr3)
mov cr3, eax
ret
!*===========================================================================*
!* data *
!*===========================================================================*
.sect .rom ! Before the string table please
.data2 0x526F ! this must be the first data entry (magic #)
#if VM_KERN_NOPAGEZERO
.align I386_PAGE_SIZE
#endif
.sect .bss
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 i386_updatepde, (int pde, u32_t val));
_PROTOTYPE( void i386_freepde, (int pde));
_PROTOTYPE( void getcr3val, (void));
/* 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_outsw, (U16_t port, phys_bytes buf, size_t count) );
_PROTOTYPE( void i386_invlpg_level0, (void) );
_PROTOTYPE( int _memcpy_k, (void *dst, void *src, size_t n) );
_PROTOTYPE( int _memcpy_k_fault, (void) );
/* protect.c */
_PROTOTYPE( void prot_init, (void) );

View File

@@ -153,6 +153,60 @@ PRIVATE void ser_debug(int c)
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()
{
struct proc *pp;
@@ -165,15 +219,7 @@ PUBLIC void ser_dump_proc()
{
if (pp->p_rts_flags & SLOT_FREE)
continue;
kprintf(
"%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);
printslot(pp);
}
if(u) { unlock; }

View File

@@ -1,21 +1,7 @@
.define _load_kernel_cr3
.define _last_cr3
#define LOADKERNELCR3 ;\
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) ;\
#define LOADCR3WITHEAX(type, newcr3, ptproc) ;\
sseg inc (_cr3switch) ;\
sseg mov eax, newcr3 ;\
sseg cmp (_last_cr3), eax ;\
@@ -23,5 +9,7 @@ sseg cmp (_last_cr3), eax ;\
mov cr3, eax ;\
sseg inc (_cr3reload) ;\
sseg mov (_last_cr3), eax ;\
sseg mov eax, (ptproc) ;\
sseg mov (_ptproc), eax ;\
8:

View File

@@ -103,3 +103,28 @@ check_runqueues_f(char *file, int line)
}
#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 <minix/debug.h>
#include "config.h"
/* Enable prints such as
@@ -25,6 +26,34 @@
/* Runtime sanity checking. */
#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 */

View File

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

View File

@@ -17,6 +17,7 @@
#include <minix/com.h>
#include <minix/endpoint.h>
#include "proc.h"
#include "debug.h"
/* Prototype declarations for PRIVATE functions. */
FORWARD _PROTOTYPE( void announce, (void));
@@ -185,6 +186,16 @@ PUBLIC void main()
*/
bill_ptr = proc_addr(IDLE); /* it has to point somewhere */
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();
}

View File

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

View File

@@ -107,6 +107,7 @@ 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. */

View File

@@ -33,7 +33,7 @@ _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 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) );
@@ -87,6 +87,7 @@ _PROTOTYPE( void cons_seth, (int pos, int n) );
#define CHECK_RUNQUEUES check_runqueues_f(__FILE__, __LINE__)
_PROTOTYPE( void check_runqueues_f, (char *file, int line) );
#endif
_PROTOTYPE( char *rtsflagstr, (int flags) );
/* system/do_safecopy.c */
_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_from(d, p, v, n) data_copy((p), (v), SYSTEM, (d), (n));
_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( int vm_copy, (vir_bytes src, struct proc *srcproc,
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,
vir_bytes vir_addr, vir_bytes bytes) );
_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) );
_PROTOTYPE( vir_bytes alloc_remote_segment, (u32_t *, segframe_t *,
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));
_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));
#endif /* PROTO_H */

View File

@@ -121,8 +121,12 @@ PUBLIC void sys_task()
if (curr < limit+extra)
{
#if 0
kprintf("SYSTEM: request %d from %d denied.\n",
call_nr, m.m_source);
#else
FIXME("privileges bypassed");
#endif
} else if (curr == limit+extra)
{
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_SEGCTL, do_segctl); /* add segment and get selector */
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 */
/* 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(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,
* 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);
kprintf("kernel trace: ");
util_stacktrace();
#if 0
minix_panic("clear_proc: system process died", rc->p_endpoint);
#endif
}
/* Make sure that the exiting process is no longer scheduled. */
@@ -619,6 +627,8 @@ PRIVATE struct proc *vmrestart_check(message *m)
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,
@@ -626,6 +636,7 @@ PRIVATE struct proc *vmrestart_check(message *m)
sizeof(message))) != OK) {
minix_panic("SYSTEM: delayed msgcopy failed", r);
}
printf("OK!\n");
RTS_LOCK_UNSET(restarting, VMREQUEST);
/* Handled; restart system loop. */

View File

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

View File

@@ -42,6 +42,8 @@ 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 */

View File

@@ -88,6 +88,9 @@ 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;
}

View File

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

View File

@@ -8,6 +8,8 @@
*/
#include "../system.h"
#if 0
#define VM_DEBUG 0 /* enable/ disable debug output */
/*===========================================================================*
@@ -27,3 +29,5 @@ message *m_ptr; /* pointer to request message */
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; }
vm_init();
if(!isokendpt(ep, &proc_nr)) {
kprintf("do_vmctl: unexpected endpoint %d from VM\n", ep);
return EINVAL;
@@ -45,6 +43,9 @@ register message *m_ptr; /* pointer to request message */
if(!RTS_ISSET(rp, VMREQUEST))
minix_panic("do_vmctl: no VMREQUEST set", NO_NUM);
printf("kernel: vm request sent by: %s / %d about %d\n",
rp->p_name, rp->p_endpoint, rp->p_vmrequest.who);
/* Reply with request fields. */
m_ptr->SVMCTL_MRG_ADDR = (char *) rp->p_vmrequest.start;
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);
/* Put on restart chain. */
printf("kernel: vm reply received for %d\n", rp->p_endpoint);
rp->p_vmrequest.nextrestart = vmrestart;
vmrestart = rp;
@@ -93,10 +95,15 @@ kprintf("SYSTEM: request %d:0x%lx-0x%lx, wrflag %d, failed\n",
}
#endif
return OK;
#if VM_KERN_NOPAGEZERO
case VMCTL_NOPAGEZERO:
case VMCTL_ENABLE_PAGING:
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;
#endif
}
/* Try architecture-specific vmctls. */

View File

@@ -96,7 +96,8 @@ PRIVATE int
drv_c[] = { DRV_C },
tty_c[] = { DRV_C, SYS_PHYSCOPY, SYS_ABORT, SYS_IOPENABLE,
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 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" },
{MFS_PROC_NR, 0,SVM_F, 32, 5, 0, SRV_T, SRV_M, c(fs_c),"mfs" },
{VM_PROC_NR, 0,SRV_F, 32, 2, 0, SRV_T, SRV_M, c(vm_c),"vm" },
{INIT_PROC_NR, 0,USR_F, 8, USER_Q, 0, USR_T, USR_M, no_c,"init" },
{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

View File

@@ -37,7 +37,7 @@ char *mess;
int nr;
{
/* 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) {
kprintf("kernel panic: %s", mess);
@@ -48,6 +48,7 @@ int nr;
kprintf("kernel stacktrace: ");
util_stacktrace();
}
/* Abort MINIX. */
minix_shutdown(NULL);
@@ -80,12 +81,13 @@ int c; /* character to append */
kmess.km_next = (kmess.km_next + 1) % _KMESS_BUF_SIZE;
} else {
int p, outprocs[] = OUTPUT_PROCS_ARRAY;
if(do_serial_debug) return;
if(minix_panicing || do_serial_debug) return;
for(p = 0; outprocs[p] != NONE; p++) {
if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
send_sig(outprocs[p], SIGKMESS);
}
}
if(!(minix_panicing || do_serial_debug)) {
for(p = 0; outprocs[p] != NONE; p++) {
if(isokprocn(outprocs[p]) && !isemptyn(outprocs[p])) {
send_sig(outprocs[p], SIGKMESS);
}
}
}
}
return;
}

View File

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

View File

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

View File

@@ -99,6 +99,7 @@ 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);
@@ -111,6 +112,7 @@ 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;
@@ -119,7 +121,9 @@ 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 */
}

View File

@@ -17,6 +17,7 @@
#include "fs.h"
#include <minix/com.h>
#include <minix/u64.h>
#include <string.h>
#include "buf.h"
#include "super.h"
#include "inode.h"
@@ -24,6 +25,9 @@
FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
FORWARD _PROTOTYPE( int rw_block, (struct buf *, int) );
char saved[100];
char *savedptr;
/*===========================================================================*
* get_block *
*===========================================================================*/
@@ -48,10 +52,19 @@ int only_search; /* if NO_READ, don't read, else act normal */
*/
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);
CHECK;
/* 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
* 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) {
b = BUFHASH(block);
bp = buf_hash[b];
CHECK;
while (bp != NIL_BUF) {
CHECK;
if (bp->b_blocknr == block && bp->b_dev == dev) {
CHECK;
/* Block needed has been found. */
if (bp->b_count == 0) rm_lru(bp);
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 != NO_DEV);
ASSERT(bp->bp);
CHECK;
return(bp);
} else {
/* 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);
CHECK;
return(bp); /* return the newly acquired block */
}

View File

@@ -452,9 +452,13 @@ 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;
}

View File

@@ -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 0
#define DO_SANITYCHECKS 1
#if DO_SANITYCHECKS
#define SANITYCHECK do { \

View File

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

View File

@@ -55,6 +55,8 @@ 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;

View File

@@ -13,6 +13,7 @@
#include <minix/ipc.h>
#include <minix/sysutil.h>
#include <minix/syslib.h>
#include <minix/debug.h>
#include <errno.h>
#include <env.h>
@@ -31,6 +32,7 @@ PUBLIC int do_fork(message *msg)
{
int r, proc, s, childproc, fullvm;
struct vmproc *vmp, *vmc;
pt_t origpt;
SANITYCHECK(SCL_FUNCTIONS);
@@ -49,6 +51,7 @@ PUBLIC int do_fork(message *msg)
vmp = &vmproc[proc]; /* parent */
vmc = &vmproc[childproc]; /* child */
vm_assert(vmc->vm_slot == childproc);
if(vmp->vm_flags & VMF_HAS_DMA) {
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;
/* The child is basically a copy of the parent. */
origpt = vmc->vm_pt;
*vmc = *vmp;
vmc->vm_slot = childproc;
vmc->vm_regions = NULL;
vmc->vm_endpoint = NONE; /* In case someone tries to use it. */
vmc->vm_pt = origpt;
vmc->vm_flags &= ~VMF_HASPT;
#if VMSTATS
vmc->vm_bytecopies = 0;
#endif
SANITYCHECK(SCL_DETAIL);
if(fullvm) {
SANITYCHECK(SCL_DETAIL);
@@ -74,6 +83,8 @@ PUBLIC int do_fork(message *msg)
return ENOMEM;
}
vmc->vm_flags |= VMF_HASPT;
SANITYCHECK(SCL_DETAIL);
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. */
child_abs = (phys_bytes) child_base << 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);
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 u32_t kern_pde_val = 0, global_bit = 0, pagedir_pde_val;
PRIVATE int proc_pde = 0;
/* 4MB page size available in hardware? */
PRIVATE int bigpage_ok = 0;
@@ -82,7 +84,6 @@ PRIVATE struct {
u32_t page_directories_phys, *page_directories = NULL;
#if SANITYCHECKS
#define PT_SANE(p) { pt_sanitycheck((p), __FILE__, __LINE__); SANITYCHECK(SCL_DETAIL); }
/*===========================================================================*
* pt_sanitycheck *
*===========================================================================*/
@@ -90,21 +91,33 @@ PUBLIC void pt_sanitycheck(pt_t *pt, char *file, int line)
{
/* Basic pt sanity check. */
int i;
int slot;
MYASSERT(pt);
MYASSERT(pt->pt_dir);
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_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);
} else {
MYASSERT(!(pt->pt_dir[i] & I386_VM_PRESENT));
}
}
}
#else
#define PT_SANE(p)
#endif
/*===========================================================================*
@@ -348,7 +361,7 @@ PRIVATE int pt_ptalloc(pt_t *pt, int pde, u32_t flags)
/* Argument must make sense. */
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
* 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. */
int p, pages, pde;
int finalpde;
SANITYCHECK(SCL_FUNCTIONS);
vm_assert(!(bytes % I386_PAGE_SIZE));
vm_assert(!(flags & ~(PTF_ALLFLAGS | PTF_MAPALLOC)));
vm_assert(!(flags & ~(PTF_ALLFLAGS)));
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;
PT_SANE(pt);
}
SANITYCHECK(SCL_FUNCTIONS);
PT_SANE(pt);
return OK;
@@ -489,7 +501,14 @@ PUBLIC int pt_new(pt_t *pt)
*/
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;
}
@@ -501,10 +520,14 @@ PUBLIC int pt_new(pt_t *pt)
/* Where to start looking for free virtual address space? */
pt->pt_virtop = 0;
PT_SANE(pt);
/* Map in kernel. */
if(pt_mapkernel(pt) != OK)
vm_panic("pt_new: pt_mapkernel failed", NO_NUM);
PT_SANE(pt);
return OK;
}
@@ -565,17 +588,15 @@ PUBLIC void pt_init(void)
*/
kern_pde_val = (KERNEL_TEXT & I386_VM_ADDR_MASK_4MB) |
I386_VM_BIGPAGE|
I386_VM_USER|
I386_VM_PRESENT|I386_VM_WRITE|global_bit;
kernel_pde = pde1;
vm_assert(kernel_pde >= 0);
free_pde = kernel_pde+1;
}
/* 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);
/* First unused pde. */
proc_pde = free_pde;
/* Initial (current) range of our virtual address space. */
lo = CLICK2ABS(vmp->vm_arch.vm_seg[T].mem_phys);
@@ -591,6 +612,12 @@ PUBLIC void pt_init(void)
vm_assert(!(lo % 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. */
for(v = lo; v < hi; v += I386_PAGE_SIZE) {
@@ -620,11 +647,10 @@ 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);
/* Give our process the new, copied, private page table. */
pt_bind(newpt, vmp);
/* Increase our hardware data segment to create virtual address
* space above our stack. We want to increase it to VM_DATATOP,
* like regular processes have.
@@ -639,19 +665,6 @@ PUBLIC void pt_init(void)
(vmp->vm_arch.vm_seg[S].mem_vir +
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.
* 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);
printf("VM: setting pagedir_pde\n");
/* Find a PDE below processes available for mapping in the
* page directories (readonly).
*/
pagedir_pde = free_pde++;
pagedir_pde_val = (page_directories_phys & I386_VM_ADDR_MASK) |
I386_VM_PRESENT | I386_VM_USER;
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);
}
I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE;
/* Tell kernel about free pde's. */
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) {
vm_panic("VMCTL_I386_FREEPDE failed", r);
}
}
/* first pde in use by process. */
proc_pde = free_pde;
kernlimit = free_pde*I386_BIG_PAGE_SIZE;
printf("VM: set limit to 0x%x\n", kernlimit);
@@ -719,6 +721,33 @@ PUBLIC void pt_init(void)
if((r=sys_vmctl(SELF, VMCTL_I386_PAGEDIRS, kpagedir)) != OK) {
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. */
return;
@@ -750,6 +779,10 @@ PUBLIC int pt_bind(pt_t *pt, struct vmproc *who)
/* Update "page directory pagetable." */
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. */
return sys_vmctl(who->vm_endpoint, VMCTL_I386_SETCR3,
pt ? pt->pt_dir_phys : 0);
@@ -765,22 +798,14 @@ PUBLIC void pt_free(pt_t *pt)
PT_SANE(pt);
for(i = 0; i < I386_VM_DIR_ENTRIES; i++) {
int p;
if(pt->pt_pt[i]) {
for(p = 0; p < I386_VM_PT_ENTRIES; p++) {
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);
}
}
for(i = 0; i < I386_VM_DIR_ENTRIES; i++)
if(pt->pt_pt[i])
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);
#endif
return;
}
@@ -797,8 +822,13 @@ PUBLIC int pt_mapkernel(pt_t *pt)
vm_assert(vmproc[VMP_SYSTEM].vm_flags & VMF_INUSE);
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 {
vm_panic("VM: pt_mapkernel: no bigpage", NO_NUM);
/* Map in text. flags: don't write, supervisor only */
if((r=pt_writemap(pt, KERNEL_TEXT, KERNEL_TEXT, KERNEL_TEXT_LEN,
I386_VM_PRESENT|global_bit, 0)) != OK)
@@ -810,40 +840,14 @@ PUBLIC int pt_mapkernel(pt_t *pt)
return r;
}
/* Kernel also wants to know about all page directories. */
pt->pt_dir[pagedir_pde] = pagedir_pde_val;
return OK;
}
/*===========================================================================*
* 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;
}
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");
}
PT_SANE(pt);
return;
return OK;
}
/*===========================================================================*
@@ -881,8 +885,10 @@ static u32_t ismapped = MAP_NONE;
if(r != OK) \
vm_panic("PHYS_MAP: pt_writemap", NO_NUM); \
ismapped = wantmapped; \
/* pt_bind() flushes TLB. */ \
pt_bind(&vmp->vm_pt, vmp); \
/* Invalidate TLB for this page. */ \
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
#define PHYS_UNMAP if(OK != pt_writemap(&vmp->vm_pt, varmap_loc, MAP_NONE,\
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;
#endif

View File

@@ -5,6 +5,8 @@
#include <stdint.h>
#include <sys/vm_i386.h>
#include "../vm.h"
/* An i386 pagetable. */
typedef struct {
/* 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)
#if SANITYCHECKS
#define PT_SANE(p) { pt_sanitycheck((p), __FILE__, __LINE__); }
#else
#define PT_SANE(p)
#endif
#endif

View File

@@ -25,73 +25,6 @@
#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 *
*===========================================================================*/

View File

@@ -77,6 +77,7 @@ PUBLIC int main(void)
#if SANITYCHECKS
nocheck = 0;
FIXME("VM SANITYCHECKS are on");
memcpy(data1, CHECKADDR, sizeof(data1));
#endif
SANITYCHECK(SCL_TOP);
@@ -114,21 +115,16 @@ PUBLIC int main(void)
switch(msg.m_source) {
case SYSTEM:
/* Kernel wants to have memory ranges
* verified.
* verified, and/or pagefaults handled.
*/
do_memory();
do_pagefaults();
break;
case PM_PROC_NR:
/* PM sends a notify() on shutdown, which
* is OK and we ignore.
*/
break;
case HARDWARE:
/* This indicates a page fault has happened,
* which we have to handle.
*/
do_pagefaults();
break;
default:
/* No-one else should send us notifies. */
printf("VM: ignoring notify() from %d\n",
@@ -242,10 +238,6 @@ PRIVATE void vm_init(void)
vmp->vm_flags |= VMF_SEPARATE;
}
/* Let architecture-dependent VM initialization use some memory. */
arch_init_vm(mem_chunks);
/* Architecture-dependent initialization. */
pt_init();
@@ -316,13 +308,6 @@ PRIVATE void vm_init(void)
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. */
#define CALLMAP(code, func, thecaller) { int i; \
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. */
if((s=sys_vmctl(ep, VMCTL_CLEAR_PAGEFAULT, r)) != OK)
vm_panic("do_pagefaults: sys_vmctl failed", ep);
}
return;
@@ -135,6 +139,9 @@ PUBLIC void do_memory(void)
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;
@@ -167,8 +174,12 @@ PUBLIC void do_memory(void)
vmp->vm_endpoint);
}
if(sys_vmctl(who, VMCTL_MEMREQ_REPLY, r) != OK)
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));
_PROTOTYPE(int map_handle_memory,(struct vmproc *vmp,
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(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(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)
{
int type = vr->flags & (VR_ANON|VR_DIRECT);
@@ -52,7 +50,7 @@ PRIVATE char *map_name(struct vir_region *vr)
/*===========================================================================*
* map_printmap *
*===========================================================================*/
PRIVATE void map_printmap(vmp)
PUBLIC void map_printmap(vmp)
struct vmproc *vmp;
{
struct vir_region *vr;
@@ -60,9 +58,10 @@ struct vmproc *vmp;
for(vr = vmp->vm_regions; vr; vr = vr->next) {
struct phys_region *ph;
int nph = 0;
printf("map_printmap: map_name: %s\n", map_name(vr));
printf("\t0x%lx - 0x%lx (len 0x%lx), %s\n",
vr->vaddr, vr->vaddr + vr->length, vr->length,
vr->vaddr + vr->length, map_name(vr));
map_name(vr));
printf("\t\tphysical: ");
for(ph = vr->first; ph; ph = ph->next) {
printf("0x%lx-0x%lx (refs %d): phys 0x%lx ",
@@ -912,6 +911,9 @@ struct vmproc *src;
dst->vm_regions = NULL;
SANITYCHECK(SCL_FUNCTIONS);
PT_SANE(&src->vm_pt);
for(vr = src->vm_regions; vr; vr = vr->next) {
struct vir_region *newvr;
struct phys_region *orig_ph, *new_ph;
@@ -958,8 +960,12 @@ struct vmproc *src;
}
SANITYCHECK(SCL_DETAIL);
PT_SANE(&src->vm_pt);
map_writept(src);
PT_SANE(&src->vm_pt);
map_writept(dst);
PT_SANE(&dst->vm_pt);
SANITYCHECK(SCL_FUNCTIONS);
return OK;

View File

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

View File

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