Merge branch 'usb'

This commit is contained in:
fslongjin 2022-07-18 16:07:47 +08:00
commit e4322ebfea
10 changed files with 386 additions and 113 deletions

View File

@ -3,22 +3,22 @@
* @author longjin * @author longjin
* @brief * @brief
* @date 2022-01-28 * @date 2022-01-28
* *
* @copyright Copyright (c) 2022 longjin * @copyright Copyright (c) 2022 longjin
* *
*/ */
#pragma once #pragma once
#include "printk.h" #include "printk.h"
#define ksuccess(...) \ #define ksuccess(...) \
do \ do \
{ \ { \
printk("[ "); \ printk("[ "); \
printk_color(GREEN, BLACK, "SUCCESS"); \ printk_color(GREEN, BLACK, "SUCCESS"); \
printk(" ] "); \ printk(" ] "); \
printk(__VA_ARGS__); \ printk(__VA_ARGS__); \
printk("\n"); \ printk("\n"); \
} while (0); } while (0);
#define kinfo(...) \ #define kinfo(...) \
@ -29,22 +29,22 @@
printk("\n"); \ printk("\n"); \
} while (0); } while (0);
#define kdebug(...) \ #define kdebug(...) \
do \ do \
{ \ { \
printk("[ DEBUG ] (%s:%d)\t", __FILE__, __LINE__); \ printk("[ DEBUG ] (%s:%d)\t", __FILE__, __LINE__); \
printk(__VA_ARGS__); \ printk(__VA_ARGS__); \
printk("\n"); \ printk("\n"); \
} while (0); } while (0);
#define kwarn(...) \ #define kwarn(...) \
do \ do \
{ \ { \
printk("[ "); \ printk("[ "); \
printk_color(YELLOW, BLACK, "WARN"); \ printk_color(YELLOW, BLACK, "WARN"); \
printk(" ] "); \ printk(" ] "); \
printk(__VA_ARGS__); \ printk(__VA_ARGS__); \
printk("\n"); \ printk("\n"); \
} while (0); } while (0);
#define kerror(...) \ #define kerror(...) \
@ -58,21 +58,21 @@
} while (0); } while (0);
#define kterminated(...) \ #define kterminated(...) \
do \ do \
{ \ { \
printk("[ "); \ printk("[ "); \
printk_color(RED, BLACK, "TERMINATED"); \ printk_color(RED, BLACK, "TERMINATED"); \
printk(" ] "); \ printk(" ] "); \
printk(__VA_ARGS__); \ printk(__VA_ARGS__); \
printk("\n"); \ printk("\n"); \
} while (0); } while (0);
#define kBUG(...) \ #define kBUG(...) \
do \ do \
{ \ { \
printk("[ "); \ printk("[ "); \
printk_color(RED, BLACK, "BUG"); \ printk_color(RED, BLACK, "BUG"); \
printk(" ] (%s:%d)\t", __FILE__, __LINE__); \ printk(" ] (%s:%d)\t", __FILE__, __LINE__); \
printk(__VA_ARGS__); \ printk(__VA_ARGS__); \
printk("\n"); \ printk("\n"); \
} while (0); } while (0);

View File

