diff --git a/include/minix/com.h b/include/minix/com.h index cc9ad0875..769184194 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -608,6 +608,14 @@ #define SVMCTL_MRG_WRITE m1_i2 /* MEMREQ_GET reply: writeflag */ #define SVMCTL_MRG_EP m1_i3 /* MEMREQ_GET reply: process */ #define SVMCTL_MRG_REQUESTOR m1_p2 /* MEMREQ_GET reply: requestor */ +#define SVMCTL_MAP_VIR_ADDR m1_p1 + +/* Reply message for VMCTL_KERN_PHYSMAP */ +#define SVMCTL_MAP_FLAGS m2_i1 /* VMMF_* */ +#define SVMCTL_MAP_PHYS_ADDR m2_l1 +#define SVMCTL_MAP_PHYS_LEN m2_l2 + +#define VMMF_UNCACHED (1L << 0) /* Codes and field names for SYS_SYSCTL. */ #define SYSCTL_CODE m1_i1 /* SYSCTL_CODE_* below */ @@ -632,6 +640,8 @@ #define VMCTL_ENABLE_PAGING 24 #define VMCTL_I386_INVLPG 25 #define VMCTL_FLUSHTLB 26 +#define VMCTL_KERN_PHYSMAP 27 +#define VMCTL_KERN_MAP_REPLY 28 /* Field names for SYS_VTIMER. */ #define VT_WHICH m2_i1 /* which timer to set/retrieve */ diff --git a/include/minix/syslib.h b/include/minix/syslib.h index 5615c6372..93aeaf3c0 100644 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -68,6 +68,9 @@ _PROTOTYPE( int sys_readbios, (phys_bytes address, void *buf, size_t size)); _PROTOTYPE( int sys_stime, (time_t boottime)); _PROTOTYPE( int sys_sysctl, (int ctl, char *arg1, int arg2)); _PROTOTYPE( int sys_sysctl_stacktrace, (endpoint_t who)); +_PROTOTYPE( int sys_vmctl_get_mapping, (int index, phys_bytes *addr, + phys_bytes *len, int *flags)); +_PROTOTYPE( int sys_vmctl_reply_mapping, (int index, vir_bytes addr)); /* Shorthands for sys_sdevio() system call. */ #define sys_insb(port, proc_ep, buffer, count) \ diff --git a/kernel/arch/i386/memory.c b/kernel/arch/i386/memory.c index fa68ecd36..6eeb659c3 100644 --- a/kernel/arch/i386/memory.c +++ b/kernel/arch/i386/memory.c @@ -715,7 +715,7 @@ void vm_print(u32_t *root) printf("page table 0x%lx:\n", root); - for(pde = 10; pde < I386_VM_DIR_ENTRIES; pde++) { + for(pde = 0; pde < I386_VM_DIR_ENTRIES; pde++) { u32_t pde_v; u32_t *pte_a; pde_v = phys_get32((u32_t) (root + pde)); @@ -1028,3 +1028,19 @@ void i386_freepde(int pde) return; freepdes[nfreepdes++] = pde; } + +PUBLIC arch_phys_map(int index, phys_bytes *addr, phys_bytes *len, int *flags) +{ + /* we don't want anything */ + return EINVAL; +} + +PUBLIC arch_phys_map_reply(int index, vir_bytes addr) +{ + return OK; +} + +PUBLIC int arch_enable_paging(void) +{ + return OK; +} diff --git a/kernel/proto.h b/kernel/proto.h index b442fe4da..d52d8ca93 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -161,5 +161,9 @@ _PROTOTYPE( int vm_suspend, (struct proc *caller, struct proc *target, phys_bytes lin, phys_bytes size, int wrflag, int type)); _PROTOTYPE( int delivermsg, (struct proc *target)); _PROTOTYPE( void arch_do_syscall, (struct proc *proc) ); +_PROTOTYPE( int arch_phys_map, (int index, phys_bytes *addr, + phys_bytes *len, int *flags)); +_PROTOTYPE( int arch_phys_map_reply, (int index, vir_bytes addr)); +_PROTOTYPE( int arch_enable_paging, (void)); #endif /* PROTO_H */ diff --git a/kernel/system/do_vmctl.c b/kernel/system/do_vmctl.c index 1a358cdbc..6f7f9f426 100644 --- a/kernel/system/do_vmctl.c +++ b/kernel/system/do_vmctl.c @@ -22,6 +22,7 @@ register message *m_ptr; /* pointer to request message */ int proc_nr, i; endpoint_t ep = m_ptr->SVMCTL_WHO; struct proc *p, *rp, *target; + int err; if(ep == SELF) { ep = m_ptr->m_source; } @@ -119,6 +120,11 @@ register message *m_ptr; /* pointer to request message */ return OK; case VMCTL_ENABLE_PAGING: + /* + * system task must not get preempted while switching to paging, + * interrupt handling is not safe + */ + lock; if(vm_running) minix_panic("do_vmctl: paging already enabled", NO_NUM); vm_init(p); @@ -126,11 +132,29 @@ register message *m_ptr; /* pointer to request message */ minix_panic("do_vmctl: paging enabling failed", NO_NUM); vmassert(p->p_delivermsg_lin == umap_local(p, D, p->p_delivermsg_vir, sizeof(message))); + if ((err = arch_enable_paging()) != OK) { + unlock; + return err; + } if(newmap(p, (struct mem_map *) m_ptr->SVMCTL_VALUE) != OK) minix_panic("do_vmctl: newmap failed", NO_NUM); FIXLINMSG(p); vmassert(p->p_delivermsg_lin); + unlock; return OK; + case VMCTL_KERN_PHYSMAP: + { + int i = m_ptr->SVMCTL_VALUE; + return arch_phys_map(i, + (phys_bytes *) &m_ptr->SVMCTL_MAP_PHYS_ADDR, + (phys_bytes *) &m_ptr->SVMCTL_MAP_PHYS_LEN, + &m_ptr->SVMCTL_MAP_FLAGS); + } + case VMCTL_KERN_MAP_REPLY: + { + return arch_phys_map_reply(m_ptr->SVMCTL_VALUE, + (vir_bytes) m_ptr->SVMCTL_MAP_VIR_ADDR); + } } /* Try architecture-specific vmctls. */ diff --git a/lib/syslib/sys_vmctl.c b/lib/syslib/sys_vmctl.c index 29f27e243..5e93bace5 100644 --- a/lib/syslib/sys_vmctl.c +++ b/lib/syslib/sys_vmctl.c @@ -69,3 +69,38 @@ PUBLIC int sys_vmctl_enable_paging(struct mem_map *map) m.SVMCTL_VALUE = (int) map; return _taskcall(SYSTASK, SYS_VMCTL, &m); } + +PUBLIC int sys_vmctl_get_mapping(int index, + phys_bytes *addr, phys_bytes *len, int *flags) +{ + int r; + message m; + + m.SVMCTL_WHO = SELF; + m.SVMCTL_PARAM = VMCTL_KERN_PHYSMAP; + m.SVMCTL_VALUE = (int) index; + + r = _taskcall(SYSTASK, SYS_VMCTL, &m); + + if(r != OK) + return r; + + *addr = m.SVMCTL_MAP_PHYS_ADDR; + *len = m.SVMCTL_MAP_PHYS_LEN; + *flags = m.SVMCTL_MAP_FLAGS; + + return OK; +} + +PUBLIC int sys_vmctl_reply_mapping(int index, vir_bytes addr) +{ + int r; + message m; + + m.SVMCTL_WHO = SELF; + m.SVMCTL_PARAM = VMCTL_KERN_MAP_REPLY; + m.SVMCTL_VALUE = index; + m.SVMCTL_MAP_VIR_ADDR = (char *) addr; + + return _taskcall(SYSTASK, SYS_VMCTL, &m); +}