Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Phineas1500/ish/llms.txt

Use this file to discover all available pages before exploring further.

The memory API provides virtual memory management, page table operations, and safe access to user space memory.

System Calls

Memory Allocation

kernel/calls.h:49
addr_t sys_brk(addr_t new_brk);
Adjusts the program break (end of the heap).
new_brk
addr_t
required
New heap end address (0 to query current break)
return
addr_t
Current or new break address on success, or previous break on error
Example:
// Query current break
addr_t current_brk = sys_brk(0);

// Extend heap by 4KB
addr_t new_brk = sys_brk(current_brk + 0x1000);
if (new_brk != current_brk + 0x1000) {
    // Error: couldn't allocate
}

Memory Mapping

kernel/calls.h:55-59
addr_t sys_mmap(addr_t args_addr);
addr_t sys_mmap2(addr_t addr, dword_t len, dword_t prot, dword_t flags, fd_t fd_no, dword_t offset);
#ifdef ISH_GUEST_64BIT
addr_t sys_mmap64(addr_t addr, addr_t len, dword_t prot, dword_t flags, fd_t fd_no, addr_t offset);
#endif
addr
addr_t
Requested address (0 for kernel to choose)
len
dword_t / addr_t
Length in bytes to map
prot
dword_t
Protection flags (PROT_READ, PROT_WRITE, PROT_EXEC)
flags
dword_t
Mapping flags (MMAP_SHARED, MMAP_PRIVATE, MMAP_FIXED, MMAP_ANONYMOUS)
fd_no
fd_t
File descriptor to map (ignored if MMAP_ANONYMOUS)
offset
dword_t / addr_t
Offset into file (in pages for mmap2, bytes for mmap64)
return
addr_t
Address of mapped region on success, negative error code on failure
Flags:
kernel/calls.h:51-54
#define MMAP_SHARED    0x1   // Share mapping with other processes
#define MMAP_PRIVATE   0x2   // Create private copy-on-write mapping
#define MMAP_FIXED     0x10  // Map at exact address (or fail)
#define MMAP_ANONYMOUS 0x20  // Not backed by file
Example:
// Allocate anonymous private memory
addr_t addr = sys_mmap2(0, 0x1000, PROT_READ | PROT_WRITE,
                        MMAP_PRIVATE | MMAP_ANONYMOUS, -1, 0);
if ((int)addr < 0) {
    // Error
}

// Map a file
fd_t fd = sys_open("/path/to/file", O_RDONLY_, 0);
addr_t mapped = sys_mmap2(0, 0x10000, PROT_READ,
                          MMAP_PRIVATE, fd, 0);

Memory Unmapping

kernel/calls.h:60
int_t sys_munmap(addr_t addr, addr_t len);
addr
addr_t
required
Starting address to unmap (must be page-aligned)
len
addr_t
required
Length in bytes to unmap
return
int_t
0 on success, negative error code on failure
Example:
int err = sys_munmap(addr, 0x1000);
if (err < 0) {
    // Error
}

Memory Protection

kernel/calls.h:61
int_t sys_mprotect(addr_t addr, addr_t len, int_t prot);
Changes protection on a region of memory.
prot
int_t
required
New protection flags (PROT_READ | PROT_WRITE | PROT_EXEC)
Example:
// Make region read-only
sys_mprotect(addr, 0x1000, PROT_READ);

User Space Access

These functions safely access memory in the emulated user space.

Read/Write Functions

kernel/calls.h:19-25
int must_check user_read(addr_t addr, void *buf, size_t count);
int must_check user_write(addr_t addr, const void *buf, size_t count);
int must_check user_read_task(struct task *task, addr_t addr, void *buf, size_t count);
int must_check user_write_task(struct task *task, addr_t addr, const void *buf, size_t count);
int must_check user_write_task_ptrace(struct task *task, addr_t addr, const void *buf, size_t count);
int must_check user_read_string(addr_t addr, char *buf, size_t max);
int must_check user_write_string(addr_t addr, const char *buf);
user_read
int
Reads data from current task’s user space
user_write
int
Writes data to current task’s user space
user_read_task
int
Reads data from specified task’s user space
user_write_task
int
Writes data to specified task’s user space
user_read_string
int
Reads null-terminated string from user space
user_write_string
int
Writes null-terminated string to user space
return
int
0 on success, negative error code on failure (e.g., -EFAULT for invalid address)
Example:
// Read 4 bytes from user space
uint32_t value;
if (user_read(user_addr, &value, sizeof(value)) < 0) {
    return -EFAULT;
}

