mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 08:06:32 +00:00
🔧 改用local apic定时器进行进程时间片更新
This commit is contained in:
@ -20,6 +20,17 @@ uint local_apic_max_LVT_entries;
|
||||
|
||||
static struct acpi_Multiple_APIC_Description_Table_t *madt;
|
||||
static struct acpi_IO_APIC_Structure_t *io_apic_ICS;
|
||||
|
||||
#define send_EOI() \
|
||||
do \
|
||||
{ \
|
||||
__asm__ __volatile__("movq $0x00, %%rdx \n\t" \
|
||||
"movq $0x00, %%rax \n\t" \
|
||||
"movq $0x80b, %%rcx \n\t" \
|
||||
"wrmsr \n\t" :: \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 初始化io_apic
|
||||
*
|
||||
@ -235,7 +246,7 @@ void apic_local_apic_init()
|
||||
// 检测是否成功启用xAPIC和x2APIC
|
||||
if (eax & 0xc00)
|
||||
kinfo("xAPIC & x2APIC enabled!");
|
||||
|
||||
|
||||
/*
|
||||
io_mfence();
|
||||
uint *svr = (uint *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + LOCAL_APIC_OFFSET_Local_APIC_SVR);
|
||||
@ -378,6 +389,10 @@ void apic_init()
|
||||
for (int i = 32; i <= 55; ++i)
|
||||
set_intr_gate(i, 0, interrupt_table[i - 32]);
|
||||
|
||||
// 设置local apic中断门
|
||||
for (int i = 150; i < 160; ++i)
|
||||
set_intr_gate(i, 0, local_apic_interrupt_table[i - 150]);
|
||||
|
||||
/*
|
||||
// 初始化主芯片
|
||||
io_out8(0x20, 0x11); // 初始化主芯片的icw1
|
||||
@ -461,7 +476,7 @@ void do_IRQ(struct pt_regs *rsp, ul number)
|
||||
// ps: 当前已经将系统调用直接使用系统调用门实现,不走这里。。
|
||||
do_syscall_int(rsp, 0);
|
||||
}
|
||||
else if (number > 0x80)
|
||||
else if (number >= 200)
|
||||
|
||||
{
|
||||
// printk_color(RED, BLACK, "SMP IPI [ %d ]\n", number);
|
||||
@ -473,6 +488,25 @@ void do_IRQ(struct pt_regs *rsp, ul number)
|
||||
irq->handler(number, irq->parameter, rsp);
|
||||
}
|
||||
}
|
||||
else if (number >= 150 && number < 160)
|
||||
{
|
||||
irq_desc_t *irq = &local_apic_interrupt_desc[number - 150];
|
||||
|
||||
// 执行中断上半部处理程序
|
||||
if (irq != NULL && irq->handler != NULL)
|
||||
irq->handler(number, irq->parameter, rsp);
|
||||
else
|
||||
kwarn("Intr vector [%d] does not have a handler!");
|
||||
// 向中断控制器发送应答消息
|
||||
if (irq->controller != NULL && irq->controller->ack != NULL)
|
||||
irq->controller->ack(number);
|
||||
else
|
||||
{
|
||||
|
||||
// 向EOI寄存器写入0x00表示结束中断
|
||||
send_EOI();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -482,7 +516,7 @@ void do_IRQ(struct pt_regs *rsp, ul number)
|
||||
// kdebug("before softirq");
|
||||
// 进入软中断处理程序
|
||||
do_softirq();
|
||||
|
||||
|
||||
// kdebug("after softirq");
|
||||
// 检测当前进程是否持有自旋锁,若持有自旋锁,则不进行抢占式的进程调度
|
||||
if (current_pcb->preempt_count > 0)
|
||||
|
@ -202,7 +202,7 @@ struct apic_IO_APIC_RTE_entry
|
||||
// 屏蔽
|
||||
#define UNMASKED 0
|
||||
#define MASKED 1
|
||||
#define APIC_LVT_INT_MASKED 0x10000
|
||||
#define APIC_LVT_INT_MASKED 0x10000UL
|
||||
|
||||
// 触发模式
|
||||
#define EDGE_TRIGGER 0 // 边沿触发
|
||||
|
@ -1,3 +1,84 @@
|
||||
#include "apic_timer.h"
|
||||
#include <exception/irq.h>
|
||||
#include <process/process.h>
|
||||
#include <common/kprint.h>
|
||||
#include <sched/sched.h>
|
||||
|
||||
uint64_t apic_timer_ticksIn1ms = 0;
|
||||
uint64_t apic_timer_ticks_result = 0;
|
||||
|
||||
void apic_timer_enable(uint64_t irq_num)
|
||||
{
|
||||
// 启动apic定时器
|
||||
uint64_t val = apic_timer_get_LVT();
|
||||
val &= (~APIC_LVT_INT_MASKED);
|
||||
apic_timer_write_LVT(val);
|
||||
}
|
||||
|
||||
void apic_timer_disable(uint64_t irq_num)
|
||||
{
|
||||
apic_timer_stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 安装local apic定时器中断
|
||||
*
|
||||
* @param irq_num 中断向量号
|
||||
* @param arg 初始计数值
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t apic_timer_install(ul irq_num, void *arg)
|
||||
{
|
||||
// 设置div16
|
||||
apic_timer_stop();
|
||||
apic_timer_set_div(APIC_TIMER_DIVISOR);
|
||||
|
||||
// 设置初始计数
|
||||
apic_timer_set_init_cnt(*(uint64_t *)arg);
|
||||
// 填写LVT
|
||||
apic_timer_set_LVT(APIC_TIMER_IRQ_NUM, 1, APIC_LVT_Timer_Periodic);
|
||||
}
|
||||
|
||||
void apic_timer_uninstall(ul irq_num)
|
||||
{
|
||||
apic_timer_write_LVT(APIC_LVT_INT_MASKED);
|
||||
}
|
||||
|
||||
hardware_intr_controller apic_timer_intr_controller =
|
||||
{
|
||||
.enable = apic_timer_enable,
|
||||
.disable = apic_timer_disable,
|
||||
.install = apic_timer_install,
|
||||
.uninstall = apic_timer_uninstall,
|
||||
.ack = apic_local_apic_edge_ack,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief local apic定时器的中断处理函数
|
||||
*
|
||||
* @param number 中断向量号
|
||||
* @param param 参数
|
||||
* @param regs 寄存器值
|
||||
*/
|
||||
void apic_timer_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
|
||||
{
|
||||
|
||||
sched_update_jiffies();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化local APIC定时器
|
||||
*
|
||||
*/
|
||||
void apic_timer_init()
|
||||
{
|
||||
if (apic_timer_ticks_result == 0)
|
||||
{
|
||||
kBUG("APIC timer ticks in 5ms is equal to ZERO!");
|
||||
while (1)
|
||||
hlt();
|
||||
}
|
||||
kinfo("Initializing apic timer for cpu %d", proc_current_cpu_id);
|
||||
|
||||
irq_register(APIC_TIMER_IRQ_NUM, &apic_timer_ticks_result, &apic_timer_handler, 0, &apic_timer_intr_controller, "apic timer");
|
||||
kinfo("Successfully initialized apic timer for cpu %d", proc_current_cpu_id);
|
||||
}
|
@ -3,7 +3,12 @@
|
||||
#include <common/unistd.h>
|
||||
#include "apic.h"
|
||||
|
||||
extern uint64_t apic_timer_ticksIn1ms;
|
||||
extern uint64_t apic_timer_ticks_result;
|
||||
// 5ms产生一次中断
|
||||
#define APIC_TIMER_INTERVAL 5
|
||||
#define APIC_TIMER_DIVISOR 3
|
||||
|
||||
#define APIC_TIMER_IRQ_NUM 151
|
||||
|
||||
/**
|
||||
* @brief 设置apic定时器的分频计数
|
||||
@ -27,34 +32,50 @@ extern uint64_t apic_timer_ticksIn1ms;
|
||||
wrmsr(0x838, init_cnt); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 停止apic定时器
|
||||
*
|
||||
*/
|
||||
#define apic_timer_stop() \
|
||||
do \
|
||||
{ \
|
||||
wrmsr(0x832, APIC_LVT_INT_MASKED); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 设置apic定时器的lvt,并启动定时器
|
||||
*
|
||||
* @param vector 中断向量号
|
||||
* @param mask 是否屏蔽(1:屏蔽, 0:不屏蔽)
|
||||
* @param mode 计时模式
|
||||
*/
|
||||
#define apic_timer_set_LVT(vector, mode) \
|
||||
do \
|
||||
{ \
|
||||
wrmsr(0x832, (mode << 17) | vector); \
|
||||
io_mfence(); \
|
||||
#define apic_timer_set_LVT(vector, mask, mode) \
|
||||
do \
|
||||
{ \
|
||||
wrmsr(0x832, (mode << 17) | vector | (mask ? (APIC_LVT_INT_MASKED) : 0)); \
|
||||
} while (0)
|
||||
|
||||
#define apic_timer_write_LVT(value) \
|
||||
do \
|
||||
{ \
|
||||
wrmsr(0x832, value); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 获取apic定时器的LVT的值
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define apic_timer_get_LVT() (rdmsr(0x832))
|
||||
/**
|
||||
* @brief 获取apic定时器当前计数值
|
||||
*
|
||||
*/
|
||||
#define apic_timer_get_current() (rdmsr(0x839))
|
||||
#define apic_timer_get_current() (rdmsr(0x839))
|
||||
|
||||
/**
|
||||
* @brief 停止apic定时器
|
||||
*
|
||||
*/
|
||||
#define apic_timer_stop() \
|
||||
do \
|
||||
{ \
|
||||
uint64_t val = apic_timer_get_LVT(); \
|
||||
val |= APIC_LVT_INT_MASKED; \
|
||||
apic_timer_write_LVT(val); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 初始化local APIC定时器
|
||||
*
|
||||
*/
|
||||
void apic_timer_init();
|
Reference in New Issue
Block a user