| /* Copyright (c) 2009, 2010 The Regents of the University of California |
| * Barret Rhoden <brho@cs.berkeley.edu> |
| * See LICENSE for details. |
| * |
| * Memory management for processes: syscall related functions, virtual memory |
| * regions, etc. */ |
| |
| #pragma once |
| |
| #include <ros/common.h> |
| #include <ros/mman.h> |
| #include <atomic.h> |
| #include <sys/queue.h> |
| #include <slab.h> |
| #include <kref.h> |
| #include <rcu.h> |
| |
| struct chan; |
| struct fd_table; |
| struct proc; /* preprocessor games */ |
| |
| #define F_OR_C_CHAN 2 |
| |
| struct file_or_chan { |
| int type; |
| struct chan *chan; |
| struct fs_file *fsf; /* weak ref, set during mmap. */ |
| struct kref kref; |
| struct rcu_head rcu; |
| }; |
| |
| char *foc_to_name(struct file_or_chan *foc); |
| char *foc_abs_path(struct file_or_chan *foc, char *path, size_t max_size); |
| ssize_t foc_read(struct file_or_chan *foc, void *buf, size_t amt, off64_t off); |
| struct file_or_chan *foc_open(char *path, int omode, int perm); |
| struct file_or_chan *fd_to_foc(struct fd_table *fdt, int fd); |
| void foc_incref(struct file_or_chan *foc); |
| void foc_decref(struct file_or_chan *foc); |
| void *foc_pointer(struct file_or_chan *foc); |
| size_t foc_get_len(struct file_or_chan *foc); |
| |
| /* Basic structure defining a region of a process's virtual memory. Note we |
| * don't refcnt these. Either they are in the TAILQ/tree, or they should be |
| * freed. There should be no other references floating around. We still need |
| * to sort out how we share memory and how we'll do private memory with these |
| * VMRs. */ |
| struct vm_region { |
| TAILQ_ENTRY(vm_region) vm_link; |
| TAILQ_ENTRY(vm_region) vm_pm_link; |
| struct proc *vm_proc; |
| uintptr_t vm_base; |
| uintptr_t vm_end; |
| int vm_prot; |
| int vm_flags; |
| struct file_or_chan *__vm_foc; |
| size_t vm_foff; |
| bool vm_ready; /* racy, for the PM checks */ |
| bool vm_shootdown_needed; |
| }; |
| TAILQ_HEAD(vmr_tailq, vm_region); /* Declares 'struct vmr_tailq' */ |
| |
| static inline bool vmr_has_file(struct vm_region *vmr) |
| { |
| return vmr->__vm_foc ? true : false; |
| } |
| |
| static inline char *vmr_to_filename(struct vm_region *vmr) |
| { |
| assert(vmr_has_file(vmr)); |
| return foc_to_name(vmr->__vm_foc); |
| } |
| |
| void vmr_init(void); |
| void unmap_and_destroy_vmrs(struct proc *p); |
| int duplicate_vmrs(struct proc *p, struct proc *new_p); |
| void print_vmrs(struct proc *p); |
| void enumerate_vmrs(struct proc *p, void (*func)(struct vm_region *vmr, void |
| *opaque), void *opaque); |
| |
| /* mmap() related functions. These manipulate VMRs and change the hardware page |
| * tables. Any requests below the LOWEST_VA will silently be upped. This may |
| * be a dynamic proc-specific variable later. */ |
| #define MMAP_LOWEST_VA PAGE_SIZE |
| #define MMAP_LD_FIXED_VA 0x100000 |
| void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags, |
| int fd, size_t offset); |
| void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags, |
| struct file_or_chan *foc, size_t offset); |
| int mprotect(struct proc *p, uintptr_t addr, size_t len, int prot); |
| int munmap(struct proc *p, uintptr_t addr, size_t len); |
| int handle_page_fault(struct proc *p, uintptr_t va, int prot); |
| int handle_page_fault_nofile(struct proc *p, uintptr_t va, int prot); |
| unsigned long populate_va(struct proc *p, uintptr_t va, unsigned long nr_pgs); |
| |
| /* These assume the mm_lock is held already */ |
| int __do_mprotect(struct proc *p, uintptr_t addr, size_t len, int prot); |
| int __do_munmap(struct proc *p, uintptr_t addr, size_t len); |
| |
| /* Kernel Dynamic Memory Mappings */ |
| struct arena *vmap_arena; |
| void vmap_init(void); |
| /* Gets PML1 page-aligned virtual addresses for the kernel's dynamic vmap. |
| * You'll need to map it to something. When you're done, 'put-' will also unmap |
| * the vaddr for you. */ |
| uintptr_t get_vmap_segment(size_t nr_bytes); |
| void put_vmap_segment(uintptr_t vaddr, size_t nr_bytes); |
| int map_vmap_segment(uintptr_t vaddr, uintptr_t paddr, unsigned long num_pages, |
| int perm); |
| /* Helper wrappers for getting and mapping a specific paddr. */ |
| uintptr_t vmap_pmem(uintptr_t paddr, size_t nr_bytes); |
| uintptr_t vmap_pmem_nocache(uintptr_t paddr, size_t nr_bytes); |
| uintptr_t vmap_pmem_writecomb(uintptr_t paddr, size_t nr_bytes); |
| int vunmap_vmem(uintptr_t vaddr, size_t nr_bytes); |