c - Using Task State Segment to handle ring 0 int -
i've been working time on easy os kernel. far i've setup idt 1 int (software). next step try ring 3 of kernel. dane me using 'trick' iret
ring switch successful, state of segment register indicate. problems occurred when tried use int $20
switch ring 0 handle interrupt. of course have setup tss able such action. here code: function encodes descriptor (i've enclosed because think can problem encoding)
void register_descriptor(unsigned entryidx, uint32_t base, uint32_t limit, uint16_t flag) { uint64_t descriptor; descriptor = limit & 0x000f0000; descriptor |= (flag << 8) & 0x00f0ff00; descriptor |= (base >> 16) & 0x000000ff; descriptor |= base & 0xff000000; descriptor <<= 32; descriptor |= base << 16; descriptor |= limit & 0x0000ffff; gdt[entryidx] = descriptor; }
tss loading gdt (zerotss()
set members of tss struct 0):
static void write_tss(unsigned num, uint16_t ss0, uint32_t esp0) { register_descriptor(num, (uint32_t) &tss_entry, sizeof(tss_entry), (tss)); zerotss(); tss_entry.ss0 = ss0; tss_entry.esp0 = esp0; tss_entry.cs = 0x18; tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x20; }
tss flush(my gdt have 6 entries (null+tss+4 segment)):
.global flush_tss flush_tss: mov $0x28, %ax ltr %ax ret
and interupt handler register:
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 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, 0x8e); registerinterupt(printonscreenint, 32); _lidt(&idtptr); } .global _lidt _lidt: push %ebp mov %esp,%ebp mov 8(%esp), %eax lidt (%eax) leave ret
finally print form bochs:
[cpu0 ] interrupt(): soft_int && (gate.dpl < cpl) [cpu0 ] interrupt(): gate descriptor not valid sys seg (vector=0x0d) [cpu0 ] interrupt(): gate descriptor not valid sys seg (vector=0x08) [cpu0 ] cpu in protected mode (active) [cpu0 ] cs.mode = 32 bit [cpu0 ] ss.mode = 32 bit [cpu0 ] efer = 0x00000000 [cpu0 ] | eax=00100d48 ebx=001058b4 ecx=00000720 edx=001058c2 [cpu0 ] | esp=0010589c ebp=0010589c esi=00101000 edi=00000000 [cpu0 ] | iopl=0 id vip vif ac vm rf nt of df if tf sf zf af pf cf [cpu0 ] | seg sltr(index|ti|rpl) base limit g d [cpu0 ] | cs:000b( 0001| 0| 3) 00000000 ffffffff 1 1 [cpu0 ] | ds:0013( 0002| 0| 3) 00000000 ffffffff 1 1 [cpu0 ] | ss:0013( 0002| 0| 3) 00000000 ffffffff 1 1 [cpu0 ] | es:0013( 0002| 0| 3) 00000000 ffffffff 1 1 [cpu0 ] | fs:0013( 0002| 0| 3) 00000000 ffffffff 1 1 [cpu0 ] | gs:0013( 0002| 0| 3) 00000000 ffffffff 1 1 [cpu0 ] | eip=001008ed (001008ed) [cpu0 ] | cr0=0x60000011 cr2=0x00000000 [cpu0 ] | cr3=0x00000000 cr4=0x00000000 [cpu0 ] 0x001008ed>> int 0x20 : cd20
i mention before introducing 2 privilege levels interrupt handler working.
Comments
Post a Comment