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