// Write data to user space
struct my_struct data = { /* ... */ };
if (user_write(user_addr, &data, sizeof(data)) < 0) {
    return -EFAULT;
}

// Read string from user space
char filename[256];
if (user_read_string(path_addr, filename, sizeof(filename)) < 0) {
    return -EFAULT;
}

Convenience Macros

kernel/calls.h:26-29
#define user_get(addr, var) user_read(addr, &(var), sizeof(var))
#define user_put(addr, var) user_write(addr, &(var), sizeof(var))
#define user_get_task(task, addr, var) user_read_task(task, addr, &(var), sizeof(var))
#define user_put_task(task, addr, var) user_write_task(task, addr, &(var), sizeof(var))
Example:
// Read single value
int32_t fd;
if (user_get(fd_addr, fd) < 0) {
    return -EFAULT;
}

// Write single value
int32_t result = 42;
if (user_put(result_addr, result) < 0) {
    return -EFAULT;
}

Memory Management Unit

MMU Structure

emu/mmu.h:31-35
struct mmu {
    struct mmu_ops *ops;        // MMU operations
    struct asbestos *asbestos;  // Memory access tracking
    uint64_t changes;           // Change counter
};

MMU Operations

emu/mmu.h:41-44
struct mmu_ops {
    void *(*translate)(struct mmu *mmu, addr_t addr, int type);
};
translate
void *
Translates guest virtual address to host pointer. Returns NULL on fault.
type
int
Access type: MEM_READ, MEM_WRITE, or MEM_WRITE_PTRACE
emu/mmu.h:37-39
#define MEM_READ 0
#define MEM_WRITE 1
#define MEM_WRITE_PTRACE 2
Example:
void *ptr = mmu_translate(cpu.mmu, guest_addr, MEM_READ);
if (ptr == NULL) {
    // Page fault
}

Page Tables

Memory Structure

The mem structure manages virtual memory mappings. 32-bit:
kernel/memory.h:67-75
struct mem {
    struct pt_entry **pgdir;    // 2-level page directory
    int pgdir_used;             // Number of allocated directories
    struct mmu mmu;             // MMU interface
    wrlock_t lock;              // Read/write lock
};
64-bit:
kernel/memory.h:54-62
struct mem {
    struct pt_hash_entry **hash_table;  // Hash table for sparse pages
    int pages_mapped;                   // Count of mapped pages
    page_t mmap_cursor;                 // Next page for mmap allocation
    struct mmu mmu;                     // MMU interface
    wrlock_t lock;                      // Read/write lock
};

Page Table Entry

kernel/memory.h:35-40
struct pt_entry {
    struct data *data;          // Backing data
    size_t offset;              // Offset into data
    unsigned flags;             // Page flags (P_READ, P_WRITE, etc.)
    struct list blocks[2];      // Block lists
};

Page Flags

kernel/memory.h:87-102
#define P_READ       (1 << 0)  // Readable
#define P_WRITE      (1 << 1)  // Writable
#define P_EXEC       (1 << 2)  // Executable
#define P_RWX        (P_READ | P_WRITE | P_EXEC)
#define P_GROWSDOWN  (1 << 3)  // Stack grows downward
#define P_COW        (1 << 4)  // Copy-on-write
#define P_ANONYMOUS  (1 << 6)  // Anonymous mapping
#define P_SHARED     (1 << 7)  // Shared mapping
#define P_GUARD      (1 << 8)  // Guard page

#define P_WRITABLE(flags) (flags & P_WRITE && !(flags & P_COW))

Page Constants

emu/mmu.h:22-29
#define PAGE_BITS 12
#define PAGE_SIZE (1 << PAGE_BITS)  // 4096 bytes
#define PAGE(addr) ((addr) >> PAGE_BITS)
#define PGOFFSET(addr) ((addr) & (PAGE_SIZE - 1))
#define PAGE_ROUND_UP(bytes) (PAGE((bytes) + PAGE_SIZE - 1))
kernel/memory.h:12-13
#define BYTES_ROUND_DOWN(bytes) (PAGE(bytes) << PAGE_BITS)
#define BYTES_ROUND_UP(bytes) (PAGE_ROUND_UP(bytes) << PAGE_BITS)
Example:
addr_t addr = 0x12345;
page_t page_num = PAGE(addr);           // 0x12
addr_t offset = PGOFFSET(addr);         // 0x345
addr_t page_start = page_num << PAGE_BITS;  // 0x12000

