新的内存管理模块 (#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:
LoGin
2023-07-22 16:22:17 +08:00
committed by GitHub
parent 0663027b11
commit d8ad0a5e77
124 changed files with 8277 additions and 5150 deletions

View 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();
}

View File

@ -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());
}

View File

@ -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(&current_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数目