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