在我的#34; wannabe-kernel"我已成功通过IDT在保护模式下启用软件中断处理。现在我转向硬件中断,以便能够为进程分配时间片。问题是我的内核没有收到任何PIT中断。
inline void outb(uint8_t port,unsigned char value)
{
__asm__ __volatile__ ("outb %%ax,%%dx": :"d" (port), "a" (value));
}
static inline uint8_t inb(uint16_t port)
{
uint8_t ret;
__asm__ __volatile__ ( "inb %1, %0" : "=a"(ret) : "d"(port) );
return ret;
}
#define PIC1 0x20
#define PIC2 0xA0
#define PIC1_COMMAND PIC1
#define PIC1_DATA (PIC1+1)
#define PIC2_COMMAND PIC2
#define PIC2_DATA (PIC2+1)
#define ICW1_ICW4 0x01
#define ICW1_SINGLE 0x02
#define ICW1_INTERVAL4 0x04
#define ICW1_LEVEL 0x08
#define ICW1_INIT 0x10
#define ICW4_8086 0x01
#define ICW4_AUTO 0x02
#define ICW4_BUF_SLAVE 0x08
#define ICW4_BUF_MASTER 0x0C
#define ICW4_SFNM 0x10
void init_pic()
{
unsigned char a1, a2;
unsigned offset_master = 0x20;
unsigned offset_slave = 0x28;
a1 = inb(PIC1_DATA);
a2 = inb(PIC2_DATA);
outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4);
outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
outb(PIC1_DATA, offset_master);
outb(PIC2_DATA, offset_slave);
outb(PIC1_DATA, 4);
outb(PIC2_DATA, 2);
outb(PIC1_DATA, ICW4_8086);
outb(PIC2_DATA, ICW4_8086);
outb(PIC1_DATA, a1);
outb(PIC2_DATA, a2);
}
#define PIT_COMMAND 0x43
#define PIT_DATA1 0x40
#define PIT_DATA2 0x41
#define PIT_DATA3 0x42
void init_pit()
{
uint32_t divisor = 1193180 / 50;
outb(PIT_COMMAND, 0x36);
uint8_t l = (uint8_t)(divisor & 0xFF);
uint8_t h = (uint8_t)( (divisor>>8) & 0xFF );
outb(PIT_DATA1, l);
outb(PIT_DATA1, h);
}
计时器处理程序
unsigned tick = 0;
void timerHandler()
{
tick++;
char* ascii_code;
itoa(ascii_code, 'd', tick);
terminal_writestring("PIT Tick: ", &terminal);
terminal_writestring(ascii_code, &terminal);
terminal_writestring("\n", &terminal);
}
bochs没有提供有关isse原因的详细信息:
00122970752e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x20)
00122970752e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00122970752e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
我已经以相同的方式注册到IDT计时器处理程序(只有条目号不同)作为软件中断处理程序。
编辑:IDT设置代码按要求:
struct __InteruptDescriptorTableEntry
{
uint16_t offset_low;
uint16_t selector;
uint8_t zero;
uint8_t type_attr;
uint16_t offset_up;
} __attribute__((packed));
typedef struct __InteruptDescriptorTableEntry IDTEntry;
struct _ITD_PTR
{
uint16_t idtSize;
uint32_t idtBaseAddr;
} __attribute__((packed));
typedef struct _ITD_PTR _IDT_PTR;
void zeroIDT()
{
unsigned i;
for(i=0;i<NUM_IDT_ENTRIES-1;++i)
{
IDTEntry nullIDTEntry = fillIDTEntry(0,0,0);
registerInterupt(nullIDTEntry, i);
}
}
void registerInterupt(const IDTEntry entry, const unsigned intNo)
{
if(intNo < NUM_IDT_ENTRIES)
InteruptDescriptorTable[intNo] = entry;
}
#define LOW_FUN_ADDR(fun) ( (uint32_t)fun & 0xFFFF )
#define UP_FUN_ADDR(fun) ( (uint32_t)fun >> 16) & 0xFFFF
IDTEntry fillIDTEntry(uint32_t intHandler,
uint16_t selector,
uint8_t type_attr)
{ IDTEntry newEntry;
newEntry.offset_low = LOW_FUN_ADDR(intHandler);
newEntry.selector = selector;
newEntry.zero = 0;
newEntry.type_attr = type_attr;
newEntry.offset_up = UP_FUN_ADDR(intHandler);
return newEntry;
}
extern void _lidt(_IDT_PTR* idtPtr);
void timerHandler_TEST();
void loadIDT()
{
zeroIDT();
_IDT_PTR idtPtr;
idtPtr.idtSize = sizeof(struct __InteruptDescriptorTableEntry)*256 - 1;
idtPtr.idtBaseAddr = (uint32_t) &InteruptDescriptorTable;
IDTEntry printOnScreenInt = fillIDTEntry((uint32_t)interupt_pritnOnScreen, 0x18, 0xee);
registerInterupt(printOnScreenInt, 50);
IDTEntry timerIntEntry = fillIDTEntry((uint32_t)timerHandler_TEST, 0x18, 0xee);
registerInterupt(printOnScreenInt, 13);
_lidt(&idtPtr);
}
汇编来源:
.global _lidt
_lidt:
push %ebp
mov %esp,%ebp
mov 8(%esp), %eax
lidt (%eax)
leave
ret
EDIT2:我已将PIT的面具更改为:
a1 = 0x7F; //master
a2 = 0xFF; //slave
仅接收PIT int,但未传递IRQ(无三重故障)。
EDIT3:info gdt
和info IDT
:
IDT[0x20]=32-Bit Interrupt Gate target=0x0018:0x001009c0, DPL=3
IDT[0x32]=32-Bit Interrupt Gate target=0x0018:0x001009c0, DPL=3
GDT:
GDT[0x00]=??? descriptor hi=0x00000000, lo=0x00000000
GDT[0x01]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x02]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
GDT[0x03]=Code segment, base=0x00000000, limit=0xffffffff, Execute/Read, Non-Conforming, Accessed, 32-bit
GDT[0x04]=Data segment, base=0x00000000, limit=0xffffffff, Read/Write, Accessed
GDT[0x05]=32-Bit TSS (Busy) at 0x00101000, length 0x00068