mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-24 21:33:27 +00:00
新的内存管理模块 (#301)
  实现了具有优秀架构设计的新的内存管理模块,对内核空间和用户空间的内存映射、分配、释放、管理等操作进行了封装,使得内核开发者可以更加方便地进行内存管理。   内存管理模块主要由以下类型的组件组成: - **硬件抽象层(MemoryManagementArch)** - 提供对具体处理器架构的抽象,使得内存管理模块可以在不同的处理器架构上运行 - **页面映射器(PageMapper)**- 提供对虚拟地址和物理地址的映射,以及页表的创建、填写、销毁、权限管理等操作。分为两种类型:内核页表映射器(KernelMapper)和用户页表映射器(位于具体的用户地址空间结构中) - **页面刷新器(PageFlusher)** - 提供对页表的刷新操作(整表刷新、单页刷新、跨核心刷新) - **页帧分配器(FrameAllocator)** - 提供对页帧的分配、释放、管理等操作。具体来说,包括BumpAllocator、BuddyAllocator - **小对象分配器** - 提供对小内存对象的分配、释放、管理等操作。指的是内核里面的SlabAllocator (SlabAllocator的实现目前还没有完成) - **MMIO空间管理器** - 提供对MMIO地址空间的分配、管理操作。(目前这个模块待进一步重构) - **用户地址空间管理机制** - 提供对用户地址空间的管理。 - VMA机制 - 提供对用户地址空间的管理,包括VMA的创建、销毁、权限管理等操作 - 用户映射管理 - 与VMA机制共同作用,管理用户地址空间的映射 - **系统调用层** - 提供对用户空间的内存管理系统调用,包括mmap、munmap、mprotect、mremap等 - **C接口兼容层** - 提供对原有的C代码的接口,是的C代码能够正常运行。 除上面的新增内容以外,其它的更改内容: - 新增二进制加载器,以及elf的解析器 - 解决由于local_irq_save、local_irq_restore函数的汇编不规范导致影响栈行为的bug。 - 解决local_irq_save未关中断的错误。 - 修复sys_gettimeofday对timezone参数的处理的bug
This commit is contained in:
13
kernel/src/smp/c_adapter.rs
Normal file
13
kernel/src/smp/c_adapter.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use super::kick_cpu;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_kick_cpu(cpu_id: usize) -> usize {
|
||||
return kick_cpu(cpu_id)
|
||||
.map(|_| 0usize)
|
||||
.unwrap_or_else(|e| e.to_posix_errno() as usize);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn rs_smp_init_idle() {
|
||||
crate::smp::init_smp_idle_process();
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
use crate::{
|
||||
arch::interrupt::ipi::send_ipi,
|
||||
arch::{asm::current::current_pcb, interrupt::ipi::send_ipi},
|
||||
exception::ipi::{IpiKind, IpiTarget},
|
||||
mm::INITIAL_PROCESS_ADDRESS_SPACE,
|
||||
syscall::SystemError,
|
||||
};
|
||||
|
||||
pub mod c_adapter;
|
||||
pub mod core;
|
||||
|
||||
pub fn kick_cpu(cpu_id: usize) -> Result<(), SystemError> {
|
||||
@ -13,9 +15,7 @@ pub fn kick_cpu(cpu_id: usize) -> Result<(), SystemError> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn rs_kick_cpu(cpu_id: usize) -> usize {
|
||||
return kick_cpu(cpu_id)
|
||||
.map(|_| 0usize)
|
||||
.unwrap_or_else(|e| e.to_posix_errno() as usize);
|
||||
/// 初始化AP核的idle进程
|
||||
pub unsafe fn init_smp_idle_process() {
|
||||
current_pcb().set_address_space(INITIAL_PROCESS_ADDRESS_SPACE());
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "ipi.h"
|
||||
|
||||
static void __smp_kick_cpu_handler(uint64_t irq_num, uint64_t param, struct pt_regs *regs);
|
||||
static void __smp__flush_tlb_ipi_handler(uint64_t irq_num, uint64_t param, struct pt_regs *regs);
|
||||
|
||||
static spinlock_t multi_core_starting_lock = {1}; // 多核启动锁
|
||||
|
||||
@ -22,13 +23,22 @@ static uint32_t total_processor_num = 0;
|
||||
static int current_starting_cpu = 0;
|
||||
|
||||
static int num_cpu_started = 1;
|
||||
extern void rs_smp_init_idle();
|
||||
|
||||
// 在head.S中定义的,APU启动时,要加载的页表
|
||||
// 由于内存管理模块初始化的时候,重置了页表,因此我们要把当前的页表传给APU
|
||||
extern uint64_t __APU_START_CR3;
|
||||
|
||||
// kick cpu 功能所使用的中断向量号
|
||||
#define KICK_CPU_IRQ_NUM 0xc8
|
||||
#define FLUSH_TLB_IRQ_NUM 0xc9
|
||||
|
||||
void smp_init()
|
||||
{
|
||||
spin_init(&multi_core_starting_lock); // 初始化多核启动锁
|
||||
// 设置多核启动时,要加载的页表
|
||||
__APU_START_CR3 = (uint64_t)get_CR3();
|
||||
|
||||
ul tmp_vaddr[MAX_SUPPORTED_PROCESSOR_NUM] = {0};
|
||||
|
||||
apic_get_ics(ACPI_ICS_TYPE_PROCESSOR_LOCAL_APIC, tmp_vaddr, &total_processor_num);
|
||||
@ -57,6 +67,7 @@ void smp_init()
|
||||
kdebug("total_processor_num=%d", total_processor_num);
|
||||
// 注册接收kick_cpu功能的处理函数。(向量号200)
|
||||
ipi_regiserIPI(KICK_CPU_IRQ_NUM, NULL, &__smp_kick_cpu_handler, NULL, NULL, "IPI kick cpu");
|
||||
ipi_regiserIPI(FLUSH_TLB_IRQ_NUM, NULL, &__smp__flush_tlb_ipi_handler, NULL, NULL, "IPI flush tlb");
|
||||
|
||||
int core_to_start = 0;
|
||||
// total_processor_num = 3;
|
||||
@ -104,7 +115,7 @@ void smp_init()
|
||||
cpu_core_info[current_starting_cpu].tss_vaddr = (uint64_t)&initial_tss[current_starting_cpu];
|
||||
|
||||
memset(&initial_tss[current_starting_cpu], 0, sizeof(struct tss_struct));
|
||||
|
||||
// kdebug("core %d, set tss", current_starting_cpu);
|
||||
set_tss_descriptor(10 + (current_starting_cpu * 2), (void *)(cpu_core_info[current_starting_cpu].tss_vaddr));
|
||||
io_mfence();
|
||||
set_tss64(
|
||||
@ -116,12 +127,14 @@ void smp_init()
|
||||
cpu_core_info[current_starting_cpu].ist_stack_start);
|
||||
io_mfence();
|
||||
|
||||
// kdebug("core %d, to send start up", current_starting_cpu);
|
||||
// 连续发送两次start-up IPI
|
||||
ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand,
|
||||
proc_local_apic_structs[i]->local_apic_id);
|
||||
io_mfence();
|
||||
ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand,
|
||||
proc_local_apic_structs[i]->local_apic_id);
|
||||
// kdebug("core %d, send start up ok", current_starting_cpu);
|
||||
}
|
||||
io_mfence();
|
||||
while (num_cpu_started != (core_to_start + 1))
|
||||
@ -130,12 +143,7 @@ void smp_init()
|
||||
kinfo("Cleaning page table remapping...\n");
|
||||
|
||||
// 由于ap处理器初始化过程需要用到0x00处的地址,因此初始化完毕后才取消内存地址的重映射
|
||||
uint64_t *global_CR3 = get_CR3();
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
*(ul *)(phys_2_virt(global_CR3) + i) = 0UL;
|
||||
}
|
||||
rs_unmap_at_low_addr();
|
||||
kdebug("init proc's preempt_count=%ld", current_pcb->preempt_count);
|
||||
kinfo("Successfully cleaned page table remapping!\n");
|
||||
}
|
||||
@ -149,8 +157,10 @@ void smp_ap_start()
|
||||
|
||||
// 切换栈基地址
|
||||
// uint64_t stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE;
|
||||
__asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) : "memory");
|
||||
__asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start) : "memory");
|
||||
__asm__ __volatile__("movq %0, %%rbp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start)
|
||||
: "memory");
|
||||
__asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(cpu_core_info[current_starting_cpu].stack_start)
|
||||
: "memory");
|
||||
|
||||
ksuccess("AP core %d successfully started!", current_starting_cpu);
|
||||
io_mfence();
|
||||
@ -164,7 +174,8 @@ void smp_ap_start()
|
||||
barrier();
|
||||
current_pcb->state = PROC_RUNNING;
|
||||
current_pcb->flags = PF_KTHREAD;
|
||||
current_pcb->mm = &initial_mm;
|
||||
current_pcb->address_space = NULL;
|
||||
rs_smp_init_idle();
|
||||
|
||||
list_init(¤t_pcb->list);
|
||||
current_pcb->addr_limit = KERNEL_BASE_LINEAR_ADDR;
|
||||
@ -190,8 +201,9 @@ void smp_ap_start()
|
||||
preempt_disable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,需要手动恢复preempt count
|
||||
io_mfence();
|
||||
current_pcb->flags |= PF_NEED_SCHED;
|
||||
sti();
|
||||
|
||||
apic_timer_ap_core_init();
|
||||
sti();
|
||||
sched();
|
||||
|
||||
while (1)
|
||||
@ -222,6 +234,12 @@ static void __smp_kick_cpu_handler(uint64_t irq_num, uint64_t param, struct pt_r
|
||||
sched();
|
||||
}
|
||||
|
||||
static void __smp__flush_tlb_ipi_handler(uint64_t irq_num, uint64_t param, struct pt_regs *regs)
|
||||
{
|
||||
if (user_mode(regs))
|
||||
return;
|
||||
flush_tlb();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前全部的cpu数目
|
||||
|
Reference in New Issue
Block a user