0001
0002
0003
0004
0005
0006 #include <linux/module.h>
0007 #include <linux/memblock.h>
0008 #include <linux/mm.h>
0009 #include <linux/pfn.h>
0010 #include <asm/page.h>
0011 #include <asm/sections.h>
0012 #include <as-layout.h>
0013 #include <init.h>
0014 #include <kern.h>
0015 #include <mem_user.h>
0016 #include <os.h>
0017
0018 static int physmem_fd = -1;
0019
0020
0021 unsigned long high_physmem;
0022 EXPORT_SYMBOL(high_physmem);
0023
0024 extern unsigned long long physmem_size;
0025
0026 void __init mem_total_pages(unsigned long physmem, unsigned long iomem,
0027 unsigned long highmem)
0028 {
0029 unsigned long phys_pages, highmem_pages;
0030 unsigned long iomem_pages, total_pages;
0031
0032 phys_pages = physmem >> PAGE_SHIFT;
0033 iomem_pages = iomem >> PAGE_SHIFT;
0034 highmem_pages = highmem >> PAGE_SHIFT;
0035
0036 total_pages = phys_pages + iomem_pages + highmem_pages;
0037
0038 max_mapnr = total_pages;
0039 }
0040
0041 void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
0042 int r, int w, int x)
0043 {
0044 __u64 offset;
0045 int fd, err;
0046
0047 fd = phys_mapping(phys, &offset);
0048 err = os_map_memory((void *) virt, fd, offset, len, r, w, x);
0049 if (err) {
0050 if (err == -ENOMEM)
0051 printk(KERN_ERR "try increasing the host's "
0052 "/proc/sys/vm/max_map_count to <physical "
0053 "memory size>/4096\n");
0054 panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, "
0055 "err = %d\n", virt, fd, offset, len, r, w, x, err);
0056 }
0057 }
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 void __init setup_physmem(unsigned long start, unsigned long reserve_end,
0080 unsigned long len, unsigned long long highmem)
0081 {
0082 unsigned long reserve = reserve_end - start;
0083 long map_size = len - reserve;
0084 int err;
0085
0086 if(map_size <= 0) {
0087 os_warn("Too few physical memory! Needed=%lu, given=%lu\n",
0088 reserve, len);
0089 exit(1);
0090 }
0091
0092 physmem_fd = create_mem_file(len + highmem);
0093
0094 err = os_map_memory((void *) reserve_end, physmem_fd, reserve,
0095 map_size, 1, 1, 1);
0096 if (err < 0) {
0097 os_warn("setup_physmem - mapping %ld bytes of memory at 0x%p "
0098 "failed - errno = %d\n", map_size,
0099 (void *) reserve_end, err);
0100 exit(1);
0101 }
0102
0103
0104
0105
0106
0107 os_seek_file(physmem_fd, __pa(__syscall_stub_start));
0108 os_write_file(physmem_fd, __syscall_stub_start, PAGE_SIZE);
0109 os_fsync_file(physmem_fd);
0110
0111 memblock_add(__pa(start), len + highmem);
0112 memblock_reserve(__pa(start), reserve);
0113
0114 min_low_pfn = PFN_UP(__pa(reserve_end));
0115 max_low_pfn = min_low_pfn + (map_size >> PAGE_SHIFT);
0116 }
0117
0118 int phys_mapping(unsigned long phys, unsigned long long *offset_out)
0119 {
0120 int fd = -1;
0121
0122 if (phys < physmem_size) {
0123 fd = physmem_fd;
0124 *offset_out = phys;
0125 }
0126 else if (phys < __pa(end_iomem)) {
0127 struct iomem_region *region = iomem_regions;
0128
0129 while (region != NULL) {
0130 if ((phys >= region->phys) &&
0131 (phys < region->phys + region->size)) {
0132 fd = region->fd;
0133 *offset_out = phys - region->phys;
0134 break;
0135 }
0136 region = region->next;
0137 }
0138 }
0139 else if (phys < __pa(end_iomem) + highmem) {
0140 fd = physmem_fd;
0141 *offset_out = phys - iomem_size;
0142 }
0143
0144 return fd;
0145 }
0146 EXPORT_SYMBOL(phys_mapping);
0147
0148 static int __init uml_mem_setup(char *line, int *add)
0149 {
0150 char *retptr;
0151 physmem_size = memparse(line,&retptr);
0152 return 0;
0153 }
0154 __uml_setup("mem=", uml_mem_setup,
0155 "mem=<Amount of desired ram>\n"
0156 " This controls how much \"physical\" memory the kernel allocates\n"
0157 " for the system. The size is specified as a number followed by\n"
0158 " one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
0159 " This is not related to the amount of memory in the host. It can\n"
0160 " be more, and the excess, if it's ever used, will just be swapped out.\n"
0161 " Example: mem=64M\n\n"
0162 );
0163
0164 extern int __init parse_iomem(char *str, int *add);
0165
0166 __uml_setup("iomem=", parse_iomem,
0167 "iomem=<name>,<file>\n"
0168 " Configure <file> as an IO memory region named <name>.\n\n"
0169 );
0170
0171
0172
0173
0174
0175
0176 struct iomem_region *iomem_regions;
0177
0178
0179 int iomem_size;
0180
0181 unsigned long find_iomem(char *driver, unsigned long *len_out)
0182 {
0183 struct iomem_region *region = iomem_regions;
0184
0185 while (region != NULL) {
0186 if (!strcmp(region->driver, driver)) {
0187 *len_out = region->size;
0188 return region->virt;
0189 }
0190
0191 region = region->next;
0192 }
0193
0194 return 0;
0195 }
0196 EXPORT_SYMBOL(find_iomem);
0197
0198 static int setup_iomem(void)
0199 {
0200 struct iomem_region *region = iomem_regions;
0201 unsigned long iomem_start = high_physmem + PAGE_SIZE;
0202 int err;
0203
0204 while (region != NULL) {
0205 err = os_map_memory((void *) iomem_start, region->fd, 0,
0206 region->size, 1, 1, 0);
0207 if (err)
0208 printk(KERN_ERR "Mapping iomem region for driver '%s' "
0209 "failed, errno = %d\n", region->driver, -err);
0210 else {
0211 region->virt = iomem_start;
0212 region->phys = __pa(region->virt);
0213 }
0214
0215 iomem_start += region->size + PAGE_SIZE;
0216 region = region->next;
0217 }
0218
0219 return 0;
0220 }
0221
0222 __initcall(setup_iomem);