166 lines
5.2 KiB
C
166 lines
5.2 KiB
C
#ifndef KERNEL_ADDRESS_SPACE_H_
|
|
#define KERNEL_ADDRESS_SPACE_H_
|
|
|
|
#include <kernel/object.h>
|
|
#include <kernel/pmap.h>
|
|
#include <kernel/vm.h>
|
|
|
|
#define ADDRESS_SPACE_COPY_ALL ((size_t)-1)
|
|
|
|
struct address_space;
|
|
struct vm_object;
|
|
|
|
struct vm_area {
|
|
/* the vm-object mapped into this area.
|
|
* if this is NULL, the vm_area represents an area of reserved memory.
|
|
* it cannot be accessed, and mapping operations with MAP_ADDRESS_ANY
|
|
* will avoid the area, but fixed address mappings in this area
|
|
* will succeed. */
|
|
struct vm_object *vma_object;
|
|
/* the address space that this vm_area is a part of */
|
|
struct address_space *vma_space;
|
|
/* used to link to vm_object->vo_mappings */
|
|
struct queue_entry vma_object_entry;
|
|
/* the memory protection flags applied to this area */
|
|
vm_prot_t vma_prot;
|
|
/* offset in bytes to the start of the object data that was mapped */
|
|
off_t vma_object_offset;
|
|
/* used to link to address_space->s_mappings */
|
|
struct btree_node vma_node;
|
|
/* address of the first byte in this area */
|
|
virt_addr_t vma_base;
|
|
/* address of the last byte in this area */
|
|
virt_addr_t vma_limit;
|
|
};
|
|
|
|
struct address_space {
|
|
struct object s_base;
|
|
|
|
/* address of the first byte in this address space */
|
|
virt_addr_t s_base_address;
|
|
/* address of the last byte in this address space */
|
|
virt_addr_t s_limit_address;
|
|
|
|
/* btree of struct vm_area representing mapped vm-objects.
|
|
* sibling entries cannot overlap each other. */
|
|
struct btree s_mappings;
|
|
/* btree of struct vm_area representing reserved regions of the
|
|
* address space.
|
|
* reserved regions will not be automatically allocated by the kernel.
|
|
* sibling entries cannot overlap each other.
|
|
* overlap between s_mappings and s_reserved IS allowed. */
|
|
struct btree s_reserved;
|
|
|
|
/* the corresponding physical address space */
|
|
pmap_t s_pmap;
|
|
};
|
|
|
|
extern kern_status_t address_space_type_init(void);
|
|
extern struct address_space *address_space_cast(struct object *obj);
|
|
|
|
/* create a new vm-region, optionally within a parent region.
|
|
* `offset` is the byte offset within the parent region where the new region
|
|
* should start.
|
|
* if no parent is specified, `offset` is the absolute virtual address of the
|
|
* start of the region.
|
|
* in both cases, `len` is the length of the new region in bytes. */
|
|
extern kern_status_t address_space_create(
|
|
virt_addr_t base,
|
|
virt_addr_t limit,
|
|
struct address_space **out);
|
|
|
|
/* map a vm-object into a vm-region.
|
|
* [region_offset,length] must fall within exactly one region, and cannot span
|
|
* multiple sibling regions.
|
|
* if [region_offset,length] falls within a child region, the map operation
|
|
* will be transparently redirected to the relevant region.
|
|
* `prot` must be allowed both by the region into which the mapping is being
|
|
* created AND the vm-object being mapped. */
|
|
extern kern_status_t address_space_map(
|
|
struct address_space *space,
|
|
virt_addr_t map_address,
|
|
struct vm_object *object,
|
|
off_t object_offset,
|
|
size_t length,
|
|
vm_prot_t prot,
|
|
virt_addr_t *out);
|
|
extern kern_status_t address_space_unmap(
|
|
struct address_space *region,
|
|
virt_addr_t base,
|
|
size_t length);
|
|
|
|
/* reserve an area of the address space. the kernel will not place any
|
|
* new mappings in this area unless explicitly told to (i.e. by not using
|
|
* MAP_ADDRESS_ANY). Use MAP_ADDRESS_ANY to have the kernel allocate a region
|
|
* of the address space for you */
|
|
extern kern_status_t address_space_reserve(
|
|
struct address_space *space,
|
|
virt_addr_t base,
|
|
size_t length,
|
|
virt_addr_t *out);
|
|
/* release a previously reserved area of the address space. */
|
|
extern kern_status_t address_space_release(
|
|
struct address_space *space,
|
|
virt_addr_t base,
|
|
size_t length);
|
|
|
|
extern bool address_space_validate_access(
|
|
struct address_space *region,
|
|
virt_addr_t base,
|
|
size_t len,
|
|
vm_prot_t prot);
|
|
|
|
/* find the mapping corresponding to the given virtual address, and page-in the
|
|
* necessary vm_page to allow the memory access to succeed. if the relevant
|
|
* vm-object page hasn't been allocated yet, it will be allocated here.
|
|
* this function must be called with `region` UNLOCKED and interrupts ENABLED.
|
|
*/
|
|
extern kern_status_t address_space_demand_map(
|
|
struct address_space *region,
|
|
virt_addr_t addr,
|
|
enum pmap_fault_flags flags);
|
|
|
|
/* read data from the user-space area of a vm-region into a kernel-mode buffer
|
|
*/
|
|
extern kern_status_t address_space_read(
|
|
struct address_space *src_region,
|
|
virt_addr_t src_ptr,
|
|
size_t count,
|
|
void *dest,
|
|
size_t *nr_read);
|
|
|
|
/* write data to the user-space area of a vm-region from a kernel-mode buffer
|
|
*/
|
|
extern kern_status_t address_space_write(
|
|
struct address_space *dst_region,
|
|
virt_addr_t dst_ptr,
|
|
size_t count,
|
|
const void *src,
|
|
size_t *nr_written);
|
|
|
|
extern kern_status_t address_space_memmove(
|
|
struct address_space *dest_space,
|
|
virt_addr_t dest_ptr,
|
|
struct address_space *src_space,
|
|
virt_addr_t src_ptr,
|
|
size_t count,
|
|
size_t *nr_moved);
|
|
|
|
extern kern_status_t address_space_memmove_v(
|
|
struct address_space *dest_space,
|
|
size_t dest_offset,
|
|
const kern_iovec_t *dest_iov,
|
|
size_t nr_dest_iov,
|
|
struct address_space *src_space,
|
|
size_t src_offset,
|
|
const kern_iovec_t *src_iov,
|
|
size_t nr_src_iov,
|
|
size_t bytes_to_move,
|
|
size_t *nr_bytes_moved);
|
|
|
|
void address_space_dump(struct address_space *region);
|
|
|
|
DEFINE_OBJECT_LOCK_FUNCTION(address_space, s_base)
|
|
|
|
#endif
|