Skip to content
This repository was archived by the owner on Dec 25, 2025. It is now read-only.

Commit c2bdfcf

Browse files
committed
Add support for 2MB/1GB pages in user address space
1 parent b394e81 commit c2bdfcf

File tree

5 files changed

+202
-99
lines changed

5 files changed

+202
-99
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#pragma once
2+
3+
#include "memory/pagemap.hpp"
4+
#include "libs/mutex.hpp"
5+
#include "libs/spinlock.hpp"
6+
#include "memory/pagemap.hpp"
7+
8+
namespace kernel::task {
9+
struct Process;
10+
}
11+
12+
namespace kernel::memory {
13+
struct UserVmRegion {
14+
uintptr_t start;
15+
size_t size;
16+
17+
size_t gap;
18+
size_t subtree_max_gap;
19+
20+
uint8_t flags;
21+
PageSize page_size;
22+
CacheType cache;
23+
24+
bool is_red = true;
25+
UserVmRegion* parent = nullptr;
26+
UserVmRegion* left = nullptr;
27+
UserVmRegion* right = nullptr;
28+
29+
uintptr_t end() const {
30+
return this->start + this->size;
31+
}
32+
};
33+
34+
class UserVmRegionAllocator {
35+
public:
36+
UserVmRegion* allocate();
37+
void deallocate(UserVmRegion* node);
38+
39+
private:
40+
void refill();
41+
42+
struct FreeNode {
43+
FreeNode* next;
44+
};
45+
46+
FreeNode* free_head = nullptr;
47+
SpinLock lock;
48+
};
49+
50+
class UserAddressSpace {
51+
public:
52+
static constexpr uintptr_t USER_START = 0x1000;
53+
static constexpr uintptr_t USER_END = 0x00007FFFFFFFFFFF;
54+
55+
static void arch_init();
56+
57+
void init(task::Process* proc);
58+
~UserAddressSpace();
59+
60+
void* allocate(size_t size, uint8_t flags = Read | Write, PageSize type = PageSize::Size4K);
61+
bool allocate_specific(uintptr_t virt_addr, size_t size, uint8_t flags, PageSize type = PageSize::Size4K);
62+
void free(void* ptr);
63+
bool handle_page_fault(uintptr_t fault_addr, size_t error_code);
64+
65+
private:
66+
uintptr_t find_hole(size_t size, size_t alignment);
67+
uintptr_t find_hole(UserVmRegion* node, size_t size, size_t alignment);
68+
69+
UserVmRegion* find_region_containing(uintptr_t addr);
70+
bool check_overlap(uintptr_t start, size_t size);
71+
72+
void insert_region(uintptr_t start, size_t size, uint8_t flags, CacheType cache, PageSize type);
73+
void delete_node(UserVmRegion* z);
74+
75+
void rotate_left(UserVmRegion* x);
76+
void rotate_right(UserVmRegion* x);
77+
void insert_fixup(UserVmRegion* z);
78+
void delete_fixup(UserVmRegion* x);
79+
80+
void update_node_metadata(UserVmRegion* x);
81+
void update_path_to_root(UserVmRegion* x);
82+
83+
UserVmRegion* predecessor(UserVmRegion* node);
84+
UserVmRegion* successor(UserVmRegion* node);
85+
86+
void free_tree(UserVmRegion* node);
87+
88+
Mutex mutex;
89+
PageMap* page_map;
90+
task::Process* process;
91+
UserVmRegion* root;
92+
UserVmRegion* cached_cursor;
93+
UserVmRegionAllocator metadata_allocator;
94+
};
95+
} // namespace kernel::memory

