make vfs & filesystems use failable copying
[minix3.git] / kernel / system / do_umap_remote.c
blob7e9c10fc18d4c54e39fc74dbff5f441c6cd6eb27
1 /* The kernel call implemented in this file:
2 * m_type: SYS_UMAP_REMOTE
4 * The parameters for this kernel call are:
5 * m5_i1: CP_SRC_PROC_NR (process number)
6 * m5_s1: UMAP_SEG (segment where address is: T, D, or S)
7 * m5_l1: CP_SRC_ADDR (virtual address)
8 * m5_i2: CP_DST_ENDPT (process number of grantee to check access for)
9 * m5_l2: CP_DST_ADDR (returns physical address)
10 * m5_l3: CP_NR_BYTES (size of datastructure)
13 #include "kernel/system.h"
15 #include <minix/endpoint.h>
17 #if USE_UMAP || USE_UMAP_REMOTE
19 #if ! USE_UMAP_REMOTE
20 #undef do_umap_remote
21 #endif
23 /*==========================================================================*
24 * do_umap_remote *
25 *==========================================================================*/
26 int do_umap_remote(struct proc * caller, message * m_ptr)
28 /* Map virtual address to physical, for non-kernel processes. */
29 int seg_type = m_ptr->UMAP_SEG & SEGMENT_TYPE;
30 int seg_index = m_ptr->UMAP_SEG & SEGMENT_INDEX;
31 vir_bytes offset = m_ptr->CP_SRC_ADDR;
32 int count = m_ptr->CP_NR_BYTES;
33 int endpt = (int) m_ptr->CP_SRC_ENDPT;
34 endpoint_t grantee = (endpoint_t) m_ptr->CP_DST_ENDPT;
35 int proc_nr, proc_nr_grantee;
36 phys_bytes phys_addr = 0, lin_addr = 0;
37 struct proc *targetpr;
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);
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;
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;
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;
73 if(!isokendpt(newep, &new_proc_nr)) {
74 printf("SYSTEM: do_umap: isokendpt failed\n");
75 return EFAULT;
78 /* New lookup. */
79 offset = newoffset;
80 targetpr = proc_addr(new_proc_nr);
81 seg_index = VIR_ADDR;
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;
90 if(!lin_addr) {
91 printf("SYSTEM:do_umap: umap_local failed\n");
92 return EFAULT;
94 if(vm_lookup(targetpr, lin_addr, &phys_addr, NULL) != OK) {
95 printf("SYSTEM:do_umap: vm_lookup failed\n");
96 return EFAULT;
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;
106 if(vm_running && vm_lookup_range(targetpr, lin_addr, NULL, count) != count) {
107 printf("SYSTEM:do_umap: not contiguous\n");
108 return EFAULT;
111 m_ptr->CP_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);
119 return (phys_addr == 0) ? EFAULT: OK;
122 #endif /* USE_UMAP || USE_UMAP_REMOTE */