1
2
3
4
5
6#include <linux/module.h>
7#include <linux/bootmem.h>
8#include <linux/mm.h>
9#include <linux/pfn.h>
10#include <asm/page.h>
11#include <as-layout.h>
12#include <init.h>
13#include <kern.h>
14#include <mem_user.h>
15#include <os.h>
16
17static int physmem_fd = -1;
18
19
20unsigned long high_physmem;
21EXPORT_SYMBOL(high_physmem);
22
23extern unsigned long long physmem_size;
24
25int __init init_maps(unsigned long physmem, unsigned long iomem,
26 unsigned long highmem)
27{
28 struct page *p, *map;
29 unsigned long phys_len, phys_pages, highmem_len, highmem_pages;
30 unsigned long iomem_len, iomem_pages, total_len, total_pages;
31 int i;
32
33 phys_pages = physmem >> PAGE_SHIFT;
34 phys_len = phys_pages * sizeof(struct page);
35
36 iomem_pages = iomem >> PAGE_SHIFT;
37 iomem_len = iomem_pages * sizeof(struct page);
38
39 highmem_pages = highmem >> PAGE_SHIFT;
40 highmem_len = highmem_pages * sizeof(struct page);
41
42 total_pages = phys_pages + iomem_pages + highmem_pages;
43 total_len = phys_len + iomem_len + highmem_len;
44
45 map = alloc_bootmem_low_pages(total_len);
46 if (map == NULL)
47 return -ENOMEM;
48
49 for (i = 0; i < total_pages; i++) {
50 p = &map[i];
51 memset(p, 0, sizeof(struct page));
52 SetPageReserved(p);
53 INIT_LIST_HEAD(&p->lru);
54 }
55
56 max_mapnr = total_pages;
57 return 0;
58}
59
60void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
61 int r, int w, int x)
62{
63 __u64 offset;
64 int fd, err;
65
66 fd = phys_mapping(phys, &offset);
67 err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
68 if (err) {
69 if (err == -ENOMEM)
70 printk(KERN_ERR "try increasing the host's "
71 "/proc/sys/vm/max_map_count to <physical "
72 "memory size>/4096\n");
73 panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
74 "err = %d\n", virt, fd, offset, len, r, w, x, err);
75 }
76}
77
78extern int __syscall_stub_start;
79
80void __init setup_physmem(unsigned long start, unsigned long reserve_end,
81 unsigned long len, unsigned long long highmem)
82{
83 unsigned long reserve = reserve_end - start;
84 int pfn = PFN_UP(__pa(reserve_end));
85 int delta = (len - reserve) >> PAGE_SHIFT;
86 int err, offset, bootmap_size;
87
88 physmem_fd = create_mem_file(len + highmem);
89
90 offset = uml_reserved - uml_physmem;
91 err = os_map_memory((void *) uml_reserved, physmem_fd, offset,
92 len - offset, 1, 1, 1);
93 if (err < 0) {
94 printf("setup_physmem - mapping %ld bytes of memory at 0x%p "
95 "failed - errno = %d\n", len - offset,
96 (void *) uml_reserved, err);
97 exit(1);
98 }
99
100
101
102
103
104 os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
105 os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE);
106 os_fsync_file(physmem_fd);
107
108 bootmap_size = init_bootmem(pfn, pfn + delta);
109 free_bootmem(__pa(reserve_end) + bootmap_size,
110 len - bootmap_size - reserve);
111}
112
113int phys_mapping(unsigned long phys, unsigned long long *offset_out)
114{
115 int fd = -1;
116
117 if (phys < physmem_size) {
118 fd = physmem_fd;
119 *offset_out = phys;
120 }
121 else if (phys < __pa(end_iomem)) {
122 struct iomem_region *region = iomem_regions;
123
124 while (region != NULL) {
125 if ((phys >= region->phys) &&
126 (phys < region->phys + region->size)) {
127 fd = region->fd;
128 *offset_out = phys - region->phys;
129 break;
130 }
131 region = region->next;
132 }
133 }
134 else if (phys < __pa(end_iomem) + highmem) {
135 fd = physmem_fd;
136 *offset_out = phys - iomem_size;
137 }
138
139 return fd;
140}
141
142static int __init uml_mem_setup(char *line, int *add)
143{
144 char *retptr;
145 physmem_size = memparse(line,&retptr);
146 return 0;
147}
148__uml_setup("mem=", uml_mem_setup,
149"mem=<Amount of desired ram>\n"
150" This controls how much \"physical\" memory the kernel allocates\n"
151" for the system. The size is specified as a number followed by\n"
152" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
153" This is not related to the amount of memory in the host. It can\n"
154" be more, and the excess, if it's ever used, will just be swapped out.\n"
155" Example: mem=64M\n\n"
156);
157
158extern int __init parse_iomem(char *str, int *add);
159
160__uml_setup("iomem=", parse_iomem,
161"iomem=<name>,<file>\n"
162" Configure <file> as an IO memory region named <name>.\n\n"
163);
164
165
166
167
168
169
170struct iomem_region *iomem_regions;
171
172
173int iomem_size;
174
175unsigned long find_iomem(char *driver, unsigned long *len_out)
176{
177 struct iomem_region *region = iomem_regions;
178
179 while (region != NULL) {
180 if (!strcmp(region->driver, driver)) {
181 *len_out = region->size;
182 return region->virt;
183 }
184
185 region = region->next;
186 }
187
188 return 0;
189}
190EXPORT_SYMBOL(find_iomem);
191
192static int setup_iomem(void)
193{
194 struct iomem_region *region = iomem_regions;
195 unsigned long iomem_start = high_physmem + PAGE_SIZE;
196 int err;
197
198 while (region != NULL) {
199 err = os_map_memory((void *) iomem_start, region->fd, 0,
200 region->size, 1, 1, 0);
201 if (err)
202 printk(KERN_ERR "Mapping iomem region for driver '%s' "
203 "failed, errno = %d\n", region->driver, -err);
204 else {
205 region->virt = iomem_start;
206 region->phys = __pa(region->virt);
207 }
208
209 iomem_start += region->size + PAGE_SIZE;
210 region = region->next;
211 }
212
213 return 0;
214}
215
216__initcall(setup_iomem);
217