xref: /minix/minix/kernel/system/do_umap_remote.c (revision 7f5f010b)
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  *==========================================================================*/
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