beng work in progress, to be explained in a future commit message :).
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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
13
include/minix/debug.h
Normal 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 */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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) );
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ LIBRARIES=libsys
|
||||
|
||||
libsys_FILES=" \
|
||||
asynsend.c \
|
||||
kmalloc.c \
|
||||
kprintf.c \
|
||||
kputc.c \
|
||||
tickdelay.c \
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 { \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 *
|
||||
*===========================================================================*/
|
||||
|
||||
@@ -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)); } \
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__); \
|
||||
|
||||
@@ -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: */
|
||||
|
||||
Reference in New Issue
Block a user