Kernel Linux0.00 analysis for multi-tasking

Source: Internet
Author: User

Tags: style blog class Code C tar

Recently we have finally debugged the multi-tasking microkernel, and we have explained how to switch tasks in protected mode. Knowledge includes: GDT,IDT,LDT,TSS, clock Interrupt service, privilege level switching, memory programming, boot and loader functions, BIOS calls, and more. The detailed knowledge also needs to study in the practice, hoped everybody progresses together. This article only makes a record, if not personally debugging the code, it may not be well understood. Take the next few days to focus on the 0.12 launcher, multi-paging needs more in-depth understanding.

; #Mode =dos; put it in front of. Code. 386p.model smalllatch=11930scrn_sel=18htss0_sel= 20hldt0_sel=28htss1_sel=30hldt1_sel= 38h.codestart:mov Eax,10hmov ds,axlss esp,fword ptr [init_stack]call setup_idtcall setup_gdtmov Eax,10hmov Ds,axmov es, Axmov Fs,axmov gs,axlss esp,fword ptr [Init_stack]mov al,36hmov edx,43hout dx,almov eax,latch mov edx,40hout dx,almov al,a Hout Dx,almov Eax,80000hmov Ecx,timer_interruptmov ax,cxmov Dx,8e00hmov Ecx,8lea esi,[ecx * 8 + idt]mov [Esi],eaxmov [esi + 4],edxmov Ecx,system_interruptmov Ax,cxmov Dx,0ef00hmov Ecx,80hlea esi,[ecx * 8 + idt]mov [Esi],eaxmov [esi + 4],edx;//Increase  Add code mov Ecx,div_intmov ax,cxmov dx,0ef00hmov Ecx,0lea esi,[ecx * 8 + idt]mov [Esi],eaxmov [esi + 4],edxpushfdand DWORD ptr [Esp],0ffffbfffhpopfdmov eax,tss0_selltr Axmov Eax,ldt0_sellldt ax;mov DWORD ptr [current],0; issue 1: Prefix 2edb 0c7h, 05HDD Curr ENTDD 0sti;///Add code;///push 17hpush init_stackpushfdpush 0fhpush task0iretdsetup_gdt:lgdt fword ptr [Lgdt_opcode] Retsetup_idt:mov edx, Ignore_initmov Eax,80000hmov Ax,Dxmov Dx,8e00hmov EDI, Idtmov ecx,256rp_idt:mov [Edi],eaxmov [edi + 4],edxadd edi,8dec ecxjne rp_idtlidt FWORD ptr [lidt_o Pcode]retwrite_char:push gspush Ebxmov Ebx,scrn_selmov gs,bxmov ebx,dword ptr [scr_loc]shl ebx,1mov BYTE ptr gs:[ebx],als HR ebx,1inc ebxcmp ebx,2000jb @fmov ebx,0@@:;mov DWORD ptr [scr_loc],ebxdb 89h, 1dhdd scr_locpop ebxpop gsret;align 4ignor E_init:push dspush Eaxmov Eax,10hmov ds,axmov eax,67call write_charpop eaxpop dsiretd;//Add code div_int:iret;align 4timer_i Nterrupt:push dspush Eaxmov Eax,10hmov Ds,axmov al,20hout 20h,almov eax,1cmp dword ptr [Current],eaxje N1;mov dword ptr [C Urrent],eaxdb 0a3hdd currentbyte 0eahWORD 0, 0, tss1_seljmp N2n1:;mov DWORD ptr [current],0db 0c7h, 05hdd CURRENTDD 0db 0e Ahword 0,0, Tss0_seln2:pop eaxpop dsiretd;align 4system_interrupt:push dspush edxpush ecxpush ebxpush Eaxmov Edx,10hmov ds , Dxcall write_charpop eaxpop ebxpop ecxpop edxpop dsiretdcurrent:dword 0scr_loc:dword 0;align 4lidt_opcode:WORD256*8-1 Dwordidtlgdt_opcode:word (END_GDT-GDT) -1dwordgdt;align 4idt:qword (0) Gdt:qword 0000000000000000hQWORD 00c09a00000007ffhqword 00c09200000007ffhqword 00c0920b80000002hword 68h, Tss0, 0e900h, 0WORD 40h, Ldt0, 0e200h, 0WORD 68h, Tss1, 0e900h, 0WORD 40  H, Ldt1, 0e200h, 0end_gdt:dword-dup (0) Init_stack:dword Init_stackword 10h;align 4ldt0:qword 0000000000000000hQWORD 00c0fa00000003ffhqword 00c0f200000003ffhtss0:dword 0DWORD Krn_stk0, 10hDWORD 0, 0, 0, 0, 0DWORD 0, 0, 0, 0, 0DWORD 0, 0, 0, 0, 0DWORD 0, 0, 0, 0, 0, 0DWORD Ldt0_sel, 8000000hDWORD, DUP (0) Krn_stk0:ldt1:QWORD 0000000000000000hQWORD 00c0fa000 00003ffhQWORD 00c0f200000003ffhtss1:dword 0DWORD Krn_stk1, 10hDWORD 0, 0, 0, 0, 0DWORD Task1, 200hDWORD 0, 0, 0, 0DWORD us R_STK1, 0, 0, 0DWORD 17h, 0fh, 17h, 17h, 17h, 17hDWORD Ldt1_sel, 8000000hDWORD Krn_stk1:task0:mov dup (0) Eax,17hmov DS , Axmov al,65int 80hmov ecx,0fffht1:loop t1jmp task0task1:mov eax,17hmov ds,axmov al,66int 80hmov ecx,0fffht2:loop t2jmp ta Sk1dword-DUP (0) usr_stk1:end start

