• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "mmz.h"
33 #include "fcntl.h"
34 #include "fs/driver.h"
35 #include "los_vm_map.h"
36 #include "los_vm_phys.h"
37 #include "los_vm_lock.h"
38 #include "los_hw.h"
39 #include "los_atomic.h"
40 #include "los_vm_common.h"
41 #include "los_process_pri.h"
42 #include "target_config.h"
43 
MmzOpen(struct file * filep)44 static int MmzOpen(struct file *filep)
45 {
46     return 0;
47 }
48 
MmzClose(struct file * filep)49 static int MmzClose(struct file *filep)
50 {
51     return 0;
52 }
53 
MmzAlloc(int cmd,unsigned long arg)54 static ssize_t MmzAlloc(int cmd, unsigned long arg)
55 {
56     UINT32 vmFlags = VM_MAP_REGION_FLAG_PERM_USER |
57                      VM_MAP_REGION_FLAG_PERM_READ |
58                      VM_MAP_REGION_FLAG_PERM_WRITE;
59     STATUS_T status;
60     MmzMemory *mmzm = (MmzMemory *)arg;
61     LosVmSpace *curVmSpace = OsCurrProcessGet()->vmSpace;
62     LosVmMapRegion *vmRegion;
63     VOID *kvaddr;
64     PADDR_T paddr;
65     VADDR_T vaddr;
66     UINT32 size = ROUNDUP(mmzm->size, PAGE_SIZE);
67     LosVmPage *vmPage = NULL;
68 
69     switch (cmd) {
70         case MMZ_CACHE_TYPE:
71             vmFlags |= VM_MAP_REGION_FLAG_CACHED;
72             break;
73         case MMZ_NOCACHE_TYPE:
74             vmFlags |= VM_MAP_REGION_FLAG_UNCACHED;
75             break;
76         default:
77             PRINT_ERR("%s %d: %d\n", __func__, __LINE__, cmd);
78             return -EINVAL;
79     }
80     vmRegion = LOS_RegionAlloc(curVmSpace, 0, size, vmFlags, 0);
81     if (vmRegion == NULL) {
82         PRINT_ERR("cmd: %d, size: %#x vaddr alloc failed\n", cmd, size);
83         return -ENOMEM;
84     }
85 
86     kvaddr = (void *)LOS_PhysPagesAllocContiguous(size >> PAGE_SHIFT);
87     if (kvaddr == NULL) {
88         LOS_RegionFree(curVmSpace, vmRegion);
89         PRINT_ERR("size: %#x paddr alloc failed\n", size);
90         return -ENOMEM;
91     }
92 
93     paddr = LOS_PaddrQuery(kvaddr);
94     mmzm->paddr = paddr;
95     vaddr = vmRegion->range.base;
96     while (size > 0) {
97         vmPage = LOS_VmPageGet(paddr);
98         if (vmPage == NULL) {
99             LOS_RegionFree(curVmSpace, vmRegion);
100             VM_ERR("Page is NULL");
101             return -EINVAL;
102         }
103         LOS_AtomicInc(&vmPage->refCounts);
104 
105         status = LOS_ArchMmuMap(&curVmSpace->archMmu, vaddr, paddr, 1, vmFlags);
106         if (status <= 0) {
107             VM_ERR("LOS_ArchMmuMap failed: %d", status);
108             LOS_RegionFree(curVmSpace, vmRegion);
109             return status;
110         }
111 
112         paddr += PAGE_SIZE;
113         vaddr += PAGE_SIZE;
114         size -= PAGE_SIZE;
115     }
116     mmzm->vaddr = (void *)vmRegion->range.base;
117     return LOS_OK;
118 }
119 
MmzMap(int cmd,unsigned long arg)120 static ssize_t MmzMap(int cmd, unsigned long arg)
121 {
122     UINT32 vmFlags = VM_MAP_REGION_FLAG_PERM_USER |
123                      VM_MAP_REGION_FLAG_PERM_READ |
124                      VM_MAP_REGION_FLAG_PERM_WRITE;
125     MmzMemory *mmzm = (MmzMemory *)arg;
126     LosVmSpace *curVmSpace = OsCurrProcessGet()->vmSpace;
127     LosVmMapRegion *vmRegion = NULL;
128     STATUS_T status = LOS_OK;
129     PADDR_T paddr = (PADDR_T)mmzm->paddr;
130     UINT32 size = ROUNDUP(mmzm->size, PAGE_SIZE);
131     VADDR_T vaddr;
132     LosVmPage *vmPage = NULL;
133 
134     switch (cmd) {
135         case MMZ_MAP_CACHE_TYPE:
136             vmFlags |= VM_MAP_REGION_FLAG_CACHED;
137             break;
138         case MMZ_MAP_NOCACHE_TYPE:
139             vmFlags |= VM_MAP_REGION_FLAG_UNCACHED;
140             break;
141         default:
142             PRINT_ERR("%s %d: %d\n", __func__, __LINE__, cmd);
143             return -EINVAL;
144     }
145 
146     vmRegion = LOS_RegionAlloc(curVmSpace, 0, size, vmFlags, 0);
147     if (vmRegion == NULL) {
148         PRINT_ERR("cmd: %d, size: %#x vaddr alloc failed\n", cmd, size);
149         return -ENOMEM;
150     }
151 
152     mmzm->vaddr = (void *)vmRegion->range.base;
153     vaddr = vmRegion->range.base;
154     while (size > 0) {
155         vmPage = LOS_VmPageGet(paddr);
156         if (vmPage == NULL) {
157             LOS_RegionFree(curVmSpace, vmRegion);
158             VM_ERR("Page is NULL");
159             return -EINVAL;
160         }
161         LOS_AtomicInc(&vmPage->refCounts);
162 
163         status = LOS_ArchMmuMap(&curVmSpace->archMmu, vaddr, paddr, 1,
164                 vmRegion->regionFlags);
165         if (status <= 0) {
166             VM_ERR("LOS_ArchMmuMap failed: %d", status);
167             LOS_RegionFree(curVmSpace, vmRegion);
168             return status;
169         }
170 
171         paddr += PAGE_SIZE;
172         vaddr += PAGE_SIZE;
173         size -= PAGE_SIZE;
174     }
175 
176     return status;
177 }
178 
MmzUnMap(unsigned long arg)179 static ssize_t MmzUnMap(unsigned long arg)
180 {
181     LosVmSpace *curVmSpace = OsCurrProcessGet()->vmSpace;
182     MmzMemory *mmzm = (MmzMemory *)arg;
183     return OsUnMMap(curVmSpace, (VADDR_T)mmzm->vaddr, mmzm->size);
184 }
185 
MmzFree(unsigned long arg)186 static ssize_t MmzFree(unsigned long arg)
187 {
188     MmzMemory *mmzm = (MmzMemory *)arg;
189     LosVmSpace *curVmSpace = OsCurrProcessGet()->vmSpace;
190     LosVmMapRegion *region = NULL;
191     STATUS_T ret = LOS_OK;
192 
193     (VOID)LOS_MuxAcquire(&curVmSpace->regionMux);
194     if ((PADDR_T)mmzm->paddr != LOS_PaddrQuery(mmzm->vaddr)) {
195         PRINT_ERR("vaddr is not equal to paddr");
196         ret = -EINVAL;
197         goto DONE;
198     }
199 
200     region = LOS_RegionFind(curVmSpace, (VADDR_T)(unsigned int)mmzm->vaddr);
201     if (region == NULL) {
202         PRINT_ERR("find region failed");
203         ret = -EINVAL;
204         goto DONE;
205     }
206 
207     ret = LOS_RegionFree(curVmSpace, region);
208     if (ret) {
209         PRINT_ERR("free region failed, ret = %d", ret);
210         ret = -EINVAL;
211     }
212 
213 DONE:
214     (VOID)LOS_MuxRelease(&curVmSpace->regionMux);
215     return ret;
216 }
217 
MmzFlush(unsigned long arg)218 static ssize_t MmzFlush(unsigned long arg)
219 {
220     MmzMemory *mmzm = (MmzMemory *)arg;
221     DCacheFlushRange((unsigned int)mmzm->vaddr, (UINT32)mmzm->vaddr + mmzm->size);
222     return LOS_OK;
223 }
224 
MmzInvalidate(unsigned long arg)225 static ssize_t MmzInvalidate(unsigned long arg)
226 {
227     MmzMemory *mmzm = (MmzMemory *)arg;
228     DCacheInvRange((unsigned int)mmzm->vaddr, (UINT32)mmzm->vaddr + mmzm->size);
229     return LOS_OK;
230 }
231 
MmzIoctl(struct file * filep,int cmd,unsigned long arg)232 static ssize_t MmzIoctl(struct file *filep, int cmd, unsigned long arg)
233 {
234     switch (cmd) {
235         case MMZ_CACHE_TYPE:
236         case MMZ_NOCACHE_TYPE:
237             return MmzAlloc(cmd, arg);
238         case MMZ_FREE_TYPE:
239             return MmzFree(arg);
240         case MMZ_MAP_CACHE_TYPE:
241         case MMZ_MAP_NOCACHE_TYPE:
242             return MmzMap(cmd, arg);
243         case MMZ_UNMAP_TYPE:
244             return MmzUnMap(arg);
245         case MMZ_FLUSH_CACHE_TYPE:
246         case MMZ_FLUSH_NOCACHE_TYPE:
247             return MmzFlush(arg);
248         case MMZ_INVALIDATE_TYPE:
249             return MmzInvalidate(arg);
250         default:
251             PRINT_ERR("%s %d: %d\n", __func__, __LINE__, cmd);
252             return -EINVAL;
253     }
254     return LOS_OK;
255 }
256 
257 static const struct file_operations_vfs g_mmzDevOps = {
258     .open = MmzOpen, /* open */
259     .close = MmzClose, /* close */
260     .ioctl = MmzIoctl, /* ioctl */
261 };
262 
DevMmzRegister(void)263 int DevMmzRegister(void)
264 {
265     return register_driver(MMZ_NODE, &g_mmzDevOps, 0666, 0); /* 0666: file mode */
266 }
267