return(ret_val);
}
+/*
+ * _pg_dir_memset_page() - Call memset on a page in a different address space
+ *
+ * SYNOPSIS
+ * int _pg_dir_memset_page(struct pagedior *ddir, void *dvaddr, int c, u32_t n);
+ *
+ * DESCRIPTION
+ * The _pg_dir_memset_page() function sets `n' bytes from the address passed in `dvaddr' within
+ * the page directory pointed to by `ddir' to the value passed in `c', and returns the number of
+ * bytes that have been set. This function does not write over page boundaries, which means it
+ * will write from `dvaddr' only to the end of the page. This means that this function may, in
+ * the worst case, write no more than one byte. For that reason, this function should be called
+ * in a loop, in order to make sure partial writes are accommodated for. In almost all cases,
+ * this function should not be used directly, and pg_dir_memset() should be used in its stead.
+ *
+ * RETURN VALUE
+ * On success, the number of bytes that have been set will be returned. Otherwise, a negative
+ * error number will be returned.
+ *
+ * ERRORS
+ * -EADDRNOTAVAIL The page at `dvattr' is not mapped in `ddir'
+ * -ENOSYS The current paging mode is not supported
+ */
int _pg_dir_memset_page(struct pagedir *ddir, void *dvaddr, int c, u32_t n)
{
int ret_val;
return(ret_val);
}
-int pg_dir_memset(struct pagedir *ddir, void *dvaddr,
- int c, u32_t n)
+/*
+ * pg_dir_memset() - Call memset in a different address space
+ *
+ * SYNOPSIS
+ * int pg_dir_memset(struct pagedir *ddir, void *dvaddr, int c, u32_t n);
+ *
+ * DESCRIPTION
+ * The pg_dir_memset() function sets `n' bytes of memory starting at `dvaddr' within the page
+ * directory pointed to by `ddir' to the value specified in `c' and returns the number of bytes
+ * that have been written. The write operation is performed page-wise, as the virtual memory
+ * region might not be continguous in physical memory.
+ * This function does not map pages into the destination page directory, meaning that it will
+ * stop if it encounters a non-present page. For that reason, the caller must check the return
+ * value of this function if there is even a slight chance that the destination memory is not
+ * mapped into the page directory.
+ *
+ * RETURN VALUE
+ * The number of bytes written is returned.
+ *
+ * ERRORS
+ * This function does not explicitly signal error conditions. However, if a partial write has
+ * occured, the memory region was not (completely) mapped into the page directory.
+ */
+int pg_dir_memset(struct pagedir *ddir, void *dvaddr, int c, u32_t n)
{
int ret_val;
ret_val = 0;
if(!ddir) {
- /* kernel pagedir - just call memset() */
+ /*
+ * Memory in the kernel page directory is continguous, which means that we can
+ * fulfill the entire request in a single swoop.
+ */
memset(dvaddr, c, n);
return((int)n);
}
return(ret_val);
}
+/*
+ * _pg_dir_xfer() - Copy a page from one address space to another one
+ *
+ * SYNOPSIS
+ * int _pg_dir_xfer(struct pagedir *ddir, void *dvaddr,
+ * struct pagedir *sdir, void *svaddr, u32_t bytes);
+ *
+ * DESCRIPTION
+ * The _pg_dir_xfer() function copies the `bytes' of memory starting at `svaddr' in the page
+ * directory pointed to by `sdir' to the memory pointed to by `dvaddr' within the page directory
+ * pointed to by `ddir', and returns the number of bytes that have been copied.
+ * This function does not read or write beyond page boundaries, which means that it will copy at
+ * most the content of a single page, and may copy as little as a single byte.
+ * This function should in most cases not be used directly, and the pg_dir_memcpy() function
+ * should be used in its stead.
+ *
+ * RETURN VALUE
+ * On success, the number of bytes that have been copied will be returned. Otherwise, a negative
+ * error number will be returned.
+ *
+ * ERRORS
+ * -EADDRNOTAVAIL Either the source or the destination addresses point to non-present pages
+ * -ENOSYS The current paging mode is not supported
+ */
int _pg_dir_xfer(struct pagedir *ddir, void *dvaddr,
struct pagedir *sdir, void *svaddr, u32_t bytes)
{
return(ret_val);
}
+/*
+ * _pg_dir_pagesize() - Get the size of a specific page in a page directory
+ *
+ * SYNOPSIS
+ * int _pg_dir_pagesize(struct pagedir *pgdir, u32_t virt, u32_t *pagesize);
+ *
+ * DESCRIPTION
+ * The _pg_dir_pagesize() function determines the size of the page pointed to by `virt' within
+ * the page directory pointed to by `pgdir' and writes the result to the dword pointed to by
+ * `pagesize'. This function is used within the kernel to determine the amount of data that can
+ * be written to a specific address without crossing page boundaries, as the page management in
+ * Corax allows pages of different sizes to be used within the same page directory.
+ *
+ * RETURN VALUE
+ * On success, zero is returned. Otherwise, a negative error number is returned and the value
+ * of `*pagesize' is left untouched.
+ *
+ * ERRORS
+ * -EADDRNOTAVAIL The page pointed to by `virt' is not present in the page directory
+ * -ENOSYS The current paging mode is not supported
+ */
int _pg_dir_pagesize(struct pagedir *pgdir, u32_t virt, u32_t *pagesize)
{
int ret_val;
return(ret_val);
}
+/*
+ * _pg_dir_vpxlate() - Look up the corresponding physical address of a virtual address
+ *
+ * SYNOPSIS
+ * int _pg_dir_vpxlate(struct pagedir *pgdir, u32_t virt, u32_t *phys);
+ *
+ * DESCRIPTION
+ * The _pg_dir_vpxlate() performs a translation of the virtual address specified by `virt' within
+ * the page directory pointed to by `pgdir' and writes the result to the dword pointed to by
+ * `phys'. The translation works essentially the same way as the MMU would have done it, except
+ * in software. This operation is potentially costly and should be used sparingly.
+ *
+ * RETURN VALUE
+ * On success, zero is returned. Otherwise, a negative error number is returned and the value of
+ * `*phys' is left untouched.
+ *
+ * ERRORS
+ * -EFAULT The page pointed to by `virt' is non-present in the page directory
+ * -ENOSYS The current paging mode is not supported
+ */
int _pg_dir_vpxlate(struct pagedir *pgdir, u32_t virt, u32_t *phys)
{
int ret_val;
return(ret_val);
}
+/*
+ * _pg_dir_kstack_map() - Map a kernel-mode stack into a page directory
+ *
+ * SYNOPSIS
+ * int _pg_dir_kstack_map(struct pagedir *pgdir);
+ *
+ * DESCRIPTION
+ * The _pg_dir_kstack_map() function attempts to map a stack for kernel-mode execution into the
+ * page directory pointed to by `pgdir'. This function also updates the state of the page
+ * directory so that the newly mapped stack is used when an interrupt occurs during execution
+ * within the page directory.
+ * The kernel-mode stack will be mapped at the virtual address CONFIG_KERNEL_STACK_BASE within
+ * the page directory. The stack will be mapped non-executable if supported by the processor and
+ * configured to do so.
+ *
+ * RETURN VALUE
+ * If successful, this function returns zero. Otherwise, a negative error number is returned and
+ * the page directory is returned to its previous state.
+ *
+ * ERRORS
+ * -ENOMEM The system ran out of memory while trying to map the stack
+ */
int _pg_dir_kstack_map(struct pagedir *pgdir)
{
int ret_val;
return(ret_val);
}
+/*
+ * _pg_dir_ustack_map() - Map a stack for user-mode execution into a page directory
+ *
+ * SYNOPSIS
+ * int _pg_dir_ustack_map(struct pagedir *pgdir);
+ *
+ * DESCRIPTION
+ * The _pg_dir_ustack_map() function maps a stack for user-mode execution into the page directory
+ * pointed to by `pgdir' and adjusts the internal state of the page directory so that the newly
+ * allocated stack will be used upon a context switch to the page directory.
+ * The user-mode stack will be mapped at the virtual address CONFIG_KERNEL_STACK_BASE - PAGE_SIZE
+ * within the page directory. The stack will be made non-executable if supported by the processor
+ * and configured to do so.
+ *
+ * RETURN VALUE
+ * Opon success, zero is returned. Otherwise, a negative error number will be returned and the
+ * page directory will be returned to its previous state.
+ *
+ * ERRORS
+ * -ENOMEM The system ran out of memory trying to allocate the stack
+ */
int _pg_dir_ustack_map(struct pagedir *pgdir)
{
int ret_val;
void* vaddr;
vaddr = (void*)((u32_t)CONFIG_KERNEL_STACK_BASE - PAGE_SIZE);
- attrs = PAGE_ATTR_PRESENT | PAGE_ATTR_WRITABLE | PAGE_ATTR_USER | PAGE_ATTR_NO_EXEC;
+ attrs = PAGE_ATTR_PRESENT | PAGE_ATTR_WRITABLE |
+ PAGE_ATTR_USER | PAGE_ATTR_NO_EXEC;
ret_val = pg_dir_map(pgdir, frame, vaddr, PAGE_SIZE, attrs);
return(ret_val);
}
+/*
+ * _pg_dir_heap_start() - Get the start address of page directory's heap
+ *
+ * SYNOPSIS
+ * static void *_pg_dir_heap_start(pg_dir_t *pd);
+ *
+ * DESCRIPTION
+ * The _pg_dir_heap_start() function returns the start address of the heap within the page
+ * directory pointed to by `pd'. If there is no heap mapped into the page directory, the end of
+ * the last memory section that is not a stack is returned instead (which is the address where
+ * the heap will be, once it has been mapped).
+ *
+ * RETURN VALUE
+ * Upon success, the virtual address of the heap will be returned (the heap may in fact not be
+ * mapped yet, though). If the position of the heap could not be determined, (void*)-1 will be
+ * returned instead.
+ *
+ * ERRORS
+ * This function does not return further information in case of an error.
+ */
static void* _pg_dir_heap_start(pg_dir_t *pd)
{
u32_t ret_val;
return((void*)ret_val);
}
+/*
+ * _pg_dir_heap_map() - Map a heap into a page directory
+ *
+ * SYNOPSIS
+ * static int _pg_dir_heap_map(pg_dir_t *pd, u32_t heap_size);
+ *
+ * DESCRIPTION
+ * The _pg_dir_heap_map() function will map a heap of size `heap_size' into the page directory
+ * pointed to by `pd'. The heap will be mapped non-executable if supported by the processor and
+ * configured to do so. The heap will be placed after the last memory region that is not a stack.
+ *
+ * RETURN VALUE
+ * Upon success, zero is returned. Otherwise, a negative error number is returned and the page
+ * directory is returned to its previous state.
+ *
+ * ERRORS
+ * -EINVAL `pd' does not reference a valid page directory
+ * -EALREADY The page directory already has a heap
+ * -ENOMEM Ran out of memory trying to allocate the heap
+ * -EBADFD The page directory is in an unusable state
+ */
static int _pg_dir_heap_map(pg_dir_t *pd, u32_t heap_size)
{
/*
reg = pd->pd_regions[i];
+ dbg_printf("Found a region at 0x%08x:%08x\n",
+ reg->reg_base, reg->reg_size);
+
switch(reg->reg_type) {
case REGION_TYPE_HEAP:
/* the page directory apparently already contains a heap */
return(ret_val);
}
+/*
+ * _clone_kernel_region() - Clone a memory region from the kernel page directory
+ *
+ * SYNOPSIS
+ * int _clone_kernel_region(pg_dir_t *kdir, region_t *reg, void *data);
+ *
+ * DESCRIPTION
+ * The _clone_kernel_region() function clones the memory region pointed to by `reg' from the
+ * page directory pointed to by `kdir' into the page directory pointed to by `data'. This
+ * function is called from pg_dir_create() by means of the pg_dir_foreach_region() function. As
+ * such, it is not meant to be called directly.
+ * If `reg' represents a .text, .bss, .data, or .rodata region, the region will be mapped
+ * directly. This function does not actually clone the pages belonging to those memory regions,
+ * as these pages cannot be modified outside of the kernel, and thus there is no need for copies
+ * that are private to a process.
+ *
+ * RETURN VALUE
+ * This function zero upon success, or a negative value if an error has occured.
+ *
+ * ERRORS
+ * This function passes on errors returned by pg_dir_map_region().
+ */
int _clone_kernel_region(pg_dir_t *kdir, region_t *reg, void *data)
{
pg_dir_t *dir;
return(ret_val);
}
+/*
+ * pg_dir_create() - Create a new page directory
+ *
+ * SYNOPSIS
+ * int pg_dir_create(pg_dir_t **dst);
+ *
+ * DESCRIPTION
+ * The pg_dir_create() function allocates a new page directory and populates it with those memory
+ * regions from the kernel that are necessary to make it usable. This function also maps stacks
+ * for execution in user-mode and kernel-mode into the newly created page directory.
+ *
+ * RETURN VALUE
+ * Upon success, this function returns zero, and the pointer pointed to by `dst' is adjusted to
+ * point to the newly allocated page directory. Otherwise, this function returns a negative error
+ * number, and the value of `*dst' is undefined.
+ *
+ * ERRORS
+ * -ENOMEM There were no empty page frames to allocate the page directory
+ * -EFAULT The system's paging mode is in an invalid state
+ *
+ * This function also passes on errors from _pg_dir_kstack_map() and _pg_dir_ustack_map().
+ */
int pg_dir_create(pg_dir_t **dst)
{
int ret_val;
return(ret_val);
}
+/*
+ * _pg_dir_map_legacy() - Map memory into a legacy page directory
+ *
+ * SYNOPSIS
+ * int _pg_dir_map_legacy(page_table_t *pd, u32_t paddr, u32_t vaddr,
+ * u32_t size, const page_attrs_t attrs);
+ *
+ * DESCRIPTION
+ * The _pg_dir_map_legacy() function maps the `size' bytes of physical memory starting at `paddr'
+ * to the virtual address `vaddr' in the page directory pointed to by `pd', applying the page
+ * attributes specified in `attrs'.
+ * If `paddr' is NULL, the physical location of the mapped memory depends on the available of
+ * allocatable page frames in the system. In this case, the allocated memory may not be
+ * continguous in physical memory. Unlike `paddr', `vaddr' may not be NULL.
+ *
+ * RETURN VALUE
+ * This function returns zero upon success, or a negative error number in an error has occured.
+ *
+ * ERRORS
+ * -ENOMEM Not enough free page frames available to satisfy the allocation
+ * -EALREADY The specified virtual memory is already (partially) mapped
+ */
static int _pg_dir_map_legacy(page_table_t *pd, u32_t paddr, u32_t vaddr,
- u32_t size, const u32_t flags)
+ u32_t size, const page_attrs_t attrs)
{
int ret_val;
*/
if(size >= PAGE_SIZE_LARGE && ALIGNED(vaddr, PAGE_SIZE_LARGE) &&
paddr && ALIGNED(paddr, PAGE_SIZE_LARGE)) {
- pd->pt_entries[pde] = paddr | PAGE_ATTR_SIZE | PAGE_ATTR_PRESENT | flags;
+ pd->pt_entries[pde] = paddr | PAGE_ATTR_SIZE |
+ PAGE_ATTR_PRESENT | attrs;
paddr += PAGE_SIZE_LARGE;
vaddr += PAGE_SIZE_LARGE;
size -= PAGE_SIZE_LARGE;
- /* skip the rest of the loop, which would attempt to populate the page table */
+ /*
+ * Skip the rest of the loop, which would attempt
+ * to populate the page table
+ */
continue;
} else {
pd->pt_entries[pde] = (u32_t)pg_frame_alloc_end();
memset((void*)pd->pt_entries[pde], 0, PAGE_SIZE);
}
- pd->pt_entries[pde] |= PAGE_ATTR_PRESENT | flags;
+ pd->pt_entries[pde] |= PAGE_ATTR_PRESENT | attrs;
}
}
pt = (page_table_t*)(pd->pt_entries[pde] & 0xfffff000);
/* make sure PAGE_ATTR_USER is set on the page table, if necessary */
- if(flags & PAGE_ATTR_USER) {
+ if(attrs & PAGE_ATTR_USER) {
pd->pt_entries[pde] |= PAGE_ATTR_USER;
}
/* also make sure the page table is writable, if necessary */
- if(flags & PAGE_ATTR_WRITABLE) {
+ if(attrs & PAGE_ATTR_WRITABLE) {
pd->pt_entries[pde] |= PAGE_ATTR_WRITABLE;
}
break;
}
- /* set the flags */
- pt->pt_entries[pte] |= PAGE_ATTR_PRESENT | flags;
+ pt->pt_entries[pte] |= PAGE_ATTR_PRESENT | attrs;
vaddr += PAGE_SIZE;
size -= PAGE_SIZE;
return(ret_val);
}
+/*
+ * _pg_dir_map_pae() - Map pages into a PAE page directory
+ *
+ * SYNOPSIS
+ * int _pg_dir_map_pae(pdpt_t *pd, u64_t paddr, u64_t vaddr,
+ * u32_t size, const page_attr_t attrs);
+ *
+ * DESCRIPTION
+ * The _pg_dir_map_pae() function maps the `size' bytes of physical memory starting at `paddr'
+ * to the virtual address `vaddr' in the page directory pointed to by `pd' and applies the page
+ * attributes in `attrs' to the newly mapped pages. If `paddr' is NULL, the physical addresses of
+ * the mapping depend on the availability of page frames in the system. In that case, the mapped
+ * memory is not guaranteed to be continguous in physical memory.
+ * This function will attempt to map the desired memory region using the largest possible page
+ * size that suits the passed parameters.
+ *
+ * RETURN VALUE
+ * This function returns zero upon success, or a negative error number if an error has occured.
+ *
+ * ERRORS
+ * -ENOMEM Not enough free page frames available to satisfy the allocation
+ * -EALREADY The specified virtual memory is already (partially) mapped
+ */
static int _pg_dir_map_pae(pdpt_t *pd, u64_t paddr, u64_t vaddr,
- u32_t size, const u32_t flags)
+ u32_t size, const page_attrs_t attrs)
{
int ret_val;
}
/* set the page attributes on the entry */
- pt->ppt_entries[pte] |= PAGE_ATTR_PRESENT | flags;
+ pt->ppt_entries[pte] |= PAGE_ATTR_PRESENT | attrs;
vaddr += PAGE_SIZE;
paddr += PAGE_SIZE;
return(ret_val);
}
+/*
+ * pg_dir_map() - Map memory into a page directory
+ *
+ * SYNOPSIS
+ * int pg_dir_map(pg_dir_t *pd, const void *phys, const void *virt,
+ * const u32_t size, const page_attrs_t attrs);
+ *
+ * DESCRIPTION
+ * The pg_dir_map() function maps the `size' bytes of physical memory pointed to by `phys' to
+ * the virtual address `virt' from the page directory pointed to by `pd', setting the page
+ * attributes according to `attrs'. If `phys' is NULL, this function will use whatever page
+ * frames are available for allocation, but they need not be continguous in memory. The value
+ * passed in `virt' may not be NULL.
+ * Depending on the paging mode configured in the kernel, this function will call either of the
+ * _pg_dir_map_legacy() or _pg_dir_map_pae() functions to perform the actual mapping of the
+ * pages.
+ *
+ * RETURN VALUE
+ * This function returns zero upon success. Otherwise, a negative error number is returned.
+ *
+ * ERRORS
+ * -ENOSYS The configured paging mode is not supported
+ * -EFAULT The configured paging mode is invalid
+ */
int pg_dir_map(pg_dir_t *pd, const void *phys, const void *virt,
- const u32_t size, const u32_t flags)
+ const u32_t size, const page_attrs_t attrs)
{
int ret_val;
u32_t asize;
case PG_MODE_LEGACY:
ret_val = _pg_dir_map_legacy((struct page_table*)pd->pd_base,
(u32_t)phys, (u32_t)virt,
- asize, flags);
+ asize, attrs);
break;
case PG_MODE_PAE:
ret_val = _pg_dir_map_pae((struct pdpt*)pd->pd_base,
(unsigned)phys, (unsigned)virt,
- asize, flags);
+ asize, attrs);
break;
case PG_MODE_IA32E:
return(ret_val);
}
+/*
+ * pg_dir_map_region() - Map a memory region from one page directory into another one
+ *
+ * SYNOPSIS
+ * int pg_dir_map_region(pg_dir_t *dpd, pg_dir_t *spd, region_t *reg);
+ *
+ * DESCRIPTION
+ * The pg_dir_map_region() function maps the memory region pointed to by `reg' from the source
+ * page directory `spd' to the destination page directory `dpd'.
+ * The region will be mapped into the destination page directory with the same page flags as used
+ * in the source page directory, unless the source page directory is the kernel page directory.
+ * In the latter case, the pages will be mapped read-only into the destination page directory.
+ *
+ * RETURN VALUE
+ * This function returns zero upon success, or a negative error number if an error has occured.
+ *
+ * ERRORS
+ * -ERANGE The maximum number of regions has been mapped into the destination page directory
+ * -EFAULT An unknown error (kernel bug) has occured
+ *
+ * This function also passes on errors from the _pg_dir_vpxlate(), pg_dir_map(), and
+ * _pg_dir_add_region() functions.
+ */
int pg_dir_map_region(pg_dir_t *dpd, pg_dir_t *spd, region_t *reg)
{
int ret_val;
return(ret_val);
}
+/*
+ * pg_dir_clone_region() - Clone a memory region from one page directory into another one
+ *
+ * SYNOPSIS
+ * int pg_dir_clone_region(pg_dir_t *dpd, pg_dir_t *spd, region_t *reg);
+ *
+ * DESCRIPTION
+ * The pg_dir_clone_region() function creates a copy of the memory region pointed to by `reg'
+ * from the source page directory `spd' and maps the copy into the destination page directory
+ * `dpd'. The memory region will be mapped with the same page attributes into the destination
+ * page directory, with the exception that PAGE_ATTR_USER will be added where necessary.
+ *
+ * RETURN VALUE
+ * -ERANGE The maximum number of regions has been mapped into the destination page directory
+ * -EFAULT An unknown error (kernel bug) has occured
+ *
+ * This function also passes on errors from the pg_dir_map(), pg_dir_memcpy(), and
+ * _pg_dir_add_region() functions.
+ */
int pg_dir_clone_region(pg_dir_t *dpd, pg_dir_t *spd, region_t *reg)
{
int ret_val;
return(ret_val);
}
+/*
+ * pg_dir_unmap() - Release a memory mapping from a page directory
+ *
+ * SYNOPSIS
+ * int pg_dir_unmap(pg_dir_t *pd, const void *base, const u32_t size);
+ *
+ * DESCRIPTION
+ * The pg_dir_unmap() function releases `size' bytes of memory starting at the virtual address
+ * `base' from the page directory pointed to by `pd'. This function is currently not implemented.
+ *
+ * RETURN VALUE
+ * This function returns zero upon success, otherwise a negative error number is returned.
+ *
+ * ERRORS
+ * -ENOSYS The function is not implemented
+ */
int pg_dir_unmap(pg_dir_t *pd, const void *base, const u32_t size)
{
return(-ENOSYS);
}
+/*
+ * pg_dir_foreach_region() - Execute a function on all memory regions in a page directory
+ *
+ * SYNOPSIS
+ * int pg_dir_foreach_region(pg_dir_t *pd, int (*func)(pg_dir_t*, region_t*, void*), void *data);
+ *
+ * DESCRIPTION
+ * The pg_dir_foreach_region() iterates over the memory regions in the page directory pointed to
+ * by `pd' and calls the function pointed to by `func' on each one of them. The function pointed
+ * to by `func' must accept three arguments; the first one is a pointer to the page directory,
+ * the second one is a pointer to the memory region, the third value passed to the function is
+ * the value that was passed to pg_dir_foreach_region() in the `data' parameter.
+ * If the function pointed to by `func' returns a negative value, pg_dir_foreach_region() will
+ * interrupt the iteration early.
+ *
+ * RETURN VALUE
+ * This function will return the value that was returned by the last call to `func'. If an error
+ * has occured, a negative error number will be returned.
+ *
+ * ERRORS
+ * -EINVAL `pd' or `func' point to an invalid value
+ */
int pg_dir_foreach_region(pg_dir_t *pd, int (*func)(pg_dir_t*, region_t*, void*), void *data)
{
int ret_val;
return(ret_val);
}
+/*
+ * _pg_dir_add_region() - Add a region to a page directory
+ *
+ * SYNOPSIS
+ * int _pg_dir_add_region(pg_dir_t *pd, void *base, u32_t size, const region_type_t type,
+ * const page_attrs_t attrs, const region_opts_t opts);
+ *
+ * DESCRIPTION
+ * The _pg_dir_add_region() function adds a region with the specified parameters to the page
+ * directory pointed to by `pd'. A region is a data structure used purely for accounting
+ * purposes. This call will not modify the paging structures referenced by the page directory.
+ * The values passed in `base' and `size' represent the base address of the memory region, and
+ * the regions size in bytes, respectively. The value of `type' determines the type of region
+ * that the memory represents. The `attrs' argument determines the page attributes that are used
+ * for pages within this region. The value in `opts' is used to determine if this region is
+ * private to this page directory, or if it may be shared.
+ *
+ * RETURN VALUE
+ * On success, this function returns zero. Otherwise, a negative error number is returned.
+ *
+ * ERRORS
+ * -EFAULT An unknown error (kernel bug) has occured
+ * -ERANGE The maximum number of regions has been mapped into the destination page directory
+ * -ENOMEM The kernel ran out of heap space
+ */
static int _pg_dir_add_region(pg_dir_t *pd, void *base, u32_t size,
region_type_t type, page_attrs_t attrs, region_opts_t opts)
{
return(ret_val);
}
+/*
+ * pg_dir_get_pdbr() - Get the base address of a page directory
+ *
+ * SYNOPSIS
+ * void *pg_dir_get_pdbr(pg_dir_t *pd);
+ *
+ * DESCRIPTION
+ * The pg_dir_get_pdbr() function returns the base address of the page directory pointed to by
+ * `pd'. The return value may be used in assigments to the page directory base register (also
+ * known as CR3 on IA-32/Intel64).
+ *
+ * RETURN VALUE
+ * The value of the variable keeping track of the PDBR within the page directory structure is
+ * returned by this function. This function does not perform any checks to ensure the validity
+ * of that value.
+ *
+ * ERRORS
+ * This function does not signal any error conditions.
+ */
void* pg_dir_get_pdbr(pg_dir_t *pd)
{
return(pd->pd_base);
}
+/*
+ * pg_dir_get_heap() - Get the virtual address of a page directory's heap
+ *
+ * SYNOPSIS
+ * void *pg_dir_get_heap(pg_dir_t *pd);
+ *
+ * DESCRIPTION
+ * The pg_dir_get_heap() function returns the virtual address of the heap that is mapped into the
+ * page directory pointed to by `pd'. This is done by iterating over all memory regions that are
+ * associated with the page directory, returning the base address of the region with type
+ * REGION_TYPE_HEAP.
+ *
+ * RETURN VALUE
+ * Upon success, the virtual base address of the heap is returned. If there is no heap mapped
+ * into the page directory, NULL will be returned instead.
+ *
+ * ERRORS
+ * This function does not convey any additional information about errors.
+ */
void* pg_dir_get_heap(pg_dir_t *pd)
{
void *ret_val;
return(ret_val);
}
+/*
+ * pg_dir_sbrk() - Change the size of a page directory's heap
+ *
+ * SYNOPSIS
+ * void *pg_dir_sbrk(pg_dir_t *pd, u32_t increment);
+ *
+ * DESCRIPTION
+ * The pg_dir_sbrk() function manipulates the size of the heap that is mapped into the page
+ * directory pointed to by `pd'. If `increment' is positive, the size of the heap will be
+ * increased by `increment' bytes by increasing the limit of the heap. If `increment' is
+ * negative, the limit of the size will be decreased by `-increment', shrinking the heap.
+ * If the value of `increment' is zero, The end of the heap will be returned without modifying
+ * its position.
+ * If there is no heap mapped into the page directory, this function will return the address
+ * where the heap will be mapped if this function is called with a positive `increment' value.
+ *
+ * RETURN VALUE
+ * Upon success, the address of the end of the heap (that is, the address right behind the heap)
+ * is returned.
+ *
+ * ERRORS
+ * This function does not signal information about errors.
+ */
void* pg_dir_sbrk(pg_dir_t *pd, i32_t increment)
{
struct region *heap;
return(pg_dir_sbrk(pd, 0));
} else {
/* could not map a heap - how do we get the error to the caller? */
+ dbg_printf("Kernel says no. (_pg_dir_heap_map() says %u)\n", -err);
return(NULL);
}
} else {
return(ret_val);
}
+/*
+ * pg_fault_debug() - Print page table entries for an address
+ *
+ * SYNOPSIS
+ * void pg_fault_debug(pg_dir_t *pdir, void *addr);
+ *
+ * DESCRIPTION
+ * The pg_fault_debug() function prints the page table entries for the virtual address `addr'
+ * within the page directory pointed to by `pdir'. This function will perform the page table
+ * lookup as it would be done by the MMU and print the encountered entries to the kernel's debug
+ * output.
+ * This function is currently only implemented for legacy IA-32 paging.
+ *
+ * RETURN VALUE
+ * void
+ *
+ * ERRORS
+ * This function does not return errors.
+ */
void pg_fault_debug(pg_dir_t *pdir, void *addr)
{
u64_t pde;
return;
}
+/*
+ * pg_dir_mmap() - Map various kinds of memory into a page directory
+ *
+ * SYNOPSIS
+ * int pg_dir_mmap(pg_dir_t *pgdir, void *addr, u32_t size, int prot, int flags, void **dst);
+ *
+ * DESCRITION
+ * The pg_dir_mmap() function maps memory into the page directory pointed to by `pgdir' according
+ * to the values specified in the remaining parameters. The function will attempt to create the
+ * mapping at the virtual address `addr'. The mapping will be created from arbitrary free page
+ * frames, meaning that they may not be continguous in physical memory.
+ * If the MAP_PHYS flag is set in `flags', this function will attempt to create an identity
+ * mapping to physical memory, thus allowing the calling process to map device memory into their
+ * address space.
+ *
+ * The attributes of the pages in the region will be set according to `prot':
+ * - If the PROT_EXEC bit is set, the pages will be made executable
+ * - If the PROT_WRITE bit is set, the pages will be made writable
+ * - If the PROT_READ bit is set, the pages will be made readable
+ *
+ * Note that, in absense of the PROT_READ bit, the pages will not be accessible from non-kernel
+ * contexts at all, so this bit should almost always be set.
+ *
+ * The visibility of the mapping is further influenced by the value of `opts':
+ * - If `opts' is REGION_OPT_SHARED, the physical memory may be shared with other processes,
+ * - otherwise the memory region will be private and not shareable with other processes.
+ * - However, mappings made with the MAP_PHYS flag cannot be made private.
+ *
+ * If the mapping has been successful, the pointer pointed to by `dst' will be made to point to
+ * the virtual address of the mapping.
+ *
+ * RETURN VALUE
+ * This function will return zero upon success, or a negative error number in the case that an
+ * error has occured. In the latter case, the value of `*dst' is undefined.
+ *
+ * ERRORS
+ * -EINVAL Either `pgdir' or `dst' are invalid pointers
+ * -EFAULT An unknown error (kernel bug) has occured
+ *
+ * This function also passes on error values returned by pg_dir_map() and _pg_dir_add_region().
+ */
int pg_dir_mmap(pg_dir_t *pgdir, void *addr, u32_t size,
int prot, int flags, void **dst)
{
/* or unmap if it can't be accounted for */
if(ret_val < 0) {
+ dbg_printf("...and unmapping again\n");
pg_dir_unmap(pgdir, addr, size);
}
}
return(ret_val);
}
+/*
+ * pg_dir_munmap() - Release a mapping made by pg_dir_mmap()
+ *
+ * SYNOPSIS
+ * int pg_dir_munmap(pg_dir_t *pgdir, void *addr, u32_t size);
+ *
+ * DESCRIPTION
+ * The pg_dir_munmap() function releases the `size' bytes of memory mapped at the virtual address
+ * `addr' inside the page directory pointed to by `pgdir'. This function is the inverse function
+ * of pg_dir_mmap().
+ *
+ * This function is currently not implemented.
+ *
+ * RETURN VALUE
+ * This function returns zero upon success, or a negative error number if an error has occured.
+ *
+ * ERRORS
+ * -ENOSYS The function is not implemented
+ */
int pg_dir_munmap(pg_dir_t *pgdir, void *addr, u32_t size)
{
return(-ENOSYS);