- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在编写一个业余爱好操作系统,并且正在尝试在内核中进行中断/异常处理。我在环 0,所以没有权限间堆栈切换等。这些是我的惯例:
#include <stdint.h>
#include "dadio.h"
#define MAX_INTERRUPTS 256
#define IDT_DESC_BIT16 0x06 //00000110
#define IDT_DESC_BIT32 0x0E //00001110
#define IDT_DESC_RING1 0x40 //01000000
#define IDT_DESC_RING2 0x20 //00100000
#define IDT_DESC_RING3 0x60 //01100000
#define IDT_DESC_PRESENT 0x80//10000000
//Structs used in this routine
typedef struct __attribute__ ((__packed__)) idtr {
uint16_t limit;
uint32_t base;
}idtr_t;
typedef struct __attribute__ ((__packed__)) gdtr {
uint16_t limit;
uint32_t base;
}gdtr_t;
typedef struct __attribute__ ((__packed__)) idt_descriptor {
uint16_t baseLo;
uint16_t sel;
uint8_t reserved;
uint8_t flags;
uint16_t baseHi;
}idt_descriptor_t;
typedef struct __attribute__((__packed__)) gdt_descriptor {
uint16_t limit;
uint16_t baseLo;
uint8_t baseMid;
uint16_t flags;
uint8_t baseHi;
} gdt_descriptor_t;
//External assembly functions
void init_pic();
void install_idt(idtr_t* address);
void enable_interrupts();
//Global variables in this routine
static idt_descriptor_t _idt[MAX_INTERRUPTS];
static idtr_t _idtr; //This will be the 6 byte base + limit
//Helper functions
static void install_ir(uint32_t index,uint16_t flags, uint16_t sel, uint32_t* handler_address);
static void default_handler();
void idt_init()
{
_idtr.base = (uint32_t)_idt;
_idtr.limit = (sizeof (idt_descriptor_t) * MAX_INTERRUPTS) -1 ;
for (int i=0;i<MAX_INTERRUPTS;i++)
{
_idt[i].baseLo = 0;
_idt[i].sel = 0;
_idt[i].reserved = 0;
_idt[i].flags = 0;
_idt[i].baseHi = 0;
}
for (int i=0;i<MAX_INTERRUPTS;i++)
install_ir(i,IDT_DESC_BIT32 | IDT_DESC_PRESENT, 0x08, (uint32_t*) default_handler);
init_pic();
install_idt(& _idtr);
enable_interrupts();
}
static void install_ir(uint32_t index,uint16_t flags, uint16_t sel, uint32_t* handler_address)
{
if (index >=MAX_INTERRUPTS) return;
_idt[index].baseLo = (uint32_t)handler_address & 0xffff;
_idt[index].baseHi = ((uint32_t)handler_address >> 16) & 0xffff;
_idt[index].reserved = 0;
_idt[index].flags = flags;
_idt[index].sel = sel;
}
static void default_handler()
{
monitor-puts("This is the default exception handler"); //This is a routine that prints messages on the screen... The gist is that it writes to 0xb8000 and so on...
for (;;);
}
汇编例程
init_pic:
mov al, 0x11 ;ICW 1 ;Expect IC4|single?|0|level?|init?|000
out 0x20,al
out 0xA0,al
mov al,0x20 ;Remapping the IRQs
out 0x21,al
mov al,0x28
out 0xA1,al
; Send ICW 3 to primary PIC
mov al, 0x4 ; 0x4 = 0100 Second bit (IR Line 2)
out 0x21, al ; write to data register of primary PIC
; Send ICW 3 to secondary PIC
mov al, 0x2 ; 010=> IR line 2
out 0xA1, al ; write to data register of secondary PIC
; Send ICW 4 - Set x86 mode --------------------------------
mov al, 1 ; bit 0 enables 80x86 mode
out 0x21, al
out 0xA1, al
; Zeroing out the data registers
mov al, 0
out 0x21, al
out 0xA1, al
ret
enable_interrupts:
sti
ret
最小内核是:
void kmain()
{
idt_init();
return;
}
如果我注释掉 idt_init 函数中的 init_pic(),我会收到消息:这是默认异常处理程序,后跟 for(;;) 。我认为这是预期的,因为一旦我启用中断,计时器之类的东西就会发送 IRQ,并且由于它默认映射到(除以零?)异常,我会收到我定义的处理程序消息。
但是如果我取消注释 init_pic(),我就不会收到该消息。据我了解,IRQ (0-15) 已重新映射到中断 vector (32 - 47)。但计时器中断仍然会触发,我应该收到消息。 (我认为,在我的例子中,所有 256 个可能的中断/异常都映射到同一个例程)。我哪里出错了?
另外,还有一个小后续问题。我知道有些异常会推送错误代码,而有些则不会。但 iret 指令不可能知道这一点,对吧?那么程序员是否有责任手动添加到 esp(弹出异常的错误代码确实会推送错误),然后执行 iret?
我读过 80386 开发人员手册,从中我了解到这一点。我是不是哪里说错了?
PS:尽管我的项目有更多代码,但我已尝试提供最少的代码。
最佳答案
一个关键点可能是当 kmain 返回时会发生什么?
后续问题很重要:你必须在 iret 之前清理堆栈。仅出于这个原因,将您的大门指向 C 函数确实很麻烦。大多数人都会制作两个程序集 stub :
#define SAVE() pusha; push %ds; push %es; push %fs; push %gs
#define RESTORE() pop %gs; pop %fs; pop %es; pop %ds; popa
#define TRAP0(n) .global vec#n; vec#n: \
pushl $(n<<8); \
pushl $0; \
SAVE(); \
call generic(); \
RESTORE(); \
add $8, %esp; \
iret
#define TRAP1(n) .global vec#n; vec#n: \
movw $n, 2(%esp); \
pushl $0; \
SAVE();\
call generic(); \
RESTORE(); \
add $8, %esp; \
iret
#define PTRAP(n) .global vec#n; vec#n: \
movw $n, 2(%esp);\
pushl $0; SAVE();\
mov %cr3, %eax; \
mov %eax, (12*4)(%esp); \
call generic(); \
RESTORE(); \
add $8, %esp; \
iret
TRAP0(0); TRAP0(1); ... TRAP0(7);
TRAP1(8); TRAP0(9);
TRAP1(10); ...TRAP1(13);
PTRAP(14); TRAP1(15); ...; TRAP1(31);
/* interrupts: */
TRAP0(32); TRAP0(33); .... TRAP0(47)
因此,您将 vec0..vec47 安装到 idt[0]..[47] 中;那么你的通用处理程序看起来就像已经传递了一个结构:
struct kstk {
uint32_t seg[4];
uint32_t reg[8];
uint32_t cr3;
uint16_t errc, trap;
uint32_t ip, cs, fl, sp, ss;
};
void handler(struct kstk x);ss、sp 是可选的。(标准免责声明,我刚刚将其输入到消息中,因此可能需要一些调整)。
关于c - IRQ 和 iret 指令语义在 32 位内核上的工作(保护模式),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60619458/
我正在使用线程 irq 实现一个中断处理模块。我面临这个错误: 1983.150961] Shut down eMMC app module init. [ 1983.151115] genirq:
我有一个 GPIO 外围设备,在设备树中定义为: gpio0: gpio@2300000 { compatible = "fsl,qoriq-gpio"; reg = ; in
我已经构建了一个静态库(*.a 用于 gcc,*.lib 用于 keil)。它的源文件之一,编译成库,包含 RADIO_IRQHandler 的定义。下面是这个名为“ral_irq_handlers.
从: http://software.intel.com/en-us/articles/introduction-to-pc-architecture/ 异常编号 10h 对应于“浮点错误”,但软件中
我正在学习 Linux 内核中的中断处理,并尝试使用下面的代码片段在 IRQ2 上注册一个虚拟 irq 处理程序。但它似乎没有被注册,因为我在内核中看到了一个负返回值和一条消息,如下所示,这是由试图执
我在制作我的第一个驱动程序 (PIT) 时遇到了问题。我之前录制的视频中清楚地解释了这个问题:https://www.youtube.com/watch?v=hjvTtVbaics&feature=y
目前我的 IRQ 是三重故障并给出除以 0 的错误。 Here是我录制的视频,它将向您展示这一点。 irq.c++: #include "irq.h" #define PIC_MASTER_CONTR
我是 Linux 内核模块开发的新手,正在尝试编写一个简单的内核模块,稍后可以将其扩展为键盘驱动程序。 我尝试了以下两种方法: 基于中断的方法 我按照给定的指南开始编写代码 here .但唯一的问题是
我有一些关于 PCI 和 IRQS 的问题。 IRQ 是如何分配给连接到 PCI 总线的设备的,它是由 BIOS 在启动时分配的,还是总线选择它或总线 Controller 自己自动选择它,谁负责选择
如果我的 PC 有两个内核——CPU0 和 CPU1,则 CPU0 的 IRQ 被禁用 (local_irq_disabled())。如何使用CPU1上的进程开启CPU0的IRQ? 最佳答案 不要。
如何在 32 位保护模式(显然是 x86)下查看 PIT IRQ 处理程序的返回值?我想我可以这样做,但我不完全确定。 pop eax ; pop last thing from stack mov
如何在 32 位保护模式(显然是 x86)下查看 PIT IRQ 处理程序的返回值?我想我可以这样做,但我不完全确定。 pop eax ; pop last thing from stack mov
我正在开发一个使用 ARM Cortex-M0 处理器的项目。在这个项目中,我需要提供计时器支持(CMSDK (SSE-200)计时器)。 因此,在 vector 表中,在 TIMER0_IRQn 表
我正在浏览下面的线程,它说内核头不想将 irq 暴露给模块。 Accessing IRQ description array within a module and displaying action
我是 Linux 内核编程的新手,很长一段时间以来我都在尝试编写模块,它应该执行以下操作:用我自己的替换默认的 irq 处理程序,然后恢复默认的处理程序,使用 IDT (尝试保存 idt 用我自己的替
当一个 IRQ 线在多个已注册的中断服务例程之间共享时,什么决定了中断线产生时 ISR 的执行顺序? 最佳答案 无论如何,顺序是不可预测的,因为正如你所说,中断线是共享的。因此,系统中有(或可能有)其
我正在浏览 arch/arm/kernel/perf_event.c 中的部分 Linux 内核源代码,并试图了解如何进行 request_irq 设置这里: static int armpmu_re
我正在开发一个玩具 unix 克隆,我正在尝试正确连接我的中断。我遇到了一个问题,我的键盘 IRQ (IRQ 1) 即使在我正确确认它之后也只触发一次等等。我也启用了 PIT 中断,以仔细检查我的 A
我目前正在学习 Derek Molloy 在他的书“Exploring Raspberry Pi - Interfacing to The Real World with Embedded Linux
我正在用 C 编写一个内核模块,它正在努力访问 IRQ 描述数组元素并显示这些元素的所有操作名称。 一开始,我认为这个irq_desc 数组就像一个宏,但编译后我明白了它不是。然后我使用了 for_e
我是一名优秀的程序员,十分优秀!