3.1.7 branch.
[minix.git] / kernel / system / do_umap.c
blobc3593481087d86601153873bb7ac4b370bf8f8e7
1 /* The kernel call implemented in this file:
2 * m_type: SYS_UMAP
4 * The parameters for this kernel call are:
5 * m5_i1: CP_SRC_PROC_NR (process number)
6 * m5_s1: CP_SRC_SPACE (segment where address is: T, D, or S)
7 * m5_l1: CP_SRC_ADDR (virtual address)
8 * m5_l2: CP_DST_ADDR (returns physical address)
9 * m5_l3: CP_NR_BYTES (size of datastructure)
12 #include "kernel/system.h"
14 #include <minix/endpoint.h>
16 #if USE_UMAP
18 /*==========================================================================*
19 * do_umap *
20 *==========================================================================*/
21 PUBLIC int do_umap(struct proc * caller, message * m_ptr)
23 /* Map virtual address to physical, for non-kernel processes. */
24 int seg_type = m_ptr->CP_SRC_SPACE & SEGMENT_TYPE;
25 int seg_index = m_ptr->CP_SRC_SPACE & SEGMENT_INDEX;
26 vir_bytes offset = m_ptr->CP_SRC_ADDR;
27 int count = m_ptr->CP_NR_BYTES;
28 int endpt = (int) m_ptr->CP_SRC_ENDPT;
29 int proc_nr, r;
30 int naughty = 0;
31 phys_bytes phys_addr = 0, lin_addr = 0;
32 struct proc *targetpr;
34 /* Verify process number. */
35 if (endpt == SELF)
36 proc_nr = _ENDPOINT_P(caller->p_endpoint);
37 else
38 if (! isokendpt(endpt, &proc_nr))
39 return(EINVAL);
40 targetpr = proc_addr(proc_nr);
42 /* See which mapping should be made. */
43 switch(seg_type) {
44 case LOCAL_SEG:
45 phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count);
46 if(!lin_addr) return EFAULT;
47 naughty = 1;
48 break;
49 case REMOTE_SEG:
50 phys_addr = lin_addr = umap_remote(targetpr, seg_index, offset, count);
51 if(!lin_addr) return EFAULT;
52 naughty = 1;
53 break;
54 case LOCAL_VM_SEG:
55 if(seg_index == MEM_GRANT) {
56 vir_bytes newoffset;
57 endpoint_t newep;
58 int new_proc_nr;
59 cp_grant_id_t grant = (cp_grant_id_t) offset;
61 if(verify_grant(targetpr->p_endpoint, ANY, grant, count, 0, 0,
62 &newoffset, &newep) != OK) {
63 printf("SYSTEM: do_umap: verify_grant in %s, grant %d, bytes 0x%lx, failed, caller %s\n", targetpr->p_name, offset, count, caller->p_name);
64 proc_stacktrace(caller);
65 return EFAULT;
68 if(!isokendpt(newep, &new_proc_nr)) {
69 printf("SYSTEM: do_umap: isokendpt failed\n");
70 return EFAULT;
73 /* New lookup. */
74 offset = newoffset;
75 targetpr = proc_addr(new_proc_nr);
76 seg_index = D;
79 if(seg_index == T || seg_index == D || seg_index == S) {
80 phys_addr = lin_addr = umap_local(targetpr, seg_index, offset, count);
81 } else {
82 printf("SYSTEM: bogus seg type 0x%lx\n", seg_index);
83 return EFAULT;
85 if(!lin_addr) {
86 printf("SYSTEM:do_umap: umap_local failed\n");
87 return EFAULT;
89 if(vm_lookup(targetpr, lin_addr, &phys_addr, NULL) != OK) {
90 printf("SYSTEM:do_umap: vm_lookup failed\n");
91 return EFAULT;
93 if(phys_addr == 0)
94 panic("vm_lookup returned zero physical address");
95 break;
96 default:
97 if((r=arch_umap(targetpr, offset, count, seg_type, &lin_addr))
98 != OK)
99 return r;
100 phys_addr = lin_addr;
103 if(vm_running && !vm_contiguous(targetpr, lin_addr, count)) {
104 printf("SYSTEM:do_umap: not contiguous\n");
105 return EFAULT;
108 m_ptr->CP_DST_ADDR = phys_addr;
109 if(naughty || phys_addr == 0) {
110 printf("kernel: umap 0x%x done by %d / %s, pc 0x%lx, 0x%lx -> 0x%lx\n",
111 seg_type, caller->p_endpoint, caller->p_name,
112 caller->p_reg.pc, offset, phys_addr);
113 printf("caller stack: ");
114 proc_stacktrace(caller);
116 return (phys_addr == 0) ? EFAULT: OK;
119 #endif /* USE_UMAP */