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); }
static void do_ops(int unused, struct host_vm_op *ops, int last) { struct host_vm_op *op; int i; for(i = 0; i <= last; i++){ op = &ops[i]; switch(op->type){ case MMAP: os_map_memory((void *) op->u.mmap.addr, op->u.mmap.fd, op->u.mmap.offset, op->u.mmap.len, op->u.mmap.r, op->u.mmap.w, op->u.mmap.x); break; case MUNMAP: os_unmap_memory((void *) op->u.munmap.addr, op->u.munmap.len); break; case MPROTECT: protect_memory(op->u.mprotect.addr, op->u.munmap.len, op->u.mprotect.r, op->u.mprotect.w, op->u.mprotect.x, 1); break; default: printk("Unknown op type %d in do_ops\n", op->type); break; } } }
void map_memory(unsigned long virt, unsigned long phys, unsigned long len, int r, int w, int x) { __u64 offset; int fd, err; fd = phys_mapping(phys, &offset); err = os_map_memory((void *) virt, fd, offset, len, r, w, x); if (err) { if (err == -ENOMEM) printk(KERN_ERR "try increasing the host's " "/proc/sys/vm/max_map_count to <physical " "memory size>/4096\n"); panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " "err = %d\n", virt, fd, offset, len, r, w, x, err); } }
int setup_iomem(void) { struct iomem_region *region = iomem_regions; unsigned long iomem_start = high_physmem + PAGE_SIZE; int err; while (region != NULL) { err = os_map_memory((void *) iomem_start, region->fd, 0, region->size, 1, 1, 0); if (err) printk(KERN_ERR "Mapping iomem region for driver '%s' " "failed, errno = %d\n", region->driver, -err); else { region->virt = iomem_start; region->phys = __pa(region->virt); } iomem_start += region->size + PAGE_SIZE; region = region->next; } return 0; }