PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches

Address Space handling. More...

Collaboration diagram for Space:

Detailed Description

Address Space handling.

Data Structures

struct  space_callback_t
 
struct  space_pinned_page_t
 Pinned page structure. More...
 
struct  space_t
 Virtual address space structure. More...
 
struct  space_mapping_t
 Helper structure for managing address space mappings. More...
 
struct  vmm_callback_t
 Space callback structure. More...
 

Macros

#define SPACE_TLB_SHOOTDOWN_TIMEOUT   (CLOCKS_PER_SEC)
 The maximum time to wait for the acknowledgements from other CPU's before panicking.
 

Typedefs

typedef void(* space_callback_func_t) (void *data)
 Space callback function.
 

Enumerations

enum  space_flags_t {
  SPACE_NONE = 0 , SPACE_USE_PMM_BITMAP = 1 << 0 , SPACE_MAP_KERNEL_BINARY = 1 << 1 , SPACE_MAP_KERNEL_HEAP = 1 << 2 ,
  SPACE_MAP_IDENTITY = 1 << 3
}
 Flags for space initialization. More...
 

Functions

uint64_t space_init (space_t *space, uintptr_t startAddress, uintptr_t endAddress, space_flags_t flags)
 Initializes a virtual address space.
 
void space_deinit (space_t *space)
 Deinitializes a virtual address space.
 
uint64_t space_pin (space_t *space, const void *address, size_t length, stack_pointer_t *userStack)
 Pins pages within a region of the address space.
 
uint64_t space_pin_terminated (space_t *space, const void *address, const void *terminator, size_t objectSize, size_t maxCount, stack_pointer_t *userStack)
 Pins a region of memory terminated by a terminator value.
 
void space_unpin (space_t *space, const void *address, size_t length)
 Unpins pages in a region previously pinned with space_pin() or space_pin_string().
 
uint64_t space_check_access (space_t *space, const void *addr, size_t length)
 Checks if a virtual memory region is within the allowed address range of the space.
 
uint64_t space_mapping_start (space_t *space, space_mapping_t *mapping, void *virtAddr, phys_addr_t physAddr, size_t length, size_t alignment, pml_flags_t flags)
 Prepare for changes to the address space mappings.
 
pml_callback_id_t space_alloc_callback (space_t *space, size_t pageAmount, space_callback_func_t func, void *data)
 Allocate a callback.
 
void space_free_callback (space_t *space, pml_callback_id_t callbackId)
 Free a callback.
 
void * space_mapping_end (space_t *space, space_mapping_t *mapping, errno_t err)
 Performs cleanup after changes to the address space mappings.
 
bool space_is_mapped (space_t *space, const void *virtAddr, size_t length)
 Checks if a virtual memory region is fully mapped.
 
uint64_t space_user_page_count (space_t *space)
 Get the number of user pages allocated in the address space.
 
phys_addr_t space_virt_to_phys (space_t *space, const void *virtAddr)
 Translate a virtual address to a physical address in the address space.
 

Macro Definition Documentation

◆ SPACE_TLB_SHOOTDOWN_TIMEOUT

#define SPACE_TLB_SHOOTDOWN_TIMEOUT   (CLOCKS_PER_SEC)

The maximum time to wait for the acknowledgements from other CPU's before panicking.

Definition at line 101 of file space.h.

Typedef Documentation

◆ space_callback_func_t

typedef void(* space_callback_func_t) (void *data)

Space callback function.

Definition at line 42 of file space.h.

Enumeration Type Documentation

◆ space_flags_t

Flags for space initialization.

Enumerator
SPACE_NONE 
SPACE_USE_PMM_BITMAP 

Use the PMM bitmap to allocate the page table, this is really only for the kernel page table as it must be within a 32 bit boundary because the smp trampoline loads it as a dword.

SPACE_MAP_KERNEL_BINARY 

Map the kernel binary into the address space.

SPACE_MAP_KERNEL_HEAP 

Map the kernel heap into the address space.

SPACE_MAP_IDENTITY 

Map the identity mapped physical memory into the address space.

