Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions kernel/src/driver/interrupt/apic/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#pragma GCC push_options
#pragma GCC optimize("O0")
// 导出定义在irq.c中的中段门表
extern void (*interrupt_table[25])(void);
extern void (*interrupt_table[26])(void);
extern uint32_t rs_current_pcb_preempt_count();
extern uint32_t rs_current_pcb_pid();
extern uint32_t rs_current_pcb_flags();
Expand Down Expand Up @@ -362,7 +362,7 @@ int apic_init()
cli();
kinfo("Initializing APIC...");
// 初始化中断门, 中断使用rsp0防止在软中断时发生嵌套,然后处理器重新加载导致数据被抹掉
for (int i = 32; i <= 56; ++i)
for (int i = 32; i <= 57; ++i)
set_intr_gate(i, 0, interrupt_table[i - 32]);

// 设置local apic中断门
Expand Down Expand Up @@ -416,7 +416,7 @@ void do_IRQ(struct pt_regs *rsp, ul number)
{
// ==========外部中断控制器========
irq_desc_t *irq = &interrupt_desc[number - 32];

// 执行中断上半部处理程序
if (irq != NULL && irq->handler != NULL)
irq->handler(number, irq->parameter, rsp);
Expand Down
63 changes: 63 additions & 0 deletions kernel/src/driver/net/dma.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use crate::arch::mm::kernel_page_flags;

use crate::arch::MMArch;

use crate::mm::kernel_mapper::KernelMapper;
use crate::mm::page::PageFlags;
use crate::mm::{
allocator::page_frame::{
allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
},
MemoryManagementArch, PhysAddr, VirtAddr,
};
use core::ptr::NonNull;
const PAGE_SIZE: usize = 4096;
/// @brief 申请用于DMA的内存页
/// @param pages 页数(4k一页)
/// @return PhysAddr 获得的内存页的初始物理地址
pub fn dma_alloc(pages: usize) -> (usize, NonNull<u8>) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里的代码下一个pr可以把它整合到mm模块里面去。并且加上守卫来保护。目前这样的写法容易造成内存泄露、越界。

let page_num = PageFrameCount::new(
((pages * PAGE_SIZE + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE).next_power_of_two(),
);
unsafe {
let (paddr, count) = allocate_page_frames(page_num).expect("e1000e: alloc page failed");
let virt = MMArch::phys_2_virt(paddr).unwrap();
// 清空这块区域,防止出现脏数据
core::ptr::write_bytes(virt.data() as *mut u8, 0, count.data() * MMArch::PAGE_SIZE);

let dma_flags: PageFlags<MMArch> = PageFlags::mmio_flags();

let mut kernel_mapper = KernelMapper::lock();
let kernel_mapper = kernel_mapper.as_mut().unwrap();
let flusher = kernel_mapper
.remap(virt, dma_flags)
.expect("e1000e: remap failed");
flusher.flush();
return (
paddr.data(),
NonNull::new(MMArch::phys_2_virt(paddr).unwrap().data() as _).unwrap(),
);
}
}
/// @brief 释放用于DMA的内存页
/// @param paddr 起始物理地址 pages 页数(4k一页)
/// @return i32 0表示成功
pub unsafe fn dma_dealloc(paddr: usize, vaddr: NonNull<u8>, pages: usize) -> i32 {
let page_count = PageFrameCount::new(
((pages * PAGE_SIZE + MMArch::PAGE_SIZE - 1) / MMArch::PAGE_SIZE).next_power_of_two(),
);

// 恢复页面属性
let vaddr = VirtAddr::new(vaddr.as_ptr() as *mut u8 as usize);
let mut kernel_mapper = KernelMapper::lock();
let kernel_mapper = kernel_mapper.as_mut().unwrap();
let flusher = kernel_mapper
.remap(vaddr, kernel_page_flags(vaddr))
.expect("e1000e: remap failed");
flusher.flush();

unsafe {
deallocate_page_frames(PhysPageFrame::new(PhysAddr::new(paddr)), page_count);
}
return 0;
}
Loading