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