irqdomain: Remove powerpc dependency from debugfs file
[GitHub/mt8127/android_kernel_alcatel_ttab.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
73395a00
AV
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>
1da177e4 16
1da177e4
LT
17static int physmem_fd = -1;
18
1da177e4
LT
19/* Changed during early boot */
20unsigned long high_physmem;
73395a00 21EXPORT_SYMBOL(high_physmem);
1da177e4 22
ae173816 23extern unsigned long long physmem_size;
1da177e4 24
97a1fcbb
JD
25int __init init_maps(unsigned long physmem, unsigned long iomem,
26 unsigned long highmem)
1da177e4
LT
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;
3dfd95b3 43 total_len = phys_len + iomem_len + highmem_len;
1da177e4 44
97a1fcbb 45 map = alloc_bootmem_low_pages(total_len);
6d536e4b 46 if (map == NULL)
60678bbc 47 return -ENOMEM;
1da177e4 48
6d536e4b 49 for (i = 0; i < total_pages; i++) {
1da177e4 50 p = &map[i];
70dc991d 51 memset(p, 0, sizeof(struct page));
1da177e4
LT
52 SetPageReserved(p);
53 INIT_LIST_HEAD(&p->lru);
54 }
55
56 max_mapnr = total_pages;
60678bbc 57 return 0;
1da177e4
LT
58}
59
1da177e4
LT
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);
6d536e4b
JD
68 if (err) {
69 if (err == -ENOMEM)
ba180fd4 70 printk(KERN_ERR "try increasing the host's "
1da177e4
LT
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
23bbd586 78extern int __syscall_stub_start;
d67b569f 79
97a1fcbb
JD
80void __init setup_physmem(unsigned long start, unsigned long reserve_end,
81 unsigned long len, unsigned long long highmem)
1da177e4
LT
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,
5c8aacea 92 len - offset, 1, 1, 1);
6d536e4b 93 if (err < 0) {
512b6fb1
JD
94 printf("setup_physmem - mapping %ld bytes of memory at 0x%p "
95 "failed - errno = %d\n", len - offset,
96 (void *) uml_reserved, err);
1da177e4
LT
97 exit(1);
98 }
99
ba180fd4
JD
100 /*
101 * Special kludge - This page will be mapped in to userspace processes
d67b569f
JD
102 * from physmem_fd, so it needs to be written out there.
103 */
104 os_seek_file(physmem_fd, __pa(&__syscall_stub_start));
a6ea4cce 105 os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE);
d67b569f 106
1da177e4
LT
107 bootmap_size = init_bootmem(pfn, pfn + delta);
108 free_bootmem(__pa(reserve_end) + bootmap_size,
109 len - bootmap_size - reserve);
110}
111
0a7675aa 112int phys_mapping(unsigned long phys, unsigned long long *offset_out)
1da177e4 113{
1da177e4
LT
114 int fd = -1;
115
6d536e4b 116 if (phys < physmem_size) {
1da177e4
LT
117 fd = physmem_fd;
118 *offset_out = phys;
119 }
6d536e4b 120 else if (phys < __pa(end_iomem)) {
1da177e4
LT
121 struct iomem_region *region = iomem_regions;
122
6d536e4b
JD
123 while (region != NULL) {
124 if ((phys >= region->phys) &&
125 (phys < region->phys + region->size)) {
1da177e4
LT
126 fd = region->fd;
127 *offset_out = phys - region->phys;
128 break;
129 }
130 region = region->next;
131 }
132 }
6d536e4b 133 else if (phys < __pa(end_iomem) + highmem) {
1da177e4
LT
134 fd = physmem_fd;
135 *offset_out = phys - iomem_size;
136 }
137
60678bbc 138 return fd;
1da177e4
LT
139}
140
141static int __init uml_mem_setup(char *line, int *add)
142{
143 char *retptr;
144 physmem_size = memparse(line,&retptr);
145 return 0;
146}
147__uml_setup("mem=", uml_mem_setup,
148"mem=<Amount of desired ram>\n"
149" This controls how much \"physical\" memory the kernel allocates\n"
150" for the system. The size is specified as a number followed by\n"
151" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
152" This is not related to the amount of memory in the host. It can\n"
153" be more, and the excess, if it's ever used, will just be swapped out.\n"
154" Example: mem=64M\n\n"
155);
156
94c282d7
JD
157extern int __init parse_iomem(char *str, int *add);
158
159__uml_setup("iomem=", parse_iomem,
160"iomem=<name>,<file>\n"
161" Configure <file> as an IO memory region named <name>.\n\n"
162);
163
164/*
165 * This list is constructed in parse_iomem and addresses filled in in
166 * setup_iomem, both of which run during early boot. Afterwards, it's
167 * unchanged.
168 */
80e39311 169struct iomem_region *iomem_regions;
94c282d7 170
80e39311
JD
171/* Initialized in parse_iomem and unchanged thereafter */
172int iomem_size;
94c282d7 173
1da177e4
LT
174unsigned long find_iomem(char *driver, unsigned long *len_out)
175{
176 struct iomem_region *region = iomem_regions;
177
6d536e4b
JD
178 while (region != NULL) {
179 if (!strcmp(region->driver, driver)) {
1da177e4 180 *len_out = region->size;
60678bbc 181 return region->virt;
1da177e4 182 }
c39e50b4
VV
183
184 region = region->next;
1da177e4
LT
185 }
186
60678bbc 187 return 0;
1da177e4 188}
73395a00 189EXPORT_SYMBOL(find_iomem);
1da177e4 190
99764fa4 191static int setup_iomem(void)
1da177e4
LT
192{
193 struct iomem_region *region = iomem_regions;
194 unsigned long iomem_start = high_physmem + PAGE_SIZE;
195 int err;
196
6d536e4b 197 while (region != NULL) {
1da177e4
LT
198 err = os_map_memory((void *) iomem_start, region->fd, 0,
199 region->size, 1, 1, 0);
6d536e4b 200 if (err)
ba180fd4
JD
201 printk(KERN_ERR "Mapping iomem region for driver '%s' "
202 "failed, errno = %d\n", region->driver, -err);
1da177e4
LT
203 else {
204 region->virt = iomem_start;
205 region->phys = __pa(region->virt);
206 }
207
208 iomem_start += region->size + PAGE_SIZE;
209 region = region->next;
210 }
211
60678bbc 212 return 0;
1da177e4
LT
213}
214
215__initcall(setup_iomem);