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