1
2
3
4
5
6#include "linux/mm.h"
7#include "linux/rbtree.h"
8#include "linux/slab.h"
9#include "linux/vmalloc.h"
10#include "linux/bootmem.h"
11#include "linux/module.h"
12#include "asm/types.h"
13#include "asm/pgtable.h"
14#include "kern_util.h"
15#include "user_util.h"
16#include "mode_kern.h"
17#include "mem.h"
18#include "mem_user.h"
19#include "os.h"
20#include "kern.h"
21#include "init.h"
22
23struct phys_desc {
24 struct rb_node rb;
25 int fd;
26 __u64 offset;
27 void *virt;
28 unsigned long phys;
29 struct list_head list;
30};
31
32static struct rb_root phys_mappings = RB_ROOT;
33
34static struct rb_node **find_rb(void *virt)
35{
36 struct rb_node **n = &phys_mappings.rb_node;
37 struct phys_desc *d;
38
39 while(*n != NULL){
40 d = rb_entry(*n, struct phys_desc, rb);
41 if(d->virt == virt)
42 return(n);
43
44 if(d->virt > virt)
45 n = &(*n)->rb_left;
46 else
47 n = &(*n)->rb_right;
48 }
49
50 return(n);
51}
52
53static struct phys_desc *find_phys_mapping(void *virt)
54{
55 struct rb_node **n = find_rb(virt);
56
57 if(*n == NULL)
58 return(NULL);
59
60 return(rb_entry(*n, struct phys_desc, rb));
61}
62
63static void insert_phys_mapping(struct phys_desc *desc)
64{
65 struct rb_node **n = find_rb(desc->virt);
66
67 if(*n != NULL)
68 panic("Physical remapping for %p already present",
69 desc->virt);
70
71 rb_link_node(&desc->rb, (*n)->rb_parent, n);
72 rb_insert_color(&desc->rb, &phys_mappings);
73}
74
75LIST_HEAD(descriptor_mappings);
76
77struct desc_mapping {
78 int fd;
79 struct list_head list;
80 struct list_head pages;
81};
82
83static struct desc_mapping *find_mapping(int fd)
84{
85 struct desc_mapping *desc;
86 struct list_head *ele;
87
88 list_for_each(ele, &descriptor_mappings){
89 desc = list_entry(ele, struct desc_mapping, list);
90 if(desc->fd == fd)
91 return(desc);
92 }
93
94 return(NULL);
95}
96
97static struct desc_mapping *descriptor_mapping(int fd)
98{
99 struct desc_mapping *desc;
100
101 desc = find_mapping(fd);
102 if(desc != NULL)
103 return(desc);
104
105 desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
106 if(desc == NULL)
107 return(NULL);
108
109 *desc = ((struct desc_mapping)
110 { .fd = fd,
111 .list = LIST_HEAD_INIT(desc->list),
112 .pages = LIST_HEAD_INIT(desc->pages) });
113 list_add(&desc->list, &descriptor_mappings);
114
115 return(desc);
116}
117
118int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w)
119{
120 struct desc_mapping *fd_maps;
121 struct phys_desc *desc;
122 unsigned long phys;
123 int err;
124
125 fd_maps = descriptor_mapping(fd);
126 if(fd_maps == NULL)
127 return(-ENOMEM);
128
129 phys = __pa(virt);
130 desc = find_phys_mapping(virt);
131 if(desc != NULL)
132 panic("Address 0x%p is already substituted\n", virt);
133
134 err = -ENOMEM;
135 desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
136 if(desc == NULL)
137 goto out;
138
139 *desc = ((struct phys_desc)
140 { .fd = fd,
141 .offset = offset,
142 .virt = virt,
143 .phys = __pa(virt),
144 .list = LIST_HEAD_INIT(desc->list) });
145 insert_phys_mapping(desc);
146
147 list_add(&desc->list, &fd_maps->pages);
148
149 virt = (void *) ((unsigned long) virt & PAGE_MASK);
150 err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0);
151 if(!err)
152 goto out;
153
154 rb_erase(&desc->rb, &phys_mappings);
155 kfree(desc);
156 out:
157 return(err);
158}
159
160static int physmem_fd = -1;
161
162static void remove_mapping(struct phys_desc *desc)
163{
164 void *virt = desc->virt;
165 int err;
166
167 rb_erase(&desc->rb, &phys_mappings);
168 list_del(&desc->list);
169 kfree(desc);
170
171 err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0);
172 if(err)
173 panic("Failed to unmap block device page from physical memory, "
174 "errno = %d", -err);
175}
176
177int physmem_remove_mapping(void *virt)
178{
179 struct phys_desc *desc;
180
181 virt = (void *) ((unsigned long) virt & PAGE_MASK);
182 desc = find_phys_mapping(virt);
183 if(desc == NULL)
184 return(0);
185
186 remove_mapping(desc);
187 return(1);
188}
189
190void physmem_forget_descriptor(int fd)
191{
192 struct desc_mapping *desc;
193 struct phys_desc *page;
194 struct list_head *ele, *next;
195 __u64 offset;
196 void *addr;
197 int err;
198
199 desc = find_mapping(fd);
200 if(desc == NULL)
201 return;
202
203 list_for_each_safe(ele, next, &desc->pages){
204 page = list_entry(ele, struct phys_desc, list);
205 offset = page->offset;
206 addr = page->virt;
207 remove_mapping(page);
208 err = os_seek_file(fd, offset);
209 if(err)
210 panic("physmem_forget_descriptor - failed to seek "
211 "to %lld in fd %d, error = %d\n",
212 offset, fd, -err);
213 err = os_read_file(fd, addr, PAGE_SIZE);
214 if(err < 0)
215 panic("physmem_forget_descriptor - failed to read "
216 "from fd %d to 0x%p, error = %d\n",
217 fd, addr, -err);
218 }
219
220 list_del(&desc->list);
221 kfree(desc);
222}
223
224EXPORT_SYMBOL(physmem_forget_descriptor);
225EXPORT_SYMBOL(physmem_remove_mapping);
226EXPORT_SYMBOL(physmem_subst_mapping);
227
228void arch_free_page(struct page *page, int order)
229{
230 void *virt;
231 int i;
232
233 for(i = 0; i < (1 << order); i++){
234 virt = __va(page_to_phys(page + i));
235 physmem_remove_mapping(virt);
236 }
237}
238
239int is_remapped(void *virt)
240{
241 struct phys_desc *desc = find_phys_mapping(virt);
242
243 return(desc != NULL);
244}
245
246
247unsigned long high_physmem;
248
249extern unsigned long physmem_size;
250
251void *to_virt(unsigned long phys)
252{
253 return((void *) uml_physmem + phys);
254}
255
256unsigned long to_phys(void *virt)
257{
258 return(((unsigned long) virt) - uml_physmem);
259}
260
261int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem)
262{
263 struct page *p, *map;
264 unsigned long phys_len, phys_pages, highmem_len, highmem_pages;
265 unsigned long iomem_len, iomem_pages, total_len, total_pages;
266 int i;
267
268 phys_pages = physmem >> PAGE_SHIFT;
269 phys_len = phys_pages * sizeof(struct page);
270
271 iomem_pages = iomem >> PAGE_SHIFT;
272 iomem_len = iomem_pages * sizeof(struct page);
273
274 highmem_pages = highmem >> PAGE_SHIFT;
275 highmem_len = highmem_pages * sizeof(struct page);
276
277 total_pages = phys_pages + iomem_pages + highmem_pages;
278 total_len = phys_len + iomem_pages + highmem_len;
279
280 if(kmalloc_ok){
281 map = kmalloc(total_len, GFP_KERNEL);
282 if(map == NULL)
283 map = vmalloc(total_len);
284 }
285 else map = alloc_bootmem_low_pages(total_len);
286
287 if(map == NULL)
288 return(-ENOMEM);
289
290 for(i = 0; i < total_pages; i++){
291 p = &map[i];
292 set_page_count(p, 0);
293 SetPageReserved(p);
294 INIT_LIST_HEAD(&p->lru);
295 }
296
297 mem_map = map;
298 max_mapnr = total_pages;
299 return(0);
300}
301
302struct page *phys_to_page(const unsigned long phys)
303{
304 return(&mem_map[phys >> PAGE_SHIFT]);
305}
306
307struct page *__virt_to_page(const unsigned long virt)
308{
309 return(&mem_map[__pa(virt) >> PAGE_SHIFT]);
310}
311
312phys_t page_to_phys(struct page *page)
313{
314 return((page - mem_map) << PAGE_SHIFT);
315}
316
317pte_t mk_pte(struct page *page, pgprot_t pgprot)
318{
319 pte_t pte;
320
321 pte_set_val(pte, page_to_phys(page), pgprot);
322 if(pte_present(pte))
323 pte_mknewprot(pte_mknewpage(pte));
324 return(pte);
325}
326
327
328static unsigned long kmem_top = 0;
329
330unsigned long get_kmem_end(void)
331{
332 if(kmem_top == 0)
333 kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
334 return(kmem_top);
335}
336
337void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
338 int r, int w, int x)
339{
340 __u64 offset;
341 int fd, err;
342
343 fd = phys_mapping(phys, &offset);
344 err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
345 if(err) {
346 if(err == -ENOMEM)
347 printk("try increasing the host's "
348 "/proc/sys/vm/max_map_count to <physical "
349 "memory size>/4096\n");
350 panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
351 "err = %d\n", virt, fd, offset, len, r, w, x, err);
352 }
353}
354
355#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
356
357void setup_physmem(unsigned long start, unsigned long reserve_end,
358 unsigned long len, unsigned long highmem)
359{
360 unsigned long reserve = reserve_end - start;
361 int pfn = PFN_UP(__pa(reserve_end));
362 int delta = (len - reserve) >> PAGE_SHIFT;
363 int err, offset, bootmap_size;
364
365 physmem_fd = create_mem_file(len + highmem);
366
367 offset = uml_reserved - uml_physmem;
368 err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
369 len - offset, 1, 1, 0);
370 if(err < 0){
371 os_print_error(err, "Mapping memory");
372 exit(1);
373 }
374
375 bootmap_size = init_bootmem(pfn, pfn + delta);
376 free_bootmem(__pa(reserve_end) + bootmap_size,
377 len - bootmap_size - reserve);
378}
379
380int phys_mapping(unsigned long phys, __u64 *offset_out)
381{
382 struct phys_desc *desc = find_phys_mapping(__va(phys & PAGE_MASK));
383 int fd = -1;
384
385 if(desc != NULL){
386 fd = desc->fd;
387 *offset_out = desc->offset;
388 }
389 else if(phys < physmem_size){
390 fd = physmem_fd;
391 *offset_out = phys;
392 }
393 else if(phys < __pa(end_iomem)){
394 struct iomem_region *region = iomem_regions;
395
396 while(region != NULL){
397 if((phys >= region->phys) &&
398 (phys < region->phys + region->size)){
399 fd = region->fd;
400 *offset_out = phys - region->phys;
401 break;
402 }
403 region = region->next;
404 }
405 }
406 else if(phys < __pa(end_iomem) + highmem){
407 fd = physmem_fd;
408 *offset_out = phys - iomem_size;
409 }
410
411 return(fd);
412}
413
414static int __init uml_mem_setup(char *line, int *add)
415{
416 char *retptr;
417 physmem_size = memparse(line,&retptr);
418 return 0;
419}
420__uml_setup("mem=", uml_mem_setup,
421"mem=<Amount of desired ram>\n"
422" This controls how much \"physical\" memory the kernel allocates\n"
423" for the system. The size is specified as a number followed by\n"
424" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
425" This is not related to the amount of memory in the host. It can\n"
426" be more, and the excess, if it's ever used, will just be swapped out.\n"
427" Example: mem=64M\n\n"
428);
429
430unsigned long find_iomem(char *driver, unsigned long *len_out)
431{
432 struct iomem_region *region = iomem_regions;
433
434 while(region != NULL){
435 if(!strcmp(region->driver, driver)){
436 *len_out = region->size;
437 return(region->virt);
438 }
439 }
440
441 return(0);
442}
443
444int setup_iomem(void)
445{
446 struct iomem_region *region = iomem_regions;
447 unsigned long iomem_start = high_physmem + PAGE_SIZE;
448 int err;
449
450 while(region != NULL){
451 err = os_map_memory((void *) iomem_start, region->fd, 0,
452 region->size, 1, 1, 0);
453 if(err)
454 printk("Mapping iomem region for driver '%s' failed, "
455 "errno = %d\n", region->driver, -err);
456 else {
457 region->virt = iomem_start;
458 region->phys = __pa(region->virt);
459 }
460
461 iomem_start += region->size + PAGE_SIZE;
462 region = region->next;
463 }
464
465 return(0);
466}
467
468__initcall(setup_iomem);
469
470
471
472
473
474
475
476
477
478
479
480