LoGin 40fe15e095
新的内存管理模块 (#303)
  实现了具有优秀架构设计的新的内存管理模块,对内核空间和用户空间的内存映射、分配、释放、管理等操作进行了封装,使得内核开发者可以更加方便地进行内存管理。

  内存管理模块主要由以下类型的组件组成:

- **硬件抽象层(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

---------

Co-authored-by: kong <kongweichao@dragonos.org>
2023-07-22 16:27:02 +08:00

340 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "msi.h"
#include "pci.h"
#include <common/errno.h>
#include <mm/mmio.h>
/**
* @brief 生成msi消息
*
* @param msi_desc msi描述符
* @return struct msi_msg_t* msi消息指针在描述符内
*/
extern struct msi_msg_t *msi_arch_get_msg(struct msi_desc_t *msi_desc);
/**
* @brief 读取msix的capability list
*
* @param msi_desc msi描述符
* @param cap_off capability list的offset
* @return struct pci_msix_cap_t 对应的capability list
*/
static __always_inline struct pci_msix_cap_t __msi_read_msix_cap_list(struct msi_desc_t *msi_desc, uint32_t cap_off)
{
struct pci_msix_cap_t cap_list = {0};
uint32_t dw0;
dw0 = pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off);
io_lfence();
cap_list.cap_id = dw0 & 0xff;
cap_list.next_off = (dw0 >> 8) & 0xff;
cap_list.msg_ctrl = (dw0 >> 16) & 0xffff;
cap_list.dword1 =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x4);
cap_list.dword2 =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x8);
return cap_list;
}
static __always_inline struct pci_msi_cap_t __msi_read_cap_list(struct msi_desc_t *msi_desc, uint32_t cap_off)
{
struct pci_msi_cap_t cap_list = {0};
uint32_t dw0;
dw0 = pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off);
cap_list.cap_id = dw0 & 0xff;
cap_list.next_off = (dw0 >> 8) & 0xff;
cap_list.msg_ctrl = (dw0 >> 16) & 0xffff;
cap_list.msg_addr_lo =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x4);
uint16_t msg_data_off = 0xc;
if (cap_list.msg_ctrl & (1 << 7)) // 64位
{
cap_list.msg_addr_hi =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x8);
}
else
{
cap_list.msg_addr_hi = 0;
msg_data_off = 0x8;
}
cap_list.msg_data = pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func,
cap_off + msg_data_off) &
0xffff;
cap_list.mask =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x10);
cap_list.pending =
pci_read_config(msi_desc->pci_dev->bus, msi_desc->pci_dev->device, msi_desc->pci_dev->func, cap_off + 0x14);
return cap_list;
}
/**
* @brief 映射设备的msix表 //MSIX表不再单独映射(To do)
*
* @param pci_dev pci设备信息结构体
* @param msix_cap msix capability list的结构体
* @return int 错误码
*/
static __always_inline int __msix_map_table(struct pci_device_structure_header_t *pci_dev,
struct pci_msix_cap_t *msix_cap)
{
// 计算bar寄存器的offset
uint32_t bar_off = 0x10 + 4 * (msix_cap->dword1 & 0x7);
// msix table相对于bar寄存器中存储的地址的offset
pci_dev->msix_offset = msix_cap->dword1 & (~0x7);
pci_dev->msix_table_size = (msix_cap->msg_ctrl & 0x7ff) + 1;
pci_dev->msix_mmio_size = pci_dev->msix_table_size * 16 + pci_dev->msix_offset;
// 申请mmio空间
mmio_create(pci_dev->msix_mmio_size, VM_IO | VM_DONTCOPY, &pci_dev->msix_mmio_vaddr, &pci_dev->msix_mmio_size);
pci_dev->msix_mmio_vaddr &= (~0xf);
uint32_t bar = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->func, bar_off);
// kdebug("pci_dev->msix_mmio_vaddr=%#018lx, bar=%#010lx, table offset=%#010lx, table_size=%#010lx, mmio_size=%d",
// pci_dev->msix_mmio_vaddr, bar, pci_dev->msix_offset, pci_dev->msix_table_size, pci_dev->msix_mmio_size);
// 将msix table映射到页表
rs_map_phys(pci_dev->msix_mmio_vaddr, bar, pci_dev->msix_mmio_size, PAGE_KERNEL_PAGE);
return 0;
}
/**
* @brief 将msi_desc中的数据填写到msix表的指定表项处
*
* @param pci_dev pci设备结构体
* @param msi_desc msi描述符
*/
static __always_inline void __msix_set_entry(struct msi_desc_t *msi_desc)
{
uint64_t *ptr =
(uint64_t *)(msi_desc->pci_dev->msix_mmio_vaddr + msi_desc->pci_dev->msix_offset + msi_desc->msi_index * 16);
*ptr = ((uint64_t)(msi_desc->msg.address_hi) << 32) | (msi_desc->msg.address_lo);
io_mfence();
++ptr;
io_mfence();
*ptr = ((uint64_t)(msi_desc->msg.vector_control) << 32) | (msi_desc->msg.data);
io_mfence();
}
/**
* @brief 清空设备的msix table的指定表项
*
* @param pci_dev pci设备
* @param msi_index 表项号
*/
static __always_inline void __msix_clear_entry(struct pci_device_structure_header_t *pci_dev, uint16_t msi_index)
{
uint64_t *ptr = (uint64_t *)(pci_dev->msix_mmio_vaddr + pci_dev->msix_offset + msi_index * 16);
*ptr = 0;
++ptr;
*ptr = 0;
}
/**
* @brief 启用 Message Signaled Interrupts
*
* @param header 设备header
* @param vector 中断向量号
* @param processor 要投递到的处理器
* @param edge_trigger 是否边缘触发
* @param assert 是否高电平触发
*
* @return 返回码
*/
int pci_enable_msi(struct msi_desc_t *msi_desc)
{
struct pci_device_structure_header_t *ptr = msi_desc->pci_dev;
uint32_t cap_ptr;
uint32_t tmp;
uint16_t message_control;
uint64_t message_addr;
// 先尝试获取msi-x若不存在则获取msi capability
if (msi_desc->pci.msi_attribute.is_msix)
{
cap_ptr = pci_enumerate_capability_list(ptr, 0x11);
if (((int32_t)cap_ptr) < 0)
{
cap_ptr = pci_enumerate_capability_list(ptr, 0x05);
if (((int32_t)cap_ptr) < 0)
return -ENOSYS;
msi_desc->pci.msi_attribute.is_msix = 0;
}
}
else
{
cap_ptr = pci_enumerate_capability_list(ptr, 0x05);
if (((int32_t)cap_ptr) < 0)
return -ENOSYS;
msi_desc->pci.msi_attribute.is_msix = 0;
}
// 获取msi消息
msi_arch_get_msg(msi_desc);
if (msi_desc->pci.msi_attribute.is_msix) // MSI-X
{
kdebug("is msix");
// 读取msix的信息
struct pci_msix_cap_t cap = __msi_read_msix_cap_list(msi_desc, cap_ptr);
// 映射msix table
__msix_map_table(msi_desc->pci_dev, &cap);
io_mfence();
// 设置msix的中断
__msix_set_entry(msi_desc);
io_mfence();
// todo: disable intx
// 使能msi-x
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp |= (1U << 31);
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
}
else
{
kdebug("is msi");
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
message_control = (tmp >> 16) & 0xffff;
// 写入message address
message_addr = ((((uint64_t)msi_desc->msg.address_hi) << 32) | msi_desc->msg.address_lo); // 获取message address
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x4, (uint32_t)(message_addr & 0xffffffff));
if (message_control & (1 << 7)) // 64位
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8,
(uint32_t)((message_addr >> 32) & 0xffffffff));
// 写入message data
tmp = msi_desc->msg.data;
if (message_control & (1 << 7)) // 64位
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0xc, tmp);
else
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8, tmp);
// 使能msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp |= (1 << 16);
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
}
return 0;
}
/**
* @brief 在已配置好msi寄存器的设备上使能msi
*
* @param header 设备头部
* @return int 返回码
*/
int pci_start_msi(void *header)
{
struct pci_device_structure_header_t *ptr = (struct pci_device_structure_header_t *)header;
uint32_t cap_ptr;
uint32_t tmp;
switch (ptr->HeaderType)
{
case 0x00: // general device
if (!(ptr->Status & 0x10))
return -ENOSYS;
cap_ptr = ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer;
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
if (tmp & 0xff != 0x5)
return -ENOSYS;
// 使能msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp |= (1 << 16);
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
break;
case 0x01: // pci to pci bridge
if (!(ptr->Status & 0x10))
return -ENOSYS;
cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
if (tmp & 0xff != 0x5)
return -ENOSYS;
// 使能msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp |= (1 << 16);
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
break;
case 0x02: // pci to card bus bridge
return -ENOSYS;
break;
default: // 不应该到达这里
return -EINVAL;
break;
}
return 0;
}
/**
* @brief 禁用指定设备的msi
*
* @param header pci header
* @return int
*/
int pci_disable_msi(void *header)
{
struct pci_device_structure_header_t *ptr = (struct pci_device_structure_header_t *)header;
uint32_t cap_ptr;
uint32_t tmp;
switch (ptr->HeaderType)
{
case 0x00: // general device
if (!(ptr->Status & 0x10))
return -ENOSYS;
cap_ptr = ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer;
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
if (tmp & 0xff != 0x5)
return -ENOSYS;
// 禁用msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp &= (~(1 << 16));
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
break;
case 0x01: // pci to pci bridge
if (!(ptr->Status & 0x10))
return -ENOSYS;
cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
if (tmp & 0xff != 0x5)
return -ENOSYS;
// 禁用msi
tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
tmp &= (~(1 << 16));
pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
break;
case 0x02: // pci to card bus bridge
return -ENOSYS;
break;
default: // 不应该到达这里
return -EINVAL;
break;
}
return 0;
}