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 109 return fd; 110 } 111 EXPORT_SYMBOL(phys_mapping); 112 113 static int __init uml_mem_setup(char *line, int *add) 114 { 115 char *retptr; 116 117 *add = 0; 118 physmem_size = memparse(line,&retptr); 119 return 0; 120 } 121 __uml_setup("mem=", uml_mem_setup, 122 "mem=<Amount of desired ram>\n" 123 " This controls how much \"physical\" memory the kernel allocates\n" 124 " for the system. The size is specified as a number followed by\n" 125 " one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" 126 " This is not related to the amount of memory in the host. It can\n" 127 " be more, and the excess, if it's ever used, will just be swapped out.\n" 128 " Example: mem=64M\n\n" 129 ); 130