1#include <mem/demand_page.h>
2#include <mem/domain.h>
3#include <mem/page_fault.h>
4
5#include "internal.h"
6
7static bool slab_pf_valid(struct page_fault_info *pfi);
8static bool slab_pf_update(vaddr_t vaddr, struct page *p);
9static paddr_t slab_pf_alloc_pages(vaddr_t vaddr, uint8_t order);
10
11struct page_fault_handler_ops ops = {
12 .is_valid_fault = slab_pf_valid,
13 .update_after_map = slab_pf_update,
14 .alloc_pages = slab_pf_alloc_pages,
15};
16
17struct page_fault_handler slab_page_fault_handler = {
18 .ops = &ops,
19};
20
21/* No need to use up extra cycles to consult the vas, we
22 * can check order map, align, and then check if it's mapped */
23static bool slab_pf_valid(struct page_fault_info *pfi) {
24 return vmm_get_phys((vaddr_t) slab_for_ptr((void *) pfi->addr)) !=
25 PADDR_MAX;
26}
27
28static bool slab_pf_update(vaddr_t vaddr, struct page *p) {
29 struct slab *slab = slab_for_ptr(ptr: (void *) vaddr);
30 vaddr_t slab_vaddr = (vaddr_t) slab;
31 pfn_t slab_vpn = PAGE_TO_PFN(slab_vaddr);
32 pfn_t vaddr_vpn = PAGE_TO_PFN(vaddr);
33 size_t idx = vaddr_vpn - slab_vpn;
34 struct page *exp = NULL;
35
36 return atomic_cas_strong(&slab->backing_pages[idx], &exp, p);
37}
38
39static paddr_t slab_pf_alloc_pages(vaddr_t vaddr, uint8_t order) {
40 enforce_precond(order == 0);
41 struct slab *s = slab_for_ptr(ptr: (void *) vaddr);
42 return domain_alloc_from_domain(cd: s->parent_cache->parent_domain->domain, pages: 1);
43}
44