void __init setup_physmem(unsigned long start, unsigned long reserve_end, unsigned long len, unsigned long long highmem) { unsigned long reserve = reserve_end - start; int pfn = PFN_UP(__pa(reserve_end)); int delta = (len - reserve) >> PAGE_SHIFT; int err, offset, bootmap_size; physmem_fd = create_mem_file(len + highmem); offset = uml_reserved - uml_physmem; err = os_map_memory((void *) uml_reserved, physmem_fd, offset, len - offset, 1, 1, 1); if (err < 0) { printf("setup_physmem - mapping %ld bytes of memory at 0x%p " "failed - errno = %d\n", len - offset, (void *) uml_reserved, err); exit(1); } /* * Special kludge - This page will be mapped in to userspace processes * from physmem_fd, so it needs to be written out there. */ os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE); bootmap_size = init_bootmem(pfn, pfn + delta); free_bootmem(__pa(reserve_end) + bootmap_size, len - bootmap_size - reserve); }
int __init can_drop_memory(void) { void *addr; int fd, ok = 0; printk("Checking host MADV_REMOVE support..."); fd = create_mem_file(UM_KERN_PAGE_SIZE); if(fd < 0){ printk("Creating test memory file failed, err = %d\n", -fd); goto out; } addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(addr == MAP_FAILED){ printk("Mapping test memory file failed, err = %d\n", -errno); goto out_close; } if(madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0){ printk("MADV_REMOVE failed, err = %d\n", -errno); goto out_unmap; } printk("OK\n"); ok = 1; out_unmap: munmap(addr, UM_KERN_PAGE_SIZE); out_close: close(fd); out: return ok; }
void remap_data(void *segment_start, void *segment_end, int w) { void *addr; unsigned long size; int data, prot; if(w) prot = PROT_WRITE; else prot = 0; prot |= PROT_READ | PROT_EXEC; size = (unsigned long) segment_end - (unsigned long) segment_start; data = create_mem_file(size); addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0); if(addr == MAP_FAILED){ perror("mapping new data segment"); exit(1); } memcpy(addr, segment_start, size); if(switcheroo(data, prot, addr, segment_start, size) < 0){ printf("switcheroo failed\n"); exit(1); } }
int main (int argc, char* argv[]) { int fd, kernel_fd = -1; /* scanning whether there's -h or --help in the options */ char c, *unit; while ((c = getopt_long(argc, argv, ":skmdx:", longopts, 0)) != -1) { switch (c) { case 'h': printf (" -d <path>, --disk=<path> specify normal disk\n" " -k <path>, --kernel=<path> specify kernel file\n" " -m NUM , --memsize=NUM specify memory size\n" " -s <path>, --swap=<path> specify swap disk\n" " -h, --help print this message and exit\n"); return 0; break; case 'k': if ((kernel_fd = open (optarg, O_RDONLY)) < 0) return 1; break; case 'm': memsize = strtol (optarg, &unit, 10); if (*unit == 'K' || *unit == 'k') memsize <<= 10; else if (*unit == 'M' || *unit == 'm') memsize <<= 20; break; default: /* ignore other options now */ break; } } if (kernel_fd < 0) { printf ("No kernel file specified.\n"); return 1; } struct stat buf; fstat (kernel_fd, &buf); fd = create_mem_file (memsize); /* map the temp file & copy boot and kernel code to the memory */ int brk_end = (int)sbrk (0); mmap ((void*)brk_end, memsize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, fd, 0); read_kernel (kernel_fd, brk_end - KERNBASE); /* map the reserved part to where it really should be */ mmap ((void*)KERNBASE, RESERVED_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, fd, 0); /* Now we have access to ginfo normally. */ ginfo->mem_fd = fd; e820_init (kernel_fd); parse_opts (argc, argv); /* unmap useless page table entries */ memcpy ((void*)(BOOT_CODE), (void*)&__boot_start, PGSIZE); stk_init (brk_end, fd); void (*boot_start) (void); boot_start = __pa (__boot_entry); boot_start (); return 0; }