001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019 #include <sos/assert.h>
020 #include <sos/kmalloc.h>
021 #include <sos/physmem.h>
022 #include <hwcore/paging.h>
023 #include <sos/kmem_slab.h>
024 #include <sos/list.h>
025 #include <hwcore/paging.h>
026
027 #include "mem.h"
028
029
030
031
032
033 struct kernel_remapped_resource
034 {
035 int ref_cnt;
036 struct sos_umem_vmm_mapped_resource mr;
037 };
038
039
040
041
042 static void resource_ref(struct sos_umem_vmm_vr * vr)
043 {
044
045 struct kernel_remapped_resource * resource;
046 resource
047 = (struct kernel_remapped_resource*)
048 sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
049
050
051 resource->ref_cnt ++;
052 }
053
054
055
056
057 static void resource_unref(struct sos_umem_vmm_vr * vr)
058 {
059
060 struct kernel_remapped_resource * resource;
061 resource
062 = (struct kernel_remapped_resource*)
063 sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data;
064
065
066 SOS_ASSERT_FATAL(resource->ref_cnt > 0);
067 resource->ref_cnt --;
068
069
070 if (resource->ref_cnt == 0)
071 sos_kfree((sos_vaddr_t)resource);
072 }
073
074
075
076
077 static sos_ret_t kmem_page_in(struct sos_umem_vmm_vr * vr,
078 sos_uaddr_t uaddr,
079 sos_bool_t write_access)
080 {
081 sos_vaddr_t vaddr;
082 sos_ret_t retval = SOS_OK;
083 sos_paddr_t ppage_paddr;
084
085
086 vaddr = uaddr - sos_umem_vmm_get_start_of_vr(vr)
087 + sos_umem_vmm_get_offset_in_resource(vr);
088
089
090 if (vaddr >= SOS_PAGING_BASE_USER_ADDRESS)
091 return -SOS_EFAULT;
092
093
094 ppage_paddr = sos_paging_get_paddr(SOS_PAGE_ALIGN_INF(vaddr));
095
096
097 if (! ppage_paddr)
098 return -SOS_EFAULT;
099
100
101 retval = sos_paging_map(ppage_paddr,
102 SOS_PAGE_ALIGN_INF(uaddr),
103 TRUE,
104 sos_umem_vmm_get_prot_of_vr(vr));
105
106 return retval;
107 }
108
109
110
111 static struct sos_umem_vmm_vr_ops kmem_ops = (struct sos_umem_vmm_vr_ops)
112 {
113 .ref = resource_ref,
114 .unref = resource_unref,
115 .page_in = kmem_page_in,
116 };
117
118
119
120 static sos_ret_t kmem_mmap(struct sos_umem_vmm_vr *vr)
121 {
122 return sos_umem_vmm_set_ops_of_vr(vr, &kmem_ops);
123 }
124
125
126
127
128 sos_ret_t sos_dev_kmem_map(struct sos_umem_vmm_as * dest_as,
129 sos_uaddr_t *uaddr,
130 sos_size_t size,
131 sos_vaddr_t offset,
132 sos_ui32_t access_rights,
133 sos_ui32_t flags)
134 {
135 sos_ret_t retval;
136 struct kernel_remapped_resource * kmem_resource;
137
138
139 kmem_resource
140 = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*kmem_resource),
141 0);
142 if (! kmem_resource)
143 return -SOS_ENOMEM;
144
145 memset(kmem_resource, 0x0, sizeof(*kmem_resource));
146 kmem_resource->mr.allowed_access_rights
147 = SOS_VM_MAP_PROT_READ
148 | SOS_VM_MAP_PROT_WRITE
149 | SOS_VM_MAP_PROT_EXEC;
150 kmem_resource->mr.custom_data = kmem_resource;
151 kmem_resource->mr.mmap = kmem_mmap;
152
153
154 retval = sos_umem_vmm_map(dest_as, uaddr, size,
155 access_rights, flags,
156 & kmem_resource->mr, offset);
157 if (SOS_OK != retval)
158 {
159 sos_kfree((sos_vaddr_t)kmem_resource);
160 return retval;
161 }
162
163 return SOS_OK;
164 }
165
166
167
168
169 static sos_ret_t physmem_page_in(struct sos_umem_vmm_vr * vr,
170 sos_uaddr_t uaddr,
171 sos_bool_t write_access)
172 {
173 sos_ret_t retval = SOS_OK;
174 sos_paddr_t ppage_paddr;
175
176
177 ppage_paddr = uaddr - sos_umem_vmm_get_start_of_vr(vr)
178 + sos_umem_vmm_get_offset_in_resource(vr);
179
180
181 retval = sos_paging_map(SOS_PAGE_ALIGN_INF(ppage_paddr),
182 SOS_PAGE_ALIGN_INF(uaddr),
183 TRUE,
184 sos_umem_vmm_get_prot_of_vr(vr));
185 return retval;
186 }
187
188
189
190 static struct sos_umem_vmm_vr_ops physmem_ops = (struct sos_umem_vmm_vr_ops)
191 {
192 .ref = resource_ref,
193 .unref = resource_unref,
194 .page_in = physmem_page_in,
195 };
196
197
198
199 static sos_ret_t physmem_mmap(struct sos_umem_vmm_vr *vr)
200 {
201 return sos_umem_vmm_set_ops_of_vr(vr, &physmem_ops);
202 }
203
204
205
206
207 sos_ret_t sos_dev_physmem_map(struct sos_umem_vmm_as * dest_as,
208 sos_uaddr_t *uaddr,
209 sos_size_t size,
210 sos_paddr_t offset,
211 sos_ui32_t access_rights,
212 sos_ui32_t flags)
213 {
214 sos_ret_t retval;
215 struct kernel_remapped_resource * physmem_resource;
216
217 physmem_resource
218 = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*physmem_resource),
219 0);
220 if (! physmem_resource)
221 return -SOS_ENOMEM;
222
223 memset(physmem_resource, 0x0, sizeof(*physmem_resource));
224 physmem_resource->mr.allowed_access_rights
225 = SOS_VM_MAP_PROT_READ
226 | SOS_VM_MAP_PROT_WRITE
227 | SOS_VM_MAP_PROT_EXEC;
228 physmem_resource->mr.custom_data = physmem_resource;
229 physmem_resource->mr.mmap = physmem_mmap;
230
231 retval = sos_umem_vmm_map(dest_as, uaddr, size,
232 access_rights, flags,
233 & physmem_resource->mr, offset);
234 if (SOS_OK != retval)
235 {
236 sos_kfree((sos_vaddr_t)physmem_resource);
237 return retval;
238 }
239
240 return SOS_OK;
241 }