1
1
use alloc:: vec;
2
2
use axerrno:: { LinuxError , LinuxResult } ;
3
3
use axhal:: paging:: MappingFlags ;
4
+ use axmm:: { PAGE_SIZE_1G , PAGE_SIZE_2M } ;
4
5
use axtask:: { TaskExtRef , current} ;
5
6
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 ,
7
+ MAP_ANONYMOUS , MAP_FIXED , MAP_HUGE_1GB , MAP_HUGE_MASK , MAP_HUGE_SHIFT , MAP_HUGETLB ,
8
+ MAP_NORESERVE , MAP_PRIVATE , MAP_SHARED , MAP_STACK , PROT_EXEC , PROT_GROWSDOWN , PROT_GROWSUP ,
9
+ PROT_READ , PROT_WRITE ,
8
10
} ;
9
- use memory_addr:: { VirtAddr , VirtAddrRange } ;
11
+ use memory_addr:: { MemoryAddr , PAGE_SIZE_4K , VirtAddr , VirtAddrRange } ;
10
12
11
13
use crate :: file:: { File , FileLike } ;
12
14
@@ -82,13 +84,26 @@ pub fn sys_mmap(
82
84
// An example is the flags contained none of MAP_PRIVATE, MAP_SHARED, or MAP_SHARED_VALIDATE.
83
85
let map_flags = MmapFlags :: from_bits_truncate ( flags) ;
84
86
87
+ // The check uses bitwise operations to
88
+ // verify that exactly one of the two mutually exclusive mapping flags is set
89
+ if ( map_flags. bits ( ) & ( MAP_PRIVATE | MAP_SHARED ) ) . count_ones ( ) != 1 {
90
+ return Err ( LinuxError :: EINVAL ) ;
91
+ }
92
+
85
93
info ! (
86
94
"sys_mmap: addr: {:x?}, length: {:x?}, prot: {:?}, flags: {:?}, fd: {:?}, offset: {:?}" ,
87
95
addr, length, permission_flags, map_flags, fd, offset
88
96
) ;
89
97
90
- let start = memory_addr:: align_down_4k ( addr) ;
91
- let end = memory_addr:: align_up_4k ( addr + length) ;
98
+ let ( map_huge, page_size) = match ( flags & MAP_HUGETLB , flags & MAP_HUGE_MASK << MAP_HUGE_SHIFT )
99
+ {
100
+ ( 0 , _) => ( false , PAGE_SIZE_4K ) ,
101
+ ( _, MAP_HUGE_1GB ) => ( true , PAGE_SIZE_1G ) ,
102
+ ( _, _) => ( true , PAGE_SIZE_2M ) ,
103
+ } ;
104
+
105
+ let start = addr. align_down ( page_size) ;
106
+ let end = ( addr + length) . align_up ( page_size) ;
92
107
let aligned_length = end - start;
93
108
debug ! (
94
109
"start: {:x?}, end: {:x?}, aligned_length: {:x?}" ,
@@ -103,18 +118,35 @@ pub fn sys_mmap(
103
118
aspace. unmap ( dst_addr, aligned_length) ?;
104
119
dst_addr
105
120
} else {
106
- aspace
107
- . find_free_area (
108
- VirtAddr :: from ( start) ,
109
- aligned_length,
110
- VirtAddrRange :: new ( aspace. base ( ) , aspace. end ( ) ) ,
111
- )
112
- . or ( aspace. find_free_area (
113
- aspace. base ( ) ,
114
- aligned_length,
115
- VirtAddrRange :: new ( aspace. base ( ) , aspace. end ( ) ) ,
116
- ) )
117
- . ok_or ( LinuxError :: ENOMEM ) ?
121
+ if map_huge {
122
+ aspace
123
+ . find_free_area_with_align (
124
+ VirtAddr :: from ( start) . align_up ( page_size) ,
125
+ aligned_length,
126
+ VirtAddrRange :: new ( aspace. base ( ) , aspace. end ( ) ) ,
127
+ page_size,
128
+ )
129
+ . or ( aspace. find_free_area_with_align (
130
+ aspace. base ( ) . align_up ( page_size) ,
131
+ aligned_length,
132
+ VirtAddrRange :: new ( aspace. base ( ) , aspace. end ( ) ) ,
133
+ page_size,
134
+ ) )
135
+ . ok_or ( LinuxError :: ENOMEM ) ?
136
+ } else {
137
+ aspace
138
+ . find_free_area (
139
+ VirtAddr :: from ( start) . align_up ( page_size) ,
140
+ aligned_length,
141
+ VirtAddrRange :: new ( aspace. base ( ) , aspace. end ( ) ) ,
142
+ )
143
+ . or ( aspace. find_free_area (
144
+ aspace. base ( ) . align_up ( page_size) ,
145
+ aligned_length,
146
+ VirtAddrRange :: new ( aspace. base ( ) , aspace. end ( ) ) ,
147
+ ) )
148
+ . ok_or ( LinuxError :: ENOMEM ) ?
149
+ }
118
150
} ;
119
151
120
152
let populate = if fd == -1 {
@@ -128,6 +160,7 @@ pub fn sys_mmap(
128
160
aligned_length,
129
161
permission_flags. into ( ) ,
130
162
populate,
163
+ page_size,
131
164
) ?;
132
165
133
166
if populate {
@@ -150,7 +183,6 @@ pub fn sys_munmap(addr: usize, length: usize) -> LinuxResult<isize> {
150
183
let curr = current ( ) ;
151
184
let process_data = curr. task_ext ( ) . process_data ( ) ;
152
185
let mut aspace = process_data. aspace . lock ( ) ;
153
- let length = memory_addr:: align_up_4k ( length) ;
154
186
let start_addr = VirtAddr :: from ( addr) ;
155
187
aspace. unmap ( start_addr, length) ?;
156
188
axhal:: arch:: flush_tlb ( None ) ;
0 commit comments