1 /* The kernel call implemented in this file:
2 * m_type: SYS_UMAP_REMOTE
3 *
4 * The parameters for this kernel call are:
5 * m_lsys_krn_sys_umap.src_endpt (process number)
6 * m_lsys_krn_sys_umap.segment (segment where address is: T, D, or S)
7 * m_lsys_krn_sys_umap.src_addr (virtual address)
8 * m_lsys_krn_sys_umap.dst_endpt (process number of grantee to check access for)
9 * m_krn_lsys_sys_umap.dst_addr (returns physical address)
10 * m_lsys_krn_sys_umap.nr_bytes (size of datastructure)
11 */
12
13 #include "kernel/system.h"
14
15 #include <minix/endpoint.h>
16
17 #if USE_UMAP || USE_UMAP_REMOTE
18
19 #if ! USE_UMAP_REMOTE
20 #undef do_umap_remote
21 #endif
22
23 /*==========================================================================*
24 * do_umap_remote *
25 *==========================================================================*/
do_umap_remote(struct proc * caller,message * m_ptr)26 int do_umap_remote(struct proc * caller, message * m_ptr)
27 {
28 /* Map virtual address to physical, for non-kernel processes. */
29 int seg_type = m_ptr->m_lsys_krn_sys_umap.segment & SEGMENT_TYPE;
30 int seg_index = m_ptr->m_lsys_krn_sys_umap.segment & SEGMENT_INDEX;
31 vir_bytes offset = m_ptr->m_lsys_krn_sys_umap.src_addr;
32 int count = m_ptr->m_lsys_krn_sys_umap.nr_bytes;
33 endpoint_t endpt = m_ptr->m_lsys_krn_sys_umap.src_endpt;
34 endpoint_t grantee = m_ptr->m_lsys_krn_sys_umap.dst_endpt;
35 int proc_nr, proc_nr_grantee;
36 phys_bytes phys_addr = 0, lin_addr = 0;
37 struct proc *targetpr;
38
39 /* Verify process number. */
40 if (endpt == SELF)
41 okendpt(caller->p_endpoint, &proc_nr);
42 else
43 if (! isokendpt(endpt, &proc_nr))
44 return(EINVAL);
45 targetpr = proc_addr(proc_nr);
46
47 /* Verify grantee endpoint */
48 if (grantee == SELF) {
49 grantee = caller->p_endpoint;
50 } else if (grantee == NONE ||
51 grantee == ANY ||
52 seg_index != MEM_GRANT ||
53 !isokendpt(grantee, &proc_nr_grantee)) {
54 return EINVAL;
55 }
56
57 /* See which mapping should be made. */
58 switch(seg_type) {
59 case LOCAL_VM_SEG:
60 if(seg_index == MEM_GRANT) {
61 vir_bytes newoffset;
62 endpoint_t newep;
63 int new_proc_nr;
64 cp_grant_id_t grant = (cp_grant_id_t) offset;
65
66 if(verify_grant(targetpr->p_endpoint, grantee, grant, count,
67 0, 0, &newoffset, &newep, NULL) != OK) {
68 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);
69 proc_stacktrace(caller);
70 return EFAULT;
71 }
72
73 if(!isokendpt(newep, &new_proc_nr)) {
74 printf("SYSTEM: do_umap: isokendpt failed\n");
75 return EFAULT;
76 }
77
78 /* New lookup. */
79 offset = newoffset;
80 targetpr = proc_addr(new_proc_nr);
81 seg_index = VIR_ADDR;
82 }
83
84 if(seg_index == VIR_ADDR) {
85 phys_addr = lin_addr = offset;
86 } else {
87 printf("SYSTEM: bogus seg type 0x%lx\n", seg_index);
88 return EFAULT;
89 }
90 if(!lin_addr) {
91 printf("SYSTEM:do_umap: umap_local failed\n");
92 return EFAULT;
93 }
94 if(vm_lookup(targetpr, lin_addr, &phys_addr, NULL) != OK) {
95 printf("SYSTEM:do_umap: vm_lookup failed\n");
96 return EFAULT;
97 }
98 if(phys_addr == 0)
99 panic("vm_lookup returned zero physical address");
100 break;
101 default:
102 printf("umap: peculiar type\n");
103 return EINVAL;
104 }
105
106 if(vm_running && vm_lookup_range(targetpr, lin_addr, NULL, count) != count) {
107 printf("SYSTEM:do_umap: not contiguous\n");
108 return EFAULT;
109 }
110
111 m_ptr->m_krn_lsys_sys_umap.dst_addr = phys_addr;
112 if(phys_addr == 0) {
113 printf("kernel: umap 0x%x done by %d / %s, pc 0x%lx, 0x%lx -> 0x%lx\n",
114 seg_type, caller->p_endpoint, caller->p_name,
115 caller->p_reg.pc, offset, phys_addr);
116 printf("caller stack: ");
117 proc_stacktrace(caller);
118 }
119 return (phys_addr == 0) ? EFAULT: OK;
120 }
121
122 #endif /* USE_UMAP || USE_UMAP_REMOTE */
123