kernel/include/memory/vma.hpp

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -95,50 +95,4 @@ class VirtualMemoryAllocator {
9595
VmRegion* cached_cursor = nullptr;
9696
VmRegionAllocator metadata_allocator;
9797
};
98-
99-
class UserAddressSpace {
100-
public:
101-
static constexpr uintptr_t USER_START = 0x1000;
102-
static constexpr uintptr_t USER_END = 0x00007FFFFFFFFFFF;
103-
104-
static void arch_init();
105-
106-
void init(task::Process* proc);
107-
~UserAddressSpace();
108-
109-
void* allocate(size_t size, uint8_t flags = Read | Write);
110-
bool allocate_specific(uintptr_t virt_addr, size_t size, uint8_t flags);
111-
void free(void* ptr);
112-
bool handle_page_fault(uintptr_t fault_addr, size_t error_code);
113-
114-
private:
115-
uintptr_t find_hole(size_t size, size_t alignment);
116-
uintptr_t find_hole(VmRegion* node, size_t size, size_t alignment);
117-
118-
VmRegion* find_region_containing(uintptr_t addr);
119-
bool check_overlap(uintptr_t start, size_t size);
120-
121-
void insert_region(uintptr_t start, size_t size, uint8_t flags, CacheType cache);
122-
void delete_node(VmRegion* z);
123-
124-
void rotate_left(VmRegion* x);
125-
void rotate_right(VmRegion* x);
126-
void insert_fixup(VmRegion* z);
127-
void delete_fixup(VmRegion* x);
128-
129-
void update_node_metadata(VmRegion* x);
130-
void update_path_to_root(VmRegion* x);
131-
132-
VmRegion* predecessor(VmRegion* node);
133-
VmRegion* successor(VmRegion* node);
134-
135-
void free_tree(VmRegion* node);
136-
137-
Mutex mutex;
138-
PageMap* page_map;
139-
task::Process* process;
140-
VmRegion* root;
141-
VmRegion* cached_cursor;
142-
VmRegionAllocator metadata_allocator;
143-
};
14498
} // namespace kernel::memory

kernel/include/task/process.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "memory/pagemap.hpp"
55
#include "libs/spinlock.hpp"
66
#include "libs/intrusive_list.hpp"
7-
#include "memory/vma.hpp"
7+
#include "memory/user_address_space.hpp"
88

99
namespace kernel::cpu {
1010
struct PerCpuData;

kernel/src/arch/x86_64/memory/user_address_space.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "hal/interrupt.hpp"
33
#include "hal/smp_manager.hpp"
44
#include "libs/log.hpp"
5+
#include "memory/memory.hpp"
56
#include "memory/vma.hpp"
67
#include "hal//interface/interrupt.hpp"
78

@@ -38,7 +39,7 @@ class PageFaultHandler : public cpu::IInterruptHandler {
3839
bool UserAddressSpace::handle_page_fault(uintptr_t fault_addr, size_t error_code) {
3940
LockGuard guard(this->mutex);
4041

41-
VmRegion* region = this->find_region_containing(fault_addr);
42+
UserVmRegion* region = this->find_region_containing(fault_addr);
4243

4344
LOG_DEBUG("PF Handler Called!");
4445

@@ -56,13 +57,21 @@ bool UserAddressSpace::handle_page_fault(uintptr_t fault_addr, size_t error_code
5657
return false;
5758
}
5859

59-
uintptr_t page_base = fault_addr & ~(PAGE_SIZE_4K - 1);
60+
size_t alignment = PAGE_SIZE_4K;
61+
62+
if (region->page_size == PageSize::Size1G) {
63+
alignment = PAGE_SIZE_1G;
64+
} else if (region->page_size == PageSize::Size2M) {
65+
alignment = PAGE_SIZE_2M;
66+
}
67+
68+
uintptr_t page_base = fault_addr & ~(alignment - 1);
6069

6170
if (this->page_map->translate(page_base) != 0) {
6271
return true;
6372
}
6473

65-
if (!this->page_map->map(page_base, region->flags, region->cache, PageSize::Size4K)) {
74+
if (!this->page_map->map(page_base, region->flags, region->cache, region->page_size)) {
6675
LOG_ERROR("Out of memory!");
6776
return false;
6877
}

0 commit comments

Comments
 (0)