245ca6bbdc4351ae3994b3df48fb848e4f74bc30
[mirror/winof/.git] / hw / mlx4 / kernel / bus / core / l2w_umem.c
1 #include <mlx4_debug.h>
2 #include "l2w.h"
3 #include "ib_verbs.h"
4
5 #if defined (EVENT_TRACING)
6 #ifdef offsetof
7 #undef offsetof
8 #endif
9 #include "l2w_umem.tmh"
10 #endif 
11
12 /**
13  * ib_umem_release - release memory pinned with ib_umem_get
14  * @umem: umem struct to release
15  */
16 void ib_umem_release(struct ib_umem *p_ib_umem)
17 {
18         MLX4_ENTER(MLX4_DBG_MEMORY);
19         if (p_ib_umem->secure_handle) {
20                 __try {
21                         MmUnsecureVirtualMemory( p_ib_umem->secure_handle );
22                         p_ib_umem->secure_handle = NULL;
23                 }
24                 __except (EXCEPTION_EXECUTE_HANDLER) {
25                         NTSTATUS Status = GetExceptionCode();
26                         UNUSED_PARAM_WOWPP(Status);
27                         MLX4_PRINT(TRACE_LEVEL_ERROR ,MLX4_DBG_MEMORY ,
28                                 ("Exception 0x%x on MmUnsecureVirtualMemory(), addr %I64x, size %I64x, seg_num %d, nr_pages %d\n", 
29                                 Status, p_ib_umem->iobuf.va, (u64)p_ib_umem->iobuf.size, 
30                                 p_ib_umem->iobuf.seg_num, p_ib_umem->iobuf.nr_pages ));
31                 }
32         }
33         if (p_ib_umem->iobuf_used)
34                 iobuf_deregister_with_cash(&p_ib_umem->iobuf);
35         kfree(p_ib_umem);
36         MLX4_EXIT(MLX4_DBG_MEMORY);
37 }
38
39
40 /**
41  * ib_umem_get - Pin and DMA map userspace memory.
42  * @context: userspace context to pin memory for
43  * @addr: userspace virtual address to start at
44  * @size: length of region to pin
45  * @access: IB_ACCESS_xxx flags for memory being pinned
46  */
47 struct ib_umem *ib_umem_get(struct ib_ucontext *context, u64 addr,
48                             size_t size, enum ib_access_flags access, boolean_t secure)
49 {
50         int err;
51         struct ib_umem *p_ib_umem;
52
53         MLX4_ENTER(MLX4_DBG_MEMORY);
54
55         // create the object
56         p_ib_umem = kzalloc(sizeof *p_ib_umem, GFP_KERNEL);
57         if (!p_ib_umem)
58                 goto done;
59
60         p_ib_umem->p_uctx = context;
61         p_ib_umem->page_size = PAGE_SIZE;
62         
63         // register the memory 
64         iobuf_init( addr, (u64)size, !!context, &p_ib_umem->iobuf);
65         err =  iobuf_register_with_cash( addr, (u64)size, !!context, 
66                 &access, &p_ib_umem->iobuf );
67         if (err)
68                 goto err_reg_mem;
69         p_ib_umem->iobuf_used = TRUE;
70
71         // TODO: map the memory for DMA
72         
73         // secure memory
74         if (!context || !secure)
75                 goto done;
76         __try {
77                 p_ib_umem->secure_handle = MmSecureVirtualMemory ( 
78                         (PVOID)(ULONG_PTR)addr, size,
79                         (access & IB_ACCESS_LOCAL_WRITE) ? PAGE_READWRITE : PAGE_READONLY );
80                 if (p_ib_umem->secure_handle == NULL) 
81                         goto err_secure;
82         }
83         __except (EXCEPTION_EXECUTE_HANDLER) {
84                 NTSTATUS Status = GetExceptionCode();
85                 UNUSED_PARAM_WOWPP(Status);
86                 MLX4_PRINT(TRACE_LEVEL_ERROR ,MLX4_DBG_MEMORY ,
87                         ("Exception 0x%x on MmSecureVirtualMemory(), addr %I64x, size %I64x, access %#x\n", 
88                         Status, addr, (u64)size, access ));
89                 goto err_secure;
90         }
91         goto done;
92
93 err_secure:
94         iobuf_deregister(&p_ib_umem->iobuf);
95
96 err_reg_mem:    
97         kfree(p_ib_umem);
98         p_ib_umem = ERR_PTR(-ENOMEM);
99
100 done:   
101         MLX4_EXIT(MLX4_DBG_MEMORY);
102         return p_ib_umem;
103 }
104
105 int ib_umem_page_count(struct ib_umem *p_ib_umem)
106 {
107         return (int)p_ib_umem->iobuf.nr_pages;
108 }
109
110 dma_addr_t ib_umem_get_dma(struct ib_umem *p_ib_umem)
111 {
112         u64 pages[1] = { 0 };
113         iobuf_iter_t iobuf_iter;
114         dma_addr_t dma_addr = { 0, 0 , 0 };
115
116         iobuf_iter_init( &p_ib_umem->iobuf, &iobuf_iter );
117         iobuf_get_tpt_seg( &p_ib_umem->iobuf, &iobuf_iter, 1, pages );
118         // TODO: convert phys address to DMA one
119         dma_addr.da = pages[0];
120
121         return dma_addr;
122 }
123
124
125 // Returns: 0 on success, -ENOMEM or -EACCESS or -EFAULT on error
126 int ib_umem_map(
127         IN              u64 va,
128         IN              u64 size,
129         IN              ib_access_t acc,
130         OUT             PMDL *mdl,
131         OUT             void **kva)
132 {
133         PMDL p_mdl;
134         int rc = 0;
135         LOCK_OPERATION lock_op = (acc & IB_AC_LOCAL_WRITE) ? IoModifyAccess : IoReadAccess;
136
137         p_mdl = IoAllocateMdl( (PVOID)(ULONG_PTR)va, (ULONG)size, FALSE,FALSE,NULL);
138         if (p_mdl == NULL) {
139                 rc = -ENOMEM;
140                 goto err_alloc_mdl;
141         }
142
143         __try { 
144                 MmProbeAndLockPages( p_mdl, UserMode, lock_op );   /* lock memory */
145         } 
146         __except (EXCEPTION_EXECUTE_HANDLER)    {
147                 MLX4_PRINT(TRACE_LEVEL_ERROR, MLX4_DBG_MEMORY, 
148                         ("MOSAL_iobuf_register: Exception 0x%x on MmProbeAndLockPages(), va %I64d, sz %I64d\n", 
149                         GetExceptionCode(), va, size));
150                 rc = -EACCES;
151                 goto err_probe;
152         }
153
154         *kva = MmMapLockedPagesSpecifyCache( p_mdl, 
155                 KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority );
156         if (*kva == NULL) {
157                 MLX4_PRINT(TRACE_LEVEL_ERROR ,MLX4_DBG_MEMORY ,("MmMapLockedPagesSpecifyCache failed\n"));
158                 rc = -EFAULT;
159                 goto err_map;
160         }
161         
162         *mdl = p_mdl;
163         return 0;
164
165 err_map:
166         MmUnlockPages(p_mdl);
167 err_probe:
168         IoFreeMdl(p_mdl);
169 err_alloc_mdl:  
170         return rc;
171 }
172
173 void ib_umem_unmap(
174         IN PMDL p_mdl,
175         IN void *kva)
176 {
177         if (kva) {
178                 MmUnmapLockedPages( kva, p_mdl );
179                 MmUnlockPages(p_mdl);
180                 IoFreeMdl(p_mdl);
181         }
182 }
183
184