Thanks to an enthusiastic netizen to provide the kernel image, learned a lot of things. Here are the records I debugged:

Code Analysis:
57:PUSHL $0x17
PUSHL $init _stack
Pushfl
PUSHL $0x0f
PUSHL $task 0
Iret



57: The SS into the stack task 0, (changed the privilege level to 3)
stack pointer into stack task 0 ESP
Into the stack flag register
Code Snippet selector (CS) into the stack task 0
instruction Pointers (EIP) into the stack as tasks
Iret the stack, respectively, assigned a value of SS,ESP,EFLAGS,CS,EIP.
Effect:
The 1.CPU privilege level is determined by 0->3 because the contents of the CS register are converted from 0x10 (RPL bit 0) to 0x0f (RPL is 3)
2. Jump to task 0 to start execution. CS Gets the code snippet descriptor base in the LDT: 0x00, offset eip=task0, so jump to task 0 to start execution
Summary: Task 0 begins execution on privilege level 3.
The value of each register before the iret instruction:
R:
ebx:0x00000000 0
ESP:0X00000BF1 3057
ebp:0x00000000 0
ESI:0X000001C5 453
EDI:0X000009C5 2501
Eip:0x000000d8
Sreg:
es:0x0010, dh=0x00c09300, DL=0X000007FF, valid=1
Data segment, base=0x00000000, LIMIT=0X007FFFFF, read/write, accessed
cs:0x0008, Dh=0x00c09b00, DL=0X000007FF, valid=3
Code segment, base=0x00000000, LIMIT=0X007FFFFF, execute/read, accessed, 32-bit
ss:0x0010, dh=0x00c09300, DL=0X000007FF, valid=7
Data segment, base=0x00000000, LIMIT=0X007FFFFF, read/write, accessed
ds:0x0010, dh=0x00c09300, DL=0X000007FF, valid=7
Data segment, base=0x00000000, LIMIT=0X007FFFFF, read/write, accessed
fs:0x0010, dh=0x00c09300, DL=0X000007FF, valid=1
Data segment, base=0x00000000, LIMIT=0X007FFFFF, read/write, accessed
gs:0x0010, dh=0x00c09300, DL=0X000007FF, valid=1
Data segment, base=0x00000000, LIMIT=0X007FFFFF, read/write, accessed
ldtr:0x0028, dh=0x0000e200, dl=0x0c0b0040, valid=1
tr:0x0020, Dh=0x0000eb00, dl=0x0c230068, valid=1
GDTR:BASE=0X000009C5, limit=0x3f
IDTR:BASE=0X000001C5, LIMIT=0X7FF


After executing the iret command:
R:
ebx:0x00000000 0
ESP:0X00000C05 3077
ebp:0x00000000 0
ESI:0X000001C5 453
EDI:0X000009C5 2501
eip:0x0000110b


ss:0x17
cs:0x0f


-------------------------------------------------------------------------


224:int $0x80
Enter in Bochs: S will go to interrupt program: System_interrupt
There are three door descriptors in the IDT table: Break gate, Trap door, Task gate.
What difference do they have? There is a type field in the descriptor. Interrupt Gate: 13, Trap door: 14, Mission door: 5.
int 0x80. After executing the instruction, the system detects an interrupt and then finds the appropriate handler based on the interrupt number 80. This is a trap door descriptor.
Based on full anatomy: 121 analysis
(1) The stack switch occurs when the process is executed at a high privilege level. The process of stack switching is as follows:
The processor obtains the segment selector and stack pointers (such as TSS.SS0, TSS.ESP0) for the stack used by the interrupt processing process from the TSS segment of the current task. The processor then presses the stack selector and stack pointer of the interrupted program into the new stack.


(2) Once the int 80 is executed, the stack switch is performed, switch to the kernel stack--krn_stk0 (ESP), 0x10 (ss) of task 0, and where do I find the kernel stack to switch to? There is a kernel stack address in the TSS of the current task.


