Ok I'm having another problem.
My "kernel" runs and I get the ltr instruction to work. Now I tried the following:
I wrote two procedures called task1 and task2. Both are compiled and linked into the kernel. They also execute in ring 0. I wrote 2 new tss descriptors and 2 new stack segment descriptors for them:
Code: Select all
;(10) this is the descriptor for the tss of task1
dw 104 ;limit of the segment
dw 0 ;base address of segment
db 0 ;still belonging to base address of segment
db 00001001 ;0 for "TSS is present"
;00 for DPL of 0
;010
;0 for "task not busy"
;1
db 00000000 ;0 for byte-granularity
;000
;0000b for last bits of segment limit
db 0 ;last byte of base address
;(11) this is the descriptor for the tss of task2
dw 104 ;limit of the segment
dw 0 ;base address of segment
db 0 ;still belonging to base address of segment
db 00001001 ;0 for "TSS is present"
;00 for DPL of 0
;010
;0 for "task not busy"
;1
db 00000000 ;0 for byte-granularity
;000
;0000b for last bits of segment limit
db 0 ;last byte of base address
;(12)..stack segment for task1
dw 0 ;limit of the segment
dw 0 ;base address of segment
db 011h ;still belonging to base address of segment
db 10010010b ;1 for "segment is present"
;00 for "privilege 0"
;1 for "data or code segment"
;0 for "data segment"
;0 for "expand downward"
;1 for writable
;0 (access flag set by cpu on 1st access)
db 01001111b ;0 for byte-granularity
;1 for 32-bit stack pointer
;0 (reserved bit)
;0 (available to system programmers)
;1111b for last bits of segment limit
db 0 ;last byte of base address
;(13)..stack segment for task2
dw 0 ;limit of the segment
dw 0 ;base address of segment
db 012h ;still belonging to base address of segment
db 10010010b ;1 for "segment is present"
;00 for "privilege 0"
;1 for "data or code segment"
;0 for "data segment"
;0 for "expand downward"
;1 for writable
;0 (access flag set by cpu on 1st access)
db 01001111b ;0 for byte-granularity
;1 for 32-bit stack pointer
;0 (reserved bit)
;0 (available to system programmers)
;1111b for last bits of segment limit
db 0 ;last byte of base address
The base addresses in these descriptors are again written to at run time to point to the following two TSS:
Code: Select all
task1state: tss_t := tss_t:[
0,
0,
$fffffffc,
IDX_TASK1STACK*@size(segdesc),
0,
0,
0,
0,
0,
0,
0,
0,
&task1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
IDX_KERNELDATA*@size(segdesc),
0,
IDX_KERNELCODE*@size(segdesc),
0,
0,
0,
IDX_KERNELDATA*@size(segdesc),
0,
IDX_MEMORY*@size(segdesc),
0,
IDX_VIDEO*@size(segdesc),
0,
0,
0,
0,
0,
$ffff
];
task2state: tss_t := tss_t:[
0,
0,
$fffffffc,
IDX_TASK2STACK*@size(segdesc),
0,
0,
0,
0,
0,
0,
0,
0,
&task2,
0,
0,
0,
0,
0,
0,
0,
0,
0,
IDX_KERNELDATA*@size(segdesc),
0,
IDX_KERNELCODE*@size(segdesc),
0,
0,
0,
IDX_KERNELDATA*@size(segdesc),
0,
IDX_MEMORY*@size(segdesc),
0,
IDX_VIDEO*@size(segdesc),
0,
0,
0,
0,
0,
$ffff
];
of type:
Code: Select all
type tss_t:
record;
backlink: word;
zeroes1: word;
sp0: dword;
ss0: word;
zeroes2: word;
sp1: dword;
ss1: word;
zeroes3: word;
sp2: dword;
ss2: word;
zeroes4: word;
cr3_reg: dword;
eip_reg: dword;
eflag_reg: dword;
eax_reg: dword;
ecx_reg: dword;
edx_reg: dword;
ebx_reg: dword;
esp_reg: dword;
ebp_reg: dword;
esi_reg: dword;
edi_reg: dword;
es_reg: word;
zeroes5: word;
cs_reg: word;
zeroes6: word;
ss_reg: word;
zeroes7: word;
ds_seg: word;
zeroes8: word;
fs_seg: word;
zeroes9: word;
gs_seg: word;
zeroes10: word;
ldt_sel: word;
zeroes11: word;
debug: byte; //set lowest bit TRUE to raise a debug exception on a task switch
zeroes12: byte;
iomap_base: word;
endrecord;
Then I introduced a variable task which tells me which task is currently running and rewrote my clock interrupt as follows:
Code: Select all
procedure clock_int; @nodisplay; @noalignstack; @noframe;
begin clock_int;
push(eax);
pushfd();
mov(task,ax);
if (ax = IDX_TASK2TSS*@size(segdesc)) then
mov(IDX_TASK1TSS*@size(segdesc),ax);
else
mov(IDX_TASK2TSS*@size(segdesc),ax);
endif;
mov(ax,task);
mov(IDX_TASK1TSS*@size(segdesc),ax);
ltreg(ax);
mov(PIC_EOI,al);
out(al,PIC1_COMMAND);
popfd();
pop(eax);
iret();
end clock_int;
But as soon as the ltreg(ax) gets executed in the timer, I get:
Code: Select all
0000641512i[VGA ] VBE known Display Interface b0c0
00000641544i[VGA ] VBE known Display Interface b0c4
00000644469i[VBIOS] VBE Bios $Id: vbe.c,v 1.58 2006/08/19 09:39:43 vruppert Exp $
00000720000i[XGUI ] charmap update. Font Height is 16
00000800000i[XGUI ] charmap update. Font Height is 16
00001088736i[BIOS ] Booting from 0000:7c00
00001830923e[CPU ] LTR: doesn't point to an available TSS descriptor!
00001830923i[CPU ] CPU is in protected mode (halted)
00001830923i[CPU ] CS.d_b = 32 bit
00001830923i[CPU ] SS.d_b = 32 bit
00001830923i[CPU ] | EAX=00000050 EBX=00000001 ECX=00000004 EDX=534d0000
00001830923i[CPU ] | ESP=0000ffdc EBP=0000fff0 ESI=ffff017a EDI=00080248
00001830923i[CPU ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf ZF af PF cf
00001830923i[CPU ] | SEG selector base limit G D
00001830923i[CPU ] | SEG sltr(index|ti|rpl) base limit G D
00001830923i[CPU ] | CS:0008( 0001| 0| 0) 00014700 0009b500 0 1
00001830923i[CPU ] | DS:0010( 0002| 0| 0) 00014700 0009b500 0 1
00001830923i[CPU ] | SS:0018( 0003| 0| 0) 00000700 000ffffc 0 1
00001830923i[CPU ] | ES:0010( 0002| 0| 0) 00014700 0009b500 0 1
00001830923i[CPU ] | FS:0030( 0006| 0| 0) 00000000 000fffff 1 1
00001830923i[CPU ] | GS:0028( 0005| 0| 0) 000b8000 000f0fa0 0 1
00001830923i[CPU ] | EIP=00000c62 (00000c62)
00001830923i[CPU ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00001830923i[CPU ] | CR3=0x00000000 CR4=0x00000000
00001830923i[CPU ] >> ltr ax : 0F00D8
00001830923e[CPU ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00001830923i[SYS ] bx_pc_system_c::Reset(SOFTWARE) called
Next at t=1830923
(0) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b ; ea5be000f0
Can anyone help me again?
PS: the mov syntax in HLA is "mov(source,target)"