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