There is one more question to consider, how does the execution process jump to the system calling program? Of course, through the trap door descriptor, which specifies the address of the handler, and then change the EIP is OK.
(3) Enter the kernel state, after the iret back through the stack (originally CS and bounce out), into the user state
Execute int 0x80, at which time the stack does switch, and the edge of the task into the stack
| Stack 0x00000e77 [0x00001117]---top---[EIP]
| STACK 0x00000e7b [0x0000000f]----------[CS]
| STACK 0x00000e7f [0x00000246]----------[EFlags]
| STACK 0x00000e83 [0X00000C05]----------[original ESP]
| STACK 0x00000e87 [0x00000017]----------[original SS]
Register information at this time:
cs:0x0008, Dh=0x00c09b00, DL=0X000007FF, valid=1
Code segment, base=0x00000000, LIMIT=0X007FFFFF, execute/read, accessed, 32-bit
ss:0x0010, dh=0x00c09300, DL=0X000007FF, valid=1
Data segment, base=0x00000000, LIMIT=0X007FFFFF, read/write, accessed
ds:0x0017, dh=0x00c0f300, DL=0X000003FF, valid=1
Data segment, base=0x00000000, LIMIT=0X003FFFFF, read/write, accessed
fs:0x0000, dh=0x00c09300, DL=0X000007FF, valid=0
gs:0x0000, dh=0x00c09300, DL=0X000007FF, valid=0
ldtr:0x0028, dh=0x0000e200, dl=0x0c0b0040, valid=1
tr:0x0020, Dh=0x0000eb00, dl=0x0c230068, valid=1
GDTR:BASE=0X000009C5, limit=0x3f
IDTR:BASE=0X000001C5, LIMIT=0X7FF


Esp:0x00000e77 3703
eip:0x00000199


This time cs=0x10, said the CPU privilege level from 3 to 0.


Protection during exceptions and interrupts: Cpl must be less than or equal to the gate. Here is satisfied, because the CPL of task 0 is 3, the system calls the trap door of DPL is also 3.


The register state is the same as above before System_interrupt executes the last sentence of the iret instruction.
After executing iret:
ESP:0X00000C05 3077
ebp:0x00000000 0
ESI:0X000001C5 453
EDI:0X000009C5 2501
eip:0x00001117 (corresponds to int 0x10 that instruction)


CS:0X000F, Dh=0x00c0fb00, DL=0X000003FF, valid=1
Code segment, base=0x00000000, LIMIT=0X003FFFFF, execute/read, accessed, 32-bit
ss:0x0017, dh=0x00c0f300, DL=0X000003FF, valid=1
Data segment, base=0x00000000, LIMIT=0X003FFFFF, read/write, accessed
ds:0x0017, dh=0x00c0f300, DL=0X000003FF, valid=1
Data segment, base=0x00000000, LIMIT=0X003FFFFF, read/write, accessed
fs:0x0000, dh=0x00c09300, DL=0X000007FF, valid=0
gs:0x0000, dh=0x00001000, dl=0x00000000, valid=0
ldtr:0x0028, dh=0x0000e200, dl=0x0c0b0040, valid=1
tr:0x0020, Dh=0x0000eb00, dl=0x0c230068, valid=1
GDTR:BASE=0X000009C5, limit=0x3f
IDTR:BASE=0X000001C5, LIMIT=0X7FF
The iret command switches to the original stack (which is mentioned in the Trap Gate book)


Call ljmp $TSS 1_sel,$0 before the register information:
eax:0x00000001 1
ecx:0x0000097c 2428
EDX:0X0000EF00 61184
ebx:0x00000000 0
esp:0x00000e6f 3695
ebp:0x00000000 0
ESI:0X000001C5 453
EDI:0X000009C5 2501
eip:0x0000017c


Sreg:
es:0x0000, dh=0x00c09300, DL=0X000007FF, valid=0
cs:0x0008, Dh=0x00c09b00, DL=0X000007FF, valid=3
Code segment, base=0x00000000, LIMIT=0X007FFFFF, execute/read, accessed, 32-bit
ss:0x0010, dh=0x00c09300, DL=0X000007FF, valid=7
Data segment, base=0x00000000, LIMIT=0X007FFFFF, read/write, accessed
ds:0x0010, dh=0x00c09300, DL=0X000007FF, valid=7
Data segment, base=0x00000000, LIMIT=0X007FFFFF, read/write, accessed
fs:0x0000, dh=0x00c09300, DL=0X000007FF, valid=0
gs:0x0000, dh=0x00001000, dl=0x00000000, valid=0
ldtr:0x0028, dh=0x0000e200, dl=0x0c0b0040, valid=1
tr:0x0020, Dh=0x0000eb00, dl=0x0c230068, valid=1
GDTR:BASE=0X000009C5, limit=0x3f
IDTR:BASE=0X000001C5, LIMIT=0X7FF


After execution:
Switch to Task 0 or 1 to obtain register information from TSS. Privilege level by 0->3.


---------------------------------------
Task 0 is running and then receives a clock interrupt, which jumps from privilege level 3 to privileged level 0 and also implements the kernel stack that switches to the current task.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

Tags Index: