1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 */ 5 6 #include <linux/module.h> 7 #include <linux/memblock.h> 8 #include <linux/mm.h> 9 #include <linux/pfn.h> 10 #include <asm/page.h> 11 #include <asm/sections.h> 12 #include <as-layout.h> 13 #include <init.h> 14 #include <kern.h> 15 #include <kern_util.h> 16 #include <mem_user.h> 17 #include <os.h> 18 19 static int physmem_fd = -1; 20 21 /* Changed during early boot */ 22 unsigned long high_physmem; 23 EXPORT_SYMBOL(high_physmem); 24 25 void __init mem_total_pages(unsigned long physmem, unsigned long iomem) 26 { 27 unsigned long phys_pages, iomem_pages, total_pages; 28 29 phys_pages = physmem >> PAGE_SHIFT; 30 iomem_pages = iomem >> PAGE_SHIFT; 31 32 total_pages = phys_pages + iomem_pages; 33 34 max_mapnr = total_pages; 35 } 36 37 void map_memory(unsigned long virt, unsigned long phys, unsigned long len, 38 int r, int w, int x) 39 { 40 __u64 offset; 41 int fd, err; 42 43 fd = phys_mapping(phys, &offset); 44 err = os_map_memory((void *) virt, fd, offset, len, r, w, x); 45 if (err) { 46 if (err == -ENOMEM) 47 printk(KERN_ERR "try increasing the host's " 48 "/proc/sys/vm/max_map_count to <physical " 49 "memory size>/4096\n"); 50 panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " 51 "err = %d\n", virt, fd, offset, len, r, w, x, err); 52 } 53 } 54 55 /** 56 * setup_physmem() - Setup physical memory for UML 57 * @start: Start address of the physical kernel memory, 58 * i.e start address of the executable image. 59 * @reserve_end: end address of the physical kernel memory. 60 * @len: Length of total physical memory that should be mapped/made 61 * available, in bytes. 62 * 63 * Creates an unlinked temporary file of size (len) and memory maps 64 * it on the last executable image address (uml_reserved). 65 * 66 * The offset is needed as the length of the total physical memory 67 * (len) includes the size of the memory used be the executable image, 68 * but the mapped-to address is the last address of the executable image 69 * (uml_reserved == end address of executable image). 70 * 71 * The memory mapped memory of the temporary file is used as backing memory 72 * of all user space processes/kernel tasks. 73 */ 74 void __init setup_physmem(unsigned long start, unsigned long reserve_end, 75 unsigned long len) 76 { 77 unsigned long reserve = reserve_end - start; 78 unsigned long map_size = len - reserve; 79 int err; 80 81 if (len <= reserve) { 82 os_warn("Too few physical memory! Needed=%lu, given=%lu\n", 83 reserve, len); 84 exit(1); 85 } 86 87 physmem_fd = create_mem_file(len); 88 89 err = os_map_memory((void *) reserve_end, physmem_fd, reserve, 90 map_size, 1, 1, 1); 91 if (err < 0) { 92 os_warn("setup_physmem - mapping %lu bytes of memory at 0x%p " 93 "failed - errno = %d\n", map_size, 94 (void *) reserve_end, err); 95 exit(1); 96 } 97 98 /* 99 * Special kludge - This page will be mapped in to userspace processes 100 * from physmem_fd, so it needs to be written out there. 101 */ 102 os_seek_file(physmem_fd, __pa(__syscall_stub_start)); 103 os_write_file(physmem_fd, __syscall_stub_start, PAGE_SIZE); 104 os_fsync_file(physmem_fd); 105 106 memblock_add(__pa(start), len); 107 memblock_reserve(__pa(start), reserve); 108 109 min_low_pfn = PFN_UP(__pa(reserve_end)); 110 max_low_pfn = min_low_pfn + (map_size >> PAGE_SHIFT); 111 } 112 113 int 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 135 return fd; 136 } 137 EXPORT_SYMBOL(phys_mapping); 138 139 static int __init uml_mem_setup(char *line, int *add) 140 { 141 char *retptr; 142 physmem_size = memparse(line,&retptr); 143 return 0; 144 } 145 __uml_setup("mem=", uml_mem_setup, 146 "mem=<Amount of desired ram>\n" 147 " This controls how much \"physical\" memory the kernel allocates\n" 148 " for the system. The size is specified as a number followed by\n" 149 " one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" 150 " This is not related to the amount of memory in the host. It can\n" 151 " be more, and the excess, if it's ever used, will just be swapped out.\n" 152 " Example: mem=64M\n\n" 153 ); 154 155 __uml_setup("iomem=", parse_iomem, 156 "iomem=<name>,<file>\n" 157 " Configure <file> as an IO memory region named <name>.\n\n" 158 ); 159 160 /* 161 * This list is constructed in parse_iomem and addresses filled in 162 * setup_iomem, both of which run during early boot. Afterwards, it's 163 * unchanged. 164 */ 165 struct iomem_region *iomem_regions; 166 167 /* Initialized in parse_iomem and unchanged thereafter */ 168 int iomem_size; 169 170 unsigned long find_iomem(char *driver, unsigned long *len_out) 171 { 172 struct iomem_region *region = iomem_regions; 173 174 while (region != NULL) { 175 if (!strcmp(region->driver, driver)) { 176 *len_out = region->size; 177 return region->virt; 178 } 179 180 region = region->next; 181 } 182 183 return 0; 184 } 185 EXPORT_SYMBOL(find_iomem); 186 187 static int setup_iomem(void) 188 { 189 struct iomem_region *region = iomem_regions; 190 unsigned long iomem_start = high_physmem + PAGE_SIZE; 191 int err; 192 193 while (region != NULL) { 194 err = os_map_memory((void *) iomem_start, region->fd, 0, 195 region->size, 1, 1, 0); 196 if (err) 197 printk(KERN_ERR "Mapping iomem region for driver '%s' " 198 "failed, errno = %d\n", region->driver, -err); 199 else { 200 region->virt = iomem_start; 201 region->phys = __pa(region->virt); 202 } 203 204 iomem_start += region->size + PAGE_SIZE; 205 region = region->next; 206 } 207 208 return 0; 209 } 210 211 __initcall(setup_iomem); 212