Skip to content

Commit f505345

Browse files
authored
内存管理修复bug (#297)
1.修正rwLock未修改锁持有计数的bug 2.修复PageMapper::create未清空页表的问题 3.解决x86_64不支持XD时,页表项填写错误的问题 4.调整elf加载器,使得能够正确的加载relibc的程序
1 parent 1f3d2ab commit f505345

33 files changed

+519
-285
lines changed

kernel/src/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ main.o: main.c
3333

3434
kernel_rust:
3535
rustup default nightly
36-
cargo +nightly-2023-01-21 build --target ./arch/x86_64/x86_64-unknown-none.json
37-
# cargo +nightly-2023-01-21 build --release --target ./arch/x86_64/x86_64-unknown-none.json
36+
# cargo +nightly-2023-01-21 build --target ./arch/x86_64/x86_64-unknown-none.json
37+
cargo +nightly-2023-01-21 build --release --target ./arch/x86_64/x86_64-unknown-none.json
3838

3939
all: kernel
4040

kernel/src/arch/x86_64/asm/irqflags.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub fn local_irq_save() -> usize {
55
let x: usize;
66
// x86_64::registers::rflags::
77
unsafe {
8-
asm!("pushfq; pop {};cli", out(reg) x, options(nomem, preserves_flags));
8+
asm!("pushfq; pop {}; cli", out(reg) x, options(nomem, preserves_flags));
99
}
1010
x
1111
}

kernel/src/arch/x86_64/mm/mod.rs

Lines changed: 129 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
pub mod barrier;
22
pub mod frame;
3+
use alloc::vec::Vec;
4+
use hashbrown::HashSet;
5+
use x86::time::rdtsc;
6+
use x86_64::registers::model_specific::EferFlags;
7+
38
use crate::driver::uart::uart::c_uart_send_str;
49
use crate::include::bindings::bindings::{
510
disable_textui, enable_textui, multiboot2_get_memory, multiboot2_iter, multiboot_mmap_entry_t,
6-
process_control_block, video_reinitialize,
11+
video_reinitialize,
712
};
813
use crate::libs::align::page_align_up;
914
use crate::libs::printk::PrintkWriter;
1015
use crate::libs::spinlock::SpinLock;
16+
1117
use crate::mm::allocator::page_frame::{FrameAllocator, PageFrameCount};
1218
use crate::mm::mmio_buddy::mmio_init;
1319
use crate::{
@@ -24,11 +30,9 @@ use crate::{kdebug, kinfo};
2430
use core::arch::asm;
2531
use core::ffi::c_void;
2632
use core::fmt::{Debug, Write};
27-
use core::mem::{self, MaybeUninit};
28-
use core::ptr::read_volatile;
29-
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
33+
use core::mem::{self};
3034

31-
use self::barrier::mfence;
35+
use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
3236

3337
pub type PageMapper =
3438
crate::mm::page::PageMapper<crate::arch::x86_64::mm::X86_64MMArch, LockedFrameAllocator>;
@@ -72,6 +76,9 @@ pub static mut BOOTSTRAP_MM_INFO: Option<X86_64MMBootstrapInfo> = None;
7276
#[derive(Debug, Clone, Copy, Hash)]
7377
pub struct X86_64MMArch;
7478

79+
/// XD标志位是否被保留
80+
static XD_RESERVED: AtomicBool = AtomicBool::new(false);
81+
7582
impl MemoryManagementArch for X86_64MMArch {
7683
/// 4K页
7784
const PAGE_SHIFT: usize = 12;
@@ -125,6 +132,8 @@ impl MemoryManagementArch for X86_64MMArch {
125132
fn _end();
126133
}
127134

135+
Self::init_xd_rsvd();
136+
128137
let bootstrap_info = X86_64MMBootstrapInfo {
129138
kernel_code_start: _text as usize,
130139
kernel_code_end: _etext as usize,
@@ -248,8 +257,28 @@ impl X86_64MMArch {
248257
}
249258
c_uart_send_str(0x3f8, "init_memory_area_from_multiboot2 end\n\0".as_ptr());
250259
kinfo!("Total memory size: {} MB, total areas from multiboot2: {mb2_count}, valid areas: {areas_count}", total_mem_size / 1024 / 1024);
260+
251261
return Ok(areas_count);
252262
}
263+
264+
fn init_xd_rsvd() {
265+
// 读取ia32-EFER寄存器的值
266+
let efer: EferFlags = x86_64::registers::model_specific::Efer::read();
267+
if !efer.contains(EferFlags::NO_EXECUTE_ENABLE) {
268+
// NO_EXECUTE_ENABLE是false,那么就设置xd_reserved为true
269+
kdebug!("NO_EXECUTE_ENABLE is false, set XD_RESERVED to true");
270+
XD_RESERVED.store(true, Ordering::Relaxed);
271+
kdebug!("11efer.contains(EferFlags::NO_EXECUTE_ENABLE)={}, XD_RESERVED={}", efer.contains(EferFlags::NO_EXECUTE_ENABLE), XD_RESERVED.load(Ordering::Relaxed));
272+
}
273+
compiler_fence(Ordering::SeqCst);
274+
275+
kdebug!("efer.contains(EferFlags::NO_EXECUTE_ENABLE)={}, XD_RESERVED={}", efer.contains(EferFlags::NO_EXECUTE_ENABLE), XD_RESERVED.load(Ordering::Relaxed));
276+
}
277+
278+
/// 判断XD标志位是否被保留
279+
pub fn is_xd_reserved() -> bool {
280+
return XD_RESERVED.load(Ordering::Relaxed);
281+
}
253282
}
254283

255284
impl VirtAddr {
@@ -344,7 +373,7 @@ unsafe fn allocator_init() {
344373

345374
for area in PHYS_MEMORY_AREAS.iter() {
346375
// kdebug!("area: base={:?}, size={:#x}, end={:?}", area.base, area.size, area.base + area.size);
347-
for i in 0..area.size / MMArch::PAGE_SIZE {
376+
for i in 0..((area.size + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE) {
348377
let paddr = area.base.add(i * MMArch::PAGE_SIZE);
349378
let vaddr = unsafe { MMArch::phys_2_virt(paddr) }.unwrap();
350379
let flags = kernel_page_flags::<MMArch>(vaddr);
@@ -422,6 +451,99 @@ unsafe fn allocator_init() {
422451
kdebug!("Text UI enabled");
423452
}
424453

454+
#[no_mangle]
455+
pub extern "C" fn rs_test_buddy() {
456+
test_buddy();
457+
}
458+
pub fn test_buddy() {
459+
// 申请内存然后写入数据然后free掉
460+
// 总共申请200MB内存
461+
const TOTAL_SIZE: usize = 200 * 1024 * 1024;
462+
463+
for i in 0..10 {
464+
kdebug!("Test buddy, round: {i}");
465+
// 存放申请的内存块
466+
let mut v: Vec<(PhysAddr, PageFrameCount)> = Vec::with_capacity(60 * 1024);
467+
// 存放已经申请的内存块的地址(用于检查重复)
468+
let mut addr_set: HashSet<PhysAddr> = HashSet::new();
469+
470+
let mut allocated = 0usize;
471+
472+
let mut free_count = 0usize;
473+
474+
while allocated < TOTAL_SIZE {
475+
let mut random_size = 0u64;
476+
unsafe { x86::random::rdrand64(&mut random_size) };
477+
// 一次最多申请4M
478+
random_size = random_size % (1024 * 4096);
479+
if random_size == 0 {
480+
continue;
481+
}
482+
let random_size =
483+
core::cmp::min(page_align_up(random_size as usize), TOTAL_SIZE - allocated);
484+
let random_size = PageFrameCount::from_bytes(random_size.next_power_of_two()).unwrap();
485+
// 获取帧
486+
let (paddr, allocated_frame_count) =
487+
unsafe { LockedFrameAllocator.allocate(random_size).unwrap() };
488+
assert!(allocated_frame_count.data().is_power_of_two());
489+
assert!(paddr.data() % MMArch::PAGE_SIZE == 0);
490+
unsafe {
491+
assert!(MMArch::phys_2_virt(paddr)
492+
.as_ref()
493+
.unwrap()
494+
.check_aligned(allocated_frame_count.data() * MMArch::PAGE_SIZE));
495+
}
496+
allocated += allocated_frame_count.data() * MMArch::PAGE_SIZE;
497+
v.push((paddr, allocated_frame_count));
498+
assert!(addr_set.insert(paddr), "duplicate address: {:?}", paddr);
499+
500+
// 写入数据
501+
let vaddr = unsafe { MMArch::phys_2_virt(paddr).unwrap() };
502+
let slice = unsafe {
503+
core::slice::from_raw_parts_mut(
504+
vaddr.data() as *mut u8,
505+
allocated_frame_count.data() * MMArch::PAGE_SIZE,
506+
)
507+
};
508+
for i in 0..slice.len() {
509+
slice[i] = ((i + unsafe { rdtsc() } as usize) % 256) as u8;
510+
}
511+
512+
// 随机释放一个内存块
513+
if v.len() > 0 {
514+
let mut random_index = 0u64;
515+
unsafe { x86::random::rdrand64(&mut random_index) };
516+
// 70%概率释放
517+
if random_index % 10 > 7 {
518+
continue;
519+
}
520+
random_index = random_index % v.len() as u64;
521+
let random_index = random_index as usize;
522+
let (paddr, allocated_frame_count) = v.remove(random_index);
523+
assert!(addr_set.remove(&paddr));
524+
unsafe { LockedFrameAllocator.free(paddr, allocated_frame_count) };
525+
free_count += allocated_frame_count.data() * MMArch::PAGE_SIZE;
526+
}
527+
}
528+
529+
kdebug!(
530+
"Allocated {} MB memory, release: {} MB, no release: {} bytes",
531+
allocated / 1024 / 1024,
532+
free_count / 1024 / 1024,
533+
(allocated - free_count)
534+
);
535+
536+
kdebug!("Now, to release buddy memory");
537+
// 释放所有的内存
538+
for (paddr, allocated_frame_count) in v {
539+
unsafe { LockedFrameAllocator.free(paddr, allocated_frame_count) };
540+
assert!(addr_set.remove(&paddr));
541+
free_count += allocated_frame_count.data() * MMArch::PAGE_SIZE;
542+
}
543+
544+
kdebug!("release done!, allocated: {allocated}, free_count: {free_count}");
545+
}
546+
}
425547
/// 全局的页帧分配器
426548
#[derive(Debug, Clone, Copy, Hash)]
427549
pub struct LockedFrameAllocator;
@@ -459,7 +581,7 @@ pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(virt: VirtAddr) -> Page
459581
let info: X86_64MMBootstrapInfo = BOOTSTRAP_MM_INFO.clone().unwrap();
460582

461583
if virt.data() >= info.kernel_code_start && virt.data() < info.kernel_code_end {
462-
// Remap kernel code read only, execute
584+
// Remap kernel code execute
463585
return PageFlags::new().set_execute(true).set_write(true);
464586
} else if virt.data() >= info.kernel_data_end && virt.data() < info.kernel_rodata_end {
465587
// Remap kernel rodata read only

kernel/src/arch/x86_64/msi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn ia64_pci_get_arch_msi_message_address(processor: u16) -> u32 {
1212
/// @return MSI Message Address
1313
pub fn ia64_pci_get_arch_msi_message_data(
1414
vector: u16,
15-
processor: u16,
15+
_processor: u16,
1616
trigger: TriggerMode,
1717
) -> u32 {
1818
match trigger {

kernel/src/arch/x86_64/syscall.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
},
1212
ipc::signal::sys_rt_sigreturn,
1313
kdebug, kinfo,
14-
mm::{ucontext::AddressSpace, verify_area, MemoryManagementArch, VirtAddr},
14+
mm::{ucontext::AddressSpace, verify_area, VirtAddr},
1515
process::exec::{load_binary_file, ExecParam, ExecParamFlags},
1616
syscall::{
1717
user_access::{check_and_clone_cstr, check_and_clone_cstr_array},
@@ -82,26 +82,26 @@ pub extern "C" fn syscall_handler(regs: &mut pt_regs) -> () {
8282
syscall_return!(SystemError::EFAULT.to_posix_errno() as u64, regs);
8383
} else {
8484
unsafe {
85-
// syscall_return!(
86-
// rs_do_execve(
87-
// path_ptr as *const u8,
88-
// argv_ptr as *const *const u8,
89-
// env_ptr as *const *const u8,
90-
// regs
91-
// ),
92-
// regs
93-
// );
9485
kdebug!("syscall: execve\n");
95-
let path = String::from("/bin/about.elf");
96-
let argv = vec![String::from("/bin/about.elf")];
97-
let envp = vec![String::from("PATH=/bin")];
98-
let r = tmp_rs_execve(path, argv, envp, regs);
99-
kdebug!("syscall: execve r: {:?}\n", r);
100-
10186
syscall_return!(
102-
r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize),
87+
rs_do_execve(
88+
path_ptr as *const u8,
89+
argv_ptr as *const *const u8,
90+
env_ptr as *const *const u8,
91+
regs
92+
),
10393
regs
104-
)
94+
);
95+
// let path = String::from("/bin/about.elf");
96+
// let argv = vec![String::from("/bin/about.elf")];
97+
// let envp = vec![String::from("PATH=/bin")];
98+
// let r = tmp_rs_execve(path, argv, envp, regs);
99+
// kdebug!("syscall: execve r: {:?}\n", r);
100+
101+
// syscall_return!(
102+
// r.map(|_| 0).unwrap_or_else(|e| e.to_posix_errno() as usize),
103+
// regs
104+
// )
105105
}
106106
}
107107
}
@@ -217,7 +217,13 @@ fn tmp_rs_execve(
217217
kdebug!("to load binary file");
218218
let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC);
219219
// 加载可执行文件
220-
let load_result = load_binary_file(&mut param)?;
220+
let load_result = load_binary_file(&mut param).unwrap_or_else(|e| {
221+
panic!(
222+
"Failed to load binary file: {:?}, path: {:?}",
223+
e,
224+
path
225+
)
226+
});
221227
kdebug!("load binary file done");
222228

223229
param.init_info_mut().args = argv;

kernel/src/driver/net/virtio_net.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ use smoltcp::{phy, wire};
99
use virtio_drivers::{device::net::VirtIONet, transport::Transport};
1010

1111
use crate::{
12-
driver::{virtio::virtio_impl::HalImpl, Driver},
13-
kdebug, kerror, kinfo,
12+
driver::{virtio::virtio_impl::HalImpl, Driver}, kerror, kinfo,
1413
libs::spinlock::SpinLock,
1514
net::{generate_iface_id, NET_DRIVERS},
1615
syscall::SystemError,

kernel/src/driver/pci/pci_irq.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ use core::ptr::NonNull;
66
use alloc::ffi::CString;
77
use alloc::vec::Vec;
88

9-
use super::pci::{HeaderType, PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError};
9+
use super::pci::{PciDeviceStructure, PciDeviceStructureGeneralDevice, PciError};
1010
use crate::arch::msi::{ia64_pci_get_arch_msi_message_address, ia64_pci_get_arch_msi_message_data};
1111
use crate::arch::{PciArch, TraitPciArch};
1212
use crate::include::bindings::bindings::{
1313
c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL,
1414
};
1515
use crate::libs::volatile::{
16-
volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
16+
volread, volwrite, Volatile, VolatileReadable, VolatileWritable,
1717
};
18-
use crate::{kdebug, kerror, kinfo, kwarn};
18+
1919
/// MSIX表的一项
2020
#[repr(C)]
2121
struct MsixEntry {
@@ -268,7 +268,7 @@ pub trait PciInterrupt: PciDeviceStructure {
268268
return Err(PciError::PciIrqError(PciIrqError::PciDeviceNotSupportIrq));
269269
}
270270
/// @brief 获取指定数量的中断号 todo 需要中断重构支持
271-
fn irq_alloc(num: u16) -> Option<Vec<u16>> {
271+
fn irq_alloc(_num: u16) -> Option<Vec<u16>> {
272272
None
273273
}
274274
/// @brief 进行PCI设备中断的安装

kernel/src/driver/virtio/transport_pci.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::driver::pci::pci::{
55
PciStandardDeviceBar, PCI_CAP_ID_VNDR,
66
};
77

8-
use crate::kdebug;
8+
99
use crate::libs::volatile::{
1010
volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
1111
};

kernel/src/driver/virtio/virtio_impl.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
use crate::arch::mm::kernel_page_flags;
2-
/// 为virtio-drivers库提供的操作系统接口
3-
use crate::include::bindings::bindings::{
4-
memory_management_struct, Page, PAGE_2M_SHIFT, PAGE_2M_SIZE, PAGE_OFFSET, PAGE_SHARED,
5-
ZONE_NORMAL,
6-
};
2+
73

84
use crate::arch::MMArch;
9-
use crate::kdebug;
5+
106
use crate::mm::kernel_mapper::KernelMapper;
117
use crate::mm::page::PageFlags;
128
use crate::mm::{

0 commit comments

Comments
 (0)