改用int250作为系统调用

This commit is contained in:
fslongjin
2022-04-12 11:54:44 +08:00
parent 011246281a
commit 2d7b2b7048
15 changed files with 236 additions and 104 deletions

View File

@ -436,7 +436,6 @@ void apic_init()
{
RCBA_vaddr = 0;
kwarn("Cannot get RCBA address. RCBA_phys=%#010lx", RCBA_phys);
}
sti();
}
@ -448,50 +447,60 @@ void apic_init()
*/
void do_IRQ(struct pt_regs *rsp, ul number)
{
switch (number & 0x80) // 以0x80为界限低于0x80的是外部中断控制器高于0x80的是Local APIC
if (number < 0x80) // 以0x80为界限低于0x80的是外部中断控制器高于0x80的是Local APIC
// 外部中断控制器
{
case 0x00: // 外部中断控制器
/* code */
irq_desc_t *irq = &interrupt_desc[number - 32];
// 执行中断上半部处理程序
if (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
{
irq_desc_t *irq = &interrupt_desc[number - 32];
// 执行中断上半部处理程序
if (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表示结束中断
__asm__ __volatile__("movq $0x00, %%rdx \n\t"
"movq $0x00, %%rax \n\t"
"movq $0x80b, %%rcx \n\t"
"wrmsr \n\t" ::
: "memory");
}
// 向EOI寄存器写入0x00表示结束中断
__asm__ __volatile__("movq $0x00, %%rdx \n\t"
"movq $0x00, %%rax \n\t"
"movq $0x80b, %%rcx \n\t"
"wrmsr \n\t" ::
: "memory");
}
break;
case 0x80:
}
else if (number >= 0x80 && number != 250)
{
printk_color(RED, BLACK, "SMP IPI [ %d ]\n", number);
apic_local_apic_edge_ack(number);
default:
}
else if (number == 250) // 系统调用
{
kdebug("receive syscall");
kdebug("rflags=%#010lx", rsp->rflags);
}
else
{
kwarn("do IRQ receive: %d", number);
break;
}
// 检测是否有未处理的软中断
if (softirq_status != 0)
do_softirq();
// 检测当前进程是否可被调度
struct process_control_block *current_proc = get_current_pcb();
if (current_proc->flags & PROC_NEED_SCHED)
if (current_pcb->flags & PROC_NEED_SCHED)
{
sched_cfs();
}
}
/**

View File

@ -50,6 +50,7 @@ hardware_intr_controller HPET_intr_controller =
void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
{
printk("(HPET)");
switch (param)
{
case 0: // 定时器0中断
@ -73,7 +74,10 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
}
if (sched_cfs_ready_queue.cpu_exec_proc_jiffies <= 0)
{
current_pcb->flags |= PROC_NEED_SCHED;
kdebug("need_sched. proc_jiffies=%ld", sched_cfs_ready_queue.cpu_exec_proc_jiffies);
}
break;
@ -138,7 +142,7 @@ int HPET_init()
// 由于这段内存与io/apic的映射在同一物理页内因此不需要重复映射
HPET_REG_BASE = SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + hpet_table->address;
}
// 读取计时精度并计算频率
uint64_t tmp;
tmp = *(uint64_t *)(HPET_REG_BASE + GCAP_ID);
@ -152,18 +156,22 @@ int HPET_init()
// 使用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);
*(uint64_t *)(HPET_REG_BASE + GEN_CONF) = 3; // 置位旧设备中断路由兼容标志位、定时器组使能标志位
io_mfence();
*(uint64_t *)(HPET_REG_BASE + MAIN_CNT) = 0;
io_mfence();
*(uint64_t *)(HPET_REG_BASE + TIM0_CONF) = 0x004c; // 设置定时器0为周期定时边沿触发投递到IO APIC的2号引脚这里有点绕写的是8259的引脚号但是因为禁用了8259因此会被路由到IO APIC的2号引脚
io_mfence();
*(uint64_t *)(HPET_REG_BASE + TIM0_COMP) = HPET_freq; // 1s触发一次中断
io_mfence();
rtc_get_cmos_time(&rtc_now);
*(uint64_t *)(HPET_REG_BASE + MAIN_CNT) = 0;
kinfo("HPET Initialized.");
*(uint64_t *)(HPET_REG_BASE + GEN_CONF) = 3; // 置位旧设备中断路由兼容标志位、定时器组使能标志位
io_mfence();
// 注册中断
irq_register(34, &entry, &HPET_handler, 0, &HPET_intr_controller, "HPET0");
kinfo("HPET Initialized.");
}

View File

@ -22,7 +22,7 @@ enum CMOSTimeSelector
int rtc_get_cmos_time(struct rtc_time_t *t)
{
// 为防止中断请求打断该过程,需要先关中断
//cli();
cli();
uint8_t status_register_B = read_cmos(0x0B); // 读取状态寄存器B
bool is_24h = ((status_register_B & 0x02) ? true : false); // 判断是否启用24小时模式
@ -53,6 +53,6 @@ int rtc_get_cmos_time(struct rtc_time_t *t)
if ((!is_24h) && t->hour & 0x80) // 将十二小时制转为24小时
t->hour = ((t->hour & 0x7f) + 12) % 24;
//sti();
sti();
return 0;
}