mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
Merge branch 'master' into patch-screen-manager
This commit is contained in:
commit
fadeee36a2
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -114,7 +114,9 @@
|
||||
"errno.h": "c",
|
||||
"bug.h": "c",
|
||||
"apic_timer.h": "c",
|
||||
"sched.h": "c"
|
||||
"sched.h": "c",
|
||||
"preempt.h": "c",
|
||||
"softirq.h": "c"
|
||||
},
|
||||
"C_Cpp.errorSquiggles": "Enabled",
|
||||
"esbonio.sphinx.confDir": ""
|
||||
|
2
Makefile
2
Makefile
@ -7,7 +7,7 @@ export ARCH=__x86_64__
|
||||
export ROOT_PATH=$(shell pwd)
|
||||
|
||||
export DEBUG=DEBUG
|
||||
export GLOBAL_CFLAGS := -mcmodel=large -fno-builtin -m64 -O0 -fno-stack-protector -D $(ARCH)
|
||||
export GLOBAL_CFLAGS := -mcmodel=large -fno-builtin -m64 -fno-stack-protector -D $(ARCH) -O1
|
||||
|
||||
ifeq ($(DEBUG), DEBUG)
|
||||
GLOBAL_CFLAGS += -g
|
||||
|
@ -11,7 +11,7 @@
|
||||
- 项目文档 **[docs.DragonOS.org](https://docs.dragonos.org)**
|
||||
- 开源论坛 **[bbs.DragonOS.org](https://bbs.dragonos.org)**
|
||||
- 开发交流QQ群 **115763565**
|
||||
|
||||
- 代码搜索引擎 [code.DragonOS.org](http://code.dragonos.org)
|
||||
## 开发环境
|
||||
|
||||
GCC>=8.0
|
||||
|
@ -10,7 +10,8 @@ This project is a operating system running on computer which is in X86_ 64 Archi
|
||||
- Home Page **[DragonOS.org](https://dragonos.org)**
|
||||
- Documentation **[docs.DragonOS.org](https://docs.dragonos.org)**
|
||||
- BBS **[bbs.DragonOS.org](https://bbs.dragonos.org)**
|
||||
|
||||
- QQ group **115763565**
|
||||
- code search engine [code.DragonOS.org](http://code.dragonos.org)
|
||||
|
||||
## Development Environment
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "cpu.h"
|
||||
#include "kprint.h"
|
||||
#include "printk.h"
|
||||
|
||||
// #pragma GCC optimize("O0")
|
||||
// cpu支持的最大cpuid指令的基础主功能号
|
||||
uint Cpu_cpuid_max_Basic_mop;
|
||||
// cpu支持的最大cpuid指令的扩展主功能号
|
||||
|
@ -93,6 +93,7 @@ struct List
|
||||
static inline void list_init(struct List *list)
|
||||
{
|
||||
list->next = list;
|
||||
io_mfence();
|
||||
list->prev = list;
|
||||
}
|
||||
|
||||
@ -106,8 +107,11 @@ static inline void list_add(struct List *entry, struct List *node)
|
||||
{
|
||||
|
||||
node->next = entry->next;
|
||||
barrier();
|
||||
node->prev = entry;
|
||||
barrier();
|
||||
node->next->prev = node;
|
||||
barrier();
|
||||
entry->next = node;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,8 @@ static uint *get_pos_VBE_FB_addr();
|
||||
*/
|
||||
static int cls();
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
/**
|
||||
* @brief 滚动窗口(尚不支持向下滚动)
|
||||
*
|
||||
@ -53,7 +55,7 @@ static int cls();
|
||||
* @param animation 是否包含滑动动画
|
||||
*/
|
||||
static int scroll(bool direction, int pixels, bool animation);
|
||||
|
||||
#pragma GCC pop_options
|
||||
/**
|
||||
* @brief 将数字按照指定的要求转换成对应的字符串(2~36进制)
|
||||
*
|
||||
@ -184,7 +186,9 @@ static void auto_newline()
|
||||
#endif
|
||||
pos.y = pos.max_y;
|
||||
int lines_to_scroll = 1;
|
||||
barrier();
|
||||
scroll(true, lines_to_scroll * pos.char_size_y, sw_show_scroll_animation);
|
||||
barrier();
|
||||
pos.y -= (lines_to_scroll - 1);
|
||||
}
|
||||
}
|
||||
@ -835,7 +839,6 @@ static int scroll(bool direction, int pixels, bool animation)
|
||||
int md = pixels % pos.char_size_y;
|
||||
if (md)
|
||||
pixels = pixels + pos.char_size_y - md;
|
||||
|
||||
if (animation == false)
|
||||
return do_scroll(direction, pixels);
|
||||
else
|
||||
@ -956,4 +959,5 @@ int sprintk(char *buf, const char *fmt, ...)
|
||||
va_end(args);
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Created by longjin on 2022/1/21.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
#define PAD_ZERO 1 // 0填充
|
||||
#define LEFT 2 // 靠左对齐
|
||||
#define RIGHT 4 // 靠右对齐
|
||||
@ -124,3 +125,4 @@ void printk_disable_animation();
|
||||
* @return int 字符串长度
|
||||
*/
|
||||
int sprintk(char *buf, const char *fmt, ...);
|
||||
#pragma GCC pop_options
|
@ -2,6 +2,8 @@
|
||||
#include <common/compiler.h>
|
||||
#include <common/kprint.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
/**
|
||||
* @brief 当condition为true时输出警告信息
|
||||
*
|
||||
@ -19,3 +21,4 @@
|
||||
goto to; \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
#pragma GCC pop_options
|
@ -10,6 +10,8 @@
|
||||
#include <process/process.h>
|
||||
#include <sched/sched.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
// 导出定义在irq.c中的中段门表
|
||||
extern void (*interrupt_table[24])(void);
|
||||
|
||||
@ -94,27 +96,7 @@ void apic_io_apic_init()
|
||||
|
||||
// 不需要手动启动IO APIC,只要初始化了RTE寄存器之后,io apic就会自动启用了。
|
||||
// 而且不是每台电脑都有RCBA寄存器,因此不需要手动启用IO APIC
|
||||
/*
|
||||
// get RCBA address
|
||||
io_out32(0xcf8, 0x8000f8f0);
|
||||
uint x = io_in32(0xcfc);
|
||||
uint *p;
|
||||
printk_color(RED, BLACK, "Get RCBA Address:%#010x\n", x);
|
||||
x = x & 0xffffc000UL;
|
||||
printk_color(RED, BLACK, "Get RCBA Address:%#010x\n", x);
|
||||
|
||||
// get OIC address
|
||||
if (x > 0xfec00000 && x < 0xfee00000)
|
||||
{
|
||||
p = (unsigned int *)(x + 0x31feUL-apic_ioapic_map.addr_phys+apic_ioapic_map.virtual_index_addr);
|
||||
}
|
||||
|
||||
// enable IOAPIC
|
||||
x = (*p & 0xffffff00) | 0x100;
|
||||
io_mfence();
|
||||
*p = x;
|
||||
io_mfence();
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -650,6 +632,7 @@ void apic_ioapic_edge_ack(ul irq_num) // 边沿触发
|
||||
*
|
||||
* @param irq_num
|
||||
*/
|
||||
|
||||
void apic_local_apic_edge_ack(ul irq_num)
|
||||
{
|
||||
// 向EOI寄存器写入0x00表示结束中断
|
||||
@ -660,6 +643,7 @@ void apic_local_apic_edge_ack(ul irq_num)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 读取指定类型的 Interrupt Control Structure
|
||||
*
|
||||
@ -734,4 +718,5 @@ void apic_make_rte_entry(struct apic_IO_APIC_RTE_entry *entry, uint8_t vector, u
|
||||
entry->destination.logical.logical_dest = dest_apicID;
|
||||
entry->destination.logical.reserved1 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma GCC pop_options
|
@ -5,6 +5,9 @@
|
||||
#include <exception/irq.h>
|
||||
#include <mm/mm.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
|
||||
#define APIC_SUCCESS 0
|
||||
#define APIC_E_NOTFOUND 1
|
||||
|
||||
@ -73,7 +76,7 @@
|
||||
// 分频配置寄存器(定时器专用)
|
||||
#define LOCAL_APIC_OFFSET_Local_APIC_CLKDIV 0x3e0
|
||||
|
||||
uint32_t RCBA_vaddr = 0;// RCBA寄存器的虚拟地址
|
||||
uint32_t RCBA_vaddr = 0; // RCBA寄存器的虚拟地址
|
||||
|
||||
/*
|
||||
|
||||
@ -318,4 +321,6 @@ void apic_local_apic_edge_ack(ul irq_num); // local apic边沿触发 应答
|
||||
* @param dest_apicID 目标apicID
|
||||
*/
|
||||
void apic_make_rte_entry(struct apic_IO_APIC_RTE_entry *entry, uint8_t vector, uint8_t deliver_mode, uint8_t dest_mode,
|
||||
uint8_t deliver_status, uint8_t polarity, uint8_t irr, uint8_t trigger, uint8_t mask, uint8_t dest_apicID);
|
||||
uint8_t deliver_status, uint8_t polarity, uint8_t irr, uint8_t trigger, uint8_t mask, uint8_t dest_apicID);
|
||||
|
||||
#pragma GCC pop_options
|
@ -4,14 +4,20 @@
|
||||
#include <common/kprint.h>
|
||||
#include <sched/sched.h>
|
||||
|
||||
// #pragma GCC push_options
|
||||
// #pragma GCC optimize("O0")
|
||||
uint64_t apic_timer_ticks_result = 0;
|
||||
|
||||
void apic_timer_enable(uint64_t irq_num)
|
||||
{
|
||||
// 启动apic定时器
|
||||
io_mfence();
|
||||
uint64_t val = apic_timer_get_LVT();
|
||||
io_mfence();
|
||||
val &= (~APIC_LVT_INT_MASKED);
|
||||
io_mfence();
|
||||
apic_timer_write_LVT(val);
|
||||
io_mfence();
|
||||
}
|
||||
|
||||
void apic_timer_disable(uint64_t irq_num)
|
||||
@ -29,18 +35,24 @@ void apic_timer_disable(uint64_t irq_num)
|
||||
uint64_t apic_timer_install(ul irq_num, void *arg)
|
||||
{
|
||||
// 设置div16
|
||||
io_mfence();
|
||||
apic_timer_stop();
|
||||
io_mfence();
|
||||
apic_timer_set_div(APIC_TIMER_DIVISOR);
|
||||
io_mfence();
|
||||
|
||||
// 设置初始计数
|
||||
apic_timer_set_init_cnt(*(uint64_t *)arg);
|
||||
io_mfence();
|
||||
// 填写LVT
|
||||
apic_timer_set_LVT(APIC_TIMER_IRQ_NUM, 1, APIC_LVT_Timer_Periodic);
|
||||
io_mfence();
|
||||
}
|
||||
|
||||
void apic_timer_uninstall(ul irq_num)
|
||||
{
|
||||
apic_timer_write_LVT(APIC_LVT_INT_MASKED);
|
||||
io_mfence();
|
||||
}
|
||||
|
||||
hardware_intr_controller apic_timer_intr_controller =
|
||||
@ -63,6 +75,7 @@ void apic_timer_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
|
||||
{
|
||||
|
||||
sched_update_jiffies();
|
||||
io_mfence();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,6 +10,8 @@ extern uint64_t apic_timer_ticks_result;
|
||||
|
||||
#define APIC_TIMER_IRQ_NUM 151
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
/**
|
||||
* @brief 设置apic定时器的分频计数
|
||||
*
|
||||
@ -78,4 +80,6 @@ extern uint64_t apic_timer_ticks_result;
|
||||
* @brief 初始化local APIC定时器
|
||||
*
|
||||
*/
|
||||
void apic_timer_init();
|
||||
void apic_timer_init();
|
||||
|
||||
#pragma GCC pop_options
|
@ -12,6 +12,8 @@
|
||||
#include <driver/interrupt/apic/apic_timer.h>
|
||||
#include <common/spinlock.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
static struct acpi_HPET_description_table_t *hpet_table;
|
||||
static uint64_t HPET_REG_BASE = 0;
|
||||
static uint32_t HPET_COUNTER_CLK_PERIOD = 0; // 主计数器时间精度(单位:飞秒)
|
||||
@ -122,7 +124,7 @@ void HPET_measure_freq()
|
||||
|
||||
// 使用I/O APIC 的IRQ2接收hpet定时器0的中断
|
||||
apic_make_rte_entry(&entry, 34, IO_APIC_FIXED, DEST_PHYSICAL, IDLE, POLARITY_HIGH, IRR_RESET, EDGE_TRIGGER, MASKED, 0);
|
||||
|
||||
|
||||
// 计算HPET0间隔多少个时钟周期触发一次中断
|
||||
uint64_t clks_to_intr = 0.001 * interval * HPET_freq;
|
||||
// kdebug("clks_to_intr=%#ld", clks_to_intr);
|
||||
@ -158,9 +160,9 @@ void HPET_measure_freq()
|
||||
// 顺便测定tsc频率
|
||||
test_tsc_start = rdtsc();
|
||||
io_mfence();
|
||||
|
||||
while (measure_apic_timer_flag == false)
|
||||
;
|
||||
kdebug("wait done");
|
||||
|
||||
irq_unregister(34);
|
||||
|
||||
@ -283,3 +285,4 @@ int HPET_init()
|
||||
// kdebug("HPET_freq=%ld", (long)HPET_freq);
|
||||
// kdebug("HPET_freq=%lf", HPET_freq);
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
@ -10,7 +10,7 @@ extern spinlock_t xhci_controller_init_lock; // xhci控制器初始化锁
|
||||
#define MAX_USB_NUM 8 // pci总线上的usb设备的最大数量
|
||||
|
||||
// 在pci总线上寻找到的usb设备控制器的header
|
||||
struct pci_device_structure_header_t *usb_pdevs[MAX_USB_NUM];
|
||||
static struct pci_device_structure_header_t *usb_pdevs[MAX_USB_NUM];
|
||||
static int usb_pdevs_count = 0;
|
||||
|
||||
/**
|
||||
@ -34,6 +34,7 @@ void usb_init()
|
||||
// 初始化每个usb控制器
|
||||
for (int i = 0; i < usb_pdevs_count; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
switch (usb_pdevs[i]->ProgIF)
|
||||
{
|
||||
case USB_TYPE_UHCI:
|
||||
@ -47,6 +48,7 @@ void usb_init()
|
||||
case USB_TYPE_XHCI:
|
||||
// 初始化对应的xhci控制器
|
||||
xhci_init((struct pci_device_structure_general_device_t *)usb_pdevs[i]);
|
||||
io_mfence();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -9,6 +9,10 @@
|
||||
#include <exception/irq.h>
|
||||
#include <driver/interrupt/apic/apic.h>
|
||||
|
||||
// 由于xhci寄存器读取需要对齐,因此禁用GCC优化选项
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
|
||||
spinlock_t xhci_controller_init_lock = {0}; // xhci控制器初始化锁(在usb_init中被初始化)
|
||||
|
||||
static int xhci_ctrl_count = 0; // xhci控制器计数
|
||||
@ -52,7 +56,6 @@ hardware_intr_controller xhci_hc_intr_controller =
|
||||
例子:不能在一个32bit的寄存器中的偏移量8的位置开始读取1个字节
|
||||
这种情况下,我们必须从32bit的寄存器的0地址处开始读取32bit,然后通过移位的方式得到其中的字节。
|
||||
*/
|
||||
|
||||
#define xhci_read_cap_reg8(id, offset) (*(uint8_t *)(xhci_hc[id].vbase + offset))
|
||||
#define xhci_get_ptr_cap_reg8(id, offset) ((uint8_t *)(xhci_hc[id].vbase + offset))
|
||||
#define xhci_write_cap_reg8(id, offset, value) (*(uint8_t *)(xhci_hc[id].vbase + offset) = (uint8_t)value)
|
||||
@ -112,15 +115,15 @@ hardware_intr_controller xhci_hc_intr_controller =
|
||||
* @brief 设置link TRB的命令(dword3)
|
||||
*
|
||||
*/
|
||||
#define xhci_TRB_set_link_cmd(trb_vaddr) \
|
||||
do \
|
||||
{ \
|
||||
#define xhci_TRB_set_link_cmd(trb_vaddr) \
|
||||
do \
|
||||
{ \
|
||||
struct xhci_TRB_normal_t *ptr = (struct xhci_TRB_normal_t *)(trb_vaddr); \
|
||||
ptr->TRB_type = TRB_TYPE_LINK; \
|
||||
ptr->ioc = 0; \
|
||||
ptr->chain = 0; \
|
||||
ptr->ent = 0; \
|
||||
ptr->cycle = 1; \
|
||||
ptr->TRB_type = TRB_TYPE_LINK; \
|
||||
ptr->ioc = 0; \
|
||||
ptr->chain = 0; \
|
||||
ptr->ent = 0; \
|
||||
ptr->cycle = 1; \
|
||||
} while (0)
|
||||
|
||||
// Common TRB types
|
||||
@ -195,11 +198,13 @@ static int xhci_hc_stop(int id)
|
||||
// 判断是否已经停止
|
||||
if (unlikely((xhci_read_op_reg32(id, XHCI_OPS_USBSTS) & (1 << 0)) == 1))
|
||||
return 0;
|
||||
|
||||
io_mfence();
|
||||
xhci_write_op_reg32(id, XHCI_OPS_USBCMD, 0x00000000);
|
||||
io_mfence();
|
||||
char timeout = 17;
|
||||
while ((xhci_read_op_reg32(id, XHCI_OPS_USBSTS) & (1 << 0)) == 0)
|
||||
{
|
||||
io_mfence();
|
||||
usleep(1000);
|
||||
if (--timeout == 0)
|
||||
return -ETIMEDOUT;
|
||||
@ -218,9 +223,11 @@ static int xhci_hc_reset(int id)
|
||||
{
|
||||
int retval = 0;
|
||||
kdebug("usbsts=%#010lx", xhci_read_op_reg32(id, XHCI_OPS_USBSTS));
|
||||
io_mfence();
|
||||
// 判断HCHalted是否置位
|
||||
if ((xhci_read_op_reg32(id, XHCI_OPS_USBSTS) & (1 << 0)) == 0)
|
||||
{
|
||||
io_mfence();
|
||||
kdebug("stopping usb hc...");
|
||||
// 未置位,需要先尝试停止usb主机控制器
|
||||
retval = xhci_hc_stop(id);
|
||||
@ -230,12 +237,16 @@ static int xhci_hc_reset(int id)
|
||||
int timeout = 500; // wait 500ms
|
||||
// reset
|
||||
uint32_t cmd = xhci_read_op_reg32(id, XHCI_OPS_USBCMD);
|
||||
io_mfence();
|
||||
kdebug("cmd=%#010lx", cmd);
|
||||
cmd |= (1 << 1);
|
||||
xhci_write_op_reg32(id, XHCI_OPS_USBCMD, cmd);
|
||||
io_mfence();
|
||||
kdebug("after rst, sts=%#010lx", xhci_read_op_reg32(id, XHCI_OPS_USBSTS));
|
||||
io_mfence();
|
||||
while (xhci_read_op_reg32(id, XHCI_OPS_USBCMD) & (1 << 1))
|
||||
{
|
||||
io_mfence();
|
||||
usleep(1000);
|
||||
if (--timeout == 0)
|
||||
return -ETIMEDOUT;
|
||||
@ -259,14 +270,15 @@ static int xhci_hc_stop_legacy(int id)
|
||||
// 判断当前entry是否为legacy support entry
|
||||
if (xhci_read_cap_reg8(id, current_offset) == XHCI_XECP_ID_LEGACY)
|
||||
{
|
||||
|
||||
io_mfence();
|
||||
// 接管控制权
|
||||
xhci_write_cap_reg32(id, current_offset, xhci_read_cap_reg32(id, current_offset) | XHCI_XECP_LEGACY_OS_OWNED);
|
||||
|
||||
io_mfence();
|
||||
// 等待响应完成
|
||||
int timeout = XHCI_XECP_LEGACY_TIMEOUT;
|
||||
while ((xhci_read_cap_reg32(id, current_offset) & XHCI_XECP_LEGACY_OWNING_MASK) != XHCI_XECP_LEGACY_OS_OWNED)
|
||||
{
|
||||
io_mfence();
|
||||
usleep(1000);
|
||||
if (--timeout == 0)
|
||||
{
|
||||
@ -277,9 +289,10 @@ static int xhci_hc_stop_legacy(int id)
|
||||
// 处理完成
|
||||
return 0;
|
||||
}
|
||||
|
||||
io_mfence();
|
||||
// 读取下一个entry的偏移增加量
|
||||
int next_off = ((xhci_read_cap_reg32(id, current_offset) & 0xff00) >> 8) << 2;
|
||||
io_mfence();
|
||||
// 将指针跳转到下一个entry
|
||||
current_offset = next_off ? (current_offset + next_off) : 0;
|
||||
} while (current_offset);
|
||||
@ -296,7 +309,9 @@ static int xhci_hc_stop_legacy(int id)
|
||||
*/
|
||||
static int xhci_hc_start_sched(int id)
|
||||
{
|
||||
io_mfence();
|
||||
xhci_write_op_reg32(id, XHCI_OPS_USBCMD, (1 << 0) | (1 >> 2) | (1 << 3));
|
||||
io_mfence();
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
|
||||
@ -308,7 +323,9 @@ static int xhci_hc_start_sched(int id)
|
||||
*/
|
||||
static int xhci_hc_stop_sched(int id)
|
||||
{
|
||||
io_mfence();
|
||||
xhci_write_op_reg32(id, XHCI_OPS_USBCMD, 0x00);
|
||||
io_mfence();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -336,13 +353,14 @@ static uint32_t xhci_hc_get_protocol_offset(int id, uint32_t list_off, const int
|
||||
do
|
||||
{
|
||||
uint32_t dw0 = xhci_read_cap_reg32(id, list_off);
|
||||
io_mfence();
|
||||
uint32_t next_list_off = (dw0 >> 8) & 0xff;
|
||||
next_list_off = next_list_off ? (list_off + (next_list_off << 2)) : 0;
|
||||
|
||||
if ((dw0 & 0xff) == XHCI_XECP_ID_PROTOCOL && ((dw0 & 0xff000000) >> 24) == version)
|
||||
{
|
||||
uint32_t dw2 = xhci_read_cap_reg32(id, list_off + 8);
|
||||
|
||||
io_mfence();
|
||||
if (offset != NULL)
|
||||
*offset = (uint32_t)(dw2 & 0xff) - 1; // 使其转换为zero based
|
||||
if (count != NULL)
|
||||
@ -368,8 +386,9 @@ static int xhci_hc_pair_ports(int id)
|
||||
{
|
||||
|
||||
struct xhci_caps_HCSPARAMS1_reg_t hcs1;
|
||||
io_mfence();
|
||||
memcpy(&hcs1, xhci_get_ptr_cap_reg32(id, XHCI_CAPS_HCSPARAMS1), sizeof(struct xhci_caps_HCSPARAMS1_reg_t));
|
||||
|
||||
io_mfence();
|
||||
// 从hcs1获取端口数量
|
||||
xhci_hc[id].port_num = hcs1.max_ports;
|
||||
|
||||
@ -385,15 +404,18 @@ static int xhci_hc_pair_ports(int id)
|
||||
// 寻找所有的usb2端口
|
||||
while (next_off)
|
||||
{
|
||||
io_mfence();
|
||||
next_off = xhci_hc_get_protocol_offset(id, next_off, 2, &offset, &cnt, &protocol_flags);
|
||||
io_mfence();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
xhci_hc[id].ports[offset + i].offset = xhci_hc[id].port_num_u2++;
|
||||
xhci_hc[id].ports[offset + i].flags = XHCI_PROTOCOL_USB2;
|
||||
|
||||
io_mfence();
|
||||
// usb2 high speed only
|
||||
if (protocol_flags & 2)
|
||||
xhci_hc[id].ports[offset + i].flags |= XHCI_PROTOCOL_HSO;
|
||||
@ -405,12 +427,15 @@ static int xhci_hc_pair_ports(int id)
|
||||
next_off = xhci_hc[id].ext_caps_off;
|
||||
while (next_off)
|
||||
{
|
||||
io_mfence();
|
||||
next_off = xhci_hc_get_protocol_offset(id, next_off, 3, &offset, &cnt, &protocol_flags);
|
||||
io_mfence();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
xhci_hc[id].ports[offset + i].offset = xhci_hc[id].port_num_u3++;
|
||||
xhci_hc[id].ports[offset + i].flags = XHCI_PROTOCOL_USB3;
|
||||
}
|
||||
@ -424,13 +449,13 @@ static int xhci_hc_pair_ports(int id)
|
||||
{
|
||||
if (unlikely(i == j))
|
||||
continue;
|
||||
|
||||
io_mfence();
|
||||
if ((xhci_hc[id].ports[i].offset == xhci_hc[id].ports[j].offset) &&
|
||||
((xhci_hc[id].ports[i].flags & XHCI_PROTOCOL_INFO) != (xhci_hc[id].ports[j].flags & XHCI_PROTOCOL_INFO)))
|
||||
{
|
||||
xhci_hc[id].ports[i].paired_port_num = j;
|
||||
xhci_hc[id].ports[i].flags |= XHCI_PROTOCOL_HAS_PAIR;
|
||||
|
||||
io_mfence();
|
||||
xhci_hc[id].ports[j].paired_port_num = i;
|
||||
xhci_hc[id].ports[j].flags |= XHCI_PROTOCOL_HAS_PAIR;
|
||||
}
|
||||
@ -440,6 +465,7 @@ static int xhci_hc_pair_ports(int id)
|
||||
// 标记所有的usb3、单独的usb2端口为激活状态
|
||||
for (int i = 0; i < xhci_hc[id].port_num; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
if (XHCI_PORT_IS_USB3(id, i) ||
|
||||
(XHCI_PORT_IS_USB2(id, i) && (!XHCI_PORT_HAS_PAIR(id, i))))
|
||||
xhci_hc[id].ports[i].flags |= XHCI_PROTOCOL_ACTIVE;
|
||||
@ -481,11 +507,12 @@ static uint64_t xhci_create_ring(int trbs)
|
||||
{
|
||||
int total_size = trbs * sizeof(struct xhci_TRB_t);
|
||||
const uint64_t vaddr = (uint64_t)kmalloc(total_size, 0);
|
||||
io_mfence();
|
||||
memset((void *)vaddr, 0, total_size);
|
||||
|
||||
io_mfence();
|
||||
// 设置最后一个trb为link trb
|
||||
xhci_TRB_set_link_cmd(vaddr + total_size - sizeof(struct xhci_TRB_t));
|
||||
|
||||
io_mfence();
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
@ -499,18 +526,19 @@ static uint64_t xhci_create_ring(int trbs)
|
||||
static uint64_t xhci_create_event_ring(int trbs, uint64_t *ret_ring_addr)
|
||||
{
|
||||
const uint64_t table_vaddr = (const uint64_t)kmalloc(64, 0); // table支持8个segment
|
||||
io_mfence();
|
||||
if (unlikely(table_vaddr == NULL))
|
||||
return -ENOMEM;
|
||||
memset((void *)table_vaddr, 0, 64);
|
||||
|
||||
// 暂时只创建1个segment
|
||||
const uint64_t seg_vaddr = (const uint64_t)kmalloc(trbs * sizeof(struct xhci_TRB_t), 0);
|
||||
|
||||
io_mfence();
|
||||
if (unlikely(seg_vaddr == NULL))
|
||||
return -ENOMEM;
|
||||
|
||||
memset((void *)seg_vaddr, 0, trbs * sizeof(struct xhci_TRB_t));
|
||||
|
||||
io_mfence();
|
||||
// 将segment地址和大小写入table
|
||||
*(uint64_t *)(table_vaddr) = virt_2_phys(seg_vaddr);
|
||||
*(uint64_t *)(table_vaddr + 8) = trbs;
|
||||
@ -522,13 +550,17 @@ static uint64_t xhci_create_event_ring(int trbs, uint64_t *ret_ring_addr)
|
||||
void xhci_hc_irq_enable(uint64_t irq_num)
|
||||
{
|
||||
int cid = xhci_find_hcid_by_irq_num(irq_num);
|
||||
io_mfence();
|
||||
if (WARN_ON(cid == -1))
|
||||
return;
|
||||
kdebug("start msi");
|
||||
io_mfence();
|
||||
pci_start_msi(xhci_hc[cid].pci_dev_hdr);
|
||||
kdebug("start sched");
|
||||
io_mfence();
|
||||
xhci_hc_start_sched(cid);
|
||||
kdebug("start ports");
|
||||
io_mfence();
|
||||
xhci_hc_start_ports(cid);
|
||||
kdebug("enabled");
|
||||
}
|
||||
@ -536,29 +568,34 @@ void xhci_hc_irq_enable(uint64_t irq_num)
|
||||
void xhci_hc_irq_disable(uint64_t irq_num)
|
||||
{
|
||||
int cid = xhci_find_hcid_by_irq_num(irq_num);
|
||||
io_mfence();
|
||||
if (WARN_ON(cid == -1))
|
||||
return;
|
||||
|
||||
xhci_hc_stop_sched(cid);
|
||||
io_mfence();
|
||||
pci_disable_msi(xhci_hc[cid].pci_dev_hdr);
|
||||
io_mfence();
|
||||
}
|
||||
|
||||
uint64_t xhci_hc_irq_install(uint64_t irq_num, void *arg)
|
||||
{
|
||||
int cid = xhci_find_hcid_by_irq_num(irq_num);
|
||||
io_mfence();
|
||||
if (WARN_ON(cid == -1))
|
||||
return -EINVAL;
|
||||
|
||||
struct xhci_hc_irq_install_info_t *info = (struct xhci_hc_irq_install_info_t *)arg;
|
||||
struct msi_desc_t msi_desc;
|
||||
memset(&msi_desc, 0, sizeof(struct msi_desc_t));
|
||||
|
||||
io_mfence();
|
||||
msi_desc.pci_dev = (struct pci_device_structure_header_t *)xhci_hc[cid].pci_dev_hdr;
|
||||
msi_desc.assert = info->assert;
|
||||
msi_desc.edge_trigger = info->edge_trigger;
|
||||
msi_desc.processor = info->processor;
|
||||
msi_desc.pci.msi_attribute.is_64 = 1;
|
||||
// todo: QEMU是使用msix的,因此要先在pci中实现msix
|
||||
io_mfence();
|
||||
int retval = pci_enable_msi(&msi_desc);
|
||||
kdebug("pci retval = %d", retval);
|
||||
kdebug("xhci irq %d installed.", irq_num);
|
||||
@ -569,9 +606,11 @@ void xhci_hc_irq_uninstall(uint64_t irq_num)
|
||||
{
|
||||
// todo
|
||||
int cid = xhci_find_hcid_by_irq_num(irq_num);
|
||||
io_mfence();
|
||||
if (WARN_ON(cid == -1))
|
||||
return;
|
||||
xhci_hc_stop(cid);
|
||||
io_mfence();
|
||||
}
|
||||
/**
|
||||
* @brief xhci主机控制器的中断处理函数
|
||||
@ -599,11 +638,14 @@ static int xhci_reset_port(const int id, const int port)
|
||||
// 相对于op寄存器基地址的偏移量
|
||||
uint64_t port_status_offset = XHCI_OPS_PRS + port * 16;
|
||||
// kdebug("to reset %d, offset=%#018lx", port, port_status_offset);
|
||||
io_mfence();
|
||||
// 检查端口电源状态
|
||||
if ((xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC) & (1 << 9)) == 0)
|
||||
{
|
||||
kdebug("port is power off, starting...");
|
||||
io_mfence();
|
||||
xhci_write_cap_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9));
|
||||
io_mfence();
|
||||
usleep(2000);
|
||||
// 检测端口是否被启用, 若未启用,则报错
|
||||
if ((xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC) & (1 << 9)) == 0)
|
||||
@ -613,10 +655,10 @@ static int xhci_reset_port(const int id, const int port)
|
||||
}
|
||||
}
|
||||
// kdebug("port:%d, power check ok", port);
|
||||
|
||||
io_mfence();
|
||||
// 确保端口的status被清0
|
||||
xhci_write_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9) | XHCI_PORTUSB_CHANGE_BITS);
|
||||
|
||||
io_mfence();
|
||||
// 重置当前端口
|
||||
if (XHCI_PORT_IS_USB3(id, port))
|
||||
xhci_write_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9) | (1 << 31));
|
||||
@ -629,7 +671,9 @@ static int xhci_reset_port(const int id, const int port)
|
||||
int timeout = 200;
|
||||
while (timeout)
|
||||
{
|
||||
io_mfence();
|
||||
uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC);
|
||||
io_mfence();
|
||||
if (XHCI_PORT_IS_USB3(id, port) && (val & (1 << 31)) == 0)
|
||||
break;
|
||||
else if (XHCI_PORT_IS_USB2(id, port) && (val & (1 << 4)) == 0)
|
||||
@ -647,12 +691,14 @@ static int xhci_reset_port(const int id, const int port)
|
||||
// 等待恢复
|
||||
usleep(USB_TIME_RST_REC * 1000);
|
||||
uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC);
|
||||
|
||||
io_mfence();
|
||||
// 如果reset之后,enable bit仍然是1,那么说明reset成功
|
||||
if (val & (1 << 1))
|
||||
{
|
||||
io_mfence();
|
||||
// 清除status change bit
|
||||
xhci_write_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC, (1 << 9) | XHCI_PORTUSB_CHANGE_BITS);
|
||||
io_mfence();
|
||||
}
|
||||
retval = 0;
|
||||
}
|
||||
@ -691,6 +737,7 @@ static int xhci_hc_start_ports(int id)
|
||||
{
|
||||
if (XHCI_PORT_IS_USB3(id, i) && XHCI_PORT_IS_ACTIVE(id, i))
|
||||
{
|
||||
io_mfence();
|
||||
// reset该端口
|
||||
if (likely(xhci_reset_port(id, i) == 0)) // 如果端口reset成功,就获取它的描述符
|
||||
// 否则,reset函数会把它给设置为未激活,并且标志配对的usb2端口是激活的
|
||||
@ -731,14 +778,18 @@ static int xhci_hc_init_intr(int id)
|
||||
|
||||
struct xhci_caps_HCSPARAMS1_reg_t hcs1;
|
||||
struct xhci_caps_HCSPARAMS2_reg_t hcs2;
|
||||
io_mfence();
|
||||
memcpy(&hcs1, xhci_get_ptr_cap_reg32(id, XHCI_CAPS_HCSPARAMS1), sizeof(struct xhci_caps_HCSPARAMS1_reg_t));
|
||||
io_mfence();
|
||||
memcpy(&hcs2, xhci_get_ptr_cap_reg32(id, XHCI_CAPS_HCSPARAMS2), sizeof(struct xhci_caps_HCSPARAMS2_reg_t));
|
||||
io_mfence();
|
||||
|
||||
uint32_t max_segs = (1 << (uint32_t)(hcs2.ERST_Max));
|
||||
uint32_t max_interrupters = hcs1.max_intrs;
|
||||
|
||||
// 创建 event ring
|
||||
retval = xhci_create_event_ring(4096, &xhci_hc[id].event_ring_vaddr);
|
||||
io_mfence();
|
||||
if (unlikely((int64_t)(retval) == -ENOMEM))
|
||||
return -ENOMEM;
|
||||
xhci_hc[id].event_ring_table_vaddr = retval;
|
||||
@ -747,15 +798,21 @@ static int xhci_hc_init_intr(int id)
|
||||
xhci_hc[id].current_event_ring_cycle = 1;
|
||||
|
||||
// 写入第0个中断寄存器组
|
||||
xhci_write_intr_reg32(id, 0, XHCI_IR_MAN, 0x3); // 使能中断并清除pending位(这个pending位是写入1就清0的)
|
||||
xhci_write_intr_reg32(id, 0, XHCI_IR_MOD, 0); // 关闭中断管制
|
||||
xhci_write_intr_reg32(id, 0, XHCI_IR_TABLE_SIZE, 1); // 当前只有1个segment
|
||||
io_mfence();
|
||||
xhci_write_intr_reg32(id, 0, XHCI_IR_MAN, 0x3); // 使能中断并清除pending位(这个pending位是写入1就清0的)
|
||||
io_mfence();
|
||||
xhci_write_intr_reg32(id, 0, XHCI_IR_MOD, 0); // 关闭中断管制
|
||||
io_mfence();
|
||||
xhci_write_intr_reg32(id, 0, XHCI_IR_TABLE_SIZE, 1); // 当前只有1个segment
|
||||
io_mfence();
|
||||
xhci_write_intr_reg64(id, 0, XHCI_IR_DEQUEUE, virt_2_phys(xhci_hc[id].event_ring_vaddr) | (1 << 3)); // 写入dequeue寄存器,并清除busy位(写1就会清除)
|
||||
xhci_write_intr_reg64(id, 0, XHCI_IR_TABLE_ADDR, virt_2_phys(xhci_hc[id].event_ring_table_vaddr)); // 写入table地址
|
||||
io_mfence();
|
||||
xhci_write_intr_reg64(id, 0, XHCI_IR_TABLE_ADDR, virt_2_phys(xhci_hc[id].event_ring_table_vaddr)); // 写入table地址
|
||||
io_mfence();
|
||||
|
||||
// 清除状态位
|
||||
xhci_write_op_reg32(id, XHCI_OPS_USBSTS, (1 << 10) | (1 << 4) | (1 << 3) | (1 << 2));
|
||||
|
||||
io_mfence();
|
||||
// 开启usb中断
|
||||
// 注册中断处理程序
|
||||
struct xhci_hc_irq_install_info_t install_info;
|
||||
@ -766,7 +823,9 @@ static int xhci_hc_init_intr(int id)
|
||||
char *buf = (char *)kmalloc(16, 0);
|
||||
memset(buf, 0, 16);
|
||||
sprintk(buf, "xHCI HC%d", id);
|
||||
io_mfence();
|
||||
irq_register(xhci_controller_irq_num[id], &install_info, &xhci_hc_irq_handler, id, &xhci_hc_intr_controller, buf);
|
||||
io_mfence();
|
||||
kfree(buf);
|
||||
|
||||
kdebug("xhci host controller %d: interrupt registered. irq num=%d", id, xhci_controller_irq_num[id]);
|
||||
@ -790,7 +849,7 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
|
||||
|
||||
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);
|
||||
|
||||
io_mfence();
|
||||
int cid = xhci_hc_find_available_id();
|
||||
if (cid < 0)
|
||||
{
|
||||
@ -801,13 +860,14 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
|
||||
memset(&xhci_hc[cid], 0, sizeof(struct xhci_host_controller_t));
|
||||
xhci_hc[cid].controller_id = cid;
|
||||
xhci_hc[cid].pci_dev_hdr = dev_hdr;
|
||||
io_mfence();
|
||||
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
|
||||
|
||||
io_mfence();
|
||||
// 为当前控制器映射寄存器地址空间
|
||||
xhci_hc[cid].vbase = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + XHCI_MAPPING_OFFSET + 65536 * xhci_hc[cid].controller_id;
|
||||
// kdebug("dev_hdr->BAR0 & (~0xf)=%#018lx", dev_hdr->BAR0 & (~0xf));
|
||||
mm_map_phys_addr(xhci_hc[cid].vbase, dev_hdr->BAR0 & (~0xf), 65536, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, true);
|
||||
|
||||
io_mfence();
|
||||
// 读取xhci控制寄存器
|
||||
uint16_t iversion = *(uint16_t *)(xhci_hc[cid].vbase + XHCI_CAPS_HCIVERSION);
|
||||
|
||||
@ -824,9 +884,11 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
|
||||
// kdebug("hcc1.xECP=%#010lx", hcc1.xECP);
|
||||
// 计算operational registers的地址
|
||||
xhci_hc[cid].vbase_op = xhci_hc[cid].vbase + xhci_read_cap_reg8(cid, XHCI_CAPS_CAPLENGTH);
|
||||
|
||||
xhci_hc[cid].db_offset = xhci_read_cap_reg32(cid, XHCI_CAPS_DBOFF) & (~0x3); // bits [1:0] reserved
|
||||
io_mfence();
|
||||
xhci_hc[cid].db_offset = xhci_read_cap_reg32(cid, XHCI_CAPS_DBOFF) & (~0x3); // bits [1:0] reserved
|
||||
io_mfence();
|
||||
xhci_hc[cid].rts_offset = xhci_read_cap_reg32(cid, XHCI_CAPS_RTSOFF) & (~0x1f); // bits [4:0] reserved.
|
||||
io_mfence();
|
||||
|
||||
xhci_hc[cid].ext_caps_off = 1UL * (hcc1.xECP) * 4;
|
||||
xhci_hc[cid].context_size = (hcc1.csz) ? 64 : 32;
|
||||
@ -845,25 +907,27 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
|
||||
pci_write_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0xd8, 0xffffffff);
|
||||
pci_write_config(dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func, 0xd0, 0xffffffff);
|
||||
}
|
||||
|
||||
io_mfence();
|
||||
// 关闭legacy支持
|
||||
FAIL_ON_TO(xhci_hc_stop_legacy(cid), failed);
|
||||
|
||||
io_mfence();
|
||||
// 重置xhci控制器
|
||||
FAIL_ON_TO(xhci_hc_reset(cid), failed);
|
||||
io_mfence();
|
||||
// 端口配对
|
||||
FAIL_ON_TO(xhci_hc_pair_ports(cid), failed);
|
||||
io_mfence();
|
||||
|
||||
// ========== 设置USB host controller =========
|
||||
// 获取页面大小
|
||||
kdebug("ops pgsize=%#010lx", xhci_read_op_reg32(cid, XHCI_OPS_PAGESIZE));
|
||||
xhci_hc[cid].page_size = (xhci_read_op_reg32(cid, XHCI_OPS_PAGESIZE) & 0xffff) << 12;
|
||||
kdebug("page size=%d", xhci_hc[cid].page_size);
|
||||
|
||||
io_mfence();
|
||||
// 获取设备上下文空间
|
||||
xhci_hc[cid].dcbaap_vaddr = (uint64_t)kmalloc(2048, 0); // 分配2KB的设备上下文地址数组空间
|
||||
memset((void *)xhci_hc[cid].dcbaap_vaddr, 0, 2048);
|
||||
|
||||
io_mfence();
|
||||
kdebug("dcbaap_vaddr=%#018lx", xhci_hc[cid].dcbaap_vaddr);
|
||||
if (unlikely(!xhci_is_aligned64(xhci_hc[cid].dcbaap_vaddr))) // 地址不是按照64byte对齐
|
||||
{
|
||||
@ -872,7 +936,7 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
|
||||
}
|
||||
// 写入dcbaap
|
||||
xhci_write_op_reg64(cid, XHCI_OPS_DCBAAP, virt_2_phys(xhci_hc[cid].dcbaap_vaddr));
|
||||
|
||||
io_mfence();
|
||||
// 创建command ring
|
||||
xhci_hc[cid].cmd_ring_vaddr = xhci_create_ring(XHCI_CMND_RING_TRBS);
|
||||
if (unlikely(!xhci_is_aligned64(xhci_hc[cid].cmd_ring_vaddr))) // 地址不是按照64byte对齐
|
||||
@ -883,17 +947,21 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
|
||||
|
||||
// 设置初始cycle bit为1
|
||||
xhci_hc[cid].cmd_trb_cycle = XHCI_TRB_CYCLE_ON;
|
||||
|
||||
io_mfence();
|
||||
// 写入command ring控制寄存器
|
||||
xhci_write_op_reg64(cid, XHCI_OPS_CRCR, virt_2_phys(xhci_hc[cid].cmd_ring_vaddr) | xhci_hc[cid].cmd_trb_cycle);
|
||||
// 写入配置寄存器
|
||||
uint32_t max_slots = hcs1.max_slots;
|
||||
kdebug("max slots = %d", max_slots);
|
||||
io_mfence();
|
||||
xhci_write_op_reg32(cid, XHCI_OPS_CONFIG, max_slots);
|
||||
io_mfence();
|
||||
// 写入设备通知控制寄存器
|
||||
xhci_write_op_reg32(cid, XHCI_OPS_DNCTRL, (1 << 1)); // 目前只有N1被支持
|
||||
io_mfence();
|
||||
|
||||
FAIL_ON_TO(xhci_hc_init_intr(cid), failed_free_dyn);
|
||||
io_mfence();
|
||||
++xhci_ctrl_count;
|
||||
spin_unlock(&xhci_controller_init_lock);
|
||||
return;
|
||||
@ -912,13 +980,15 @@ failed_free_dyn:; // 释放动态申请的内存
|
||||
kfree((void *)xhci_hc[cid].event_ring_vaddr);
|
||||
|
||||
failed:;
|
||||
io_mfence();
|
||||
// 取消地址映射
|
||||
mm_unmap(xhci_hc[cid].vbase, 65536);
|
||||
|
||||
io_mfence();
|
||||
// 清空数组
|
||||
memset((void *)&xhci_hc[cid], 0, sizeof(struct xhci_host_controller_t));
|
||||
|
||||
failed_exceed_max:;
|
||||
kerror("Failed to initialize controller: bus=%d, dev=%d, func=%d", dev_hdr->header.bus, dev_hdr->header.device, dev_hdr->header.func);
|
||||
spin_unlock(&xhci_controller_init_lock);
|
||||
}
|
||||
}
|
||||
#pragma GCC pop_options
|
@ -2,7 +2,7 @@
|
||||
#include <driver/usb/usb.h>
|
||||
#include <driver/pci/pci.h>
|
||||
#include <driver/pci/msi.h>
|
||||
|
||||
// #pragma GCC optimize("O0")
|
||||
#define XHCI_MAX_HOST_CONTROLLERS 4 // 本驱动程序最大支持4个xhci root hub controller
|
||||
#define XHCI_MAX_ROOT_HUB_PORTS 128 // 本驱动程序最大支持127个root hub 端口(第0个保留)
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <common/kprint.h>
|
||||
#include <mm/mm.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
//描述符表的结构体
|
||||
struct desc_struct
|
||||
{
|
||||
@ -184,4 +186,6 @@ void set_tss64(unsigned int *Table, unsigned long rsp0, unsigned long rsp1, unsi
|
||||
*(unsigned long *)(Table + 19) = ist6;
|
||||
*(unsigned long *)(Table + 21) = ist7;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#pragma GCC pop_options
|
@ -1,7 +1,8 @@
|
||||
|
||||
#include "irq.h"
|
||||
#include <common/errno.h>
|
||||
|
||||
// 对进行
|
||||
|
||||
#if _INTR_8259A_
|
||||
#include <driver/interrupt/8259A/8259A.h>
|
||||
#else
|
||||
@ -13,6 +14,8 @@
|
||||
#include "gate.h"
|
||||
#include <mm/slab.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
// 保存函数调用现场的寄存器
|
||||
#define SAVE_ALL_REGS \
|
||||
"cld; \n\t" \
|
||||
@ -254,3 +257,4 @@ void irq_init()
|
||||
|
||||
#endif
|
||||
}
|
||||
#pragma GCC optimize("O0")
|
@ -10,10 +10,11 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <common/glib.h>
|
||||
|
||||
#include <process/ptrace.h>
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("O0")
|
||||
|
||||
#define IRQ_NUM 24
|
||||
#define SMP_IRQ_NUM 10
|
||||
@ -165,3 +166,4 @@ int irq_unregister(ul irq_num);
|
||||
* @brief 初始化中断模块
|
||||
*/
|
||||
void irq_init();
|
||||
#pragma GCC pop_options
|
@ -34,11 +34,12 @@
|
||||
#include <driver/video/video.h>
|
||||
|
||||
#include <driver/interrupt/apic/apic_timer.h>
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O3")
|
||||
unsigned int *FR_address = (unsigned int *)0xb8000; //帧缓存区的地址
|
||||
ul bsp_idt_size, bsp_gdt_size;
|
||||
|
||||
struct memory_desc memory_management_struct = {{0}, 0};
|
||||
|
||||
// struct Global_Memory_Descriptor memory_management_struct = {{0}, 0};
|
||||
void test_slab();
|
||||
|
||||
@ -126,12 +127,19 @@ void system_initialize()
|
||||
current_pcb->preempt_count = 0;
|
||||
// 先初始化系统调用模块
|
||||
syscall_init();
|
||||
io_mfence();
|
||||
// 再初始化进程模块。顺序不能调转
|
||||
sched_init();
|
||||
io_mfence();
|
||||
|
||||
timer_init();
|
||||
|
||||
// 这里必须加内存屏障,否则会出错
|
||||
io_mfence();
|
||||
smp_init();
|
||||
io_mfence();
|
||||
|
||||
|
||||
cpu_init();
|
||||
ps2_keyboard_init();
|
||||
// ps2_mouse_init();
|
||||
@ -144,20 +152,24 @@ void system_initialize()
|
||||
|
||||
// process_init();
|
||||
HPET_init();
|
||||
io_mfence();
|
||||
HPET_measure_freq();
|
||||
io_mfence();
|
||||
// current_pcb->preempt_count = 0;
|
||||
// kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq());
|
||||
|
||||
|
||||
process_init();
|
||||
// 对显示模块进行高级初始化,启用double buffer
|
||||
video_init(true);
|
||||
io_mfence();
|
||||
|
||||
// fat32_init();
|
||||
HPET_enable();
|
||||
|
||||
|
||||
io_mfence();
|
||||
// 系统初始化到此结束,剩下的初始化功能应当放在初始内核线程中执行
|
||||
apic_timer_init();
|
||||
|
||||
io_mfence();
|
||||
}
|
||||
|
||||
//操作系统内核从这里开始执行
|
||||
@ -181,8 +193,9 @@ void Start_Kernel(void)
|
||||
mb2_magic &= 0xffffffff;
|
||||
multiboot2_magic = (uint)mb2_magic;
|
||||
multiboot2_boot_info_addr = mb2_info + PAGE_OFFSET;
|
||||
|
||||
io_mfence();
|
||||
system_initialize();
|
||||
io_mfence();
|
||||
|
||||
while (1)
|
||||
hlt();
|
||||
@ -191,5 +204,7 @@ void Start_Kernel(void)
|
||||
void ignore_int()
|
||||
{
|
||||
kwarn("Unknown interrupt or fault at RIP.\n");
|
||||
while(1);
|
||||
}
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#pragma GCC pop_options
|
@ -11,7 +11,10 @@
|
||||
static ul Total_Memory = 0;
|
||||
static ul total_2M_pages = 0;
|
||||
static ul root_page_table_phys_addr = 0; // 内核层根页表的物理地址
|
||||
// #pragma GCC push_options
|
||||
// #pragma GCC optimize("O3")
|
||||
|
||||
struct memory_desc memory_management_struct = {{0}, 0};
|
||||
/**
|
||||
* @brief 虚拟地址长度所需要的entry数量
|
||||
*
|
||||
@ -82,9 +85,10 @@ void mm_init()
|
||||
int count;
|
||||
|
||||
multiboot2_iter(multiboot2_get_memory, mb2_mem_info, &count);
|
||||
|
||||
io_mfence();
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
//可用的内存
|
||||
if (mb2_mem_info->type == 1)
|
||||
Total_Memory += mb2_mem_info->len;
|
||||
@ -103,12 +107,12 @@ void mm_init()
|
||||
printk("[ INFO ] Total amounts of RAM : %ld bytes\n", Total_Memory);
|
||||
|
||||
// 计算有效内存页数
|
||||
|
||||
io_mfence();
|
||||
for (int i = 0; i < memory_management_struct.len_e820; ++i)
|
||||
{
|
||||
if (memory_management_struct.e820[i].type != 1)
|
||||
continue;
|
||||
|
||||
io_mfence();
|
||||
// 将内存段的起始物理地址按照2M进行对齐
|
||||
ul addr_start = PAGE_2M_ALIGN(memory_management_struct.e820[i].BaseAddr);
|
||||
// 将内存段的终止物理地址的低2M区域清空,以实现对齐
|
||||
@ -117,7 +121,7 @@ void mm_init()
|
||||
// 内存段不可用
|
||||
if (addr_end <= addr_start)
|
||||
continue;
|
||||
|
||||
io_mfence();
|
||||
total_2M_pages += ((addr_end - addr_start) >> PAGE_2M_SHIFT);
|
||||
}
|
||||
kinfo("Total amounts of 2M pages : %ld.", total_2M_pages);
|
||||
@ -126,16 +130,18 @@ void mm_init()
|
||||
ul max_addr = memory_management_struct.e820[memory_management_struct.len_e820].BaseAddr + memory_management_struct.e820[memory_management_struct.len_e820].Length;
|
||||
// 初始化mms的bitmap
|
||||
// bmp的指针指向截止位置的4k对齐的上边界(防止修改了别的数据)
|
||||
io_mfence();
|
||||
memory_management_struct.bmp = (unsigned long *)((memory_management_struct.start_brk + PAGE_4K_SIZE - 1) & PAGE_4K_MASK);
|
||||
memory_management_struct.bits_size = max_addr >> PAGE_2M_SHIFT; // 物理地址空间的最大页面数
|
||||
memory_management_struct.bmp_len = (((unsigned long)(max_addr >> PAGE_2M_SHIFT) + sizeof(unsigned long) * 8 - 1) / 8) & (~(sizeof(unsigned long) - 1)); // bmp由多少个unsigned long变量组成
|
||||
io_mfence();
|
||||
|
||||
// 初始化bitmap, 先将整个bmp空间全部置位。稍后再将可用物理内存页复位。
|
||||
memset(memory_management_struct.bmp, 0xff, memory_management_struct.bmp_len);
|
||||
|
||||
io_mfence();
|
||||
kdebug("1212112");
|
||||
// 初始化内存页结构
|
||||
// 将页结构映射于bmp之后
|
||||
|
||||
memory_management_struct.pages_struct = (struct Page *)(((unsigned long)memory_management_struct.bmp + memory_management_struct.bmp_len + PAGE_4K_SIZE - 1) & PAGE_4K_MASK);
|
||||
|
||||
memory_management_struct.count_pages = max_addr >> PAGE_2M_SHIFT;
|
||||
@ -143,18 +149,25 @@ void mm_init()
|
||||
// 将pages_struct全部清空,以备后续初始化
|
||||
memset(memory_management_struct.pages_struct, 0x00, memory_management_struct.pages_struct_len); // init pages memory
|
||||
|
||||
kdebug("ffff");
|
||||
io_mfence();
|
||||
// 初始化内存区域
|
||||
memory_management_struct.zones_struct = (struct Zone *)(((ul)memory_management_struct.pages_struct + memory_management_struct.pages_struct_len + PAGE_4K_SIZE - 1) & PAGE_4K_MASK);
|
||||
io_mfence();
|
||||
// 由于暂时无法计算zone结构体的数量,因此先将其设为0
|
||||
memory_management_struct.count_zones = 0;
|
||||
io_mfence();
|
||||
// zones-struct 成员变量暂时按照5个来计算
|
||||
memory_management_struct.zones_struct_len = (10 * sizeof(struct Zone) + sizeof(ul) - 1) & (~(sizeof(ul) - 1));
|
||||
io_mfence();
|
||||
memset(memory_management_struct.zones_struct, 0x00, memory_management_struct.zones_struct_len);
|
||||
|
||||
// ==== 遍历e820数组,完成成员变量初始化工作 ===
|
||||
|
||||
kdebug("ddd");
|
||||
for (int i = 0; i < memory_management_struct.len_e820; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
if (memory_management_struct.e820[i].type != 1) // 不是操作系统可以使用的物理内存
|
||||
continue;
|
||||
ul addr_start = PAGE_2M_ALIGN(memory_management_struct.e820[i].BaseAddr);
|
||||
@ -200,7 +213,7 @@ void mm_init()
|
||||
|
||||
// 初始化0~2MB的物理页
|
||||
// 由于这个区间的内存由多个内存段组成,因此不会被以上代码初始化,需要我们手动配置page[0]。
|
||||
|
||||
io_mfence();
|
||||
memory_management_struct.pages_struct->zone = memory_management_struct.zones_struct;
|
||||
memory_management_struct.pages_struct->addr_phys = 0UL;
|
||||
set_page_attr(memory_management_struct.pages_struct, PAGE_PGT_MAPPED | PAGE_KERNEL_INIT | PAGE_KERNEL);
|
||||
@ -216,27 +229,13 @@ void mm_init()
|
||||
ZONE_NORMAL_INDEX = 0;
|
||||
ZONE_UNMAPPED_INDEX = 0;
|
||||
|
||||
/*
|
||||
for (int i = 0; i < memory_management_struct.count_zones; ++i)
|
||||
{
|
||||
struct Zone *z = memory_management_struct.zones_struct + i;
|
||||
// printk_color(ORANGE, BLACK, "zone_addr_start:%#18lx, zone_addr_end:%#18lx, zone_length:%#18lx, pages_group:%#18lx, count_pages:%#18lx\n",
|
||||
// z->zone_addr_start, z->zone_addr_end, z->zone_length, z->pages_group, z->count_pages);
|
||||
|
||||
// 1GB以上的内存空间不做映射
|
||||
// if (z->zone_addr_start >= 0x100000000 && (!ZONE_UNMAPPED_INDEX))
|
||||
// ZONE_UNMAPPED_INDEX = i;
|
||||
}
|
||||
*/
|
||||
|
||||
// kdebug("ZONE_DMA_INDEX=%d\tZONE_NORMAL_INDEX=%d\tZONE_UNMAPPED_INDEX=%d", ZONE_DMA_INDEX, ZONE_NORMAL_INDEX, ZONE_UNMAPPED_INDEX);
|
||||
// 设置内存页管理结构的地址,预留了一段空间,防止内存越界。
|
||||
memory_management_struct.end_of_struct = (ul)((ul)memory_management_struct.zones_struct + memory_management_struct.zones_struct_len + sizeof(long) * 32) & (~(sizeof(long) - 1));
|
||||
|
||||
// printk_color(ORANGE, BLACK, "code_start:%#18lx, code_end:%#18lx, data_end:%#18lx, kernel_end:%#18lx, end_of_struct:%#18lx\n",
|
||||
// memory_management_struct.kernel_code_start, memory_management_struct.kernel_code_end, memory_management_struct.kernel_data_end, memory_management_struct.kernel_end, memory_management_struct.end_of_struct);
|
||||
|
||||
|
||||
// 初始化内存管理单元结构所占的物理页的结构体
|
||||
|
||||
ul mms_max_page = (virt_2_phys(memory_management_struct.end_of_struct) >> PAGE_2M_SHIFT); // 内存管理单元所占据的序号最大的物理页
|
||||
// kdebug("mms_max_page=%ld", mms_max_page);
|
||||
|
||||
@ -245,6 +244,7 @@ void mm_init()
|
||||
// 第0个page已经在上方配置
|
||||
for (ul j = 1; j <= mms_max_page; ++j)
|
||||
{
|
||||
barrier();
|
||||
tmp_page = memory_management_struct.pages_struct + j;
|
||||
page_init(tmp_page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
|
||||
page_num = tmp_page->addr_phys >> PAGE_2M_SHIFT;
|
||||
@ -278,6 +278,7 @@ unsigned long page_init(struct Page *page, ul flags)
|
||||
if ((!page->ref_counts) || (page->attr & PAGE_SHARED))
|
||||
{
|
||||
++page->ref_counts;
|
||||
barrier();
|
||||
++page->zone->total_pages_link;
|
||||
}
|
||||
return 0;
|
||||
@ -976,4 +977,5 @@ int8_t mm_is_2M_page(uint64_t paddr)
|
||||
if(likely((paddr >> PAGE_2M_SHIFT)<total_2M_pages))
|
||||
return 1;
|
||||
else return 0;
|
||||
}
|
||||
}
|
||||
// #pragma GCC pop_options
|
@ -145,6 +145,7 @@
|
||||
do \
|
||||
{ \
|
||||
ul tmp; \
|
||||
io_mfence();\
|
||||
__asm__ __volatile__( \
|
||||
"movq %%cr3, %0\n\t" \
|
||||
"movq %0, %%cr3\n\t" \
|
||||
|
@ -348,9 +348,9 @@ ul slab_init()
|
||||
kinfo("Initializing SLAB...");
|
||||
// 将slab的内存池空间放置在mms的后方
|
||||
ul tmp_addr = memory_management_struct.end_of_struct;
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
spin_init(&kmalloc_cache_group[i].lock);
|
||||
// 将slab内存池对象的空间放置在mms的后面,并且预留4个unsigned long 的空间以防止内存越界
|
||||
kmalloc_cache_group[i].cache_pool_entry = (struct slab_obj *)memory_management_struct.end_of_struct;
|
||||
@ -370,7 +370,7 @@ ul slab_init()
|
||||
|
||||
// bmp后方预留4个unsigned long的空间防止内存越界,且按照8byte进行对齐
|
||||
memory_management_struct.end_of_struct = (ul)(memory_management_struct.end_of_struct + kmalloc_cache_group[i].cache_pool_entry->bmp_len + (sizeof(ul) << 2)) & (~(sizeof(ul) - 1));
|
||||
|
||||
io_mfence();
|
||||
// @todo:此处可优化,直接把所有位设置为0,然后再对部分不存在对应的内存对象的位设置为1
|
||||
memset(kmalloc_cache_group[i].cache_pool_entry->bmp, 0xff, kmalloc_cache_group[i].cache_pool_entry->bmp_len);
|
||||
for (int j = 0; j < kmalloc_cache_group[i].cache_pool_entry->bmp_count; ++j)
|
||||
@ -378,6 +378,7 @@ ul slab_init()
|
||||
|
||||
kmalloc_cache_group[i].count_total_using = 0;
|
||||
kmalloc_cache_group[i].count_total_free = kmalloc_cache_group[i].cache_pool_entry->count_free;
|
||||
io_mfence();
|
||||
}
|
||||
|
||||
struct Page *page = NULL;
|
||||
@ -388,13 +389,17 @@ ul slab_init()
|
||||
ul page_num = 0;
|
||||
for (int i = PAGE_2M_ALIGN(virt_2_phys(tmp_addr)) >> PAGE_2M_SHIFT; i <= tmp_page_mms_end; ++i)
|
||||
{
|
||||
|
||||
page = memory_management_struct.pages_struct + i;
|
||||
page_num = page->addr_phys >> PAGE_2M_SHIFT;
|
||||
*(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
|
||||
++page->zone->count_pages_using;
|
||||
io_mfence();
|
||||
--page->zone->count_pages_free;
|
||||
page_init(page, PAGE_KERNEL_INIT | PAGE_KERNEL | PAGE_PGT_MAPPED);
|
||||
|
||||
}
|
||||
io_mfence();
|
||||
|
||||
// 为slab内存池对象分配内存空间
|
||||
ul *virt = NULL;
|
||||
@ -406,8 +411,11 @@ ul slab_init()
|
||||
page = Virt_To_2M_Page(virt);
|
||||
|
||||
page_num = page->addr_phys >> PAGE_2M_SHIFT;
|
||||
|
||||
*(memory_management_struct.bmp + (page_num >> 6)) |= (1UL << (page_num % 64));
|
||||
|
||||
++page->zone->count_pages_using;
|
||||
io_mfence(); // 该位置必须加一个mfence,否则O3优化运行时会报错
|
||||
--page->zone->count_pages_free;
|
||||
page_init(page, PAGE_PGT_MAPPED | PAGE_KERNEL | PAGE_KERNEL_INIT);
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
#include <ktest/ktest.h>
|
||||
|
||||
// #pragma GCC push_options
|
||||
// #pragma GCC optimize("O0")
|
||||
|
||||
spinlock_t process_global_pid_write_lock; // 增加pid的写锁
|
||||
long process_global_pid = 1; // 系统中最大的pid
|
||||
|
||||
@ -100,6 +103,7 @@ uint64_t process_exit_mm(struct process_control_block *pcb);
|
||||
uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb, uint64_t stack_start, uint64_t stack_size, struct pt_regs *current_regs);
|
||||
|
||||
void process_exit_thread(struct process_control_block *pcb);
|
||||
|
||||
/**
|
||||
* @brief 切换进程
|
||||
*
|
||||
@ -108,7 +112,8 @@ void process_exit_thread(struct process_control_block *pcb);
|
||||
* 由于程序在进入内核的时候已经保存了寄存器,因此这里不需要保存寄存器。
|
||||
* 这里切换fs和gs寄存器
|
||||
*/
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
void __switch_to(struct process_control_block *prev, struct process_control_block *next)
|
||||
{
|
||||
initial_tss[proc_current_cpu_id].rsp0 = next->thread->rbp;
|
||||
@ -124,6 +129,7 @@ void __switch_to(struct process_control_block *prev, struct process_control_bloc
|
||||
__asm__ __volatile__("movq %0, %%fs \n\t" ::"a"(next->thread->fs));
|
||||
__asm__ __volatile__("movq %0, %%gs \n\t" ::"a"(next->thread->gs));
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
/**
|
||||
* @brief 打开要执行的程序文件
|
||||
@ -299,6 +305,8 @@ load_elf_failed:;
|
||||
* @param envp 环境变量
|
||||
* @return ul 错误码
|
||||
*/
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
|
||||
{
|
||||
|
||||
@ -403,6 +411,7 @@ ul do_execve(struct pt_regs *regs, char *path, char *argv[], char *envp[])
|
||||
exec_failed:;
|
||||
process_do_exit(tmp);
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
/**
|
||||
* @brief 内核init进程
|
||||
@ -410,6 +419,8 @@ exec_failed:;
|
||||
* @param arg
|
||||
* @return ul 参数
|
||||
*/
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
ul initial_kernel_thread(ul arg)
|
||||
{
|
||||
// kinfo("initial proc running...\targ:%#018lx", arg);
|
||||
@ -446,6 +457,7 @@ ul initial_kernel_thread(ul arg)
|
||||
current_pcb->thread->rip = (ul)ret_from_system_call;
|
||||
current_pcb->thread->rsp = (ul)current_pcb + STACK_SIZE - sizeof(struct pt_regs);
|
||||
current_pcb->thread->fs = USER_DS | 0x3;
|
||||
barrier();
|
||||
current_pcb->thread->gs = USER_DS | 0x3;
|
||||
|
||||
// 主动放弃内核线程身份
|
||||
@ -467,7 +479,7 @@ ul initial_kernel_thread(ul arg)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
/**
|
||||
* @brief 当子进程退出后向父进程发送通知
|
||||
*
|
||||
@ -517,23 +529,29 @@ ul process_do_exit(ul code)
|
||||
int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigned long flags)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
barrier();
|
||||
memset(®s, 0, sizeof(regs));
|
||||
|
||||
barrier();
|
||||
// 在rbx寄存器中保存进程的入口地址
|
||||
regs.rbx = (ul)fn;
|
||||
// 在rdx寄存器中保存传入的参数
|
||||
regs.rdx = (ul)arg;
|
||||
|
||||
barrier();
|
||||
regs.ds = KERNEL_DS;
|
||||
barrier();
|
||||
regs.es = KERNEL_DS;
|
||||
barrier();
|
||||
regs.cs = KERNEL_CS;
|
||||
barrier();
|
||||
regs.ss = KERNEL_DS;
|
||||
barrier();
|
||||
|
||||
// 置位中断使能标志位
|
||||
regs.rflags = (1 << 9);
|
||||
|
||||
barrier();
|
||||
// rip寄存器指向内核线程的引导程序
|
||||
regs.rip = (ul)kernel_thread_func;
|
||||
barrier();
|
||||
// kdebug("kernel_thread_func=%#018lx", kernel_thread_func);
|
||||
// kdebug("&kernel_thread_func=%#018lx", &kernel_thread_func);
|
||||
// kdebug("1111\tregs.rip = %#018lx", regs.rip);
|
||||
@ -577,23 +595,34 @@ void process_init()
|
||||
for (int i = 256; i < 512; ++i)
|
||||
{
|
||||
uint64_t *tmp = idle_pml4t_vaddr + i;
|
||||
barrier();
|
||||
if (*tmp == 0)
|
||||
{
|
||||
void *pdpt = kmalloc(PAGE_4K_SIZE, 0);
|
||||
barrier();
|
||||
memset(pdpt, 0, PAGE_4K_SIZE);
|
||||
barrier();
|
||||
set_pml4t(tmp, mk_pml4t(virt_2_phys(pdpt), PAGE_KERNEL_PGT));
|
||||
}
|
||||
}
|
||||
barrier();
|
||||
|
||||
flush_tlb();
|
||||
/*
|
||||
kdebug("initial_thread.rbp=%#018lx", initial_thread.rbp);
|
||||
kdebug("initial_tss[0].rsp1=%#018lx", initial_tss[0].rsp1);
|
||||
kdebug("initial_tss[0].ist1=%#018lx", initial_tss[0].ist1);
|
||||
*/
|
||||
// 初始化pid的写锁
|
||||
|
||||
spin_init(&process_global_pid_write_lock);
|
||||
|
||||
// 初始化进程的循环链表
|
||||
list_init(&initial_proc_union.pcb.list);
|
||||
barrier();
|
||||
kernel_thread(initial_kernel_thread, 10, CLONE_FS | CLONE_SIGNAL); // 初始化内核线程
|
||||
barrier();
|
||||
|
||||
initial_proc_union.pcb.state = PROC_RUNNING;
|
||||
initial_proc_union.pcb.preempt_count = 0;
|
||||
initial_proc_union.pcb.cpu_id = 0;
|
||||
@ -617,6 +646,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
|
||||
|
||||
// 为新的进程分配栈空间,并将pcb放置在底部
|
||||
tsk = (struct process_control_block *)kmalloc(STACK_SIZE, 0);
|
||||
barrier();
|
||||
|
||||
if (tsk == NULL)
|
||||
{
|
||||
@ -624,13 +654,17 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
|
||||
return retval;
|
||||
}
|
||||
|
||||
barrier();
|
||||
memset(tsk, 0, sizeof(struct process_control_block));
|
||||
io_mfence();
|
||||
// 将当前进程的pcb复制到新的pcb内
|
||||
memcpy(tsk, current_pcb, sizeof(struct process_control_block));
|
||||
io_mfence();
|
||||
|
||||
// 初始化进程的循环链表结点
|
||||
list_init(&tsk->list);
|
||||
|
||||
io_mfence();
|
||||
// 判断是否为内核态调用fork
|
||||
if (current_pcb->flags & PF_KTHREAD && stack_start != 0)
|
||||
tsk->flags |= PF_KFORK;
|
||||
@ -641,11 +675,14 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
|
||||
// 增加全局的pid并赋值给新进程的pid
|
||||
spin_lock(&process_global_pid_write_lock);
|
||||
tsk->pid = process_global_pid++;
|
||||
|
||||
barrier();
|
||||
// 加入到进程链表中
|
||||
tsk->next_pcb = initial_proc_union.pcb.next_pcb;
|
||||
barrier();
|
||||
initial_proc_union.pcb.next_pcb = tsk;
|
||||
barrier();
|
||||
tsk->parent_pcb = current_pcb;
|
||||
barrier();
|
||||
|
||||
spin_unlock(&process_global_pid_write_lock);
|
||||
|
||||
@ -654,7 +691,7 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
|
||||
|
||||
tsk->parent_pcb = current_pcb;
|
||||
wait_queue_init(&tsk->wait_child_proc_exit, NULL);
|
||||
|
||||
barrier();
|
||||
list_init(&tsk->list);
|
||||
|
||||
retval = -ENOMEM;
|
||||
@ -1047,6 +1084,7 @@ uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block
|
||||
|
||||
child_regs = (struct pt_regs *)(((uint64_t)pcb) + STACK_SIZE - size);
|
||||
memcpy(child_regs, (void *)current_regs, size);
|
||||
barrier();
|
||||
// 然后重写新的栈中,每个栈帧的rbp值
|
||||
process_rewrite_rbp(child_regs, pcb);
|
||||
}
|
||||
@ -1054,6 +1092,7 @@ uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block
|
||||
{
|
||||
child_regs = (struct pt_regs *)((uint64_t)pcb + STACK_SIZE - sizeof(struct pt_regs));
|
||||
memcpy(child_regs, current_regs, sizeof(struct pt_regs));
|
||||
barrier();
|
||||
child_regs->rsp = stack_start;
|
||||
}
|
||||
|
||||
@ -1087,4 +1126,6 @@ uint64_t process_copy_thread(uint64_t clone_flags, struct process_control_block
|
||||
*/
|
||||
void process_exit_thread(struct process_control_block *pcb)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// #pragma GCC pop_options
|
@ -9,7 +9,6 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <common/cpu.h>
|
||||
#include <common/glib.h>
|
||||
#include <mm/mm.h>
|
||||
@ -19,6 +18,8 @@
|
||||
#include <filesystem/VFS/VFS.h>
|
||||
#include <common/wait_queue.h>
|
||||
|
||||
|
||||
|
||||
// 进程最大可拥有的文件描述符数量
|
||||
#define PROC_MAX_FD_NUM 16
|
||||
|
||||
@ -213,17 +214,21 @@ struct tss_struct
|
||||
.io_map_base_addr = 0 \
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("O0")
|
||||
// 获取当前的pcb
|
||||
struct process_control_block *get_current_pcb()
|
||||
{
|
||||
struct process_control_block *current = NULL;
|
||||
// 利用了当前pcb和栈空间总大小为32k大小对齐,将rsp低15位清空,即可获得pcb的起始地址
|
||||
barrier();
|
||||
__asm__ __volatile__("andq %%rsp, %0 \n\t"
|
||||
: "=r"(current)
|
||||
: "0"(~32767UL));
|
||||
barrier();
|
||||
return current;
|
||||
};
|
||||
|
||||
#pragma GCC pop_options
|
||||
#define current_pcb get_current_pcb()
|
||||
|
||||
#define GET_CURRENT_PCB \
|
||||
@ -350,7 +355,7 @@ int kernel_thread(unsigned long (*fn)(unsigned long), unsigned long arg, unsigne
|
||||
asm volatile("movq %0, %%cr3 \n\t" ::"r"(next_pcb->mm->pgd) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
// flush_tlb(); \
|
||||
// flush_tlb();
|
||||
|
||||
// 获取当前cpu id
|
||||
#define proc_current_cpu_id (current_pcb->cpu_id)
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <driver/video/video.h>
|
||||
#include <common/spinlock.h>
|
||||
|
||||
|
||||
struct sched_queue_t sched_cfs_ready_queue[MAX_CPU_NUM]; // 就绪队列
|
||||
|
||||
/**
|
||||
|
@ -45,4 +45,5 @@ void sched_init();
|
||||
* @brief 当时钟中断到达时,更新时间片
|
||||
*
|
||||
*/
|
||||
void sched_update_jiffies();
|
||||
void sched_update_jiffies();
|
||||
|
||||
|
@ -30,43 +30,51 @@ void smp_init()
|
||||
|
||||
// kdebug("processor num=%d", total_processor_num);
|
||||
for (int i = 0; i < total_processor_num; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
proc_local_apic_structs[i] = (struct acpi_Processor_Local_APIC_Structure_t *)(tmp_vaddr[i]);
|
||||
}
|
||||
|
||||
//*(uchar *)0x20000 = 0xf4; // 在内存的0x20000处写入HLT指令(AP处理器会执行物理地址0x20000的代码)
|
||||
// 将引导程序复制到物理地址0x20000处
|
||||
memcpy((unsigned char *)phys_2_virt(0x20000), _apu_boot_start, (unsigned long)&_apu_boot_end - (unsigned long)&_apu_boot_start);
|
||||
|
||||
io_mfence();
|
||||
// 设置多核IPI中断门
|
||||
for (int i = 200; i < 210; ++i)
|
||||
set_intr_gate(i, 0, SMP_interrupt_table[i - 200]);
|
||||
|
||||
memset((void *)SMP_IPI_desc, 0, sizeof(irq_desc_t) * SMP_IRQ_NUM);
|
||||
|
||||
io_mfence();
|
||||
|
||||
// 注册接收bsp处理器的hpet中断转发的处理函数
|
||||
ipi_regiserIPI(0xc8, NULL, &ipi_0xc8_handler, NULL, NULL, "IPI 0xc8");
|
||||
|
||||
io_mfence();
|
||||
ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x00, ICR_INIT, ICR_ALL_EXCLUDE_Self, true, 0x00);
|
||||
kdebug("total_processor_num=%d", total_processor_num);
|
||||
for (int i = 1; i < total_processor_num; ++i) // i从1开始,不初始化bsp
|
||||
{
|
||||
io_mfence();
|
||||
if (proc_local_apic_structs[i]->ACPI_Processor_UID == 0)
|
||||
--total_processor_num;
|
||||
io_mfence();
|
||||
if (proc_local_apic_structs[i]->local_apic_id > total_processor_num)
|
||||
{
|
||||
--total_processor_num;
|
||||
continue;}
|
||||
{
|
||||
--total_processor_num;
|
||||
continue;
|
||||
}
|
||||
kdebug("[core %d] acpi processor UID=%d, APIC ID=%d, flags=%#010lx", i, proc_local_apic_structs[i]->ACPI_Processor_UID, proc_local_apic_structs[i]->local_apic_id, proc_local_apic_structs[i]->flags);
|
||||
|
||||
io_mfence();
|
||||
spin_lock(&multi_core_starting_lock);
|
||||
preempt_enable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,bsp的自旋锁持有计数不会发生改变,需要手动恢复preempt count
|
||||
preempt_enable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,bsp的自旋锁持有计数不会发生改变,需要手动恢复preempt count
|
||||
current_starting_cpu = proc_local_apic_structs[i]->local_apic_id;
|
||||
|
||||
|
||||
io_mfence();
|
||||
// 为每个AP处理器分配栈空间
|
||||
cpu_core_info[current_starting_cpu].stack_start = (uint64_t)kmalloc(STACK_SIZE, 0) + STACK_SIZE;
|
||||
cpu_core_info[current_starting_cpu].ist_stack_start = (uint64_t)(kmalloc(STACK_SIZE, 0)) + STACK_SIZE;
|
||||
io_mfence();
|
||||
memset((void *)cpu_core_info[current_starting_cpu].stack_start - STACK_SIZE, 0, STACK_SIZE);
|
||||
memset((void *)cpu_core_info[current_starting_cpu].ist_stack_start - STACK_SIZE, 0, STACK_SIZE);
|
||||
io_mfence();
|
||||
|
||||
// 设置ap处理器的中断栈及内核栈中的cpu_id
|
||||
((struct process_control_block *)(cpu_core_info[current_starting_cpu].stack_start - STACK_SIZE))->cpu_id = proc_local_apic_structs[i]->local_apic_id;
|
||||
@ -77,18 +85,18 @@ void smp_init()
|
||||
memset(&initial_tss[current_starting_cpu], 0, sizeof(struct tss_struct));
|
||||
|
||||
set_tss_descriptor(10 + (current_starting_cpu * 2), (void *)(cpu_core_info[current_starting_cpu].tss_vaddr));
|
||||
|
||||
io_mfence();
|
||||
set_tss64((uint *)cpu_core_info[current_starting_cpu].tss_vaddr, cpu_core_info[current_starting_cpu].stack_start, cpu_core_info[current_starting_cpu].stack_start, cpu_core_info[current_starting_cpu].stack_start,
|
||||
cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start, cpu_core_info[current_starting_cpu].ist_stack_start);
|
||||
|
||||
io_mfence();
|
||||
// 连续发送两次start-up IPI
|
||||
ipi_send_IPI(DEST_PHYSICAL, IDLE, ICR_LEVEL_DE_ASSERT, EDGE_TRIGGER, 0x20, ICR_Start_up, ICR_No_Shorthand, true, 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, true, proc_local_apic_structs[i]->local_apic_id);
|
||||
}
|
||||
|
||||
io_mfence();
|
||||
while (num_cpu_started != total_processor_num)
|
||||
__asm__ __volatile__("pause" ::
|
||||
: "memory");
|
||||
pause();
|
||||
|
||||
kinfo("Cleaning page table remapping...\n");
|
||||
|
||||
@ -96,6 +104,7 @@ void smp_init()
|
||||
uint64_t *global_CR3 = get_CR3();
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
io_mfence();
|
||||
*(ul *)(phys_2_virt(global_CR3) + i) = 0UL;
|
||||
}
|
||||
kdebug("init proc's preempt_count=%ld", current_pcb->preempt_count);
|
||||
@ -121,7 +130,7 @@ void smp_ap_start()
|
||||
__asm__ __volatile__("movq %0, %%rsp \n\t" ::"m"(stack_start)
|
||||
: "memory");*/
|
||||
ksuccess("AP core successfully started!");
|
||||
|
||||
io_mfence();
|
||||
++num_cpu_started;
|
||||
|
||||
kdebug("current cpu = %d", current_starting_cpu);
|
||||
@ -154,7 +163,8 @@ void smp_ap_start()
|
||||
|
||||
// kdebug("IDT_addr = %#018lx", phys_2_virt(IDT_Table));
|
||||
spin_unlock(&multi_core_starting_lock);
|
||||
preempt_disable();// 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,需要手动恢复preempt count
|
||||
preempt_disable(); // 由于ap处理器的pcb与bsp的不同,因此ap处理器放锁时,需要手动恢复preempt count
|
||||
io_mfence();
|
||||
sti();
|
||||
|
||||
while (1)
|
||||
@ -176,4 +186,4 @@ void smp_ap_start()
|
||||
void ipi_0xc8_handler(uint64_t irq_num, uint64_t param, struct pt_regs *regs)
|
||||
{
|
||||
sched_update_jiffies();
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,18 @@ extern uint64_t sys_clock(struct pt_regs *regs);
|
||||
* @brief 导出系统调用处理函数的符号
|
||||
*
|
||||
*/
|
||||
#define SYSCALL_COMMON(syscall_num, symbol) extern unsigned long symbol(struct pt_regs *regs);
|
||||
SYSCALL_COMMON(0, system_call_not_exists); // 导出system_call_not_exists函数
|
||||
#undef SYSCALL_COMMON // 取消前述宏定义
|
||||
|
||||
/**
|
||||
* @brief 系统调用不存在时的处理函数
|
||||
*
|
||||
* @param regs 进程3特权级下的寄存器
|
||||
* @return ul
|
||||
*/
|
||||
ul system_call_not_exists(struct pt_regs *regs)
|
||||
{
|
||||
kerror("System call [ ID #%d ] not exists.", regs->rax);
|
||||
return ESYSCALL_NOT_EXISTS;
|
||||
} // 取消前述宏定义
|
||||
|
||||
/**
|
||||
* @brief 重新定义为:把系统调用函数加入系统调用表
|
||||
|
@ -36,11 +36,7 @@ long enter_syscall_int(ul syscall_id, ul arg0, ul arg1, ul arg2, ul arg3, ul arg
|
||||
* @param regs 进程3特权级下的寄存器
|
||||
* @return ul
|
||||
*/
|
||||
ul system_call_not_exists(struct pt_regs *regs)
|
||||
{
|
||||
kerror("System call [ ID #%d ] not exists.", regs->rax);
|
||||
return ESYSCALL_NOT_EXISTS;
|
||||
}
|
||||
ul system_call_not_exists(struct pt_regs *regs);
|
||||
|
||||
/**
|
||||
* @brief 打印字符串的系统调用
|
||||
|
9
tools/batch_delete_loop.py
Normal file
9
tools/batch_delete_loop.py
Normal file
@ -0,0 +1,9 @@
|
||||
import os
|
||||
|
||||
start = int(input("Start from: "))
|
||||
end = int(input("End at: "))
|
||||
|
||||
for i in range(start, end+1):
|
||||
print("Deleting: " + str(i))
|
||||
os.system("sudo losetup -d /dev/loop" + str(i))
|
||||
print("Done!")
|
Loading…
x
Reference in New Issue
Block a user