|  | /* 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); | 
|  | 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); |