Definition at line 26 of file space.h.

Function Documentation

◆ space_init()

uint64_t space_init ( space_t space,
uintptr_t  startAddress,
uintptr_t  endAddress,
space_flags_t  flags 
)

Initializes a virtual address space.

Parameters
spaceThe address space to initialize.
startAddressThe starting address for allocations in this address space.
endAddressThe ending address for allocations in this address space.
flagsFlags to control the initialization behavior.
Returns
On success, 0. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • ENOMEM: Not enough memory to initialize the address space.

Definition at line 64 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_deinit()

void space_deinit ( space_t space)

Deinitializes a virtual address space.

Parameters
spaceThe address space to deinitialize.

Definition at line 121 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_pin()

uint64_t space_pin ( space_t space,
const void *  address,
size_t  length,
stack_pointer_t userStack 
)

Pins pages within a region of the address space.

Used to prevent TOCTOU attacks, where a system call provides some user space region, the kernel then checks that its mapped and after that check a seperate thread in the user space process unmaps or modifies that regions mappings while the kernel is still using it.

Our solution is to pin any user space pages that are accessed or modified during the syscall, meaning that a special flag is set in the address spaces page tables that prevent those pages from being unmapped or modified until they are unpinned which happens when the syscall is finished in space_unpin().

If the region is not fully mapped, or the region is not within the spaces startAddress and endAddress range, the function will fail.

If any page in the region is already at its maximum pin depth, the calling thread will block until the page is unpinned by another thread.

If a user stack is provided and the region to pin is both unmapped and within the stack region, memory will be allocated and mapped to the relevant region in the user stack. This is needed as its possible for a user space process to pass an address to a system call that is in its user stack but not yet mapped. For example, it could create a big buffer on its stack then pass it to a syscall without first accessing it, meaning no page fault would have occurred to map the pages.