Memory Initialization

kernel/memory.h:78-80
void mem_init(struct mem *mem);
void mem_destroy(struct mem *mem);
mem_init
void
Initializes empty address space
mem_destroy
void
Frees all memory and destroys address space
Example:
struct mem mem;
mem_init(&mem);

// Use memory...

mem_destroy(&mem);

Page Table Operations

kernel/memory.h:82-85
struct pt_entry *mem_pt(struct mem *mem, page_t page);
void mem_next_page(struct mem *mem, page_t *page);
mem_pt
struct pt_entry *
Gets page table entry for given page number
mem_next_page
void
Increments page number, skipping unallocated regions. For iteration.
Example:
// Iterate over all mapped pages
for (page_t page = 0; page < MEM_PAGES; mem_next_page(&mem, &page)) {
    struct pt_entry *entry = mem_pt(&mem, page);
    if (entry != NULL) {
        // Process mapped page
    }
}

Mapping Functions

kernel/memory.h:104-120
bool pt_is_hole(struct mem *mem, page_t start, pages_t pages);
page_t pt_find_hole(struct mem *mem, pages_t size);

int pt_map(struct mem *mem, page_t start, pages_t pages, void *memory, size_t offset, unsigned flags);
int pt_map_nothing(struct mem *mem, page_t page, pages_t pages, unsigned flags);
int pt_unmap(struct mem *mem, page_t start, pages_t pages);
int pt_unmap_always(struct mem *mem, page_t start, pages_t pages);
int pt_set_flags(struct mem *mem, page_t start, pages_t pages, int flags);
int pt_copy_on_write(struct mem *src, struct mem *dst, page_t start, page_t pages);
pt_is_hole
bool
Checks if region is unmapped. Returns true if unmapped.
pt_find_hole
page_t
Finds unmapped region of given size. Returns starting page number.
pt_map
int
Maps host memory into guest address space. Takes ownership of memory.
pt_map_nothing
int
Maps anonymous zero-filled pages
pt_unmap
int
Unmaps pages. Returns -1 if any part is not mapped.
pt_unmap_always
int
Unmaps pages. Doesn’t care if already unmapped.
pt_set_flags
int
Changes protection flags on mapped pages
pt_copy_on_write
int
Copies pages from src to dst using copy-on-write
Example:
// Allocate and map memory
void *memory = malloc(PAGE_SIZE * 4);
if (pt_map(&mem, 0x1000 >> PAGE_BITS, 4, memory, 0, P_READ | P_WRITE) < 0) {
    free(memory);
    return -ENOMEM;
}

// Map anonymous pages
if (pt_map_nothing(&mem, 0x5000 >> PAGE_BITS, 8, P_READ | P_WRITE) < 0) {
    return -ENOMEM;
}

// Change protection
pt_set_flags(&mem, 0x1000 >> PAGE_BITS, 4, P_READ);  // Make read-only

// Unmap
pt_unmap(&mem, 0x1000 >> PAGE_BITS, 4);

Memory Pointer Access

kernel/memory.h:123-124
void *mem_ptr(struct mem *mem, addr_t addr, int type);
int mem_segv_reason(struct mem *mem, addr_t addr);
mem_ptr
void *
Translates guest address to host pointer. Must call with mem read-locked. Returns NULL on fault.
mem_segv_reason
int
Gets reason for segmentation fault at address
Example:
read_wrlock(&mem.lock);
void *ptr = mem_ptr(&mem, guest_addr, MEM_WRITE);
if (ptr != NULL) {
    *(uint32_t *)ptr = 0x12345678;
}
read_wrunlock(&mem.lock);

Data Backing

Pages are backed by data structures that reference host memory.
kernel/memory.h:20-33
struct data {
    void *data;                 // Host memory pointer (immutable)
    size_t size;                // Size in bytes (immutable)
    atomic_uint refcount;       // Reference count

    // For /proc/pid/maps
    struct fd *fd;              // Backing file descriptor
    size_t file_offset;         // Offset into file
    const char *name;           // Mapping name
};
Data structures are reference counted and shared between pages with copy-on-write.