Skip to content

Commit f6950e7

Browse files
Ticonderoga2017Mivik
authored andcommitted
[mm] support huge page alloc (oscomp#54)
1. Support hugepage mmap. 2. Modify the testcase to avoid panic when allocating multiple consecutive 1GB huge pages.
1 parent e5e024b commit f6950e7

File tree

9 files changed

+356
-24
lines changed

9 files changed

+356
-24
lines changed

Cargo.lock

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ axfs-ng-vfs = { git = "https://github.com/Mivik/axfs-ng-vfs", rev = "517cd09" }
4444
axerrno = "0.1"
4545
bitflags = "2.6"
4646
cfg-if = "1.0"
47-
linkme = "0.3"
47+
linkme = "0.3.33"
4848
linux-raw-sys = { version = "0.9.3", default-features = false, features = [
4949
"no_std",
5050
"general",

api/src/imp/ipc/shm.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use linux_raw_sys::ctypes::{c_long, c_ushort};
1414
use linux_raw_sys::general::*;
1515
use memory_addr::{PAGE_SIZE_4K, VirtAddr, VirtAddrRange};
1616
use page_table_entry::MappingFlags;
17+
use page_table_multiarch::PageSize;
1718

1819
use crate::imp::ipc::{BiBTreeMap, IPCID_ALLOCATOR};
1920
use crate::ptr::{UserPtr, nullable};
@@ -388,12 +389,14 @@ pub fn sys_shmat(shmid: i32, addr: usize, shmflg: u32) -> LinuxResult<isize> {
388389
VirtAddr::from(start_aligned),
389390
length,
390391
VirtAddrRange::new(aspace.base(), aspace.end()),
392+
PageSize::Size4K,
391393
)
392394
.or_else(|| {
393395
aspace.find_free_area(
394396
aspace.base(),
395397
length,
396398
VirtAddrRange::new(aspace.base(), aspace.end()),
399+
PageSize::Size4K,
397400
)
398401
})
399402
.ok_or(LinuxError::ENOMEM)?;
@@ -413,10 +416,16 @@ pub fn sys_shmat(shmid: i32, addr: usize, shmflg: u32) -> LinuxResult<isize> {
413416
// map the virtual address range to the physical address
414417
if let Some(phys_pages) = shm_inner.phys_pages.clone() {
415418
// Another proccess has attached the shared memory
416-
aspace.map_shared(start_addr, length, mapping_flags, Some(phys_pages))?;
419+
aspace.map_shared(
420+
start_addr,
421+
length,
422+
mapping_flags,
423+
Some(phys_pages),
424+
PageSize::Size4K,
425+
)?;
417426
} else {
418427
// This is the first process to attach the shared memory
419-
let result = aspace.map_shared(start_addr, length, mapping_flags, None);
428+
let result = aspace.map_shared(start_addr, length, mapping_flags, None, PageSize::Size4K);
420429

421430
match result {
422431
Ok(pages) => {

api/src/imp/mm/mmap.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
use alloc::vec;
22
use axerrno::{LinuxError, LinuxResult};
3-
use axhal::paging::MappingFlags;
3+
use axhal::paging::{MappingFlags, PageSize};
44
use axtask::{TaskExtRef, current};
5-
use linux_raw_sys::general::{
6-
MAP_ANONYMOUS, MAP_FIXED, MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED, MAP_STACK, PROT_EXEC,
7-
PROT_GROWSDOWN, PROT_GROWSUP, PROT_READ, PROT_WRITE,
8-
};
9-
use memory_addr::{VirtAddr, VirtAddrRange};
5+
use linux_raw_sys::general::*;
6+
use memory_addr::{MemoryAddr, VirtAddr, VirtAddrRange, align_up_4k};
107

118
use crate::file::{File, FileLike};
129

@@ -63,6 +60,10 @@ bitflags::bitflags! {
6360
const NORESERVE = MAP_NORESERVE;
6461
/// Allocation is for a stack.
6562
const STACK = MAP_STACK;
63+
/// Huge page
64+
const HUGE = MAP_HUGETLB;
65+
/// Huge page 1g size
66+
const HUGE_1GB = MAP_HUGETLB | MAP_HUGE_1GB;
6667
}
6768
}
6869

@@ -81,14 +82,25 @@ pub fn sys_mmap(
8182
// TODO: check illegal flags for mmap
8283
// An example is the flags contained none of MAP_PRIVATE, MAP_SHARED, or MAP_SHARED_VALIDATE.
8384
let map_flags = MmapFlags::from_bits_truncate(flags);
85+
if map_flags.contains(MmapFlags::PRIVATE | MmapFlags::SHARED) {
86+
return Err(LinuxError::EINVAL);
87+
}
8488

8589
info!(
8690
"sys_mmap: addr: {:x?}, length: {:x?}, prot: {:?}, flags: {:?}, fd: {:?}, offset: {:?}",
8791
addr, length, permission_flags, map_flags, fd, offset
8892
);
8993

90-
let start = memory_addr::align_down_4k(addr);
91-
let end = memory_addr::align_up_4k(addr + length);
94+
let page_size = if map_flags.contains(MmapFlags::HUGE_1GB) {
95+
PageSize::Size1G
96+
} else if map_flags.contains(MmapFlags::HUGE) {
97+
PageSize::Size2M
98+
} else {
99+
PageSize::Size4K
100+
};
101+
102+
let start = addr.align_down(page_size);
103+
let end = (addr + length).align_up(page_size);
92104
let aligned_length = end - start;
93105
debug!(
94106
"start: {:x?}, end: {:x?}, aligned_length: {:x?}",
@@ -108,11 +120,13 @@ pub fn sys_mmap(
108120
VirtAddr::from(start),
109121
aligned_length,
110122
VirtAddrRange::new(aspace.base(), aspace.end()),
123+
page_size,
111124
)
112125
.or(aspace.find_free_area(
113126
aspace.base(),
114127
aligned_length,
115128
VirtAddrRange::new(aspace.base(), aspace.end()),
129+
page_size,
116130
))
117131
.ok_or(LinuxError::ENOMEM)?
118132
};
@@ -128,6 +142,7 @@ pub fn sys_mmap(
128142
aligned_length,
129143
permission_flags.into(),
130144
populate,
145+
page_size,
131146
)?;
132147

133148
if populate {
@@ -141,7 +156,7 @@ pub fn sys_mmap(
141156
let length = core::cmp::min(length, file_size - offset);
142157
let mut buf = vec![0u8; length];
143158
file.read_at(&mut buf, offset as u64)?;
144-
aspace.write(start_addr, &buf)?;
159+
aspace.write(start_addr, page_size, &buf)?;
145160
}
146161
Ok(start_addr.as_usize() as _)
147162
}
@@ -150,7 +165,7 @@ pub fn sys_munmap(addr: usize, length: usize) -> LinuxResult<isize> {
150165
let curr = current();
151166
let process_data = curr.task_ext().process_data();
152167
let mut aspace = process_data.aspace.lock();
153-
let length = memory_addr::align_up_4k(length);
168+
let length = align_up_4k(length);
154169
let start_addr = VirtAddr::from(addr);
155170
aspace.unmap(start_addr, length)?;
156171
axhal::arch::flush_tlb(None);
@@ -169,8 +184,9 @@ pub fn sys_mprotect(addr: usize, length: usize, prot: u32) -> LinuxResult<isize>
169184
let curr = current();
170185
let process_data = curr.task_ext().process_data();
171186
let mut aspace = process_data.aspace.lock();
172-
let length = memory_addr::align_up_4k(length);
187+
let length = align_up_4k(length);
173188
let start_addr = VirtAddr::from(addr);
189+
// TODO: is 4k right here?
174190
aspace.protect(start_addr, length, permission_flags.into())?;
175191

176192
Ok(0)

api/src/imp/task/clone.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ pub fn sys_clone(
153153
curr.task_ext().process_data().aspace.clone()
154154
} else {
155155
let mut aspace = curr.task_ext().process_data().aspace.lock();
156-
let mut aspace = aspace.clone_or_err()?;
156+
let mut aspace = aspace.try_clone()?;
157157
copy_from_kernel(&mut aspace)?;
158158
Arc::new(Mutex::new(aspace))
159159
};

api/src/ptr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fn check_region(start: VirtAddr, layout: Layout, access_flags: MappingFlags) ->
2424

2525
let page_start = start.align_down_4k();
2626
let page_end = (start + layout.size()).align_up_4k();
27-
aspace.populate_area(page_start, page_end - page_start)?;
27+
aspace.populate_area(page_start, page_end - page_start, access_flags)?;
2828

2929
Ok(())
3030
}

0 commit comments

Comments
 (0)