Parameters
spaceThe target address space.
addressThe address to pin, can be NULL if length is 0.
lengthThe length of the region pointed to by address, in bytes.
userStackPointer to the user stack of the calling thread, can be NULL, see above. @return On success,0. On failure,ERRanderrnois set to: -EINVAL: Invalid parameters. -EOVERFLOW: Address overflow. -EFAULT: The region is not fully mapped or within the provided user stack. -ENOMEM`: Not enough memory.

Definition at line 281 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_pin_terminated()

uint64_t space_pin_terminated ( space_t space,
const void *  address,
const void *  terminator,
size_t  objectSize,
size_t  maxCount,
stack_pointer_t userStack 
)

Pins a region of memory terminated by a terminator value.

Pins pages in the address space starting from address up to maxSize bytes or until the specified terminator is found.

Used for null-terminated strings or other buffers that have a specific terminator.

Parameters
spaceThe target address space.
addressThe starting address of the region to pin.
terminatorThe terminator value to search for.
objectSizeThe size of each object to compare against the terminator, in bytes.
maxCountThe maximum number of objects to scan before failing.
userStackPointer to the user stack of the calling thread, can be NULL, see space_pin().
Returns
On success, the number of bytes pinned, not including the terminator. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • EOVERFLOW: Address overflow.
  • EFAULT: The region is not fully mapped or within the provided user stack.
  • ENOMEM: Not enough memory.

Definition at line 330 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_unpin()

void space_unpin ( space_t space,
const void *  address,
size_t  length 
)

Unpins pages in a region previously pinned with space_pin() or space_pin_string().

Will wake up any threads waiting to pin the same pages.

Parameters
spaceThe target address space.
addressThe address of the region to unpin, can be NULL if length is 0.
lengthThe length of the region pointed to by address, in bytes.

Definition at line 418 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_check_access()

uint64_t space_check_access ( space_t space,
const void *  addr,
size_t  length 
)

Checks if a virtual memory region is within the allowed address range of the space.

Checks that the given memory region is within the startAddress and endAddress range of the space, really only used in system calls that might access unmapped user space memory for example mmap(), in such cases we dont want to pin the "buffer" since we expect that it is not yet mapped.

Parameters
spaceThe target address space.
addrThe starting address of the memory region, can be NULL if length is 0.
lengthThe length of the memory region, in bytes.
Returns
On success, 0. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • EOVERFLOW: Address overflow.
  • EFAULT: The region is outside the allowed address range.

Definition at line 444 of file space.c.

Here is the caller graph for this function:

◆ space_mapping_start()

uint64_t space_mapping_start ( space_t space,
space_mapping_t mapping,
void *  virtAddr,
phys_addr_t  physAddr,
size_t  length,
size_t  alignment,
pml_flags_t  flags 
)

Prepare for changes to the address space mappings.

Will return with the spaces mutex acquired for writing, which must be released by calling space_mapping_end().

If flags & PML_USER then the addresses must be in the user space range.

Note
Handling page faults to grow stacks requires mapping memory, this means that if we were to run out of memory while executing this function, it could lead to a deadlock. To avoid this, this function will call stack_pointer_poke() to ensure that sufficient stack space is available.
Parameters
spaceThe target address space.
mappingWill be filled with parsed information about the mapping.
virtAddrThe virtual address the mapping will apply to. Can be NULL to let the kernel choose an address.
physAddrThe physical address to map from. Can be PHYS_ADDR_INVALID.
lengthThe length of the virtual memory region to modify, in bytes.
alignmentThe required alignment for the virtual memory region in bytes.
flagsThe page table flags for the mapping.
Returns
On success, 0. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • EOVERFLOW: Address overflow.
  • EFAULT: The addresses are outside the allowed range.
  • ENOMEM: Not enough memory.

Definition at line 494 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_alloc_callback()

pml_callback_id_t space_alloc_callback ( space_t space,
size_t  pageAmount,
space_callback_func_t  func,
void *  data 
)

Allocate a callback.

Must be called between space_mapping_start() and space_mapping_end().

When pageAmount number of pages with this callback ID are unmapped or the address space is freed, the callback function will be called with the provided private data.

Parameters
spaceThe target address space.
pageAmountThe number of pages the callback is responsible for.
funcThe callback function.
privatePrivate data to pass to the callback function.
Returns
On success, returns the callback ID. On failure, returns PML_MAX_CALLBACK.

Definition at line 571 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_free_callback()

void space_free_callback ( space_t space,
pml_callback_id_t  callbackId 
)

Free a callback.

Must be called between space_mapping_start() and space_mapping_end().

Allows the callback ID to be reused. The callback function will not be called.

Parameters
spaceThe target address space.
callbackIdThe callback ID to free.

Definition at line 612 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_mapping_end()

void * space_mapping_end ( space_t space,
space_mapping_t mapping,
errno_t  err 
)

Performs cleanup after changes to the address space mappings.

Must be called after space_mapping_start().

Parameters
spaceThe target address space.
mappingThe parsed information about the mapping.
errThe error code, if 0 then no error.
Returns
If err is EOK, returns the virtual address of the mapping. If err is not EOK, returns NULL and errno is set to err.

Definition at line 630 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_is_mapped()

bool space_is_mapped ( space_t space,
const void *  virtAddr,
size_t  length 
)

Checks if a virtual memory region is fully mapped.

Parameters
spaceThe target address space.
virtAddrThe virtual address of the memory region.
lengthThe length of the memory region, in bytes.
Returns
true if the entire region is mapped, false otherwise.

Definition at line 650 of file space.c.

Here is the call graph for this function:

◆ space_user_page_count()

uint64_t space_user_page_count ( space_t space)

Get the number of user pages allocated in the address space.

Will count the number of pages with the PML_OWNED flag set in user space.

Parameters
spaceThe target address space.
Returns
The number of user pages mapped.

Definition at line 657 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ space_virt_to_phys()

phys_addr_t space_virt_to_phys ( space_t space,
const void *  virtAddr 
)

Translate a virtual address to a physical address in the address space.

Parameters
spaceThe target address space.
virtAddrThe virtual address to translate.
Returns
On success, 0. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • EFAULT: The virtual address is not mapped.

Definition at line 670 of file space.c.

Here is the call graph for this function:
Here is the caller graph for this function: