AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
fault.c File Reference

Page faults: a process's page brought in when it first touches it. More...

#include <core/system.h>
#include <core/panic.h>
#include <core/arch.h>
#include <mm/pmap.h>
#include <mm/vm.h>
#include <sys/sched.h>
#include <sys/signal.h>

Go to the source code of this file.

Data Structures

struct  pf
 What a page fault is about, passed to each of the steps below. More...

Functions

static int check_violation (int flags, int vm_flags)
 Returns whether an access of kind flags (PF_*) is one the mapping's permissions vm_flags don't allow.
static int pf_present (struct pf *pf)
 Handles a fault on a page that is mapped, but not with the permission the access needed: a write to a page that is read-only because a fork shared it.
static int pf_anon (struct pf *pf)
 Handles a fault on a page that the process's anon has (a page it wrote to before).
static struct vm_page * vm_object_page (struct vm_object *vm_object, hash_t hash, size_t off)
 Returns an object's page at offset off, reading it in with the object's pager if the object doesn't have it yet.
static int pf_object (struct pf *pf)
 Handles a fault on a page of the object the mapping is of (a file's page).
static int pf_zero (struct pf *pf)
 Handles a fault on a page that nothing has yet: a new page, zeroed, in the process's anon.
int mm_page_fault (vaddr_t vaddr, int flags)
 Handles a page fault in the current process's address space.

Detailed Description

Page faults: a process's page brought in when it first touches it.

A process's memory is mapped lazily. A page is mapped only when the process first reads or writes it, and the fault that the access raises comes here. The page comes from one of three places, tried in order:

  1. the process's anon (vm_anon), the pages it has written to, which copy on write when a fork shares them;
  2. the object the mapping is of (vm_object): a file's pages, read in by its pager;
  3. a new page, zeroed.

See docs/kernel/memory.md.

Definition in file fault.c.

Function Documentation

◆ check_violation()

int check_violation ( int flags,
int vm_flags )
inlinestatic

Returns whether an access of kind flags (PF_*) is one the mapping's permissions vm_flags don't allow.

Definition at line 41 of file fault.c.

References check_violation(), vm_entry::flags, PF_EXEC, PF_READ, PF_WRITE, VM_UR, VM_UW, and VM_UX.

Referenced by check_violation(), and mm_page_fault().

◆ mm_page_fault()

int mm_page_fault ( vaddr_t vaddr,
int flags )

Handles a page fault in the current process's address space.

The architecture calls it from its page fault handler.

If the address isn't mapped, or the mapping doesn't allow the access, the fault can't be resolved, and the architecture decides what follows: a SIGSEGV, a failed copy (EFAULT) for a system call, or a panic for the kernel's own access. If there's no memory to resolve it, the process is also killed (SIGKILL): it couldn't go on.

Parameters
vaddrthe address that faulted
flagsthe kind of access (PF_READ, PF_WRITE, PF_EXEC, and PF_PRESENT if a page was mapped there)
Returns
0 if the fault is resolved (the page is mapped now), or -EFAULT if it isn't

Definition at line 395 of file fault.c.

References pf::addr, vm_entry::base, check_violation(), curproc, curthread, pf::flags, vm_entry::flags, pf::hash, mm_page_fault(), NULL, pf::off, vm_entry::off, PAGE_ALIGN, pf_anon(), pf_object(), PF_PRESENT, pf_present(), pf_zero(), vm_space::pmap, printk(), signal_proc_send(), vm_entry::vm_anon, vm_entry::vm_object, and vm_space_find().

Referenced by abort(), arch_mm_page_fault(), and mm_page_fault().

◆ pf_anon()

int pf_anon ( struct pf * pf)
inlinestatic

Handles a fault on a page that the process's anon has (a page it wrote to before).

A shared anon is copied first, if the fork that shared it asked for that. A read maps the page read-only; a write maps it read-write if only this process has it, and copies it otherwise.

Returns 1 if the fault is handled, 0 if the anon doesn't have the page, or a negative errno.

Definition at line 119 of file fault.c.

References pf::addr, vm_anon::arefs, hashmap_node::entry, pf::flags, vm_anon::flags, vm_aref::flags, vm_entry::flags, pf::hash, kfree(), kmalloc(), M_ZERO, mm_page_alloc(), mm_page_incref(), mm_page_map(), NULL, pf::off, vm_page::off, vm_page::paddr, panic, pf_anon(), PF_WRITE, vm_space::pmap, pmap_page_copy(), vm_anon::ref, vm_aref::ref, vm_page::ref, vm_entry::vm_anon, vm_anon_copy(), vm_anon_decref(), VM_COPY, pf::vm_entry, VM_KW, vm_page::vm_object, vm_aref::vm_page, VM_PERM, pf::vm_space, and VM_UW.

Referenced by mm_page_fault(), and pf_anon().

◆ pf_object()

int pf_object ( struct pf * pf)
inlinestatic

Handles a fault on a page of the object the mapping is of (a file's page).

A read-only mapping maps the object's page itself. A writable one gets a copy, in the process's anon: what it writes is its own.

Returns 1 if the fault is handled, or a negative errno (-EIO if the page couldn't be read in).

Definition at line 249 of file fault.c.

References pf::addr, vm_anon::arefs, vm_entry::flags, pf::hash, kfree(), kmalloc(), M_ZERO, mm_page_alloc(), mm_page_dealloc(), mm_page_incref(), mm_page_map(), NULL, pf::off, vm_page::off, vm_page::paddr, pf_object(), vm_space::pmap, pmap_page_copy(), vm_anon::ref, vm_aref::ref, vm_page::ref, vm_entry::vm_anon, vm_anon_new(), pf::vm_entry, vm_entry::vm_object, vm_page::vm_object, vm_object_page(), vm_aref::vm_page, VM_PERM, pf::vm_space, and VM_UW.

Referenced by mm_page_fault(), and pf_object().

◆ pf_present()

int pf_present ( struct pf * pf)
inlinestatic

Handles a fault on a page that is mapped, but not with the permission the access needed: a write to a page that is read-only because a fork shared it.

If only this process has the page, it gets it read-write, after copying it if the page is still shared with an object.

Returns 1 if the fault is handled, 0 if another step has to handle it, or a negative errno.

Definition at line 58 of file fault.c.

References pf::addr, vm_anon::arefs, hashmap_node::entry, vm_aref::flags, vm_entry::flags, pf::hash, mm_page_alloc(), mm_page_decref(), mm_page_map(), NULL, pf::off, vm_page::off, vm_page::paddr, PAGE_SIZE, pf_present(), vm_space::pmap, pmap_page_copy(), pmap_protect(), vm_anon::ref, vm_aref::ref, vm_page::ref, vm_entry::vm_anon, VM_COPY, pf::vm_entry, vm_page::vm_object, vm_aref::vm_page, VM_PERM, and pf::vm_space.

Referenced by mm_page_fault(), and pf_present().

◆ pf_zero()

int pf_zero ( struct pf * pf)
inlinestatic

Handles a fault on a page that nothing has yet: a new page, zeroed, in the process's anon.

Returns 1 if the fault is handled, or a negative errno.

Definition at line 326 of file fault.c.

References pf::addr, vm_anon::arefs, vm_entry::flags, pf::hash, kfree(), kmalloc(), M_ZERO, memset(), mm_page_alloc(), mm_page_dealloc(), mm_page_map(), pf::off, vm_page::off, vm_page::paddr, PAGE_SIZE, pf_zero(), vm_space::pmap, pmap_protect(), pmap_remove(), vm_anon::ref, vm_aref::ref, vm_page::ref, vm_entry::vm_anon, vm_anon_new(), pf::vm_entry, VM_KW, vm_aref::vm_page, VM_PERM, and pf::vm_space.

Referenced by mm_page_fault(), and pf_zero().

◆ vm_object_page()

struct vm_page * vm_object_page ( struct vm_object * vm_object,
hash_t hash,
size_t off )
inlinestatic

Returns an object's page at offset off, reading it in with the object's pager if the object doesn't have it yet.

Returns NULL if it couldn't be read in (no memory, or a read error).

Definition at line 222 of file fault.c.

References hashmap_node::entry, hashmap_node::hash, vm_pager::in, NULL, vm_page::off, vm_object::pager, vm_object::pages, printk(), and vm_object_page().

Referenced by pf_object(), and vm_object_page().