@ -41,7 +41,7 @@ void acpi_iter_SDT(bool (*_fun)(const struct acpi_system_description_table_heade
ul *ent = &(xsdt->Entry); ul *ent = &(xsdt->Entry);
for (int i = 0; i < acpi_XSDT_Entry_num; ++i) for (int i = 0; i < acpi_XSDT_Entry_num; ++i)
{ {
mm_map_phys_addr(ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * i, (*(ent + i)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * i, (*(ent + i)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
sdt_header = (struct acpi_system_description_table_header_t *)((ul)(ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * i)); sdt_header = (struct acpi_system_description_table_header_t *)((ul)(ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * i));
if (_fun(sdt_header, _data) == true) if (_fun(sdt_header, _data) == true)
@ -134,7 +134,7 @@ void acpi_init()
acpi_use_xsdt = true; acpi_use_xsdt = true;
ul xsdt_phys_base = rsdpv2->XsdtAddress & PAGE_2M_MASK; ul xsdt_phys_base = rsdpv2->XsdtAddress & PAGE_2M_MASK;
acpi_XSDT_offset = rsdpv2->XsdtAddress - xsdt_phys_base; acpi_XSDT_offset = rsdpv2->XsdtAddress - xsdt_phys_base;
mm_map_phys_addr(ACPI_XSDT_VIRT_ADDR_BASE, xsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_XSDT_VIRT_ADDR_BASE, xsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
kdebug("XSDT mapped!"); kdebug("XSDT mapped!");
xsdt = (struct acpi_XSDT_Structure_t *)(ACPI_XSDT_VIRT_ADDR_BASE + acpi_XSDT_offset); xsdt = (struct acpi_XSDT_Structure_t *)(ACPI_XSDT_VIRT_ADDR_BASE + acpi_XSDT_offset);
@ -146,20 +146,20 @@ void acpi_init()
printk_color(ORANGE, BLACK, "XSDT Length=%dbytes.\n", xsdt->header.Length); printk_color(ORANGE, BLACK, "XSDT Length=%dbytes.\n", xsdt->header.Length);
printk_color(ORANGE, BLACK, "XSDT Entry num=%d\n", acpi_XSDT_Entry_num); printk_color(ORANGE, BLACK, "XSDT Entry num=%d\n", acpi_XSDT_Entry_num);
mm_map_phys_addr(ACPI_XSDT_VIRT_ADDR_BASE, xsdt_phys_base, xsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_XSDT_VIRT_ADDR_BASE, xsdt_phys_base, xsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
// 映射所有的Entry的物理地址 // 映射所有的Entry的物理地址
ul *ent = &(xsdt->Entry); ul *ent = &(xsdt->Entry);
for (int j = 0; j < acpi_XSDT_Entry_num; ++j) for (int j = 0; j < acpi_XSDT_Entry_num; ++j)
{ {
kdebug("entry=%#018lx, virt=%#018lx", (*(ent + j)) & PAGE_2M_MASK, ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * j); kdebug("entry=%#018lx, virt=%#018lx", (*(ent + j)) & PAGE_2M_MASK, ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * j);
// 映射RSDT ENTRY的物理地址 // 映射RSDT ENTRY的物理地址
mm_map_phys_addr(ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * j, (*(ent + j)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_XSDT_DESCRIPTION_HEDERS_BASE + PAGE_2M_SIZE * j, (*(ent + j)) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
} }
*/ */
// 由于解析XSDT出现问题。暂时只使用Rsdpv2的rsdt但是这是不符合ACPI规范的 // 由于解析XSDT出现问题。暂时只使用Rsdpv2的rsdt但是这是不符合ACPI规范的
ul rsdt_phys_base = rsdpv2->rsdp1.RsdtAddress & PAGE_2M_MASK; ul rsdt_phys_base = rsdpv2->rsdp1.RsdtAddress & PAGE_2M_MASK;
acpi_RSDT_offset = rsdpv2->rsdp1.RsdtAddress - rsdt_phys_base; acpi_RSDT_offset = rsdpv2->rsdp1.RsdtAddress - rsdt_phys_base;
mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
kdebug("RSDT mapped!(v2)"); kdebug("RSDT mapped!(v2)");
rsdt = (struct acpi_RSDT_Structure_t *)(ACPI_RSDT_VIRT_ADDR_BASE + acpi_RSDT_offset); rsdt = (struct acpi_RSDT_Structure_t *)(ACPI_RSDT_VIRT_ADDR_BASE + acpi_RSDT_offset);
// 计算RSDT Entry的数量 // 计算RSDT Entry的数量
@ -169,7 +169,7 @@ void acpi_init()
printk_color(ORANGE, BLACK, "RSDT Length=%dbytes.\n", rsdt->header.Length); printk_color(ORANGE, BLACK, "RSDT Length=%dbytes.\n", rsdt->header.Length);
printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num); printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, rsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, rsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
// 映射所有的Entry的物理地址 // 映射所有的Entry的物理地址
acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK; acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;
// 由于地址只是32bit的并且存在脏数据这里需要手动清除高32bit否则会触发#GP // 由于地址只是32bit的并且存在脏数据这里需要手动清除高32bit否则会触发#GP
@ -178,7 +178,7 @@ void acpi_init()
kdebug("entry=%#018lx", rsdt->Entry); kdebug("entry=%#018lx", rsdt->Entry);
kdebug("acpi_RSDT_entry_phys_base=%#018lx", acpi_RSDT_entry_phys_base); kdebug("acpi_RSDT_entry_phys_base=%#018lx", acpi_RSDT_entry_phys_base);
// 映射RSDT ENTRY的物理地址 // 映射RSDT ENTRY的物理地址
mm_map_phys_addr(ACPI_DESCRIPTION_HEDERS_BASE, acpi_RSDT_entry_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_DESCRIPTION_HEDERS_BASE, acpi_RSDT_entry_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
} }
else if (rsdpv1->RsdtAddress != (uint)0x00UL) else if (rsdpv1->RsdtAddress != (uint)0x00UL)
{ // 映射RSDT的物理地址到页表 { // 映射RSDT的物理地址到页表
@ -186,7 +186,7 @@ void acpi_init()
// 由于页表映射的原因需要清除低21位地址才能填入页表 // 由于页表映射的原因需要清除低21位地址才能填入页表
ul rsdt_phys_base = rsdpv1->RsdtAddress & PAGE_2M_MASK; ul rsdt_phys_base = rsdpv1->RsdtAddress & PAGE_2M_MASK;
acpi_RSDT_offset = rsdpv1->RsdtAddress - rsdt_phys_base; acpi_RSDT_offset = rsdpv1->RsdtAddress - rsdt_phys_base;
mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
kdebug("RSDT mapped!"); kdebug("RSDT mapped!");
rsdt = (struct acpi_RSDT_Structure_t *)(ACPI_RSDT_VIRT_ADDR_BASE + acpi_RSDT_offset); rsdt = (struct acpi_RSDT_Structure_t *)(ACPI_RSDT_VIRT_ADDR_BASE + acpi_RSDT_offset);
// 计算RSDT Entry的数量 // 计算RSDT Entry的数量
@ -196,7 +196,7 @@ void acpi_init()
printk_color(ORANGE, BLACK, "RSDT Length=%dbytes.\n", rsdt->header.Length); printk_color(ORANGE, BLACK, "RSDT Length=%dbytes.\n", rsdt->header.Length);
printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num); printk_color(ORANGE, BLACK, "RSDT Entry num=%d\n", acpi_RSDT_Entry_num);
mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, rsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_RSDT_VIRT_ADDR_BASE, rsdt_phys_base, rsdt->header.Length + PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
// 映射所有的Entry的物理地址 // 映射所有的Entry的物理地址
acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK; acpi_RSDT_entry_phys_base = ((ul)(rsdt->Entry)) & PAGE_2M_MASK;
// 由于地址只是32bit的并且存在脏数据这里需要手动清除高32bit否则会触发#GP // 由于地址只是32bit的并且存在脏数据这里需要手动清除高32bit否则会触发#GP
@ -205,7 +205,7 @@ void acpi_init()
kdebug("entry=%#018lx", rsdt->Entry); kdebug("entry=%#018lx", rsdt->Entry);
kdebug("acpi_RSDT_entry_phys_base=%#018lx", acpi_RSDT_entry_phys_base); kdebug("acpi_RSDT_entry_phys_base=%#018lx", acpi_RSDT_entry_phys_base);
// 映射RSDT ENTRY的物理地址 // 映射RSDT ENTRY的物理地址
mm_map_phys_addr(ACPI_DESCRIPTION_HEDERS_BASE, acpi_RSDT_entry_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(ACPI_DESCRIPTION_HEDERS_BASE, acpi_RSDT_entry_phys_base, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
} }
else else
{ {

View File

@ -43,7 +43,7 @@ void ahci_init()
kdebug("((struct pci_device_structure_general_device_t *)phys_2_virt(ahci_devs[0])))->BAR5= %#018lx", ((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5); kdebug("((struct pci_device_structure_general_device_t *)phys_2_virt(ahci_devs[0])))->BAR5= %#018lx", ((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5);
uint32_t bar5 = ((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5; uint32_t bar5 = ((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5;
mm_map_phys_addr(AHCI_MAPPING_BASE, (ul)(bar5)&PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(AHCI_MAPPING_BASE, (ul)(bar5)&PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
kdebug("ABAR mapped!"); kdebug("ABAR mapped!");
for (int i = 0; i < count_ahci_devices; ++i) for (int i = 0; i < count_ahci_devices; ++i)
{ {

View File

@ -69,7 +69,7 @@ void apic_io_apic_init()
// kdebug("(ul)apic_ioapic_map.virtual_index_addr=%#018lx", (ul)apic_ioapic_map.virtual_index_addr); // kdebug("(ul)apic_ioapic_map.virtual_index_addr=%#018lx", (ul)apic_ioapic_map.virtual_index_addr);
// 填写页表,完成地址映射 // 填写页表,完成地址映射
mm_map_phys_addr((ul)apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr((ul)apic_ioapic_map.virtual_index_addr, apic_ioapic_map.addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
// 设置IO APIC ID 为0x0f000000 // 设置IO APIC ID 为0x0f000000
*apic_ioapic_map.virtual_index_addr = 0x00; *apic_ioapic_map.virtual_index_addr = 0x00;
@ -198,7 +198,7 @@ void apic_init_ap_core_local_apic()
void apic_local_apic_init() void apic_local_apic_init()
{ {
// 映射Local APIC 寄存器地址 // 映射Local APIC 寄存器地址
mm_map_phys_addr(APIC_LOCAL_APIC_VIRT_BASE_ADDR, 0xfee00000UL, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD); mm_map_phys_addr(APIC_LOCAL_APIC_VIRT_BASE_ADDR, 0xfee00000UL, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
uint a, b, c, d; uint a, b, c, d;
cpu_cpuid(1, 0, &a, &b, &c, &d); cpu_cpuid(1, 0, &a, &b, &c, &d);

View File

@ -2,12 +2,14 @@
#include <common/kprint.h> #include <common/kprint.h>
#include <debug/bug.h> #include <debug/bug.h>
#include <process/spinlock.h> #include <process/spinlock.h>
#include <mm/mm.h>
#include <debug/traceback/traceback.h>
spinlock_t xhci_controller_init_lock; // xhci控制器初始化锁(在usb_init中被初始化) spinlock_t xhci_controller_init_lock; // xhci控制器初始化锁(在usb_init中被初始化)
static int xhci_ctrl_count = 0; // xhci控制器计数 static int xhci_ctrl_count = 0; // xhci控制器计数
static struct xhci_host_controller_t xhci_hc[MAX_XHCI_HOST_CONTROLLERS] = {0};
/** /**
* @brief xhci控制器 * @brief xhci控制器
@ -17,12 +19,41 @@ static int xhci_ctrl_count = 0; // xhci控制器计数
void xhci_init(struct pci_device_structure_general_device_t *dev_hdr) void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
{ {
spin_lock(&xhci_controller_init_lock); spin_lock(&xhci_controller_init_lock);
kinfo("Initializing xhci host controller: bus=%#02x, device=%#02x, func=%#02x, VendorID=%#04x, irq_line=%d, irq_pin=%d", dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, dev_hdr->header.Vendor_ID, dev_hdr->Interrupt_Line, dev_hdr->Interrupt_PIN ); kinfo("Initializing xhci host controller: bus=%#02x, device=%#02x, func=%#02x, VendorID=%#04x, irq_line=%d, irq_pin=%d", dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, dev_hdr->header.Vendor_ID, dev_hdr->Interrupt_Line, dev_hdr->Interrupt_PIN);
xhci_hc[xhci_ctrl_count].controller_id = xhci_ctrl_count;
xhci_hc[xhci_ctrl_count].pci_dev_hdr = dev_hdr;
pci_write_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0x4, 0x0006); // mem I/O access enable and bus master enable pci_write_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0x4, 0x0006); // mem I/O access enable and bus master enable
// 为当前控制器映射寄存器地址空间
xhci_hc[xhci_ctrl_count].vbase = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + XHCI_MAPPING_OFFSET + PAGE_2M_SIZE * xhci_hc[xhci_ctrl_count].controller_id;
kdebug("dev_hdr->BAR0 & (~0xf)=%#018lx", dev_hdr->BAR0 & (~0xf));
mm_map_phys_addr(xhci_hc[xhci_ctrl_count].vbase, dev_hdr->BAR0 & (~0xf), 65536, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, true);
// 读取xhci控制寄存器
uint16_t iversion = *(uint16_t *)(xhci_hc[xhci_ctrl_count].vbase + XHCI_CAPS_HCIVERSION);
uint32_t dboff = *(uint16_t *)(xhci_hc[xhci_ctrl_count].vbase + XHCI_CAPS_DBOFF);
// kdebug("dboff=%ld", dboff);
// struct xhci_caps_HCSPARAMS1_reg_t hcs1 = *(struct xhci_caps_HCSPARAMS1_reg_t *)(xhci_hc[xhci_ctrl_count].vbase + XHCI_CAPS_HCSPARAMS1);
// kdebug("hcs1.max_ports=%d, hcs1.max_slots=%d, hcs1.max_intrs=%d", hcs1.max_ports, hcs1.max_slots, hcs1.max_intrs);
// kdebug("caps size=%d", *(uint8_t *)xhci_hc[xhci_ctrl_count].vbase);
// kdebug("iversion=%#06x", iversion);
if (iversion < 0x95)
{
kwarn("Unsupported/Unknowned xHCI controller version: %#06x. This may cause unexpected behavior.", iversion);
}
++xhci_ctrl_count; ++xhci_ctrl_count;
spin_unlock(&xhci_controller_init_lock); spin_unlock(&xhci_controller_init_lock);
return;
failed:;
// 取消地址映射
mm_unmap(xhci_hc[xhci_ctrl_count].vbase, 65536);
// 清空数组
memset((void *)&xhci_hc[xhci_ctrl_count], 0, sizeof(struct xhci_host_controller_t));
spin_unlock(&xhci_controller_init_lock);
} }

View File

@ -2,6 +2,8 @@
#include <driver/usb/usb.h> #include <driver/usb/usb.h>
#include <driver/pci/pci.h> #include <driver/pci/pci.h>
#define MAX_XHCI_HOST_CONTROLLERS 8
// xhci Capability Registers offset // xhci Capability Registers offset
#define XHCI_CAPS_CAPLENGTH 0x00 // Cap 寄存器组的长度 #define XHCI_CAPS_CAPLENGTH 0x00 // Cap 寄存器组的长度
#define XHCI_CAPS_RESERVED 0x01 #define XHCI_CAPS_RESERVED 0x01
@ -14,14 +16,63 @@
#define XHCI_CAPS_RTSOFF 0x18 // Runtime register space offset #define XHCI_CAPS_RTSOFF 0x18 // Runtime register space offset
#define XHCI_CAPS_HCCPARAMS2 0x1c // capability params 2 #define XHCI_CAPS_HCCPARAMS2 0x1c // capability params 2
struct xhci_caps_HCSPARAMS1_reg_t struct xhci_caps_HCSPARAMS1_reg_t
{ {
unsigned max_slots : 8; // 最大插槽数 unsigned max_slots : 8; // 最大插槽数
unsigned max_intrs : 11; // 最大中断数 unsigned max_intrs : 11; // 最大中断数
unsigned reserved : 5; unsigned reserved : 5;
unsigned max_ports : 8; // 最大端口数 unsigned max_ports : 8; // 最大端口数
}__attribute__((packed)); } __attribute__((packed));
struct xhci_caps_HCSPARAMS2_reg_t
{
unsigned ist : 4; // 同步调度阈值
unsigned ERST_Max : 4; // Event Ring Segment Table Max
unsigned Reserved : 13;
unsigned max_scratchpad_buf_HI5 : 5; // 草稿行buffer地址高5bit
unsigned spr : 1; // scratchpad restore
unsigned max_scratchpad_buf_LO5 : 5; // 草稿行buffer地址低5bit
} __attribute__((packed));
struct xhci_caps_HCSPARAMS3_reg_t
{
uint8_t u1_device_exit_latency; // 0~10ms
uint8_t Reserved;
uint16_t u2_device_exit_latency; // 0~2047ms
} __attribute__((packed));
struct xhci_caps_HCCPARAMS1_reg_t
{
unsigned ac64 : 1; // 64-bit addressing capability
unsigned bnc : 1; // bw negotiation capability
unsigned csz : 1; // context size
unsigned ppc : 1; // 端口电源控制
unsigned pind : 1; // port indicators
unsigned lhrc : 1; // Light HC reset capability
unsigned ltc : 1; // latency tolerance messaging capability
unsigned nss : 1; // no secondary SID support
unsigned pae : 1; // parse all event data
unsigned spc : 1; // Stopped - Short packet capability
unsigned sec : 1; // Stopped EDTLA capability
unsigned cfc : 1; // Continuous Frame ID capability
unsigned MaxPSASize : 4; // Max Primary Stream Array Size
uint16_t xECP; // xhci extended capabilities pointer
} __attribute__((packed));
struct xhci_caps_HCCPARAMS2_reg_t
{
unsigned u3c : 1; // U3 Entry Capability
unsigned cmc : 1; // ConfigEP command Max exit latency too large
unsigned fsc : 1; // Force Save Context Capability
unsigned ctc : 1; // Compliance Transition Capability
unsigned lec : 1; // large ESIT payload capability
unsigned cic : 1; // configuration information capability
unsigned Reserved : 26;
} __attribute__((packed));
/** /**
@ -36,11 +87,11 @@ struct xhci_port_info_t
uint8_t reserved; uint8_t reserved;
} __attribute__((packed)); } __attribute__((packed));
struct xhci_controller_t struct xhci_host_controller_t
{ {
struct pci_device_structure_general_device_t *pci_dev_hdr; // 指向pci header结构体的指针 struct pci_device_structure_general_device_t *pci_dev_hdr; // 指向pci header结构体的指针
int controller_id; // 操作系统给controller的编号 int controller_id; // 操作系统给controller的编号
int vbase; // 虚拟地址basebar0映射到的虚拟地址 uint64_t vbase; // 虚拟地址basebar0映射到的虚拟地址
struct xhci_port_info_t *ports; // 指向端口信息数组的指针 struct xhci_port_info_t *ports; // 指向端口信息数组的指针
}; };

View File

@ -50,7 +50,7 @@ void init_frame_buffer(bool level)
sc_info.height = info.framebuffer_height; sc_info.height = info.framebuffer_height;
sc_info.length = 1UL * sc_info.width * sc_info.height; sc_info.length = 1UL * sc_info.width * sc_info.height;
mm_map_proc_page_table(global_CR3, true, sc_info.fb_vaddr, sc_info.fb_paddr, get_VBE_FB_length() << 2, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false, true); mm_map_proc_page_table(global_CR3, true, sc_info.fb_vaddr, sc_info.fb_paddr, get_VBE_FB_length() << 2, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false, true, false);
set_pos_VBE_FB_addr((uint *)sc_info.fb_vaddr); set_pos_VBE_FB_addr((uint *)sc_info.fb_vaddr);
} }
else // 高级初始化,增加双缓冲区的支持 else // 高级初始化,增加双缓冲区的支持
@ -58,7 +58,7 @@ void init_frame_buffer(bool level)
// 申请双重缓冲区 // 申请双重缓冲区
struct Page *p = alloc_pages(ZONE_NORMAL, PAGE_2M_ALIGN(sc_info.length << 2) / PAGE_2M_SIZE, 0); struct Page *p = alloc_pages(ZONE_NORMAL, PAGE_2M_ALIGN(sc_info.length << 2) / PAGE_2M_SIZE, 0);
sc_info.double_fb_vaddr = (uint64_t)phys_2_virt(p->addr_phys); sc_info.double_fb_vaddr = (uint64_t)phys_2_virt(p->addr_phys);
mm_map_proc_page_table(global_CR3, true, sc_info.double_fb_vaddr, p->addr_phys, PAGE_2M_ALIGN(sc_info.length << 2), PAGE_KERNEL_PAGE, false, true); mm_map_proc_page_table(global_CR3, true, sc_info.double_fb_vaddr, p->addr_phys, PAGE_2M_ALIGN(sc_info.length << 2), PAGE_KERNEL_PAGE, false, true, false);
// 将原有的数据拷贝到double buffer里面 // 将原有的数据拷贝到double buffer里面
memcpy((void *)sc_info.double_fb_vaddr, (void *)sc_info.fb_vaddr, sc_info.length << 2); memcpy((void *)sc_info.double_fb_vaddr, (void *)sc_info.fb_vaddr, sc_info.length << 2);

View File

@ -4,9 +4,12 @@
#include <common/kprint.h> #include <common/kprint.h>
#include <driver/multiboot2/multiboot2.h> #include <driver/multiboot2/multiboot2.h>
#include <process/process.h> #include <process/process.h>
#include <common/compiler.h>
#include <common/errno.h>
#include <debug/traceback/traceback.h>
ul Total_Memory = 0; static ul Total_Memory = 0;
ul total_2M_pages = 0; static ul total_2M_pages = 0;
static ul root_page_table_phys_addr = 0; // 内核层根页表的物理地址 static ul root_page_table_phys_addr = 0; // 内核层根页表的物理地址
/** /**
@ -48,6 +51,23 @@ static void mm_calculate_entry_num(uint64_t length, mm_pgt_entry_num_t *ent)
*/ */
uint64_t mm_get_PDE(ul proc_page_table_addr, bool is_phys, ul virt_addr, bool clear); uint64_t mm_get_PDE(ul proc_page_table_addr, bool is_phys, ul virt_addr, bool clear);
/**
* @brief 0
*
* @param ptr
* @return int8_t -> 1
* -> 0
*/
int8_t mm_check_page_table(uint64_t *ptr)
{
for (int i = 0; i < 512; ++i, ++ptr)
{
if (*ptr != 0)
return 1;
}
return 0;
}
void mm_init() void mm_init()
{ {
kinfo("Initializing memory management unit..."); kinfo("Initializing memory management unit...");
@ -451,7 +471,7 @@ void free_pages(struct Page *page, int number)
/** /**
* @brief * @brief
* 0~4GB的物理页映射到线性地址空 * 线
*/ */
void page_table_init() void page_table_init()
{ {
@ -470,10 +490,7 @@ void page_table_init()
for (int j = 0; j < z->count_pages; ++j) for (int j = 0; j < z->count_pages; ++j)
{ {
// if (p->addr_phys) mm_map_proc_page_table((uint64_t)get_CR3(), true, (ul)phys_2_virt(p->addr_phys), p->addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE, false, true, false);
// kdebug("(ul)phys_2_virt(p->addr_phys)=%#018lx",(ul)phys_2_virt(p->addr_phys));
// mm_map_phys_addr((ul)phys_2_virt(p->addr_phys), p->addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE);
mm_map_proc_page_table((uint64_t)get_CR3(), true, (ul)phys_2_virt(p->addr_phys), p->addr_phys, PAGE_2M_SIZE, PAGE_KERNEL_PAGE, false, true);
++p; ++p;
++js; ++js;
@ -491,18 +508,20 @@ void page_table_init()
* @param virt_addr_start * @param virt_addr_start
* @param phys_addr_start * @param phys_addr_start
* @param length * @param length
* @param flags
* @param use4k 使4k页
*/ */
void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags) int mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool use4k)
{ {
uint64_t global_CR3 = (uint64_t)get_CR3(); uint64_t global_CR3 = (uint64_t)get_CR3();
mm_map_proc_page_table(global_CR3, true, virt_addr_start, phys_addr_start, length, flags, false, true); return mm_map_proc_page_table(global_CR3, true, virt_addr_start, phys_addr_start, length, flags, false, true, use4k);
} }
void mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags) int mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags)
{ {
uint64_t global_CR3 = (uint64_t)get_CR3(); uint64_t global_CR3 = (uint64_t)get_CR3();
mm_map_proc_page_table(global_CR3, true, virt_addr_start, phys_addr_start, length, flags, true, true); return mm_map_proc_page_table(global_CR3, true, virt_addr_start, phys_addr_start, length, flags, true, true, false);
} }
/** /**
@ -515,8 +534,9 @@ void mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul
* @param length * @param length
* @param user 访 * @param user 访
* @param flush tlb * @param flush tlb
* @param use4k 使4k页
*/ */
void mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user, bool flush) int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user, bool flush, bool use4k)
{ {
// 计算线性地址对应的pml4页表项的地址 // 计算线性地址对应的pml4页表项的地址
@ -579,22 +599,68 @@ void mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_
--pgt_num.num_PDE; --pgt_num.num_PDE;
// 计算当前2M物理页对应的pdt的页表项的物理地址 // 计算当前2M物理页对应的pdt的页表项的物理地址
ul *pde_ptr = pd_ptr + pde_id; ul *pde_ptr = pd_ptr + pde_id;
if (*pde_ptr != 0 && user)
// ====== 使用4k页 =======
if (unlikely(use4k))
{ {
// kwarn("page already mapped!"); // kdebug("use 4k");
// 如果是用户态可访问的页,则释放当前新获取的物理页 if (*pde_ptr == 0)
free_pages(Phy_to_2M_Page((ul)phys_addr_start + length_mapped), 1); {
length_mapped += PAGE_2M_SIZE; // 创建四级页表
continue; // kdebug("create PT");
uint64_t *vaddr = kmalloc(PAGE_4K_SIZE, 0);
memset(vaddr, 0, PAGE_4K_SIZE);
set_pdt(pde_ptr, mk_pdt(virt_2_phys(vaddr), (user ? PAGE_USER_PDE : PAGE_KERNEL_PDE)));
}
else if (unlikely(*pde_ptr & (1 << 7)))
{
// 当前页表项已经被映射了2MB物理页
goto failed;
}
uint64_t pte_id = (((virt_addr_start + length_mapped) >> PAGE_4K_SHIFT) & 0x1ff);
uint64_t *pt_ptr = (uint64_t *)phys_2_virt(*pde_ptr & (~0x1fffUL));
// 循环填写4级页表初始化4K页
for (; pgt_num.num_PTE > 0 && pte_id < 512; ++pte_id)
{
--pgt_num.num_PTE;
uint64_t *pte_ptr = pt_ptr + pte_id;
if (unlikely(*pte_ptr != 0))
{
kwarn("pte already exists.");
length_mapped += PAGE_4K_SIZE;
}
set_pt(pte_ptr, mk_pt((ul)phys_addr_start + length_mapped, flags | (user ? PAGE_USER_4K_PAGE : PAGE_KERNEL_4K_PAGE)));
}
}
// ======= 使用2M页 ========
else
{
if (unlikely(*pde_ptr != 0 && user))
{
kwarn("page already mapped!");
// 如果是用户态可访问的页,则释放当前新获取的物理页
if (likely(((ul)phys_addr_start + length_mapped) < total_2M_pages)) // 校验是否为内存中的物理页
free_pages(Phy_to_2M_Page((ul)phys_addr_start + length_mapped), 1);
length_mapped += PAGE_2M_SIZE;
continue;
}
// 页面写穿,禁止缓存
set_pdt(pde_ptr, mk_pdt((ul)phys_addr_start + length_mapped, flags | (user ? PAGE_USER_PAGE : PAGE_KERNEL_PAGE)));
length_mapped += PAGE_2M_SIZE;
} }
// 页面写穿,禁止缓存
set_pdt(pde_ptr, mk_pdt((ul)phys_addr_start + length_mapped, flags | (user ? PAGE_USER_PAGE : PAGE_KERNEL_PAGE)));
length_mapped += PAGE_2M_SIZE;
} }
} }
} }
if (flush) if (likely(flush))
flush_tlb(); flush_tlb();
return 0;
failed:;
kerror("Map memory failed. use4k=%d, vaddr=%#018lx, paddr=%#018lx", use4k, virt_addr_start, phys_addr_start);
return -EFAULT;
} }
/** /**
@ -701,11 +767,41 @@ void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_sta
// 计算当前2M物理页对应的pdt的页表项的物理地址 // 计算当前2M物理页对应的pdt的页表项的物理地址
ul *pde_ptr = pd_ptr + pde_id; ul *pde_ptr = pd_ptr + pde_id;
*pde_ptr = 0; // 存在4级页表
if (unlikely(((*pde_ptr) & (1 << 7)) == 0))
{
// 存在4K页
uint64_t pte_id = (((virt_addr_start + length_unmapped) >> PAGE_4K_SHIFT) & 0x1ff);
uint64_t *pt_ptr = (uint64_t *)phys_2_virt(*pde_ptr & (~0x1fffUL));
uint64_t *pte_ptr = pt_ptr + pte_id;
length_unmapped += PAGE_2M_SIZE; // 循环处理4K页表
for (; pgt_num.num_PTE > 0 && pte_id < 512; ++pte_id, ++pte_ptr)
{
--pgt_num.num_PTE;
// todo: 当支持使用slab分配4K内存作为进程的4K页之后在这里需要释放这些4K对象
*pte_ptr = 0;
length_unmapped += PAGE_4K_SIZE;
}
// 4级页表已经空了释放页表
if (unlikely(mm_check_page_table(pt_ptr)) == 0)
kfree(pt_ptr);
}
else
{
*pde_ptr = 0;
length_unmapped += PAGE_2M_SIZE;
}
} }
// 3级页表已经空了释放页表
if (unlikely(mm_check_page_table(pd_ptr)) == 0)
kfree(pd_ptr);
} }
// 2级页表已经空了释放页表
if (unlikely(mm_check_page_table(pdpt_ptr)) == 0)
kfree(pdpt_ptr);
} }
flush_tlb(); flush_tlb();
} }
@ -793,8 +889,8 @@ uint64_t mm_do_brk(uint64_t old_brk_end_addr, int64_t offset)
{ {
for (uint64_t i = old_brk_end_addr; i < end_addr; i += PAGE_2M_SIZE) for (uint64_t i = old_brk_end_addr; i < end_addr; i += PAGE_2M_SIZE)
{ {
kdebug("map [%#018lx]", i); // kdebug("map [%#018lx]", i);
mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, i, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true); mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, i, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true, false);
} }
current_pcb->mm->brk_end = end_addr; current_pcb->mm->brk_end = end_addr;
} }
@ -850,9 +946,36 @@ bool mm_check_mapped(ul page_table_phys_addr, uint64_t virt_addr)
// 读取pdt页表项 // 读取pdt页表项
tmp = phys_2_virt(((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr) >> PAGE_2M_SHIFT) & 0x1ff))); tmp = phys_2_virt(((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr) >> PAGE_2M_SHIFT) & 0x1ff)));
// todo: 增加对使用了4K页的页表的检测 // pde页表项为0
if (*tmp != 0) if (*tmp == 0)
return 0;
if (*tmp & (1 << 7))
{
// 当前为2M物理页
return true; return true;
}
else else
return false; {
// 存在4级页表
tmp = phys_2_virt(((ul *)(*tmp & (~0xfffUL)) + (((ul)(virt_addr) >> PAGE_4K_SHIFT) & 0x1ff)));
if (*tmp != 0)
return true;
else
return false;
}
}
/**
* @brief 2M页()
*
* @param paddr
* @return int8_t -> 1
* -> 0
*/
int8_t mm_is_2M_page(uint64_t paddr)
{
if(likely((paddr >> PAGE_2M_SHIFT)<total_2M_pages))
return 1;
else return 0;
} }

View File

@ -77,6 +77,8 @@
// bit 12 Page Attribute Table // bit 12 Page Attribute Table
#define PAGE_PAT (1UL << 12) #define PAGE_PAT (1UL << 12)
// 对于PTE而言第7位是PAT
#define PAGE_4K_PAT (1UL << 7)
// bit 8 Global Page:1,global;0,part // bit 8 Global Page:1,global;0,part
#define PAGE_GLOBAL (1UL << 8) #define PAGE_GLOBAL (1UL << 8)
@ -111,17 +113,26 @@
// 1,0 // 1,0
#define PAGE_KERNEL_DIR (PAGE_R_W | PAGE_PRESENT) #define PAGE_KERNEL_DIR (PAGE_R_W | PAGE_PRESENT)
// 1,0 (4级页表在3级页表中的页表项的属性)
#define PAGE_KERNEL_PDE (PAGE_R_W | PAGE_PRESENT)
// 7,1,0 // 7,1,0
#define PAGE_KERNEL_PAGE (PAGE_PS | PAGE_R_W | PAGE_PRESENT) #define PAGE_KERNEL_PAGE (PAGE_PS | PAGE_R_W | PAGE_PRESENT)
#define PAGE_KERNEL_4K_PAGE (PAGE_R_W | PAGE_PRESENT)
#define PAGE_USER_PGT (PAGE_U_S | PAGE_R_W | PAGE_PRESENT) #define PAGE_USER_PGT (PAGE_U_S | PAGE_R_W | PAGE_PRESENT)
// 2,1,0 // 2,1,0
#define PAGE_USER_DIR (PAGE_U_S | PAGE_R_W | PAGE_PRESENT) #define PAGE_USER_DIR (PAGE_U_S | PAGE_R_W | PAGE_PRESENT)
// 1,0 (4级页表在3级页表中的页表项的属性)
#define PAGE_USER_PDE (PAGE_U_S | PAGE_R_W | PAGE_PRESENT)
// 7,2,1,0 // 7,2,1,0
#define PAGE_USER_PAGE (PAGE_PS | PAGE_U_S | PAGE_R_W | PAGE_PRESENT) #define PAGE_USER_PAGE (PAGE_PS | PAGE_U_S | PAGE_R_W | PAGE_PRESENT)
#define PAGE_USER_4K_PAGE (PAGE_U_S | PAGE_R_W | PAGE_PRESENT)
// ===== 错误码定义 ==== // ===== 错误码定义 ====
// 物理页结构体为空 // 物理页结构体为空
#define EPAGE_NULL 1 #define EPAGE_NULL 1
@ -172,7 +183,7 @@ struct memory_desc
ul kernel_code_start, kernel_code_end; // 内核程序代码段起始地址、结束地址 ul kernel_code_start, kernel_code_end; // 内核程序代码段起始地址、结束地址
ul kernel_data_end, rodata_end; // 内核程序数据段结束地址、 内核程序只读段结束地址 ul kernel_data_end, rodata_end; // 内核程序数据段结束地址、 内核程序只读段结束地址
uint64_t start_brk; // 堆地址的起始位置 uint64_t start_brk; // 堆地址的起始位置
ul end_of_struct; // 内存页管理结构的结束地址 ul end_of_struct; // 内存页管理结构的结束地址
}; };
@ -234,7 +245,6 @@ int ZONE_DMA_INDEX = 0;
int ZONE_NORMAL_INDEX = 0; // low 1GB RAM ,was mapped in pagetable int ZONE_NORMAL_INDEX = 0; // low 1GB RAM ,was mapped in pagetable
int ZONE_UNMAPPED_INDEX = 0; // above 1GB RAM,unmapped in pagetable int ZONE_UNMAPPED_INDEX = 0; // above 1GB RAM,unmapped in pagetable
// 初始化内存管理单元 // 初始化内存管理单元
void mm_init(); void mm_init();
@ -345,7 +355,7 @@ typedef struct
/** /**
* @brief * @brief
* 0~4GB的物理页映射到线性地址空 * 线
*/ */
void page_table_init(); void page_table_init();
@ -355,8 +365,10 @@ void page_table_init();
* @param virt_addr_start * @param virt_addr_start
* @param phys_addr_start * @param phys_addr_start
* @param length * @param length
* @param flags
* @param use4k 使4k页
*/ */
void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags); int mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool use4k);
/** /**
* @brief * @brief
@ -368,27 +380,66 @@ void mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flag
* @param length * @param length
* @param user 访 * @param user 访
* @param flush tlb * @param flush tlb
* @param use4k 使4k页
*/ */
void mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user, bool flush); int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user, bool flush, bool use4k);
int mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags);
void mm_map_phys_addr_user(ul virt_addr_start, ul phys_addr_start, ul length, ul flags); /**
* @brief
*
* @param proc_page_table_addr
* @param is_phys
* @param virt_addr_start
* @param length
*/
void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul length);
/**
* @brief
*
* @param virt_addr
* @param length
*/
#define mm_unmap(virt_addr, length) ({ \
mm_unmap_proc_table((uint64_t)get_CR3(), true, virt_addr, length); \
})
/** /**
* @brief * @brief
* *
* @param page_table_phys_addr * @param page_table_phys_addr
* @param virt_addr * @param virt_addr
* @return true * @return true
* @return false * @return false
*/ */
bool mm_check_mapped(ul page_table_phys_addr, uint64_t virt_addr); bool mm_check_mapped(ul page_table_phys_addr, uint64_t virt_addr);
/**
* @brief 2M页()
*
* @param paddr
* @return int8_t -> 1
* -> 0
*/
int8_t mm_is_2M_page(uint64_t paddr);
/**
* @brief 0
*
* @param ptr
* @return int8_t -> 1
* -> 0
*/
int8_t mm_check_page_table(uint64_t *ptr);
/** /**
* @brief * @brief
* *
* @todo * @todo
* @param old_brk_end_addr * @param old_brk_end_addr
* @param offset * @param offset
* @return uint64_t * @return uint64_t
*/ */
uint64_t mm_do_brk(uint64_t old_brk_end_addr, int64_t offset); uint64_t mm_do_brk(uint64_t old_brk_end_addr, int64_t offset);

View File

@ -1,17 +1,19 @@
#include "process.h" #include "process.h"
#include <exception/gate.h>
#include <common/printk.h> #include <common/printk.h>
#include <common/kprint.h> #include <common/kprint.h>
#include <syscall/syscall.h>
#include <syscall/syscall_num.h>
#include <mm/slab.h>
#include <sched/sched.h>
#include <filesystem/fat32/fat32.h>
#include <common/stdio.h> #include <common/stdio.h>
#include <process/spinlock.h> #include <common/compiler.h>
#include <common/libELF/elf.h> #include <common/libELF/elf.h>
#include <driver/video/video.h> #include <driver/video/video.h>
#include <exception/gate.h>
#include <filesystem/fat32/fat32.h>
#include <mm/slab.h>
#include <process/spinlock.h>
#include <syscall/syscall.h>
#include <syscall/syscall_num.h>
#include <sched/sched.h>
spinlock_t process_global_pid_write_lock; // 增加pid的写锁 spinlock_t process_global_pid_write_lock; // 增加pid的写锁
long process_global_pid = 1; // 系统中最大的pid long process_global_pid = 1; // 系统中最大的pid
@ -246,7 +248,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
// todo: 改用slab分配4K大小内存块并映射到4K页 // todo: 改用slab分配4K大小内存块并映射到4K页
if (!mm_check_mapped((uint64_t)current_pcb->mm->pgd, virt_base)) // 未映射,则新增物理页 if (!mm_check_mapped((uint64_t)current_pcb->mm->pgd, virt_base)) // 未映射,则新增物理页
{ {
mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, virt_base, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true); mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, virt_base, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true, false);
memset((void *)virt_base, 0, PAGE_2M_SIZE); memset((void *)virt_base, 0, PAGE_2M_SIZE);
} }
@ -273,7 +275,7 @@ static int process_load_elf_file(struct pt_regs *regs, char *path)
uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys; uint64_t pa = alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys;
mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, current_pcb->mm->stack_start - PAGE_2M_SIZE, pa, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true); mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, current_pcb->mm->stack_start - PAGE_2M_SIZE, pa, PAGE_2M_SIZE, PAGE_USER_PAGE, true, true, false);
// 清空栈空间 // 清空栈空间
memset((void *)(current_pcb->mm->stack_start - PAGE_2M_SIZE), 0, PAGE_2M_SIZE); memset((void *)(current_pcb->mm->stack_start - PAGE_2M_SIZE), 0, PAGE_2M_SIZE);
@ -651,11 +653,6 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
// 拷贝成功 // 拷贝成功
retval = tsk->pid; retval = tsk->pid;
// kdebug("fork done: tsk->pid=%d", tsk->pid);
// kdebug("current_pcb->mm->brk_end=%#018lx", current_pcb->mm->brk_end);
// mm_map_proc_page_table((uint64_t)current_pcb->mm->pgd, true, 0x0000500000000000, alloc_pages(ZONE_NORMAL, 1, PAGE_PGT_MAPPED)->addr_phys, PAGE_2M_SIZE, PAGE_USER_PAGE, true);
// 唤醒进程 // 唤醒进程
process_wakeup(tsk); process_wakeup(tsk);
@ -922,8 +919,28 @@ uint64_t process_exit_mm(struct process_control_block *pcb)
{ {
if ((current_pdt + k)->pdt == 0) if ((current_pdt + k)->pdt == 0)
continue; continue;
// 释放内存页 // 存在4级页表
free_pages(Phy_to_2M_Page((current_pdt + k)->pdt & (~0x1fffUL)), 1); if (unlikely(((current_pdt + k)->pdt & (1 << 7)) == 0))
{
// 存在4K页
uint64_t *pt_ptr = (uint64_t *)phys_2_virt((current_pdt + k)->pdt & (~0x1fffUL));
uint64_t *pte_ptr = pt_ptr;
// 循环处理4K页表, 直接清空
// todo: 当支持使用slab分配4K内存作为进程的4K页之后在这里需要释放这些4K对象
for (int16_t g = 0; g < 512; ++g, ++pte_ptr)
*pte_ptr = 0;
// 4级页表已经空了释放页表
if (unlikely(mm_check_page_table(pt_ptr)) == 0)
kfree(pt_ptr);
}
else
{
// 释放内存页
if (mm_is_2M_page((current_pdt + k)->pdt & (~0x1fffUL))) // 校验是否为内存中的物理页
free_pages(Phy_to_2M_Page((current_pdt + k)->pdt & (~0x1fffUL)), 1);
}
} }
// 释放三级页表 // 释放三级页表
kfree(current_pdt); kfree(current_pdt);