/kernel/branches/gfx_kernel/core/debug.inc |
---|
0,0 → 1,499 |
; diamond, 2006 |
sys_debug_services: |
cmp eax, 9 |
ja @f |
jmp dword [sys_debug_services_table+eax*4] |
@@: ret |
sys_debug_services_table: |
dd debug_set_event_data |
dd debug_getcontext |
dd debug_setcontext |
dd debug_detach |
dd debug_suspend |
dd debug_resume |
dd debug_read_process_memory |
dd debug_write_process_memory |
dd debug_terminate |
dd debug_set_drx |
debug_set_event_data: |
; in: ebx = pointer |
; destroys eax |
mov eax, [0x3000] |
shl eax, 8 |
mov [eax+0x80000+APPDATA.dbg_event_mem], ebx |
ret |
get_debuggee_slot: |
; in: ebx=PID |
; out: CF=1 if error |
; CF=0 and eax=slot*0x20 if ok |
; out: interrupts disabled |
cli |
mov eax, ebx |
call pid_to_slot |
test eax, eax |
jz .ret_bad |
shl eax, 5 |
push ebx |
mov ebx, [0x3000] |
cmp [0x80000+eax*8+APPDATA.debugger_slot], ebx |
pop ebx |
jnz .ret_bad |
; clc ; automatically |
ret |
.ret_bad: |
stc |
ret |
debug_detach: |
; in: ebx=pid |
; destroys eax,ebx |
call get_debuggee_slot |
jc .ret |
and dword [eax*8+0x80000+APPDATA.debugger_slot], 0 |
call do_resume |
.ret: |
sti |
ret |
debug_terminate: |
; in: ebx=pid |
call get_debuggee_slot |
jc debug_detach.ret |
mov ebx, eax |
shr ebx, 5 |
push 2 |
pop eax |
jmp sys_system |
debug_suspend: |
; in: ebx=pid |
; destroys eax,ebx |
call get_debuggee_slot |
jc .ret |
mov bl, [0x3000+eax+TASKDATA.state] ; process state |
test bl, bl |
jz .1 |
cmp bl, 5 |
jnz .ret |
mov bl, 2 |
.2: mov [0x3000+eax+TASKDATA.state], bl |
.ret: |
sti |
ret |
.1: |
inc ebx |
jmp .2 |
do_resume: |
mov bl, [0x3000+eax+TASKDATA.state] |
cmp bl, 1 |
jz .1 |
cmp bl, 2 |
jnz .ret |
mov bl, 5 |
.2: mov [0x3000+eax+TASKDATA.state], bl |
.ret: ret |
.1: dec ebx |
jmp .2 |
debug_resume: |
; in: ebx=pid |
; destroys eax,ebx |
call get_debuggee_slot |
jc .ret |
call do_resume |
.ret: sti |
ret |
debug_getcontext: |
; in: |
; ebx=pid |
; ecx=sizeof(CONTEXT) |
; edx->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp ecx, 28h |
jnz .ret |
add edx, std_application_base_address |
push ebx |
mov ebx, edx |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .ret |
imul eax, tss_step/32 |
add eax, tss_data |
mov edi, edx |
cmp [l.cs - tss_sceleton + eax], app_code |
jnz .ring0 |
lea esi, [l.eip - tss_sceleton + eax] |
shr ecx, 2 |
rep movsd |
jmp .ret |
.ring0: |
; note that following code assumes that all interrupt/exception handlers |
; saves ring-3 context by push ds es, pushad in this order |
mov esi, [l.esp0 - tss_sceleton + eax] |
; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), ds, es, pushad |
sub esi, 8+12+8+20h |
lodsd |
mov [edi+24h], eax |
lodsd |
mov [edi+20h], eax |
lodsd |
mov [edi+1Ch], eax |
lodsd |
lodsd |
mov [edi+14h], eax |
lodsd |
mov [edi+10h], eax |
lodsd |
mov [edi+0Ch], eax |
lodsd |
mov [edi+8], eax |
add esi, 8 |
lodsd |
mov [edi], eax |
lodsd |
lodsd |
mov [edi+4], eax |
lodsd |
mov [edi+18h], eax |
.ret: |
sti |
ret |
debug_setcontext: |
; in: |
; ebx=pid |
; ecx=sizeof(CONTEXT) |
; edx->CONTEXT |
; destroys eax,ecx,edx,esi,edi |
cmp ecx, 28h |
jnz .ret |
add edx, std_application_base_address |
push ebx |
mov ebx, edx |
call check_region |
pop ebx |
dec eax |
jnz .ret |
call get_debuggee_slot |
jc .stiret |
imul eax, tss_step/32 |
add eax, tss_data |
mov esi, edx |
cmp [l.cs - tss_sceleton + eax], app_code |
jnz .ring0 |
lea edi, [l.eip - tss_sceleton + eax] |
shr ecx, 2 |
rep movsd |
jmp .stiret |
.ring0: |
mov edi, [l.esp0 - tss_sceleton + eax] |
sub edi, 8+12+8+20h |
mov eax, [esi+24h] |
stosd |
mov eax, [esi+20h] |
stosd |
mov eax, [esi+1Ch] |
stosd |
scasd |
mov eax, [esi+14h] |
stosd |
mov eax, [esi+10h] |
stosd |
mov eax, [esi+0Ch] |
stosd |
mov eax, [esi+8] |
stosd |
add edi, 8 |
mov eax, [esi] |
stosd |
scasd |
mov eax, [esi+4] |
stosd |
mov eax, [esi+18h] |
stosd |
.stiret: |
sti |
.ret: |
ret |
debug_set_drx: |
call get_debuggee_slot |
jc .errret |
mov ebp, eax |
lea eax, [eax*8+0x80000+APPDATA.dbg_regs] |
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3 |
; [eax+10]=dr7 |
add edx, std_application_base_address |
jc .errret |
cmp cl, 3 |
ja .errret |
mov ebx, dr7 |
shr ebx, cl |
shr ebx, cl |
test ebx, 2 ; bit 1+2*index = G0..G3, global break enable |
jnz .errret2 |
test ch, ch |
jns .new |
; clear breakpoint |
movzx ecx, cl |
add ecx, ecx |
and dword [eax+ecx*2], 0 ; clear DR<i> |
btr dword [eax+10h], ecx ; clear L<i> bit |
test byte [eax+10h], 55h |
jnz .okret |
imul eax, ebp, tss_step/32 |
and byte [eax + tss_data + l.trap - tss_sceleton], not 1 |
.okret: |
and dword [esp+36], 0 |
sti |
ret |
.errret: |
sti |
mov dword [esp+36], 1 |
ret |
.errret2: |
sti |
mov dword [esp+36], 2 |
ret |
.new: |
; add new breakpoint |
; cl=index; ch=flags; edx=address |
test ch, 0xF0 |
jnz .errret |
mov bl, ch |
and bl, 3 |
cmp bl, 2 |
jz .errret |
mov bl, ch |
shr bl, 2 |
cmp bl, 2 |
jz .errret |
test dl, bl |
jnz .errret |
or byte [eax+10h+1], 3 ; set GE and LE flags |
movzx ebx, ch |
movzx ecx, cl |
add ecx, ecx |
bts dword [eax+10h], ecx ; set L<i> flag |
add ecx, ecx |
mov [eax+ecx], edx ; set DR<i> |
shl ebx, cl |
mov edx, 0xF |
shl edx, cl |
not edx |
and [eax+10h+2], dx |
or [eax+10h+2], bx ; set R/W and LEN fields |
imul eax, ebp, tss_step/32 |
or byte [eax + tss_data + l.trap - tss_sceleton], 1 |
jmp .okret |
debug_read_process_memory: |
; in: |
; ebx=pid |
; ecx=length |
; esi->buffer in debugger |
; edx=address in debuggee |
; out: [esp+36]=sizeof(read) |
; destroys all |
add esi, std_application_base_address |
push ebx |
mov ebx, esi |
call check_region |
pop ebx |
dec eax |
jnz .err |
call get_debuggee_slot |
jc .err |
shr eax, 5 |
mov ebx, esi |
call read_process_memory |
sti |
mov dword [esp+36], eax |
ret |
.err: |
or dword [esp+36], -1 |
ret |
debug_write_process_memory: |
; in: |
; ebx=pid |
; ecx=length |
; esi->buffer in debugger |
; edx=address in debuggee |
; out: [esp+36]=sizeof(write) |
; destroys all |
add esi, std_application_base_address |
push ebx |
mov ebx, esi |
call check_region |
pop ebx |
dec eax |
jnz debug_read_process_memory.err |
call get_debuggee_slot |
jc debug_read_process_memory.err |
shr eax, 5 |
mov ebx, esi |
call write_process_memory |
sti |
mov [esp+36], eax |
ret |
debugger_notify: |
; in: eax=debugger slot |
; ecx=size of debug message |
; [esp+4]..[esp+4+ecx]=message |
; interrupts must be disabled! |
; destroys all general registers |
; interrupts remain disabled |
xchg ebp, eax |
mov edi, [timer_ticks] |
add edi, 500 ; 5 sec timeout |
.1: |
mov eax, ebp |
shl eax, 8 |
mov edx, [0x80000+eax+APPDATA.dbg_event_mem] |
test edx, edx |
jz .ret |
; read buffer header |
push ecx |
push eax |
push eax |
mov eax, ebp |
mov ebx, esp |
mov ecx, 8 |
call read_process_memory |
cmp eax, ecx |
jz @f |
add esp, 12 |
jmp .ret |
@@: |
cmp dword [ebx], 0 |
jg @f |
.2: |
pop ecx |
pop ecx |
pop ecx |
cmp dword [0x3000], 1 |
jnz .notos |
cmp [timer_ticks], edi |
jae .ret |
.notos: |
sti |
call change_task |
cli |
jmp .1 |
@@: |
mov ecx, [ebx+8] |
add ecx, [ebx+4] |
cmp ecx, [ebx] |
ja .2 |
; advance buffer position |
push ecx |
mov ecx, 4 |
sub ebx, ecx |
mov eax, ebp |
add edx, ecx |
call write_process_memory |
pop eax |
; write message |
mov eax, ebp |
add edx, ecx |
add edx, [ebx+8] |
add ebx, 20 |
pop ecx |
pop ecx |
pop ecx |
call write_process_memory |
; new debug event |
mov eax, ebp |
shl eax, 8 |
or byte [0x80000+eax+APPDATA.event_mask+1], 1 ; set flag 100h |
.ret: |
ret |
debug_exc: |
; int 1 = #DB |
save_ring3_context |
cld |
mov ax, os_data |
mov ds, ax |
mov es, ax |
mov eax, dr6 |
test ax, ax |
jns @f |
; this is exception from task switch |
; set DRx registers for task and continue |
mov eax, [0x3000] |
shl eax, 8 |
add eax, 0x80000+APPDATA.dbg_regs |
mov ecx, [eax+0] |
mov dr0, ecx |
mov ecx, [eax+4] |
mov dr1, ecx |
mov ecx, [eax+8] |
mov dr2, ecx |
mov ecx, [eax+0Ch] |
mov dr3, ecx |
xor ecx, ecx |
mov dr6, ecx |
mov ecx, [eax+10h] |
mov dr7, ecx |
restore_ring3_context |
iretd |
@@: |
push eax |
xor eax, eax |
mov dr6, eax |
; test if debugging |
cli |
mov eax, [0x3000] |
shl eax, 8 |
mov eax, [0x80000+eax+APPDATA.debugger_slot] |
test eax, eax |
jnz .debug |
sti |
; not debuggee => say error and terminate |
add esp, 28h+4 |
mov [error_interrupt], 1 |
call show_error_parameters |
mov edx, [0x3010] |
mov byte [edx+TASKDATA.state], 4 |
jmp change_task |
.debug: |
; we are debugged process, notify debugger and suspend ourself |
; eax=debugger PID |
pop edx |
mov ebx, dr7 |
mov cl, not 1 |
.l1: |
test bl, 1 |
jnz @f |
and dl, cl |
@@: |
shr ebx, 2 |
add cl, cl |
inc ecx |
cmp cl, not 10h |
jnz .l1 |
push edx ; DR6 image |
mov ecx, [0x3010] |
push dword [ecx+TASKDATA.pid] ; PID |
push 12 |
pop ecx |
push 3 ; 3 = debug exception |
call debugger_notify |
pop ecx |
pop ecx |
pop ecx |
mov edx, [0x3010] |
mov byte [edx+TASKDATA.state], 1 ; suspended |
call change_task |
restore_ring3_context |
iretd |
/kernel/branches/gfx_kernel/core/mem.inc |
---|
0,0 → 1,469 |
if ~defined mem_inc |
mem_inc_fix: |
mem_inc fix mem_inc_fix |
;include "memmanag.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;High-level memory management in MenuetOS. |
;;It uses memory manager in memmanager.inc |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
second_base_address=0xC0000000 |
std_application_base_address=0x10000000 |
general_page_table_ dd 0 |
general_page_table=general_page_table_+second_base_address |
;----------------------------------------------------------------------------- |
create_general_page_table: |
;input |
; none |
;output |
; none |
;Procedure create general page directory and write |
;it address to [general_page_table]. |
pushad |
mov eax,1 ;alloc 1 page |
mov ebx,general_page_table ;write address to [general_page_table] |
call MEM_Alloc_Pages ;allocate page directory |
mov eax,[general_page_table] |
call MEM_Get_Linear_Address ;eax - linear address of page directory |
mov edi,eax |
mov ebx,eax ;copy address of page directory to safe place |
xor eax,eax |
mov ecx,4096/4 |
cld |
rep stosd ;clear page directory |
mov eax,4 |
mov edx,eax |
call MEM_Alloc_Pages ;alloc page tables for 0x0-0x1000000 region |
cmp eax,edx |
jnz $ ;hang if not enough memory |
;fill page tables |
xor esi,esi |
mov ebp,7 |
.loop: |
;esi - number of page in page directory |
;ebp - current page address |
;ebx - linear address of page directory |
mov eax,[ebx+4*esi] |
add dword [ebx+4*esi],7 ;add flags to address of page table |
call MEM_Get_Linear_Address |
;eax - linear address of page table |
mov ecx,4096/4 |
;ecx (counter) - number of pages in page table |
;current address=4Mb*esi |
.loop1: |
mov [eax],ebp ;write page address (with flags) in page table |
add eax,4 |
add ebp,4096 ;size of page=4096 bytes |
loop .loop1 |
inc esi ;next page directory entry |
cmp esi,edx |
jnz .loop |
;map region 0x80000000-0x807fffff to LFB |
mov eax,2 ;size of the region is 4Mb so only 1 page table needed |
mov edx,ebx ;ebx still contains linear address of the page directory |
add ebx,0x800 |
call MEM_Alloc_Pages ;alloc page table for the region |
mov eax,[ebx] |
add dword [ebx],7 ;add flags |
call MEM_Get_Linear_Address ;get linear address of the page table |
mov ecx,4096/4 ;number of pages in page table |
mov edi,[0xfe80] |
add edi,7 |
.loop3: |
;eax - linear address of page table |
;edi - current linear address with flags |
mov [eax],edi |
add eax,4 |
add edi,4096 |
loop .loop3 |
mov eax,[ebx+4] |
call MEM_Get_Linear_Address |
add dword [ebx+4],7 |
mov ecx,4096/4 |
.loop31: |
mov [eax],edi |
add eax,4 |
add edi,4096 |
loop .loop31 |
;map region 0xC0000000-* to 0x0-* |
mov esi,edx ;esi=linear address of the page directory |
lea edi,[esi+(second_base_address shr 20)];add offset of entry (0xC00) |
mov ecx,4 |
rep movsd ;first 16Mb of the region mapped as 0x0-0x1000000 block |
mov eax,[0xfe8c] ;eax=memory size |
add eax,0x3fffff |
shr eax,22 |
mov esi,eax ;calculate number of entries in page directory |
sub esi,4 ;subtract entries for first 16Mb. |
mov ebp,0x1000000+7 ;start physical address with flags |
;mapping memory higher than 16Mb |
.loop4: |
;esi (counter) - number of entries in page directory |
;edi - address of entry |
test esi,esi |
jle .loop4end |
call MEM_Alloc_Page ;alloc page table for entry in page directory |
mov [edi],eax |
add dword [edi],7 ;write physical address of page table in page directory |
add edi,4 ;move entry pointer |
call MEM_Get_Linear_Address |
mov ecx,eax |
xor edx,edx |
.loop5: |
;ecx - linear address of page table |
;edx - index of page in page table |
;ebp - current mapped physical address with flags |
mov [ecx+4*edx],ebp ;write address of page in page table |
add ebp,0x1000 ;move to next page |
inc edx |
cmp edx,4096/4 |
jl .loop5 |
dec esi |
jmp .loop4 |
.loop4end: |
.set_cr3: |
;set value of cr3 register to the address of page directory |
mov eax,[general_page_table] |
add eax,8+16 ;add flags |
mov cr3,eax ;now we have full access paging |
popad |
ret |
;----------------------------------------------------------------------------- |
simple_clone_cr3_table: |
;Parameters: |
; eax - physical address of cr3 table (page directory) |
;result: |
; eax - physical address of clone of cr3 table. |
;Function copy only page directory. |
push ecx |
push edx |
push esi |
push edi |
call MEM_Get_Linear_Address |
;eax - linear address of cr3 table |
mov esi,eax |
call MEM_Alloc_Page |
test eax,eax |
jz .failed |
;eax - physical address of new page diretory |
mov edx,eax |
call MEM_Get_Linear_Address |
mov edi,eax |
mov ecx,4096/4 |
cld |
;esi - address of old page directory |
;edi - address of new page directory |
rep movsd ;copy page directory |
mov eax,edx |
.failed: |
pop edi |
pop esi |
pop edx |
pop ecx |
ret |
;----------------------------------------------------------------------------- |
create_app_cr3_table: |
;Parameters: |
; eax - slot of process (index in 0x3000 table) |
;result: |
; eax - physical address of table. |
;This function create page directory for new process and |
;write it physical address to offset 0xB8 of extended |
;process information. |
push ebx |
mov ebx,eax |
mov eax,[general_page_table] |
call simple_clone_cr3_table ;clone general page table |
shl ebx,8 |
mov [second_base_address+0x80000+ebx+APPDATA.dir_table],eax ;save address of page directory |
pop ebx |
ret |
;----------------------------------------------------------------------------- |
get_cr3_table: |
;Input: |
; eax - slot of process |
;result: |
; eax - physical address of page directory |
shl eax,8 ;size of process extended information=256 bytes |
mov eax,[second_base_address+0x80000+eax+APPDATA.dir_table] |
ret |
;----------------------------------------------------------------------------- |
dispose_app_cr3_table: |
;Input: |
; eax - slot of process |
;result: |
; none |
;This procedure frees page directory, |
;page tables and all memory of process. |
pushad |
mov ebp,eax |
;ebp = process slot in the procedure. |
shl eax,8 |
mov eax,[second_base_address+0x80000+eax+APPDATA.dir_table] |
mov ebx,eax |
;ebx = physical address of page directory |
call MEM_Get_Linear_Address |
mov edi,eax |
;edi = linear address of page directory |
mov eax,[edi+(std_application_base_address shr 20)] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov esi,eax |
;esi = linear address of first page table |
;search threads |
; mov ecx,0x200 |
xor edx,edx |
mov eax,0x2 |
.loop: |
;eax = current slot of process |
mov ecx,eax |
shl ecx,5 |
cmp byte [second_base_address+0x3000+ecx+TASKDATA.state],9 ;if process running? |
jz .next ;skip empty slots |
shl ecx,3 |
cmp [second_base_address+0x80000+ecx+APPDATA.dir_table],ebx ;compare page directory addresses |
jnz .next |
inc edx ;thread found |
.next: |
inc eax |
cmp eax,[0x3004] ;exit loop if we look through all processes |
jle .loop |
;edx = number of threads |
;our process is zombi so it isn't counted |
cmp edx,1 |
jg .threadsexists |
;if there isn't threads then clear memory. |
add edi,std_application_base_address shr 20 |
.loop1: |
;edi = linear address of current directory entry |
;esi = linear address of current page table |
test esi,esi |
jz .loop1end |
xor ecx,ecx |
.loop2: |
;ecx = index of page |
mov eax,[esi+4*ecx] |
test eax,eax |
jz .loopend ;skip empty entries |
and eax,not (4096-1) ;clear flags |
push ecx |
call MEM_Free_Page ;free page |
pop ecx |
.loopend: |
inc ecx |
cmp ecx,1024 ;there are 1024 pages in page table |
jl .loop2 |
mov eax,esi |
call MEM_Free_Page_Linear ;free page table |
.loop1end: |
add edi,4 ;move to next directory entry |
mov eax,[edi] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov esi,eax ;calculate linear address of new page table |
test edi,0x800 |
jz .loop1 ;test if we at 0x80000000 address? |
and edi,not (4096-1) ;clear offset of page directory entry |
mov eax,edi |
call MEM_Free_Page_Linear ;free page directory |
popad |
ret |
.threadsexists: ;do nothing |
popad ;last thread will free memory |
ret |
;----------------------------------------------------------------------------- |
mem_alloc_specified_region: |
;eax - linear directory address |
;ebx - start address (aligned to 4096 bytes) |
;ecx - size in pages |
;result: |
; eax=1 - ok |
; eax=0 - failed |
;Try to alloc and map ecx pages to [ebx;ebx+4096*ecx) interval. |
pushad |
mov ebp,ebx ;save start address for recoil |
mov esi,eax |
.gen_loop: |
;esi = linear directory address |
;ebx = current address |
;ecx = remaining size in pages |
mov edx,ebx |
shr edx,22 |
mov edi,[esi+4*edx] ;find directory entry for current address |
test edi,edi |
jnz .table_exists ;check if page table allocated |
call MEM_Alloc_Page ;alloc page table |
test eax,eax |
jz .failed |
mov [esi+4*edx],eax |
add dword [esi+4*edx],7 ;write it address with flags |
call MEM_Get_Linear_Address |
call mem_fill_page ;clear page table |
jmp .table_linear |
.table_exists: |
;calculate linear address of page table |
mov eax,edi |
and eax,not (4096-1) ;clear flags |
call MEM_Get_Linear_Address |
.table_linear: |
;eax = linear address of page table |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) ;calculate index in page table |
mov edi,eax |
.loop: |
;edi = linear address of page table |
;edx = current page table index |
;ecx = remaining size in pages |
;ebx = current address |
test ecx,ecx |
jle .endloop1 ;all requested pages allocated |
call MEM_Alloc_Page ;alloc new page |
test eax,eax |
jz .failed |
mov [edi+4*edx],eax |
add dword [edi+4*edx],7 ;write it address with flags |
call MEM_Get_Linear_Address |
call mem_fill_page ;clear new page |
;go to next page table entry |
dec ecx |
add ebx,4096 |
inc edx |
test edx,(1024-1) |
jnz .loop |
jmp .gen_loop |
.endloop1: |
popad |
mov eax,1 ;ok |
ret |
.failed: |
;calculate data for recoil |
sub ebx,ebp |
shr ebx,12 |
mov ecx,ebx ;calculate number of allocated pages |
mov eax,esi ;restore linear address of page directory |
mov ebx,ebp ;restore initial address |
call mem_free_specified_region ;free all allocated pages |
popad |
xor eax,eax ;fail |
ret |
;----------------------------------------------------------------------------- |
mem_fill_page: |
;Input: |
; eax - address |
;result: |
; none |
;set to zero 4096 bytes at eax address. |
push ecx |
push edi |
mov edi,eax |
mov ecx,4096/4 |
xor eax,eax |
rep stosd |
lea eax,[edi-4096] |
pop edi |
pop ecx |
ret |
;----------------------------------------------------------------------------- |
mem_free_specified_region: |
;eax - linear page directory address |
;ebx - start address (aligned to 4096 bytes) |
;ecx - size in pages |
;result - none |
;Free pages in [ebx;ebx+4096*ecx) region. |
pushad |
mov esi,eax |
xor ebp,ebp |
.gen_loop: |
;esi = linear page directory address |
;ebx = current address |
;ecx = remaining pages |
;ebp = 0 for first page table |
; 1 otherwise |
mov edx,ebx |
shr edx,22 |
mov eax,[esi+4*edx] ;find directory entry for current address |
and eax,not (4096-1) |
test eax,eax |
jnz .table_exists |
;skip absent page tables |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) ;edx - index of current page |
add ebx,1 shl 22 |
add ecx,edx |
and ebx,not ((1 shl 22)-1) |
mov ebp,1 ;set flag |
sub ecx,1024 ;ecx=ecx-(1024-edx) |
jg .gen_loop |
popad |
ret |
.table_exists: |
call MEM_Get_Linear_Address |
;eax - linear address of table |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) ;edx - index of current page |
mov edi,eax |
.loop: |
;edi = linear address of page table entry |
;edx = index of page table entry |
;ecx = remaining pages |
test ecx,ecx |
jle .endloop1 |
mov eax,[edi+4*edx] |
and eax,not (4096-1) |
call MEM_Free_Page ;free page |
mov dword [edi+4*edx],0 ;and clear page table entry |
dec ecx |
inc edx |
cmp edx,1024 |
jl .loop |
test ebp,ebp |
jz .first_page |
mov eax,edi |
call MEM_Free_Page_Linear ;free page table |
mov edx,ebx |
shr edx,22 |
mov dword [esi+4*edx],0 ;and clear page directory entry |
.first_page: |
add ebx,1 shl 22 |
and ebx,not ((1 shl 22)-1) ;calculate new current address |
mov ebp,1 ;set flag |
jmp .gen_loop |
.endloop1: |
popad |
ret |
end if |
/kernel/branches/gfx_kernel/core/memmanag.inc |
---|
0,0 → 1,833 |
if ~defined memmanager_inc |
memmanager_inc_fix: |
memmanager_inc fix memmanager_inc_fix |
;for testing in applications |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; Memory allocator for MenuetOS kernel |
;; Andrey Halyavin, halyavin@land.ru 2005 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; heap block structure - |
;; you can handle several ranges of |
;; pages simultaneosly. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
.heap_linear_address equ 0 |
.heap_block_size equ 4 |
.heap_physical_address equ 8 |
.heap_reserved equ 12 |
.heap_block_info equ 16 |
max_heaps equ 8 |
.range_info equ 36 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; memory manager data |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
uglobal |
MEM_heap_block rd .heap_block_info*max_heaps/4 |
MEM_heap_count rd 1 |
MEM_cli_count rd 1 |
MEM_cli_prev rd 1 |
MEM_FreeSpace rd 1 |
; MEM_AllSpace rd 1 |
endg |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Init |
;;Initialize memory manager structures. |
;;Must be called first. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Init: |
push eax |
xor eax,eax |
mov [MEM_cli_prev],eax ;init value = 0 |
dec eax |
mov [MEM_cli_count],eax ;init value = -1 |
pop eax |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Heap_Lock |
;;Wait until all operations with heap will be finished. |
;;Between MEM_Heap_Lock and MEM_Heap_UnLock operations |
;;with heap are forbidden. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Heap_Lock: |
pushfd |
cli |
inc dword [MEM_cli_count] |
jz MEM_Heap_First_Lock |
add esp,4 |
ret |
MEM_Heap_First_Lock: ;save interrupt flag |
shr dword [esp],9 |
and dword [esp],1 |
pop dword [MEM_cli_prev] |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Heap_UnLock |
;;After this routine operations with heap are allowed. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Heap_UnLock: |
dec dword [MEM_cli_count] |
js MEM_Heap_UnLock_last |
ret |
MEM_Heap_UnLock_last: |
cmp dword [MEM_cli_prev],0 ;restore saved interrupt flag |
jz MEM_Heap_UnLock_No_sti |
sti |
MEM_Heap_UnLock_No_sti: |
ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Heap |
;;Add new range to memory manager. |
;;eax - linear address |
;;ebx - size in pages |
;;ecx - physical address |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
MEM_Add_Heap: |
push edx |
call MEM_Heap_Lock |
mov edx,[MEM_heap_count] |
cmp edx,max_heaps |
jz MEM_Add_Heap_Error |
inc dword [MEM_heap_count] |
shl edx,4 |
mov [MEM_heap_block+edx+.heap_linear_address],eax |
mov [MEM_heap_block+edx+.heap_block_size],ebx |
shl dword [MEM_heap_block+edx+.heap_block_size],12 |
mov [MEM_heap_block+edx+.heap_physical_address],ecx |
lea edx,[4*ebx+.range_info+4095] ;calculate space for page info table |
and edx,0xFFFFF000 |
push edi |
mov edi,edx |
shr edi,12 |
sub edi,ebx ;edi=-free space |
sub [MEM_FreeSpace],edi |
; sub [MEM_AllSpace],edi |
mov [eax],eax |
add [eax],edx ;first 4 bytes - pointer to first free page |
;clean page info area |
lea edi,[eax+4] |
mov ecx,edx |
shr ecx,2 |
push eax |
xor eax,eax |
rep stosd |
pop eax |
pop edi |
;create free pages list. |
mov ecx,[eax] |
shl ebx,12 |
add eax,ebx ;eax - address after block |
MEM_Add_Heap_loop: |
add ecx,4096 |
mov [ecx-4096],ecx ;set forward pointer |
cmp ecx,eax |
jnz MEM_Add_Heap_loop |
mov dword [ecx-4096],0 ;set end of list |
MEM_Add_Heap_ret: |
call MEM_Heap_UnLock |
pop edx |
ret |
MEM_Add_Heap_Error: |
xor eax,eax |
jmp MEM_Add_Heap_ret |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Physical_Address |
;;Translate linear address to physical address |
;;Parameters: |
;; eax - linear address |
;;Result: |
;; eax - physical address |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Physical_Address |
MEM_Get_Physical_Address: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Physical_Address_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
jl MEM_Get_Physical_Address_next |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jge MEM_Get_Physical_Address_next |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
jmp MEM_Get_Physical_Address_loopend |
MEM_Get_Physical_Address_next: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Get_Physical_Address_loop |
xor eax,eax ;address not found |
MEM_Get_Physical_Address_loopend: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Linear_Address |
;;Translate physical address to linear address. |
;;Parameters: |
;; eax - physical address |
;;Result: |
;; eax - linear address |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Linear_Address |
MEM_Get_Linear_Address: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Linear_Address_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
jl MEM_Get_Linear_Address_Next |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jge MEM_Get_Linear_Address_Next |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
call MEM_Heap_UnLock |
pop ecx |
ret |
MEM_Get_Linear_Address_Next: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Get_Linear_Address_loop |
call MEM_Heap_UnLock |
pop ecx |
xor eax,eax ;address not found |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Page |
;;Allocate and add reference to page |
;;Result: |
;; eax<>0 - physical address of page |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Page |
MEM_Alloc_Page: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Page_loop: |
push ecx |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [ecx],0 |
jz MEM_Alloc_Page_loopend |
mov eax,[ecx] |
push dword [eax] |
pop dword [ecx] |
sub eax,ecx |
push eax |
shr eax,10 |
mov word [ecx+.range_info+eax],1 |
pop eax |
pop ecx |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
dec [MEM_FreeSpace] |
jmp MEM_Alloc_Page_ret |
MEM_Alloc_Page_loopend: |
pop ecx |
sub ecx,16 |
jns MEM_Alloc_Page_loop |
xor eax,eax |
MEM_Alloc_Page_ret: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Page_Linear |
;;Allocate and add reference to page |
;;Result: |
;; eax<>0 - linear address of page |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Page_Linear |
MEM_Alloc_Page_Linear: |
push ecx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Page_Linear_loop: |
push ecx |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [ecx],0 |
jz MEM_Alloc_Page_Linear_loopend |
mov eax,[ecx] |
push dword [eax] |
pop dword [ecx] |
push eax |
sub eax,ecx |
shr eax,10 |
mov word [ecx+.range_info+eax],1 |
pop eax |
pop ecx |
dec [MEM_FreeSpace] |
jmp MEM_Alloc_Page_Linear_ret |
MEM_Alloc_Page_Linear_loopend: |
pop ecx |
sub ecx,16 |
jns MEM_Alloc_Page_Linear_loop |
xor eax,eax |
MEM_Alloc_Page_Linear_ret: |
call MEM_Heap_UnLock |
pop ecx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Page |
;;Remove reference and free page if number of |
;;references is equal to 0 |
;;Parameters: |
;; eax - physical address of page |
;;Result: |
;; eax - 1 success |
;; eax - 0 failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if (used MEM_Free_Page) | (used MEM_Free_Page_Linear) |
MEM_Free_Page: |
test eax,eax |
jz MEM_Free_Page_Zero |
test eax,0xFFF |
jnz MEM_Free_Page_Not_Aligned |
push ebx |
push ecx |
push edx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Free_Page_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
js MEM_Free_Page_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Free_Page_Heap_loopend |
MEM_Free_Page_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Free_Page_Heap_loop |
xor eax,eax |
inc eax |
jmp MEM_Free_Page_ret |
MEM_Free_Page_Heap_loopend: |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov ebx,eax |
add eax,ecx |
shr ebx,10 |
mov edx,[ecx+.range_info+ebx] |
test edx,0x80000000 |
jnz MEM_Free_Page_Bucket |
test dx,dx |
jz MEM_Free_Page_Error |
dec word [ecx+.range_info+ebx] |
jnz MEM_Free_Page_OK |
MEM_Free_Page_Bucket: |
push dword [ecx] |
mov [ecx],eax |
pop dword [eax] |
mov dword [ecx+.range_info+ebx],0 |
inc [MEM_FreeSpace] |
MEM_Free_Page_OK: |
mov eax,1 |
MEM_Free_Page_ret: |
call MEM_Heap_UnLock |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Page_Error: |
xor eax,eax |
jmp MEM_Free_Page_ret |
MEM_Free_Page_Zero: |
inc eax |
ret |
MEM_Free_Page_Not_Aligned: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Page_Linear |
;;Remove reference and free page if number of |
;;references is equal to 0 |
;;Parameters: |
;; eax - linear address of page |
;;Result: |
;; eax - 1 success |
;; eax - 0 failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Page_Linear |
MEM_Free_Page_Linear: |
test eax,eax |
jz MEM_Free_Page_Zero |
test eax,0xFFF |
jnz MEM_Free_Page_Not_Aligned |
push ebx |
push ecx |
push edx |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Free_Page_Linear_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
js MEM_Free_Page_Linear_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Free_Page_Heap_loopend |
MEM_Free_Page_Linear_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Free_Page_Linear_Heap_loop |
xor eax,eax |
inc eax |
jmp MEM_Free_Page_ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Pages |
;;Allocates set of pages. |
;;Parameters: |
;; eax - number of pages |
;; ebx - buffer for physical addresses |
;;Result: |
;; eax - number of allocated pages |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Pages |
MEM_Alloc_Pages: |
push eax |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Alloc_Pages_ret |
MEM_Alloc_Pages_loop: |
call MEM_Alloc_Page |
test eax,eax |
jz MEM_Alloc_Pages_ret |
mov [ebx],eax |
add ebx,4 |
dec ecx |
jnz MEM_Alloc_Pages_loop |
MEM_Alloc_Pages_ret: |
sub [esp+8],ecx |
pop ecx |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc_Pages_Linear |
;;Allocates set of pages. |
;;Parameters: |
;; eax - number of pages |
;; ebx - buffer for linear addresses |
;;Result: |
;; eax - number of allocated pages |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc_Pages_Linear |
MEM_Alloc_Pages_Linear: |
push eax |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Alloc_Pages_Linear_ret |
MEM_Alloc_Pages_Linear_loop: |
call MEM_Alloc_Page_Linear |
test eax,eax |
jz MEM_Alloc_Pages_Linear_ret |
mov [ebx],eax |
add ebx,4 |
dec ecx |
jnz MEM_Alloc_Pages_Linear_loop |
MEM_Alloc_Pages_Linear_ret: |
sub [esp+8],ecx |
pop ecx |
pop ebx |
pop eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Pages |
;;Parameters: |
;; eax - number of pages |
;; ebx - array of addresses |
;;Result: |
;; eax=1 - succcess |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Pages |
MEM_Free_Pages: |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Free_Pages_ret |
MEM_Free_Pages_loop: |
mov eax,[ebx] |
call MEM_Free_Page |
add ebx,4 |
test eax,eax |
jz MEM_Free_Pages_ret |
dec ecx |
jnz MEM_Free_Pages_loop |
MEM_Free_Pages_ret: |
pop ecx |
pop ebx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free_Pages_Linear |
;;Parameters: |
;; eax - number of pages |
;; ebx - array of addresses |
;;Result: |
;; eax=1 - succcess |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free_Pages_Linear |
MEM_Free_Pages_Linear: |
push ebx |
push ecx |
mov ecx,eax |
test ecx,ecx |
jz MEM_Free_Pages_Linear_ret |
MEM_Free_Pages_Linear_loop: |
mov eax,[ebx] |
call MEM_Free_Page_Linear |
add ebx,4 |
test eax,eax |
jz MEM_Free_Pages_Linear_ret |
dec ecx |
jnz MEM_Free_Pages_Linear_loop |
MEM_Free_Pages_Linear_ret: |
pop ecx |
pop ebx |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Heap_Number |
;;Calculate number of heap which pointer belongs to. |
;;Parameter: |
;; eax - address |
;;Result: |
;; ecx - number of heap*16. |
;; eax=0 if address not found. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Heap_Number |
MEM_Get_Heap_Number: |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Heap_loop: |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
jl MEM_Get_Heap_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Get_Heap_loopend |
MEM_Get_Heap_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
sub ecx,16 |
jns MEM_Get_Heap_loop |
call MEM_Heap_UnLock |
xor eax,eax |
ret |
MEM_Get_Heap_loopend: |
add eax,[MEM_heap_block+ecx+.heap_physical_address] |
call MEM_Heap_UnLock |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Get_Heap_Number_Linear |
;;Calculate number of heap which pointer belongs to. |
;;Parameter: |
;; eax - address |
;;Result: |
;; ecx - number of heap*16. |
;; eax=0 if address not found. |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Get_Heap_Number_Linear |
MEM_Get_Heap_Number_Linear: |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Get_Heap_Linear_loop: |
sub eax,[MEM_heap_block+ecx+.heap_linear_address] |
jl MEM_Get_Heap_Linear_loopnext |
cmp eax,[MEM_heap_block+ecx+.heap_block_size] |
jl MEM_Get_Heap_Linear_loopend |
MEM_Get_Heap_Linear_loopnext: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
sub ecx,16 |
jns MEM_Get_Heap_Linear_loop |
call MEM_Heap_UnLock |
xor eax,eax |
ret |
MEM_Get_Heap_Linear_loopend: |
add eax,[MEM_heap_block+ecx+.heap_linear_address] |
call MEM_Heap_UnLock |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Alloc |
;;Allocate small region. |
;;Parameters: |
;; eax - size (0<eax<=4096) |
;;Result: |
;; eax - linear address |
;; eax=0 - not enough memory |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Alloc |
MEM_Alloc: |
;find chain |
test eax,eax |
jng MEM_Alloc_Wrong_Size |
cmp eax,4096 |
jg MEM_Alloc_Wrong_Size |
push ebx |
push ecx |
push edx |
push esi |
dec eax |
shr eax,4 |
xor edx,edx |
MEM_Alloc_Find_Size: |
add edx,4 |
shr eax,1 |
jnz MEM_Alloc_Find_Size |
MEM_Alloc_Size_Found: |
mov ecx,edx |
shr ecx,2 |
add ecx,4 |
mov eax,1 |
shl eax,cl |
mov esi,eax |
;esi - block size |
;edx - offset |
call MEM_Heap_Lock |
mov ecx,[MEM_heap_count] |
dec ecx |
shl ecx,4 |
MEM_Alloc_Find_Heap: |
mov eax,[MEM_heap_block+ecx+.heap_linear_address] |
cmp dword [eax+edx],0 |
jnz MEM_Alloc_Use_Existing |
sub ecx,16 |
jns MEM_Alloc_Find_Heap |
;create new bucket page |
call MEM_Alloc_Page_Linear |
call MEM_Get_Heap_Number_Linear |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
mov [ecx+edx],eax |
lea ebx,[eax+4096] |
MEM_Alloc_List_loop: |
mov [eax],eax |
mov [eax+4],eax |
add [eax],esi |
sub [eax+4],esi |
add eax,esi |
cmp eax,ebx |
jnz MEM_Alloc_List_loop |
sub ebx,esi |
mov dword [ebx],0 |
sub eax,4096 |
mov dword [eax+4],0 |
mov eax,ecx |
MEM_Alloc_Use_Existing: |
mov ebx,eax |
mov eax,[eax+edx] |
mov ecx,[eax] |
mov [ebx+edx],ecx |
test ecx,ecx |
jz MEM_Alloc_Became_Empty |
mov dword [ecx+4],0 |
MEM_Alloc_Became_Empty: |
mov ecx,eax |
sub ecx,ebx |
shr ecx,10 |
and ecx,0xFFFFFFFC |
inc byte [ebx+.range_info+ecx+2] |
shr edx,2 |
add edx,128 |
dec edx |
mov [ebx+.range_info+ecx+3],dl |
MEM_Alloc_ret: |
call MEM_Heap_UnLock |
pop esi |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Alloc_Wrong_Size: |
xor eax,eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Free |
;;Parameters: |
;; eax - linear address |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Free |
MEM_Free: |
test eax,eax |
jz MEM_Free_Zero |
push ebx |
push ecx |
push edx |
push esi |
push edi |
push ebp |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number_Linear |
test eax,eax |
jz MEM_Free_ret |
mov edx,eax |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
sub edx,ecx |
shr edx,10 |
and edx,0xFFFFFFFC |
mov ebx,[ecx+.range_info+edx] |
mov esi,ebx |
shr esi,24 |
sub esi,128 |
mov edi,[ecx+4+4*esi] |
mov [eax],edi |
mov dword [eax+4],0 |
test edi,edi |
jz MEM_Free_Empty_List |
mov [edi+4],eax |
MEM_Free_Empty_List: |
mov [ecx+4+4*esi],eax |
sub ebx,0x10000 |
mov [ecx+.range_info+edx],ebx |
test ebx,0xFF0000 |
jnz MEM_Free_ret |
;delete empty blocks on the page |
lea edx,[esi+5] |
and eax,0xFFFFF000 |
mov edi,eax |
mov eax,1 |
xchg ecx,edx |
shl eax,cl |
mov ecx,edx |
mov edx,eax |
;edx - size of block |
;edi - start of page |
mov eax,edi |
lea ebx,[eax+4096] |
MEM_Free_Block_loop: |
cmp dword [eax+4],0 |
jnz MEM_Free_Block_Not_First |
mov ebp,dword [eax] |
mov [ecx+4+4*esi],ebp |
test ebp,ebp |
jz MEM_Free_Block_Last |
mov dword [ebp+4],0 |
MEM_Free_Block_Last: |
jmp MEM_Free_Block_loop_end |
MEM_Free_Block_Not_First: |
mov ebp,dword [eax] |
push ebp |
mov ebp,dword [eax+4] |
pop dword [ebp] |
mov ebp,dword [eax] |
test ebp,ebp |
jz MEM_Free_Block_loop_end |
push dword [eax+4] |
pop dword [ebp+4] |
; jmp MEM_Free_Block_loop_end |
MEM_Free_Block_loop_end: |
add eax,edx |
cmp eax,ebx |
jnz MEM_Free_Block_loop |
mov eax,edi |
call MEM_Free_Page_Linear |
MEM_Free_ret: |
call MEM_Heap_UnLock |
pop ebp |
pop edi |
pop esi |
pop edx |
pop ecx |
pop ebx |
ret |
MEM_Free_Zero: |
inc eax |
ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Reference |
;; eax - physical address of page |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Add_Reference |
MEM_Add_Reference: |
push ebx |
push ecx |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number |
test eax,eax |
jz MEM_Add_Reference_ret |
sub eax,[MEM_heap_block+ecx+.heap_physical_address] |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
shr eax,10 |
and eax,0xFFFFFFFC |
test dword [ecx+eax+.range_info],0x80000000 |
jnz MEM_Add_Reference_failed |
inc dword [ecx+eax+.range_info] |
MEM_Add_Reference_ret: |
call MEM_Heap_UnLock |
pop ecx |
pop ebx |
ret |
MEM_Add_Reference_failed: |
xor eax,eax |
jmp MEM_Add_Reference_ret |
end if |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;MEM_Add_Reference_Linear |
;; eax - linear address of page |
;;Result: |
;; eax=1 - success |
;; eax=0 - failed |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
if used MEM_Add_Reference_Linear |
MEM_Add_Reference_Linear: |
push ebx |
push ecx |
call MEM_Heap_Lock |
call MEM_Get_Heap_Number_Linear |
test eax,eax |
jz MEM_Add_Reference_Linear_ret |
mov ecx,[MEM_heap_block+ecx+.heap_linear_address] |
sub eax,ecx |
shr eax,10 |
and eax,0xFFFFFFFC |
test dword [ecx+eax+.range_info],0x80000000 |
jnz MEM_Add_Reference_Linear_failed |
inc dword [ecx+eax+.range_info] |
mov eax,1 |
MEM_Add_Reference_Linear_ret: |
call MEM_Heap_UnLock |
pop ecx |
pop ebx |
ret |
MEM_Add_Reference_Linear_failed: |
xor eax,eax |
jmp MEM_Add_Reference_Linear_ret |
end if |
end if ;memmanager.inc |
/kernel/branches/gfx_kernel/core/newproce.inc |
---|
0,0 → 1,1615 |
if ~defined newprocess_inc |
newprocess_inc_fix: |
newprocess_inc fix newprocess_inc_fix |
include "mem.inc" |
include "memmanag.inc" |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;Working with new types of processes. |
;;Author: Khalyavin Andrey halyavin@land.ru |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
iglobal |
new_process_loading db 'K : New Process - loading',13,10,0 |
new_process_running db 'K : New Process - done',13,10,0 |
start_not_enough_memory db 'K : New Process - not enough memory',13,10,0 |
endg |
;----------------------------------------------------------------------------- |
find_new_process_place: |
;input: |
; none |
;result: |
; eax=[new_process_place]<>0 - ok |
; 0 - failed. |
;This function find least empty slot. |
;It doesn't increase [0x3004]! |
mov eax,0x3000+second_base_address |
push ebx |
mov ebx,[0x3004] |
inc ebx |
shl ebx,5 |
add ebx,eax ;ebx - address of process information for (last+1) slot |
.newprocessplace: |
;eax = address of process information for current slot |
cmp eax,ebx |
jz .endnewprocessplace ;empty slot after high boundary |
add eax,0x20 |
cmp word [eax+TASKDATA.state],9 ;check process state, 9 means that process slot is empty |
jnz .newprocessplace |
.endnewprocessplace: |
mov ebx,eax |
sub eax,0x3000+second_base_address |
shr eax,5 ;calculate slot index |
cmp eax,256 |
jge .failed ;it should be <256 |
mov word [ebx+TASKDATA.state],9 ;set process state to 9 (for slot after hight boundary) |
mov [new_process_place],eax ;save process slot |
pop ebx |
ret |
.failed: |
xor eax,eax |
pop ebx |
ret |
;----------------------------------------------------------------------------- |
safe_sti: |
cmp byte [0xe000], 1 |
jne @f |
sti |
@@:ret |
new_start_application_floppy: |
;input: |
; eax - pointer to filename |
; ebx - parameters to pass |
; edx - flags |
;result: |
; eax - pid of new process |
; or 0 if call fails. |
mov [appl_path],edi |
pushad |
mov esi,new_process_loading |
call sys_msg_board_str ;write to debug board |
;wait application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
;we can change system tables now |
push edi |
push ebx |
push eax |
call find_new_process_place ;find empty process slot |
sti |
test eax,eax |
mov ecx, -0x20 ; too many processes |
jz .failed |
mov edi,eax |
shl edi,8 |
add edi,0x80000 |
mov ecx,256/4 |
xor eax,eax |
cld |
rep stosd ;clean extended information about process |
;set new process name |
mov [appl_path_size],eax |
pop eax |
push eax |
.find_last_byte: |
cmp byte [eax],0 |
jz .find_last_byte_end |
inc eax |
inc [appl_path_size] |
jmp .find_last_byte |
.find_last_byte_end: |
add [appl_path_size],24 |
sub eax,11 ;last 11 bytes = application name |
; mov eax,[esp] ;eax - pointer to file name |
mov ebx,[new_process_place] |
shl ebx,8 |
add ebx,0x80000 + APPDATA.app_name |
mov ecx,11 |
call memmove |
;read header of file |
mov eax,[esp] |
mov ebx,1 ;index of first block |
mov ecx,2 ;number of blocks |
mov edx,0x90000 ;temp area |
mov esi,12 ;file name length |
mov edi,[esp+8] |
; cli |
call floppy_fileread ;read file from FD |
; sti |
mov ecx, eax |
neg ecx |
jnz .cleanfailed |
;check MENUET signature |
mov ecx, -0x1F ; not Menuet/Kolibri executable |
cmp [0x90000],dword 'MENU' |
jnz .cleanfailed |
cmp [0x90004],word 'ET' |
jnz .cleanfailed |
call get_app_params ;parse header fields |
test esi, esi |
jz .cleanfailed |
mov eax,[new_process_place] |
inc ecx ; -0x1E = no memory |
call create_app_cr3_table ;create page directory for new process |
test eax,eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address ;calculate linear address of it |
mov ebx,std_application_base_address |
mov ecx,[app_mem] |
add ecx,4095 |
shr ecx,12 |
mov edx,eax |
call mem_alloc_specified_region ;allocate memory for application |
test eax,eax |
mov ecx, -0x1E |
jz .cleanfailed_mem1 |
mov eax,[edx+(std_application_base_address shr 20)] |
and eax,not (4096-1) ;eax - physical address of first (for application memory) page table |
call MEM_Get_Linear_Address |
mov edx,eax |
;read file |
mov ebx,1 |
mov esi,12 ;length of file name |
.loop1: |
;edx = linear address of current page table entry |
;ebx = index of current block in file |
push edx |
mov eax,[edx] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov edx,eax ;read file block to current page |
mov eax,[esp+4] ;restore pointer to file name |
mov ecx,8 ;number of blocks read |
push ebx |
mov edi,[esp+16] |
; cli |
call floppy_fileread |
;ebx=file size |
; sti |
pop ecx |
shr ebx,9 |
cmp ecx,ebx |
jg .endloop1 ;if end of file? |
mov ebx,ecx |
test eax,eax |
jnz .endloop1 ;check io errors |
pop edx |
add ebx,8 ;go to next page |
add edx,4 |
jmp .loop1 |
.endloop1: |
add esp,8+4 ;pop linear address of page table entry and pointer to file name |
call new_start_application_fl.add_app_parameters |
mov [esp+28],eax |
popad |
ret |
.cleanfailed_mem1: |
;there is mem for directory entry, but there is no mem for pages |
;so free directory entry |
mov eax,[new_process_place] |
shl eax,8 |
mov eax,[0x80000+eax+APPDATA.dir_table] |
call MEM_Free_Page |
.cleanfailed_mem: |
;there is no mem for directory entry, display message. |
mov esi,start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: ;clean process name |
push ecx ; save error code |
;can't read file, clean process name. |
;this avoid problems with panel application. |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 + APPDATA.app_name |
mov ecx,11 |
mov eax,' ' |
cld |
rep stosb |
pop eax |
.failed: |
;no more slots |
add esp,8+4 |
mov [application_table_status],0 |
mov [esp+1Ch], eax |
popad |
sti |
ret |
;----------------------------------------------------------------------------- |
new_start_application_fl: |
;input: |
; eax - pointer to filename |
; ebx - parameters to pass |
; edx - flags |
;result: |
; eax - pid of new process |
; or 0 if call fails. |
mov [appl_path],edi |
mov [appl_path_size],36 |
pushad |
mov esi,new_process_loading |
call sys_msg_board_str ;write to debug board |
;wait application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
;we can change system tables now |
push ebx |
push eax |
call find_new_process_place ;find empty process slot |
call safe_sti |
test eax,eax |
mov ecx, -0x20 ; too many processes |
jz .failed |
mov edi,eax |
shl edi,8 |
add edi,0x80000 |
mov ecx,256/4 |
xor eax,eax |
cld |
rep stosd ;clean extended information about process |
;set new process name |
mov eax,[esp] ;eax - pointer to file name |
mov ebx,[new_process_place] |
shl ebx,8 |
add ebx,0x80000 + APPDATA.app_name |
mov ecx,11 |
call memmove |
;read header of file |
mov ebx,1 ;index of first block |
mov ecx,2 ;number of blocks |
mov edx,0x90000 ;temp area |
mov esi,12 ;file name length |
cli |
call fileread ;read file from RD |
call safe_sti |
mov ecx, eax |
neg ecx |
jnz .cleanfailed |
;check MENUET signature |
mov ecx, -0x1F ; not Menuet/Kolibri executable |
cmp [0x90000],dword 'MENU' |
jnz .cleanfailed |
cmp [0x90004],word 'ET' |
jnz .cleanfailed |
call get_app_params ;parse header fields |
test esi,esi |
jz .cleanfailed |
mov eax,[new_process_place] |
inc ecx ; -0x1E = no memory |
call create_app_cr3_table ;create page directory for new process |
test eax,eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address ;calculate linear address of it |
mov ebx,std_application_base_address |
mov ecx,[app_mem] |
add ecx,4095 |
shr ecx,12 |
mov edx,eax |
call mem_alloc_specified_region ;allocate memory for application |
test eax,eax |
mov ecx, -0x1E |
jz .cleanfailed_mem1 |
mov eax,[edx+(std_application_base_address shr 20)] |
and eax,not (4096-1) ;eax - physical address of first (for application memory) page table |
call MEM_Get_Linear_Address |
mov edx,eax |
;read file |
mov ebx,1 |
mov esi,12 ;length of file name |
.loop1: |
;edx = linear address of current page table entry |
;ebx = index of current block in file |
push edx |
mov eax,[edx] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov edx,eax ;read file block to current page |
mov eax,[esp+4] ;restore pointer to file name |
mov ecx,8 ;number of blocks read |
push ebx |
cli |
call fileread |
;ebx=file size |
call safe_sti |
pop ecx |
shr ebx,9 |
cmp ecx,ebx |
jg .endloop1 ;if end of file? |
mov ebx,ecx |
test eax,eax |
jnz .endloop1 ;check io errors |
pop edx |
add ebx,8 ;go to next page |
add edx,4 |
jmp .loop1 |
.endloop1: |
add esp,8 ;pop linear address of page table entry and pointer to file name |
call .add_app_parameters |
mov [esp+28],eax |
popad |
ret |
.cleanfailed_mem1: |
;there is mem for directory entry, but there is no mem for pages |
;so free directory entry |
mov eax,[new_process_place] |
shl eax,8 |
mov eax,[0x80000+eax+APPDATA.dir_table] |
call MEM_Free_Page |
.cleanfailed_mem: |
;there is no mem for directory entry, display message. |
mov esi,start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: ;clean process name |
push ecx ; save error code |
;can't read file, clean process name. |
;this avoid problems with panel application. |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000+APPDATA.app_name |
mov ecx,11 |
mov eax,' ' |
cld |
rep stosb |
pop eax |
.failed: |
;no more slots |
add esp,8 |
mov [application_table_status],0 |
mov [esp+1Ch], eax |
popad |
call safe_sti |
ret |
.add_app_parameters: |
;input: |
; [esp] - pointer to parameters |
; [esp+4]-[esp+36] pushad registers. |
;result |
; eax - pid of new process |
; or zero if failed |
cli |
mov ebx,[new_process_place] |
cmp ebx,[0x3004] |
jle .noinc |
inc dword [0x3004] ;update number of processes |
.noinc: |
; mov ebx,[new_process_place] |
;set 0x8c field of extended information about process |
;(size of application memory) |
shl ebx,8 |
mov eax,[app_mem] |
mov [second_base_address+0x80000+APPDATA.mem_size+ebx],eax |
;set 0x10 field of information about process |
;(application base address) |
; mov ebx,[new_process_place] |
; shl ebx,5 |
shr ebx,3 |
mov dword [second_base_address+0x3000+ebx+TASKDATA.mem_start],std_application_base_address |
;add command line parameters |
.add_command_line: |
mov edx,[app_i_param] |
test edx,edx |
jz .no_command_line ;application don't need parameters |
mov eax,[esp+4] |
test eax,eax |
jz .no_command_line ;no parameters specified |
;calculate parameter length |
mov esi,eax |
xor ecx,ecx |
.command_line_len: |
cmp byte [esi],0 |
jz .command_line_len_end |
inc esi |
inc ecx |
cmp ecx,256 |
jl .command_line_len |
.command_line_len_end: |
;ecx - parameter length |
;edx - address of parameters in new process address space |
mov ebx,eax ;ebx - address of parameters in our address space |
mov eax,[new_process_place] |
call write_process_memory ;copy parameters to new process address space |
.no_command_line: |
;****************************************************************** |
mov edx,[app_i_icon] |
test edx,edx |
jz .no_command_line_1 ;application don't need path of file |
mov ebx,[appl_path] |
mov ecx,[appl_path_size] |
mov eax,[new_process_place] |
call write_process_memory ;copy path of file to new process address space |
.no_command_line_1: |
;****************************************************************** |
mov ebx,[new_process_place] |
mov eax,ebx |
shl ebx,5 |
add ebx,0x3000 ;ebx - pointer to information about process |
mov [ebx+TASKDATA.wnd_number],al ;set window number on screen = process slot |
mov [ebx+TASKDATA.event_mask],dword 1+2+4 ;set default event flags (see 40 function) |
inc dword [process_number] |
mov eax,[process_number] |
mov [ebx+TASKDATA.pid],eax ;set PID |
mov ecx,ebx |
add ecx,draw_data-0x3000 ;ecx - pointer to draw data |
;set draw data to full screen |
mov [ecx+RECT.left],dword 0 |
mov [ecx+RECT.top],dword 0 |
mov eax,[0xfe00] |
mov [ecx+RECT.right],eax |
mov eax,[0xfe04] |
mov [ecx+RECT.bottom],eax |
;set window state to 'normal' (non-minimized/maximized/rolled-up) state |
mov [ecx+WDATA.fl_wstate],WSTATE_NORMAL |
;set cr3 register in TSS of application |
mov ecx,[new_process_place] |
shl ecx,8 |
mov eax,[0x80000+APPDATA.dir_table+ecx] |
add eax,8+16 ;add flags |
mov [l.cr3],eax |
mov eax,[app_start] |
mov [l.eip],eax ;set eip in TSS |
mov eax,[app_esp] |
mov [l.esp],eax ;set stack in TSS |
;gdt |
;mov ebx,[new_process_place] |
;shl ebx,3 |
mov ax,app_code ;ax - selector of code segment |
;add ax,bx |
mov [l.cs],ax |
mov ax,app_data |
;add ax,bx ;ax - selector of data segment |
mov [l.ss],ax |
mov [l.ds],ax |
mov [l.es],ax |
mov [l.fs],ax |
mov ax,graph_data ;ax - selector of graphic segment |
mov [l.gs],ax |
mov [l.io],word 128 |
mov [l.eflags],dword 0x11202 |
mov [l.ss0],os_data |
mov ebx,[new_process_place] |
shl ebx,12 |
add ebx,sysint_stack_data+4096 |
mov [l.esp0],ebx |
;copy tss to it place |
mov eax,tss_sceleton |
mov ebx,[new_process_place] |
imul ebx,tss_step |
add ebx,tss_data ;ebx - address of application TSS |
mov ecx,120 |
call memmove |
;Add IO access table - bit array of permitted ports |
or eax,-1 |
mov edi,[new_process_place] |
imul edi,tss_step |
add edi,tss_data+128 |
mov ecx,2048 |
cld |
rep stosd ;full access to 2048*8=16384 ports |
mov ecx,ebx ;ecx - address of application TSS |
mov edi,[new_process_place] |
shl edi,3 |
;set TSS descriptor |
mov [edi+gdts+tss0+0],word tss_step ;limit (size) |
mov [edi+gdts+tss0+2],cx ;part of offset |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+tss0+4],al ;part of offset |
mov [edi+gdts+tss0+7],ah ;part of offset |
mov [edi+gdts+tss0+5],word 01010000b*256+11101001b ;system flags |
;flush keyboard and buttons queue |
mov [0xf400],byte 0 |
mov [0xf500],byte 0 |
mov edi,[new_process_place] |
shl edi,5 |
add edi,window_data |
mov ebx,[new_process_place] |
movzx esi,word [0xC000+ebx*2] |
lea esi,[0xC400+esi*2] |
call windowactivate ;gui initialization |
mov ebx,[new_process_place] |
shl ebx,5 |
; set if debuggee |
test byte [esp+28], 1 |
jz .no_debug |
mov [0x3000+ebx+TASKDATA.state], 1 ; set process state - suspended |
mov eax, [0x3000] |
mov [0x80000+ebx*8+APPDATA.debugger_slot], eax ;set debugger PID - current |
jmp .debug |
.no_debug: |
mov [0x3000+ebx+TASKDATA.state], 0 ; set process state - running |
.debug: |
mov esi,new_process_running |
call sys_msg_board_str ;output information about succefull startup |
; add esp,4 ;pop pointer to parameters |
; popad |
mov eax,[process_number] ;set result |
mov [application_table_status],0 ;unlock application_table_status mutex |
call safe_sti |
ret 4 |
;----------------------------------------------------------------------------- |
new_sys_threads: |
;eax=1 - create thread |
; ebx=thread start |
; ecx=thread stack value |
;result: |
; eax=pid |
xor edx,edx ; flags=0 |
pushad |
cmp eax,1 |
jnz .ret ;other subfunctions |
mov esi,new_process_loading |
call sys_msg_board_str |
;lock application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
je .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
;find free process slot |
call find_new_process_place |
test eax,eax |
jz .failed |
;set parameters for thread |
xor eax,eax |
mov [app_i_param],eax |
mov [app_i_icon],eax |
mov [app_start],ebx |
mov [app_esp],ecx |
mov esi,[0x3000] |
shl esi,8 |
add esi,0x80000+APPDATA.app_name |
mov ebx,esi ;ebx=esi - pointer to extended information about current thread |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000 |
lea edx, [edi+APPDATA.app_name] ;edx=edi - pointer to extended infomation about new thread |
mov ecx,256/4 |
rep stosd ;clean extended information about new thread |
mov edi,edx |
mov ecx,11 |
rep movsb ;copy process name |
mov eax,[ebx+APPDATA.mem_size] |
mov [app_mem],eax ;set memory size |
mov eax,[ebx+APPDATA.dir_table] |
mov dword [edx-APPDATA.app_name+APPDATA.dir_table],eax ;copy page directory |
; mov eax,[new_process_place] |
; mov ebx,[0x3000] |
; call addreference_app_cr3_table |
push 0 ;no parameters |
call new_start_application_fl.add_app_parameters ;start thread |
mov [esp+28],eax |
popad |
ret |
.failed: |
sti |
popad |
mov eax,-1 |
ret |
.ret: |
popad |
ret |
;----------------------------------------------------------------------------- |
new_mem_resize: |
;input: |
; ebx - new size |
;result: |
; [esp+36]:=0 - normal |
; [esp+36]:=1 - error |
;This function set new application memory size. |
mov esi,ebx ;save new size |
add ebx,4095 |
and ebx,not (4096-1) ;round up size |
mov ecx,[0x3000] |
shl ecx,8 |
mov edx,[0x80000 + APPDATA.mem_size +ecx] |
add edx,4095 |
and edx,not (4096-1) ;old size |
mov eax,[0x80000 + APPDATA.dir_table+ecx] |
call MEM_Get_Linear_Address |
;eax - linear address of page directory |
call MEM_Heap_Lock ;guarantee that two threads willn't |
;change memory size simultaneously |
cmp ebx,edx |
; mov esi,ebx ;save new size |
jg .expand |
.free: |
sub edx,ebx |
jz .unlock ;do nothing |
mov ecx,edx |
shr ecx,12 |
add ebx,std_application_base_address |
call mem_free_specified_region ;free unnecessary pages |
jmp .unlock |
.expand: |
sub ebx,edx |
mov ecx,ebx |
shr ecx,12 |
mov ebx,edx |
add ebx,std_application_base_address |
call mem_alloc_specified_region ;alloc necessary pages |
test eax,eax |
jz .failed ;not enough memory |
.unlock: |
mov ebx,esi |
mov eax,[0x3000] |
shl eax,8 |
mov [eax+0x80000 + APPDATA.mem_size],ebx ;write new memory size |
;search threads and update |
;application memory size infomation |
mov ecx,[eax+0x80000 + APPDATA.dir_table] |
mov eax,2 |
.search_threads: |
;eax = current slot |
;ebx = new memory size |
;ecx = page directory |
cmp eax,[0x3004] |
jg .search_threads_end |
mov edx,eax |
shl edx,5 |
cmp word [0x3000+edx+TASKDATA.state],9 ;if slot empty? |
jz .search_threads_next |
shl edx,3 |
cmp [edx+0x80000+APPDATA.dir_table],ecx ;if it is our thread? |
jnz .search_threads_next |
mov [edx+0x80000+APPDATA.mem_size],ebx ;update memory size |
.search_threads_next: |
inc eax |
jmp .search_threads |
.search_threads_end: |
call MEM_Heap_UnLock |
mov dword [esp+36],0 |
ret |
.failed: |
call MEM_Heap_UnLock |
mov dword [esp+36],1 |
ret |
;----------------------------------------------------------------------------- |
pid_to_slot: |
;Input: |
; eax - pid of process |
;Output: |
; eax - slot of process or 0 if process don't exists |
;Search process by PID. |
push ebx |
push ecx |
mov ebx,[0x3004] |
shl ebx,5 |
mov ecx,2*32 |
.loop: |
;ecx=offset of current process info entry |
;ebx=maximum permitted offset |
cmp byte [second_base_address+0x3000+ecx+TASKDATA.state],9 |
jz .endloop ;skip empty slots |
cmp [second_base_address+0x3000+ecx+TASKDATA.pid],eax ;check PID |
jz .pid_found |
.endloop: |
add ecx,32 |
cmp ecx,ebx |
jle .loop |
pop ecx |
pop ebx |
xor eax,eax |
ret |
.pid_found: |
shr ecx,5 |
mov eax,ecx ;convert offset to index of slot |
pop ecx |
pop ebx |
ret |
;----------------------------------------------------------------------------- |
is_new_process: |
;Input: |
; eax - process slot |
;Output: |
; eax=1 - it is new process |
; eax=0 - it is old process |
; shl eax,5 |
; mov eax,[second_base_address+0x3000+eax+0x10] |
; cmp eax,std_application_base_address ;check base address of application |
; jz .new_process |
; xor eax,eax |
; ret |
;.new_process: |
mov eax,1 |
ret |
;----------------------------------------------------------------------------- |
write_process_memory: |
;Input: |
; eax - process slot |
; ebx - buffer address |
; ecx - buffer size |
; edx - start address in other process |
;Output: |
; eax - number of bytes written |
pushad |
shl eax,8 |
mov eax,[0x80000+eax+APPDATA.dir_table] |
call MEM_Get_Linear_Address |
mov ebp,eax |
;ebp=linear address of page directory of other process. |
add edx,std_application_base_address ;convert to linear address |
test ecx,ecx |
jle .ret |
.write_loop: |
;ebx = current buffer address |
;ecx>0 = current size |
;edx = current address in other process |
;ebp = linear address of page directory |
call MEM_Heap_Lock ;cli |
mov esi,edx |
shr esi,22 |
mov eax,[ebp+4*esi] ;find page directory entry |
and eax,not (4096-1) ;clear flags |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address ;calculate linear address of page table |
test eax,eax |
jz .page_not_found |
mov esi,edx |
shr esi,12 |
and esi,1023 |
mov eax,[eax+4*esi] ;find page table entry |
and eax,not (4096-1) |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address ;calculate linear address of page |
test eax,eax |
jz .page_not_found |
mov edi,eax |
call MEM_Add_Reference_Linear;guarantee that page willn't disappear |
call MEM_Heap_UnLock ;sti |
mov esi,edx |
and esi,4095 |
add edi,esi ;add offset in page |
;edi = linear address corresponding edx in other process |
sub esi,4096 |
neg esi ;esi - number of remaining bytes in page |
cmp esi,ecx |
jl .min_ecx |
mov esi,ecx |
.min_ecx: ;esi=min(ecx,esi) - number of bytes to write |
sub ecx,esi |
push ecx |
mov ecx,esi ;ecx - number of bytes to write |
mov esi,ebx ;esi - source, edi - destination |
add edx,ecx ;move pointer in address space of other process |
push edi |
;move ecx bytes |
test ecx,3 |
jnz .not_aligned |
shr ecx,2 |
rep movsd |
jmp .next_iter |
.not_aligned: |
rep movsb |
.next_iter: |
pop eax |
and eax,not (4096-1) ;eax - linear address of current page |
call MEM_Free_Page_Linear ;free reference |
mov ebx,esi ;new pointer to buffer - movsb automaticaly advance it. |
pop ecx ;restore number of remaining bytes |
test ecx,ecx |
jnz .write_loop |
.ret: |
popad |
mov eax,ecx |
ret |
.page_not_found: |
call MEM_Heap_UnLock ;error has appeared in critical region |
sub ecx,[esp+24] ;[esp+24]<-->ecx |
neg ecx ;ecx=number_of_written_bytes |
mov [esp+28],ecx ;[esp+28]<-->eax |
popad |
ret |
;----------------------------------------------------------------------------- |
syscall_test: |
;for testing memory manager from applications. |
mov edx,ecx |
mov ecx,ebx |
call trans_address |
mov ebx,eax |
mov eax,[0x3000] |
call read_process_memory |
ret |
;----------------------------------------------------------------------------- |
read_process_memory: |
;Input: |
; eax - process slot |
; ebx - buffer address |
; ecx - buffer size |
; edx - start address in other process |
;Output: |
; eax - number of bytes read. |
pushad |
shl eax,8 |
mov eax,[0x80000+eax+APPDATA.dir_table] |
call MEM_Get_Linear_Address |
mov ebp,eax |
add edx,std_application_base_address |
.read_loop: |
;ebx = current buffer address |
;ecx>0 = current size |
;edx = current address in other process |
;ebp = linear address of page directory |
call MEM_Heap_Lock ;cli |
mov esi,edx |
shr esi,22 |
mov eax,[ebp+4*esi] ;find page directory entry |
and eax,not (4096-1) |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address |
test eax,eax |
jz .page_not_found |
mov esi,edx |
shr esi,12 |
and esi,1023 |
mov eax,[eax+4*esi] ;find page table entry |
and eax,not (4096-1) |
test eax,eax |
jz .page_not_found |
call MEM_Get_Linear_Address ;calculate linear address of page |
test eax,eax |
jz .page_not_found |
mov esi,eax |
call MEM_Add_Reference_Linear;guarantee that page willn't disappear |
call MEM_Heap_UnLock ;sti |
mov edi,edx |
and edi,4095 |
add esi,edi ;add offset in page |
;esi = linear address corresponding edx in other process |
sub edi,4096 |
neg edi |
;edi=min(edi,ecx) - number of bytes to copy |
cmp edi,ecx |
jl .min_ecx |
mov edi,ecx |
.min_ecx: |
sub ecx,edi ;update size of remaining bytes |
add edx,edi ;update current pointer in other address space. |
push ecx |
mov ecx,edi ;ecx - number of bytes to read |
mov edi,ebx ;esi - source, edi - destination |
push esi |
;move ecx bytes |
test ecx,3 |
jnz .not_aligned |
shr ecx,2 |
rep movsd |
jmp .next_iter |
.not_aligned: |
rep movsb |
.next_iter: |
pop eax |
and eax,not (4096-1) ;eax - linear address of current page |
call MEM_Free_Page_Linear ;free reference |
mov ebx,edi ;new pointer to buffer - movsb automaticaly advance it. |
pop ecx ;restore number of remaining bytes |
test ecx,ecx |
jnz .read_loop |
popad |
mov eax,ecx |
ret |
.page_not_found: |
call MEM_Heap_UnLock ;error has appeared in critical region |
sub ecx,[esp+24] ;[esp+24]<-->ecx |
neg ecx ;ecx=number_of_read_bytes |
mov [esp+28],ecx ;[esp+28]<-->eax |
popad |
ret |
;----------------------------------------------------------------------------- |
check_region: |
;input: |
; ebx - start of buffer |
; ecx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
mov eax,[0x3000] |
jmp check_process_region |
;----------------------------------------------------------------------------- |
check_process_region: |
;input: |
; eax - slot |
; ebx - start of buffer |
; ecx - size of buffer |
;result: |
; eax = 1 region lays in app memory |
; eax = 0 region don't lays in app memory |
test ecx,ecx |
jle .ok |
shl eax,5 |
cmp word [0x3000+eax+TASKDATA.state],0 |
jnz .failed |
shl eax,3 |
mov eax,[0x80000+eax+APPDATA.dir_table] |
test eax,eax |
jz .failed |
call MEM_Get_Linear_Address |
push ebx |
push ecx |
push edx |
mov edx,ebx |
and edx,not (4096-1) |
sub ebx,edx |
add ecx,ebx |
mov ebx,edx |
add ecx,(4096-1) |
and ecx,not (4096-1) |
.loop: |
;eax - linear address of page directory |
;ebx - current page |
;ecx - current size |
mov edx,ebx |
shr edx,22 |
mov edx,[eax+4*edx] |
and edx,not (4096-1) |
test edx,edx |
jz .failed1 |
push eax |
mov eax,edx |
call MEM_Get_Linear_Address |
mov edx,ebx |
shr edx,12 |
and edx,(1024-1) |
mov eax,[eax+4*edx] |
and eax,not (4096-1) |
test eax,eax |
pop eax |
jz .failed1 |
add ebx,4096 |
sub ecx,4096 |
jg .loop |
pop edx |
pop ecx |
pop ebx |
.ok: |
mov eax,1 |
ret |
.failed1: |
pop edx |
pop ecx |
pop ebx |
.failed: |
xor eax,eax |
ret |
;----------------------------------------------------------------------------- |
new_sys_ipc: |
;input: |
; eax=1 - set ipc buffer area |
; ebx=address of buffer |
; ecx=size of buffer |
; eax=2 - send message |
; ebx=PID |
; ecx=address of message |
; edx=size of message |
cmp eax,1 |
jnz .no_ipc_def |
;set ipc buffer area |
mov edi,[0x3000] |
shl edi,8 |
add edi,0x80000 |
cli |
mov [edi+APPDATA.ipc_start],ebx ;set fields in extended information area |
mov [edi+APPDATA.ipc_size],ecx |
sti |
mov [esp+36],dword 0 ;success |
ret |
.no_ipc_def: |
cmp eax,2 |
jnz .no_ipc_send |
;send message |
cli |
;obtain slot from PID |
mov eax,ebx |
call pid_to_slot |
test eax,eax |
jz .no_pid |
mov ebp,eax |
;ebp = slot of other process |
shl eax,8 |
mov edi,[eax+0x80000+APPDATA.ipc_start] ;is ipc area defined? |
test edi,edi |
jz .no_ipc_area |
mov esi,[eax+0x80000+APPDATA.ipc_size] ;esi - size of buffer |
push dword -1 ;temp variable for read_process_memory |
mov ebx,esp |
push ecx |
push edx |
mov ecx,4 ;read 4 bytes |
mov eax,ebp |
mov edx,edi ;from beginning of buffer. |
call read_process_memory |
mov eax,[esp+8] |
test eax,eax |
jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now |
add edx,4 ;move to next 4 bytes |
mov eax,ebp |
call read_process_memory ;read size of occupied space in buffer |
sub esi,8 |
sub esi,[esp] |
sub esi,[esp+8] ;esi=(buffer size)-(occupied size)-(message size)-(header of message size) |
js .buffer_overflow ;esi<0 - not enough memory in buffer |
mov esi,[esp+8] ;previous offset |
add dword [esp+8],8 |
mov edi,[esp] |
add [esp+8],edi ;add (size of message)+(size of header of message) to [buffer+4] |
mov eax,ebp |
call write_process_memory |
add edx,esi |
sub edx,4 ;move to beginning of place for our message |
mov eax,[second_base_address+0x3010] |
mov eax,[eax+TASKDATA.pid] ;eax - our PID |
mov [esp+8],eax |
mov eax,ebp |
call write_process_memory ;write PID |
mov ebx,esp ;address of size of message |
mov eax,ebp |
add edx,4 |
call write_process_memory ;write size of message |
add edx,4 |
pop ecx ;ecx - size of message |
pop eax |
call trans_address |
mov ebx,eax ;ebx - linear address of message |
add esp,4 ;pop temporary variable |
mov eax,ebp |
call write_process_memory ;write message |
sti |
;awake other process |
shl ebp,8 |
mov eax,ebp |
or [eax+0x80000+APPDATA.event_mask],dword 0x40 |
cmp dword [check_idle_semaphore],20 |
jge .ipc_no_cis |
mov dword [check_idle_semaphore],5 |
.ipc_no_cis: |
mov dword [esp+36],0 |
ret |
.no_ipc_send: |
mov dword [esp+36],-1 |
ret |
.no_pid: |
sti |
mov dword [esp+36],4 |
ret |
.no_ipc_area: |
sti |
mov dword [esp+36],1 |
ret |
.ipc_blocked: |
sti |
add esp,12 |
mov dword [esp+36],2 |
ret |
.buffer_overflow: |
sti |
add esp,12 |
mov dword [esp+36],3 |
ret |
;----------------------------------------------------------------------------- |
trans_address: |
;Input |
; eax - application address |
;Output |
; eax - linear address for kernel |
add eax,std_application_base_address |
ret |
;----------------------------------------------------------------------------- |
new_start_application_hd: |
;eax - file name (kernel address) |
;ebx - file name length |
;ecx - work area (kernel address) |
;edx - flags |
;ebp - parameters |
mov [appl_path],edi |
pushad |
mov esi,new_process_loading |
call sys_msg_board_str ;write message to message board |
;lock application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status],0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
push ebp |
push ebx |
push eax |
push ecx |
call find_new_process_place ;find new process slot |
sti |
test eax,eax |
mov ecx, -0x20 ; too many processes |
jz .failed |
;write application name |
xor eax,eax |
mov [appl_path_size],eax |
mov eax,[esp+4] |
.find_last_byte: |
cmp byte [eax],0 |
jz .find_last_byte_end |
inc eax |
inc [appl_path_size] |
jmp .find_last_byte |
.find_last_byte_end: |
add [appl_path_size],24 |
lea esi,[eax-11] ;last 11 bytes = application name |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000+APPDATA.app_name |
mov ecx,11 |
cld |
rep movsb ;copy name to extended information about process |
;read header |
mov eax,[esp+4] ;file name |
mov esi,[esp] ;work area |
mov ecx,1 ;read from first block |
mov edx,1 ;read 1 block |
call read_hd_file |
mov ecx, eax |
neg ecx |
jnz .cleanfailed |
pop esi |
push esi |
;check menuet signature |
mov ecx, -0x1F ; not Menuet/Kolibri executable |
cmp [esi+1024+0],dword 'MENU' ;read_hd_file function write file to +1024 offset |
jnz .cleanfailed |
cmp [esi+1024+4],word 'ET' |
jnz .cleanfailed |
add esi,1024 |
mov edi,0x90000 |
mov ecx,512/4 |
cld |
rep movsd ;copy first block to 0x90000 address for get_app_params function |
call get_app_params |
mov ecx, -0x1F ; not Menuet/Kolibri executable |
test esi,esi |
jz .cleanfailed |
mov eax,[new_process_place] |
inc ecx ; -0x1E = no memory |
call create_app_cr3_table ;create page directory |
test eax,eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address |
mov ebx,std_application_base_address |
mov ecx,[app_mem] |
add ecx,4096-1 |
shr ecx,12 |
mov edx,eax ;edx - linear address of page directory |
call mem_alloc_specified_region ;allocate memory for application |
mov ecx, -0x1E ; no memory |
test eax,eax |
jz .cleanfailed_mem1 |
add edx,(std_application_base_address shr 20) |
mov eax,[edx] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
push edx ;save pointer to first page table |
mov edx,eax |
;read file |
mov ecx,1 |
xor ebp,ebp |
.loop1: |
;[esp] - pointer to current page directory entry |
;edx - pointer to current page table |
;ebp - offset in page |
;ecx - current cluster |
push edx |
mov eax,[esp+12] ;file name |
mov ebx,[esp+16] ;file name length |
mov esi,[esp+8] ;work area |
mov edx,1 ;number of blocks to read |
push ecx |
push ebp |
cli |
call read_hd_file |
sti |
pop ebp |
test eax,eax |
jnz .endloop1 ;check io errors |
mov esi,[esp+8+4] ;work area |
add esi,1024 |
mov eax,[esp+4] ;current page table |
mov eax,[eax] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address;calculate linear page address |
lea edi,[eax+ebp] ;add page offset |
mov ecx,512/4 |
cld |
rep movsd ;copy data |
pop ecx |
inc ecx ;next block |
mov eax,[app_i_end] ;todo: precalculate ([app_i_end]+4095)/4096 |
add eax,512-1 |
shr eax,9 ;calculate application image size |
cmp ecx,eax |
jg .endloop11 |
pop edx |
add ebp,512 ;new offset |
test ebp,4096 |
jz .loop1 |
xor ebp,ebp |
add edx,4 ;go to next page |
test edx,(4096-1) |
jnz .loop1 |
add dword [esp],4 ;go to next directory entry |
mov eax,[esp] |
mov eax,[eax] |
and eax,not (4096-1) |
call MEM_Get_Linear_Address |
mov edx,eax |
jmp .loop1 |
.endloop1: |
add esp,4 ;pop ecx |
.endloop11: |
add esp,4+4 ;pop edx, pop edx |
;add_app_parameters |
add esp,12 ;now pointer to parameters is on the top of the stack |
call new_start_application_fl.add_app_parameters ;start process |
mov [esp+28],eax |
popad |
ret |
.cleanfailed_mem1: |
;there is mem for directory entry, but there is no mem for pages |
;so free directory entry |
mov eax,[new_process_place] |
shl eax,8 |
mov eax,[0x80000+eax+APPDATA.dir_table] |
call MEM_Free_Page |
.cleanfailed_mem: |
;there is no mem for directory entry, display message. |
mov esi,start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: ;clean process name |
push ecx |
;can't read file, clean process name. |
;this avoid problems with panel application. |
mov edi,[new_process_place] |
shl edi,8 |
add edi,0x80000+APPDATA.app_name |
mov ecx,11 |
mov eax,' ' |
cld |
rep stosb |
pop eax |
.failed: |
;no more slots |
add esp,16 |
mov [esp+1Ch], eax |
popad |
mov [application_table_status],0 |
sti |
ret |
end if |
; \begin{diamond} |
include 'debug.inc' |
fs_execute: |
; ebx - cmdline |
; edx - flags |
; ebp - full filename |
; [esp+4] = procedure DoRead, [esp+8] = filesize & [esp+12]... - arguments for it |
pushad |
; check filename length - with terminating NULL must be no more than 1024 symbols |
mov edi, ebp |
mov ecx, 1024 |
xor eax, eax |
repnz scasb |
jz @f |
popad |
mov eax, -ERROR_FILE_NOT_FOUND |
ret |
@@: |
mov esi, new_process_loading |
call sys_msg_board_str ; write message to message board |
; lock application_table_status mutex |
.table_status: |
cli |
cmp [application_table_status], 0 |
jz .stf |
sti |
call change_task |
jmp .table_status |
.stf: |
call set_application_table_status |
push ebx ; save command line pointer for add_app_parameters |
call find_new_process_place ; find new process slot |
call safe_sti |
test eax, eax |
mov ecx, -0x20 ; too many processes |
jz .failed |
; write application name |
push edi |
mov ecx, edi |
sub ecx, ebp |
mov [appl_path], ebp |
mov [appl_path_size], ecx |
dec edi |
std |
mov al, '/' |
repnz scasb |
cld |
jnz @f |
inc edi |
@@: |
inc edi |
; now edi points to name without path |
mov esi, edi |
mov ecx, 8 ; 8 chars for name |
mov edi, [new_process_place] |
shl edi, cl |
add edi, 0x80000+APPDATA.app_name |
.copy_process_name_loop: |
lodsb |
cmp al, '.' |
jz .copy_process_name_done |
test al, al |
jz .copy_process_name_done |
stosb |
loop .copy_process_name_loop |
.copy_process_name_done: |
mov al, ' ' |
rep stosb |
pop eax |
mov cl, 3 ; 3 chars for extension |
dec esi |
@@: |
dec eax |
cmp eax, esi |
jbe .copy_process_ext_done |
cmp byte [eax], '.' |
jnz @b |
lea esi, [eax+1] |
.copy_process_ext_loop: |
lodsb |
test al, al |
jz .copy_process_ext_done |
stosb |
loop .copy_process_ext_loop |
.copy_process_ext_done: |
mov al, ' ' |
rep stosb |
; read header |
lea eax, [esp+8+36] |
mov edi, 0x90000 |
call dword [eax-4] |
mov ecx, eax |
neg ecx |
jnz .cleanfailed |
; check menuet signature |
mov ecx, -0x1F |
cmp dword [0x90000], 'MENU' |
jnz .cleanfailed |
cmp word [0x90004], 'ET' |
jnz .cleanfailed |
call get_app_params |
mov ecx, -0x1F |
test esi, esi |
jz .cleanfailed |
mov eax, [new_process_place] |
inc ecx ; -0x1E = no memory |
call create_app_cr3_table |
test eax, eax |
jz .cleanfailed_mem |
call MEM_Get_Linear_Address |
mov ebx, std_application_base_address |
mov ecx, [app_mem] |
add ecx, 4095 |
shr ecx, 12 |
mov edx, eax ; edx - linear address of page directory |
call mem_alloc_specified_region |
mov ecx, -0x1E ; no memory |
test eax, eax |
jz .cleanfailed_mem1 |
add edx, std_application_base_address shr 20 |
mov eax, [edx] |
and eax, not 4095 |
call MEM_Get_Linear_Address |
push edx ; save pointer to first page table |
mov edx, eax |
; read file |
; first block is already read to 0x90000 |
mov eax, [edx] |
and eax, not 0xFFF |
call MEM_Get_Linear_Address |
mov esi, 0x90000 |
mov edi, eax |
mov ecx, 512/4 |
rep movsd |
sub edi, eax |
.loop1: |
; [esp] = pointer to current page directory entry |
; edx = pointer to current page table |
; edi = offset in page |
mov eax, [edx] |
and eax, not 0xFFF |
call MEM_Get_Linear_Address |
push edi |
add edi, eax |
lea eax, [esp+8+36+8] |
call dword [eax-4] |
pop edi |
test eax, eax |
jnz .endloop1 |
add edi, 512 ; new offset |
cmp edi, 4096 |
jb .loop1 |
xor edi, edi |
add edx, 4 ; go to next page |
test edx, 4096-1 |
jnz .loop1 |
pop eax |
add eax, 4 ; go to next directory entry |
push eax |
mov eax, [eax] |
and eax, not 0xFFF |
call MEM_Get_Linear_Address |
mov edx, eax |
jmp .loop1 |
.endloop1: |
pop edx |
cmp eax, 6 |
jnz .cleanfailed_mem2 |
call new_start_application_fl.add_app_parameters |
mov [esp+28], eax |
popad |
ret |
.cleanfailed_mem2: |
; file read error; free all allocated mem |
mov ecx, eax |
neg ecx |
mov eax, [new_process_place] |
call dispose_app_cr3_table |
jmp .cleanfailed |
.cleanfailed_mem1: |
; there is mem for directory entry, but there is no mem for pages |
; so free directory entry |
mov eax, [new_process_place] |
shl eax, 8 |
mov eax, [0x80000+eax+0xB8] |
call MEM_Free_Page |
.cleanfailed_mem: |
; there is no mem for directory entry, display message |
mov esi, start_not_enough_memory |
call sys_msg_board_str |
.cleanfailed: |
push ecx |
; clean process name, this avoid problems with @panel |
mov edi, [new_process_place] |
shl edi, 8 |
add edi, 0x80000+APPDATA.app_name |
mov ecx, 11 |
mov al, ' ' |
rep stosb |
pop eax |
.failed: |
pop ebx |
mov [esp+28], eax |
popad |
mov [application_table_status], 0 |
call safe_sti |
ret |
; \end{diamond} |
/kernel/branches/gfx_kernel/core/physmem.inc |
---|
0,0 → 1,220 |
virtual at 0 |
physical_mem_block: |
.start rd 1 |
.size rd 1 |
.flags rd 1 ;0-free, pid-used. |
.sizeof: |
end virtual |
max_physical_mem_blocks = 24 |
uglobal |
num_physical_mem_blocks rd 1 |
physical_mem_blocks rd 3*max_physical_mem_blocks |
endg |
Init_Physical_Memory_Manager: |
pushad |
mov edi,physical_mem_blocks |
mov ecx,3*max_physical_mem_blocks |
xor eax,eax |
cld |
rep stosd |
mov dword [num_physical_mem_blocks],2 |
mov [physical_mem_blocks+physical_mem_block.start],0x60000 |
mov [physical_mem_blocks+physical_mem_block.size],0x20000 ;128Kb |
mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.start],0x780000 |
mov [physical_mem_blocks+physical_mem_block.sizeof+physical_mem_block.size],0x80000 ;512Kb |
popad |
ret |
Insert_Block: |
;input: |
; eax - handle |
;output: |
; none |
push eax ecx esi edi |
sub eax,[num_physical_mem_blocks] |
neg eax |
mov edi,physical_mem_block.sizeof |
imul eax,edi |
shr eax,2 |
mov ecx,eax |
mov esi,[num_physical_mem_blocks] |
imul esi,edi |
add esi,physical_mem_blocks |
lea edi,[esi+physical_mem_block.sizeof] |
std |
rep movsd |
pop edi esi ecx eax |
ret |
Delete_Block: |
;input: |
; eax - handle |
;output: |
; none |
pushad |
mov edi,eax |
sub eax,[num_physical_mem_blocks] |
neg eax |
dec eax |
mov esi,physical_mem_block.sizeof |
imul eax,esi |
imul edi,esi |
add edi,physical_mem_blocks |
lea esi,[edi+physical_mem_block.sizeof] |
mov ecx,eax |
shr ecx,2 |
cld |
rep movsd |
popad |
ret |
Allocate_Physical_Block: |
;input: |
; eax - size |
;output: |
; eax - address or 0 if not enough memory. |
pushad |
cmp [num_physical_mem_blocks],max_physical_mem_blocks |
jge .error |
mov ebx,eax |
xor eax,eax |
mov esi,physical_mem_blocks |
.loop: |
cmp dword [esi+physical_mem_block.flags],0 |
jnz .next |
cmp [esi+physical_mem_block.size],ebx |
jg .addblock |
jz .noaddblock |
.next: |
inc eax |
add esi,physical_mem_block.sizeof |
cmp eax,[num_physical_mem_blocks] |
jl .loop |
.error: |
popad |
xor eax,eax |
ret |
.noaddblock: |
mov eax,[esi+physical_mem_block.start] |
mov [esp+28],eax |
mov eax,[0x3010] |
mov eax,[eax+TASKDATA.pid] |
mov [esi+physical_mem_block.flags],eax |
popad |
ret |
.addblock: |
call Insert_Block |
inc dword [num_physical_mem_blocks] |
mov eax,[esi+physical_mem_block.start] |
mov [esp+28],eax |
mov ecx,[0x3010] |
mov ecx,[ecx+TASKDATA.pid] |
mov [esi+physical_mem_block.flags],ecx |
mov ecx,[esi+physical_mem_block.size] |
mov [esi+physical_mem_block.size],ebx |
sub ecx,ebx |
mov [esi+physical_mem_block.sizeof+physical_mem_block.size],ecx |
add ebx,[esi+physical_mem_block.start] |
mov [esi+physical_mem_block.sizeof+physical_mem_block.start],ebx |
mov dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0 |
popad |
ret |
Free_Physical_Block: |
;input: |
; eax - address |
;output: |
; none |
pushad |
test eax,eax |
jz .ret |
mov ebx,eax |
xor eax,eax |
mov esi,physical_mem_blocks |
.loop: |
cmp ebx,[esi+physical_mem_block.start] |
jz .endloop |
inc eax |
add esi,physical_mem_block.sizeof |
cmp eax,[num_physical_mem_blocks] |
jl .loop |
jmp .ret |
.endloop: |
mov dword [esi+physical_mem_block.flags],0 |
test eax,eax |
jz .no_union_previous |
cmp dword [esi-physical_mem_block.sizeof+physical_mem_block.flags],0 |
jnz .no_union_previous |
mov ebx,[esi-physical_mem_block.sizeof+physical_mem_block.start] |
add ebx,[esi-physical_mem_block.sizeof+physical_mem_block.size] |
cmp ebx,[esi+physical_mem_block.start] |
jnz .no_union_previous |
mov ebx,[esi+physical_mem_block.size] |
add [esi-physical_mem_block.sizeof+physical_mem_block.size],ebx |
call Delete_Block |
dec eax |
dec [num_physical_mem_blocks] |
.no_union_previous: |
inc eax |
cmp eax,[num_physical_mem_blocks] |
jge .no_union_next |
cmp dword [esi+physical_mem_block.sizeof+physical_mem_block.flags],0 |
jnz .no_union_next |
mov ebx,[esi+physical_mem_block.start] |
add ebx,[esi+physical_mem_block.size] |
cmp ebx,[esi+physical_mem_block.sizeof+physical_mem_block.start] |
jnz .no_union_next |
mov ebx,[esi+physical_mem_block.sizeof+physical_mem_block.size] |
add [esi+physical_mem_block.size],ebx |
call Delete_Block |
dec [num_physical_mem_blocks] |
.no_union_next: |
.ret: |
popad |
ret |
sys_allocate_physical_block: |
;eax - subfunction number |
mov eax,ebx |
call Allocate_Physical_Block |
mov [esp+36],eax |
ret |
sys_free_physical_block: |
;eax - subfunction number |
mov eax,ebx |
call Free_Physical_Block |
ret |
sys_set_buffer: |
add ecx,std_application_base_address |
isys_set_buffer: ;for using in kernel |
;eax - subfunction number |
;ebx - physical address |
;ecx - buffer start |
;edx - buffer size |
lea edi,[ebx+second_base_address] |
mov esi,ecx |
mov ecx,edx |
cld |
rep movsb |
ret |
sys_get_buffer: |
add ecx,std_application_base_address |
isys_get_buffer: ;for using in kernel |
;eax - subfunction number |
;ebx - physical address |
;ecx - buffer start |
;edx - buffer size |
mov edi,ecx |
lea esi,[ebx+second_base_address] |
mov ecx,edx |
cld |
rep movsb |
ret |
sys_internal_services: |
cmp eax,4 |
jle sys_sheduler |
cmp eax,5 |
jz sys_allocate_physical_block |
cmp eax,6 |
jz sys_free_physical_block |
cmp eax,7 |
jz sys_set_buffer |
cmp eax,8 |
jz sys_get_buffer |
ret |
/kernel/branches/gfx_kernel/core/sched.inc |
---|
0,0 → 1,191 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; IRQ0 HANDLER (TIMER INTERRUPT) ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
irq0: |
save_ring3_context |
mov ax, os_data |
mov ds, ax |
mov es, ax |
inc dword [timer_ticks] |
mov eax, [timer_ticks] |
call playNote ; <<<--- Speaker driver |
cmp eax,[next_usage_update] |
jb .nocounter |
add eax,100 |
mov [next_usage_update],eax |
call updatecputimes |
.nocounter: |
cmp [0xffff], byte 1 |
jne .change_task |
mov al,0x20 ; send End Of Interrupt signal |
mov dx,0x20 |
out dx,al |
mov [0xffff], byte 0 |
restore_ring3_context |
iret |
.change_task: |
call update_counters |
call find_next_task |
mov ecx, eax |
mov al,0x20 ; send End Of Interrupt signal |
mov dx,0x20 |
out dx,al |
test ecx, ecx ; if there is only one running process |
jnz .return |
call do_change_task |
.return: |
restore_ring3_context |
iret |
align 4 |
change_task: |
pushfd |
cli |
pushad |
call update_counters |
call find_next_task |
test eax, eax ; the same task -> skip switch |
jnz .return |
mov [0xffff],byte 1 |
call do_change_task |
.return: |
popad |
popfd |
ret |
uglobal |
align 4 |
far_jump: |
.offs dd ? |
.sel dw ? |
context_counter dd ? ;noname & halyavin |
next_usage_update dd ? |
timer_ticks dd ? |
prev_slot dd ? |
event_sched dd ? |
endg |
update_counters: |
mov edi, [0x3010] |
mov ebx, [edi+TASKDATA.counter_add] ; time stamp counter add |
call _rdtsc |
sub eax, ebx |
add eax, [edi+TASKDATA.counter_sum] ; counter sum |
mov [edi+TASKDATA.counter_sum], eax |
ret |
; Find next task to execute |
; result: ebx = number of the selected task |
; eax = 1 if the task is the same |
; edi = address of the data for the task in ebx |
; [0x3000] = ebx and [0x3010] = edi |
; corrupts other regs |
find_next_task: |
mov ebx, [0x3000] |
mov edi, [0x3010] |
mov [prev_slot], ebx |
.waiting_for_termination: |
.waiting_for_reuse: |
.waiting_for_event: |
.suspended: |
cmp ebx, [0x3004] |
jb @f |
mov edi, 0x3000 |
xor ebx, ebx |
@@: |
add edi,0x20 |
inc ebx |
mov al, byte [edi+TASKDATA.state] |
test al, al |
jz .found |
cmp al, 1 |
jz .suspended |
cmp al, 2 |
jz .suspended |
cmp al, 3 |
je .waiting_for_termination |
cmp al, 4 |
je .waiting_for_termination |
cmp al, 9 |
je .waiting_for_reuse |
mov [0x3000],ebx |
mov [0x3010],edi |
cmp al, 5 |
jne .noevents |
call get_event_for_app |
test eax, eax |
jz .waiting_for_event |
mov [event_sched], eax |
mov [edi+TASKDATA.state], byte 0 |
.noevents: |
.found: |
mov [0x3000],ebx |
mov [0x3010],edi |
call _rdtsc |
mov [edi+TASKDATA.counter_add],eax |
xor eax, eax |
cmp ebx, [prev_slot] |
sete al |
ret |
; in: ebx = TSS selector index |
do_change_task: |
shl ebx, 3 |
xor eax, eax |
add ebx, tss0 |
mov [far_jump.sel], bx ; selector |
mov [far_jump.offs], eax ; offset |
jmp pword [far_jump] |
inc [context_counter] ;noname & halyavin |
ret |
align 4 |
updatecputimes: |
mov eax,[idleuse] |
mov [idleusesec],eax |
mov [idleuse],dword 0 |
mov ecx, [0x3004] |
mov edi, 0x3020 |
.newupdate: |
mov ebx,[edi+TASKDATA.counter_sum] |
mov [edi+TASKDATA.cpu_usage],ebx |
mov [edi+TASKDATA.counter_sum],dword 0 |
add edi,0x20 |
dec ecx |
jnz .newupdate |
ret |
/kernel/branches/gfx_kernel/core/sync.inc |
---|
0,0 → 1,111 |
if ~defined sync_inc |
sync_inc_fix: |
sync_inc fix sync_inc_fix |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;Synhronization for MenuetOS. ;; |
;;Author: Halyavin Andrey, halyavin@land.ru ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;simplest mutex. |
macro SimpleMutex name |
{ |
; iglobal |
name dd 0 |
name#.type = 1 |
; endg |
} |
macro WaitSimpleMutex name |
{ |
local start_wait,ok |
start_wait=$ |
cli |
cmp [name],dword 0 |
jz ok |
sti |
call change_task |
jmp start_wait |
ok=$ |
push eax |
mov eax,dword [0x3010+second_base_address] |
mov eax,[eax+TASKDATA.pid] |
mov [name],eax |
pop eax |
sti |
} |
macro ReleaseSimpleMutex name |
{ |
mov [name],dword 0 |
} |
macro TryWaitSimpleMutex name ;result in eax and in flags |
{ |
local ok,try_end |
cmp [name],dword 0 |
jz ok |
xor eax,eax |
jmp try_end |
ok=$ |
xor eax,eax |
inc eax |
try_end=$ |
} |
macro SimpleCriticalSection name |
{ |
; iglobal |
name dd 0 |
dd 0 |
name#.type=2 |
; endg |
} |
macro WaitSimpleCriticalSection name |
{ |
local start_wait,first_wait,inc_counter,end_wait |
push eax |
mov eax,[0x3010+second_base_address] |
mov eax,[eax+TASKDATA.pid] |
start_wait=$ |
cli |
cmp [name],dword 0 |
jz first_wait |
cmp [name],eax |
jz inc_counter |
sti |
call change_task |
jmp start_wait |
first_wait=$ |
mov [name],eax |
mov [name+4],dword 1 |
jmp end_wait |
inc_counter=$ |
inc dword [name+4] |
end_wait=$ |
sti |
pop eax |
} |
macro ReleaseSimpleCriticalSection name |
{ |
local release_end |
dec dword [name+4] |
jnz release_end |
mov [name],dword 0 |
release_end=$ |
} |
macro TryWaitSimpleCriticalSection name ;result in eax and in flags |
{ |
local ok,try_end |
mov eax,[0x3000+second_base_address] |
mov eax,[eax+TASKDATA.pid] |
cmp [name],eax |
jz ok |
cmp [name],0 |
jz ok |
xor eax,eax |
jmp try_end |
ok=$ |
xor eax,eax |
inc eax |
try_end=$ |
} |
_cli equ call MEM_HeapLock |
_sti equ call MEM_HeapUnLock |
end if |
/kernel/branches/gfx_kernel/core/sys32.inc |
---|
0,0 → 1,1017 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; MenuetOS process management, protected ring3 ;; |
;; ;; |
;; Distributed under GPL. See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
; GDT TABLE |
gdts: |
dw gdte-$-1 |
dd gdts |
dw 0 |
int_code_l: |
os_code_l: |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10011010b |
db 0x00 |
int_data_l: |
os_data_l: |
dw 0xffff |
dw 0x0000 |
db 0x00 |
dw 11011111b *256 +10010010b |
db 0x00 |
; --------------- APM --------------------- |
apm_code_32: |
dw 0x10 ; limit 64kb |
db 0, 0, 0 |
dw 11011111b *256 +10011010b |
db 0x00 |
apm_code_16: |
dw 0x10 |
db 0, 0, 0 |
dw 10011111b *256 +10011010b |
db 0x00 |
apm_data_16: |
dw 0x10 |
db 0, 0, 0 |
dw 10011111b *256 +10010010b |
db 0x00 |
; ----------------------------------------- |
app_code_l: |
dw ((0x80000000-std_application_base_address) shr 12) and 0xffff |
dw 0 |
db 0 |
dw 11010000b*256+11111010b+256*((0x80000000-std_application_base_address) shr 28) |
db std_application_base_address shr 24 |
app_data_l: |
dw (0x80000000-std_application_base_address) shr 12 and 0xffff |
dw 0 |
db 0 |
dw 11010000b*256+11110010b+256*((0x80000000-std_application_base_address) shr 28) |
db std_application_base_address shr 24 |
graph_data_l: |
dw 0x3ff |
dw 0x0000 |
db 0x00 |
dw 11010000b *256 +11110010b |
db 0x00 |
tss0_l: |
times (max_processes+10) dd 0,0 |
gdte: |
idtreg: |
dw 8*0x41-1 |
dd idts+8 |
label idts at 0xB100-8 |
uglobal |
tss_sceleton: |
l.back dw 0,0 |
l.esp0 dd 0 |
l.ss0 dw 0,0 |
l.esp1 dd 0 |
l.ss1 dw 0,0 |
l.esp2 dd 0 |
l.ss2 dw 0,0 |
l.cr3 dd 0 |
l.eip dd 0 |
l.eflags dd 0 |
l.eax dd 0 |
l.ecx dd 0 |
l.edx dd 0 |
l.ebx dd 0 |
l.esp dd 0 |
l.ebp dd 0 |
l.esi dd 0 |
l.edi dd 0 |
l.es dw 0,0 |
l.cs dw 0,0 |
l.ss dw 0,0 |
l.ds dw 0,0 |
l.fs dw 0,0 |
l.gs dw 0,0 |
l.ldt dw 0,0 |
l.trap dw 0 |
l.io dw 0 |
endg |
build_process_gdt_tss_pointer: |
mov ecx,tss_data |
mov edi,0 |
setgdtl2: |
mov [edi+gdts+ tss0 +0], word tss_step |
mov [edi+gdts+ tss0 +2], cx |
mov eax,ecx |
shr eax,16 |
mov [edi+gdts+ tss0 +4], al |
mov [edi+gdts+ tss0 +7], ah |
mov [edi+gdts+ tss0 +5], word 01010000b *256 +11101001b |
add ecx,tss_step |
add edi,8 |
cmp edi,8*(max_processes+5) |
jbe setgdtl2 |
ret |
build_interrupt_table: |
mov edi, idts+8 |
mov esi, sys_int |
mov ecx, 0x40 |
@@: |
mov eax, [esi] |
mov [edi], ax ; lower part of offset |
mov [edi+2], word os_code ; segment selector |
shr eax, 16 |
mov [edi+4], word 10001110b shl 8 ; interrupt descriptor |
mov [edi+6], ax |
add esi, 4 |
add edi, 8 |
dec ecx |
jnz @b |
;mov edi,8*0x40+idts+8 |
mov [edi + 0], word (i40 and ((1 shl 16)-1)) |
mov [edi + 2], word os_code |
mov [edi + 4], word 11101110b*256 |
mov [edi + 6], word (i40 shr 16) |
ret |
iglobal |
sys_int: |
dd e0,debug_exc,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15 |
dd e16,e17 |
times 14 dd unknown_interrupt |
dd irq0 ,irq1 ,p_irq2 ,p_irq3 ,p_irq4 ,p_irq5,p_irq6 ,p_irq7 |
dd p_irq8,p_irq9,p_irq10,p_irq11,p_irq12,irqD ,p_irq14,p_irq15 |
times 16 dd unknown_interrupt |
dd i40 |
endg |
macro save_ring3_context |
{ |
push ds es |
pushad |
} |
macro restore_ring3_context |
{ |
popad |
pop es ds |
} |
; simply return control to interrupted process |
unknown_interrupt: |
iret |
macro exc_wo_code [num] |
{ |
forward |
e#num : |
save_ring3_context |
mov bl, num |
jmp exc_c |
} |
macro exc_w_code [num] |
{ |
forward |
e#num : |
add esp, 4 |
save_ring3_context |
mov bl, num |
jmp exc_c |
} |
exc_wo_code 0, 1, 2, 3, 4, 5, 6, 9, 15, 16 ; 18, 19 |
exc_w_code 8, 10, 11, 12, 13, 14, 17 |
exc_c: |
mov ax, os_data |
mov ds, ax |
mov es, ax |
; test if debugging |
cli |
mov eax, [0x3000] |
shl eax, 8 |
mov eax, [0x80000+eax+APPDATA.debugger_slot] |
test eax, eax |
jnz .debug |
sti |
; not debuggee => say error and terminate |
add esp, 28h |
movzx eax, bl |
mov [error_interrupt], eax |
call show_error_parameters |
mov edx, [0x3010] |
mov [edx + TASKDATA.state], byte 4 |
jmp change_task |
.debug: |
; we are debugged process, notify debugger and suspend ourself |
; eax=debugger PID |
cld |
movzx ecx, bl |
push ecx |
mov ecx, [0x3010] |
push dword [ecx+TASKDATA.pid] ; PID of current process |
push 12 |
pop ecx |
push 1 ; 1=exception |
call debugger_notify |
pop ecx |
pop ecx |
pop ecx |
mov edx, [0x3010] |
mov byte [edx+TASKDATA.state], 1 ; suspended |
call change_task |
restore_ring3_context |
iretd |
;;;;;;;;;;;;;;;;;;;;;;; |
;; FPU ERROR HANDLER ;; |
;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
e7: |
save_ring3_context |
clts |
mov ax, os_data |
mov ds, ax |
mov es, ax |
mov eax, [prev_user_of_fpu] |
shl eax, 8 |
add eax, 0x80000 + APPDATA.fpu_save_area |
fsave [eax] |
mov eax, [0x3000] |
mov [prev_user_of_fpu], eax |
shl eax, 8 |
add eax, 0x80000 |
cmp [eax + APPDATA.is_fpu_saved], 0 |
je @f |
frstor [eax+APPDATA.fpu_save_area] |
@@: |
mov [eax + APPDATA.is_fpu_saved], 1 |
restore_ring3_context |
iret |
iglobal |
prev_user_of_fpu dd 1 |
endg |
writehex: |
pusha |
mov edi, [write_error_to] |
mov esi, 8 |
@@: |
mov ecx, eax |
and ecx, 0xf |
mov cl,[ecx+hexletters] |
mov [edi],cl |
dec edi |
shr eax,4 |
dec esi |
jnz @b |
popa |
ret |
iglobal |
hexletters db '0123456789ABCDEF' |
error_interrupt dd -1 |
process_error db 'K : Process - forced terminate INT: 00000000',13,10,0 |
process_pid db 'K : Process - forced terminate PID: 00000000',13,10,0 |
process_eip db 'K : Process - forced terminate EIP: 00000000',13,10,0 |
system_error db 'K : Kernel error',13,10,0 |
endg |
uglobal |
write_error_to dd 0x0 |
endg |
show_error_parameters: |
mov [write_error_to],process_pid+43 |
mov eax,[0x3000] |
shl eax, 5 |
mov eax,[0x3000+TASKDATA.pid+eax] |
call writehex |
mov [write_error_to],process_error+43 |
mov eax,[error_interrupt] |
call writehex |
cmp dword [esp+4+4], os_code ; CS |
jnz @f |
mov esi,system_error |
call sys_msg_board_str |
@@: |
mov eax, [esp+4] ; EIP |
mov [write_error_to],process_eip+43 |
call writehex |
mov esi,process_error |
call sys_msg_board_str |
mov esi,process_pid |
call sys_msg_board_str |
mov esi,process_eip |
call sys_msg_board_str |
ret |
; irq1 -> hid/keyboard.inc |
macro irqh [num] |
{ |
forward |
p_irq#num : |
save_ring3_context |
mov edi, num |
jmp irq_c |
} |
irqh 2,5,7,8,9,10,11,14,15 |
irq_c: |
mov ax, os_data |
mov ds, ax |
mov es, ax |
call irqhandler |
restore_ring3_context |
iret |
p_irq6: |
save_ring3_context |
mov ax, os_data |
mov ds, ax |
mov es, ax |
call fdc_irq |
call ready_for_next_irq |
restore_ring3_context |
iret |
p_irq3: |
save_ring3_context |
mov ax, os_data |
mov ds, ax |
mov es, ax |
cmp [com2_mouse_detected],0 |
je old_irq3_handler |
call check_mouse_data_com2 |
jmp p_irq3_1 |
old_irq3_handler: |
mov edi,3 |
call irqhandler |
p_irq3_1: |
restore_ring3_context |
iret |
p_irq4: |
save_ring3_context |
mov ax, os_data |
mov ds, ax |
mov es, ax |
cmp [com1_mouse_detected],0 |
je old_irq4_handler |
call check_mouse_data_com1 |
jmp p_irq4_1 |
old_irq4_handler: |
mov edi,4 |
call irqhandler |
p_irq4_1: |
restore_ring3_context |
iret |
p_irq12: |
save_ring3_context |
mov ax, os_data |
mov ds, ax |
mov es, ax |
call check_mouse_data_ps2 |
restore_ring3_context |
iret |
ready_for_next_irq: |
mov [check_idle_semaphore],5 |
mov al, 0x20 |
out 0x20, al |
ret |
ready_for_next_irq_1: |
mov [check_idle_semaphore],5 |
mov al, 0x20 |
out 0xa0,al |
out 0x20, al |
ret |
irqD: |
save_ring3_context |
mov ax, os_data |
mov ds, ax |
mov es, ax |
mov dx,0xf0 |
mov al,0 |
out dx,al |
mov dx,0xa0 |
mov al,0x20 |
out dx,al |
mov dx,0x20 |
out dx,al |
restore_ring3_context |
iret |
irqhandler: |
push edi |
mov esi,edi ; 1 |
shl esi,6 ; 1 |
add esi,irq00read ; 1 |
shl edi,12 ; 1 |
add edi,0x2E0000 |
mov ecx,16 |
mov [check_idle_semaphore],5 |
irqnewread: |
dec ecx |
js irqover |
mov dx,[esi] ; 2+ |
cmp dx,0 ; 1 |
jz irqover |
cmp [esi+3],byte 1 ; 2 ; byte read |
jne noirqbyte ; 4-11 |
in al,dx |
mov edx,[edi] |
cmp edx,4000 |
je irqfull |
mov ebx,edi |
add ebx,0x10 |
add ebx,edx |
mov [ebx],al |
inc edx |
mov [edi],edx |
add esi,4 |
jmp irqnewread |
noirqbyte: |
cmp [esi+3],byte 2 ; word read |
jne noirqword |
in ax,dx |
mov edx,[edi] |
cmp edx,4000 |
je irqfull |
mov ebx,edi |
add ebx,0x10 |
add ebx,edx |
mov [ebx],ax |
add edx,2 |
mov [edi],edx |
add esi,4 |
jmp irqnewread |
noirqword: |
irqfull: |
irqover: |
mov al,0x20 ; ready for next irq |
out 0x20,al |
pop ebx |
cmp ebx,7 |
jbe noa0 |
out 0xa0,al |
noa0: |
ret |
set_application_table_status: |
push eax |
mov eax,[0x3000] |
shl eax, 5 |
add eax,0x3000+TASKDATA.pid |
mov eax,[eax] |
mov [application_table_status],eax |
pop eax |
ret |
clear_application_table_status: |
push eax |
mov eax,[0x3000] |
shl eax, 5 |
add eax,0x3000+TASKDATA.pid |
mov eax,[eax] |
cmp eax,[application_table_status] |
jne apptsl1 |
mov [application_table_status],0 |
apptsl1: |
pop eax |
ret |
sys_resize_app_memory: |
; eax = 1 - resize |
; ebx = new amount of memory |
cmp eax,1 |
jne .no_application_mem_resize |
jmp new_mem_resize ;resize for new type of processes |
.no_application_mem_resize: |
ret |
get_app_params: |
push eax |
cmp [0x90000+6],word '00' |
jne no_00_header |
mov eax,[0x90000+12] |
mov [app_start],eax |
mov eax,[0x90000+16] |
mov [app_i_end],eax |
mov eax,[0x90000+20] |
mov [app_mem],eax |
shr eax,1 |
sub eax,0x10 |
mov [app_esp],eax |
mov eax,[0x90000+24] |
mov [app_i_param],eax |
mov [app_i_icon],dword 0 |
pop eax |
mov esi,1 |
ret |
no_00_header: |
cmp [0x90000+6],word '01' |
jne no_01_header |
mov eax,[0x90000+12] |
mov [app_start],eax |
mov eax,[0x90000+16] |
mov [app_i_end],eax |
mov eax,[0x90000+20] |
mov [app_mem],eax |
mov eax,[0x90000+24] |
mov [app_esp],eax |
mov eax,[0x90000+28] |
mov [app_i_param],eax |
mov eax,[0x90000+32] |
mov [app_i_icon],eax |
pop eax |
mov esi,1 |
ret |
no_01_header: |
pop eax |
mov esi,0 |
ret |
start_application_fl: |
jmp new_start_application_fl |
;************************************************************************ |
start_application_floppy: |
jmp new_start_application_floppy |
;******************************************************************** |
start_application_hd: |
jmp new_start_application_hd |
uglobal |
new_process_place dd 0x0 |
app_start dd 0x0 |
app_i_end dd 0x0 |
app_mem dd 0x0 |
app_esp dd 0x0 |
app_i_param dd 0x0 |
app_i_icon dd 0x0 |
;app_mem_pos dd 0x0 |
appl_path dd 0x0 |
appl_path_size dd 0x0 |
endg |
;iglobal |
;hd_app_string db 'HDAPP ' |
;process_loading db 'K : Process - loading ',13,10,0 |
;process_running db 'K : Process - done',13,10,0 |
;first_gdt_search dd 0x2 |
;endg |
sys_threads: |
; eax=1 create thread |
; |
; ebx=thread start |
; ecx=thread stack value |
; |
; on return : eax = pid |
jmp new_sys_threads |
iglobal |
process_terminating db 'K : Process - terminating',13,10,0 |
process_terminated db 'K : Process - done',13,10,0 |
endg |
terminate: ; terminate application |
push esi |
mov esi,process_terminating |
call sys_msg_board_str |
pop esi |
@@: |
cli |
cmp [application_table_status],0 |
je term9 |
sti |
call change_task |
jmp @b |
term9: |
call set_application_table_status |
mov eax,esi |
call dispose_app_cr3_table |
cmp [prev_user_of_fpu],esi ; if user fpu last -> fpu user = 1 |
jne fpu_ok_1 |
mov [prev_user_of_fpu],1 |
fpu_ok_1: |
mov [0xf400],byte 0 ; empty keyboard buffer |
mov [0xf500],byte 0 ; empty button buffer |
; remove defined hotkeys |
mov eax, hotkey_list |
.loop: |
cmp [eax+8], esi |
jnz .cont |
mov ecx, [eax] |
jecxz @f |
push dword [eax+12] |
pop dword [ecx+12] |
@@: |
mov ecx, [eax+12] |
push dword [eax] |
pop dword [ecx] |
xor ecx, ecx |
mov [eax], ecx |
mov [eax+4], ecx |
mov [eax+8], ecx |
mov [eax+12], ecx |
.cont: |
add eax, 16 |
cmp eax, hotkey_list+256*16 |
jb .loop |
; remove hotkeys in buffer |
mov eax, hotkey_buffer |
.loop2: |
cmp [eax], esi |
jnz .cont2 |
and dword [eax+4], 0 |
and dword [eax], 0 |
.cont2: |
add eax, 8 |
cmp eax, hotkey_buffer+120*8 |
jb .loop2 |
mov ecx,esi ; remove buttons |
bnewba2: |
mov edi,[0xfe88] |
mov eax,edi |
cld |
movzx ebx,word [edi] |
inc bx |
bnewba: |
dec bx |
jz bnmba |
add eax,0x10 |
cmp cx,[eax] |
jnz bnewba |
pusha |
mov ecx,ebx |
inc ecx |
shl ecx,4 |
mov ebx,eax |
add eax,0x10 |
call memmove |
dec dword [edi] |
popa |
jmp bnewba2 |
bnmba: |
pusha ; save window coordinates for window restoring |
cld |
shl esi,5 |
add esi,window_data |
mov eax,[esi+WDATA.box.left] |
mov [dlx],eax |
add eax,[esi+WDATA.box.width] |
mov [dlxe],eax |
mov eax,[esi+WDATA.box.top] |
mov [dly],eax |
add eax,[esi+WDATA.box.height] |
mov [dlye],eax |
mov [esi+WDATA.box.left], 0 |
mov [esi+WDATA.box.width], 5 |
mov eax,[0xFE04] |
mov [esi+WDATA.box.top],eax |
mov [esi+WDATA.box.height], 5 |
xor eax, eax |
mov [esi+WDATA.cl_workarea],eax |
mov [esi+WDATA.cl_titlebar],eax |
mov [esi+WDATA.cl_frames],eax |
mov dword [esi+WDATA.reserved],eax ; clear all flags: wstate, redraw, wdrawn |
lea edi, [esi-window_data+draw_data] |
mov ecx,32/4 |
rep stosd |
popa |
; debuggee test |
pushad |
mov edi, esi |
shl edi, 5 |
mov eax, [0x80000+edi*8+APPDATA.debugger_slot] |
test eax, eax |
jz .nodebug |
push 8 |
pop ecx |
push dword [0x3000+edi+TASKDATA.pid] ; PID |
push 2 |
call debugger_notify |
pop ecx |
pop ecx |
.nodebug: |
popad |
pusha ; at 0x80000+ |
mov edi,esi |
shl edi,8 |
add edi,0x80000 |
mov ecx,256/4 |
xor eax, eax |
rep stosd |
popa |
pusha ; name to spaces |
mov edi,esi |
shl edi,8 |
add edi,0x80000+APPDATA.app_name |
mov ecx,11 |
mov eax,' ' |
rep stosb |
popa |
; activate window |
movzx eax, word [0xC000 + esi*2] |
cmp eax, [0x3004] |
jne .dont_activate |
pushad |
.check_next_window: |
dec eax |
cmp eax, 1 |
jbe .nothing_to_activate |
lea esi, [0xc400+eax*2] |
movzx edi, word [esi] ; edi = process |
shl edi, 5 |
cmp [0x3000 + edi + TASKDATA.state], byte 9 ; skip dead slots |
je .check_next_window |
add edi, window_data |
call waredraw |
.nothing_to_activate: |
popad |
.dont_activate: |
push esi ; remove hd1 & cd & flp reservation |
shl esi, 5 |
mov esi, [esi+0x3000+TASKDATA.pid] |
cmp [hd1_status], esi |
jnz @f |
mov [hd1_status], 0 |
@@: |
cmp [cd_status], esi |
jnz @f |
mov [cd_status], 0 |
@@: |
cmp [flp_status], esi |
jnz @f |
mov [flp_status], 0 |
@@: |
pop esi |
pusha ; remove all irq reservations |
mov eax,esi |
shl eax, 5 |
mov eax,[eax+0x3000+TASKDATA.pid] |
mov edi,irq_owner |
mov ecx,16 |
newirqfree: |
scasd |
jne nofreeirq |
mov [edi-4],dword 0 |
nofreeirq: |
loop newirqfree |
popa |
pusha ; remove all port reservations |
mov edx,esi |
shl edx, 5 |
add edx,0x3000 |
mov edx,[edx+TASKDATA.pid] |
rmpr0: |
mov esi,[0x2d0000] |
cmp esi,0 |
je rmpr9 |
rmpr3: |
mov edi,esi |
shl edi,4 |
add edi,0x2d0000 |
cmp edx,[edi] |
je rmpr4 |
dec esi |
jnz rmpr3 |
jmp rmpr9 |
rmpr4: |
mov ecx,256 |
sub ecx,esi |
shl ecx,4 |
mov esi,edi |
add esi,16 |
cld |
rep movsb |
dec dword [0x2d0000] |
jmp rmpr0 |
rmpr9: |
popa |
mov edi,esi ; do not run this process slot |
shl edi, 5 |
mov [edi+0x3000 + TASKDATA.state],byte 9 |
; debugger test - terminate all debuggees |
mov eax, 2 |
mov ecx, 0x80000+2*0x100+APPDATA.debugger_slot |
.xd0: |
cmp eax, [0x3004] |
ja .xd1 |
cmp dword [ecx], esi |
jnz @f |
and dword [ecx], 0 |
pushad |
xchg eax, ebx |
mov eax, 2 |
call sys_system |
popad |
@@: |
inc eax |
add ecx, 0x100 |
jmp .xd0 |
.xd1: |
; call systest |
sti ; .. and life goes on |
mov eax, [dlx] |
mov ebx, [dly] |
mov ecx, [dlxe] |
mov edx, [dlye] |
call [calculatescreen] |
xor eax, eax |
xor esi, esi |
call redrawscreen |
mov [0xfff4],byte 0 ; no mouse background |
mov [0xfff5],byte 0 ; draw mouse |
mov [application_table_status],0 |
mov esi,process_terminated |
call sys_msg_board_str |
ret |
iglobal |
boot_sched_1 db 'Building gdt tss pointer',0 |
boot_sched_2 db 'Building IDT table',0 |
endg |
build_scheduler: |
mov esi,boot_sched_1 |
call boot_log |
call build_process_gdt_tss_pointer |
mov esi,boot_sched_2 |
call boot_log |
call build_interrupt_table |
ret |
/kernel/branches/gfx_kernel/core/syscall.inc |
---|
0,0 → 1,151 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSTEM CALL ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
i40: |
push ds es |
pushad |
cld |
mov ax,word os_data |
mov ds,ax |
mov es,ax |
; for syscall trace function |
call save_registers |
; load all registers in crossed order |
mov edi,[esp+28] ; eax |
mov eax,[esp+16] ; ebx |
mov ebx,[esp+24] ; ecx |
mov ecx,[esp+20] ; edx |
mov edx,[esp+4] ; esi |
mov esi,[esp+0] ; edi |
; enable interupts - a task switch or an IRQ _CAN_ interrupt i40 handler |
sti |
push eax |
and edi,0xff |
call dword [servetable+edi*4] |
pop eax |
cli |
popad |
pop es ds |
iretd |
align 4 |
save_registers: |
mov esi, [0x3010] |
mov eax, [esi+TASKDATA.pid] ; load PID |
lea esi, [esp+4] |
inc [save_syscall_count] |
mov edi,[save_syscall_count] |
and edi,0xF |
shl edi,6 |
add edi,save_syscall_data+32 |
mov [edi-32],eax |
mov ecx,32 / 4 |
cld |
rep movsd |
ret |
uglobal |
save_syscall_count dd 0x0 |
endg |
label save_syscall_data dword at 0x5000 |
iglobal |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; SYSTEM FUNCTIONS TABLE ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 4 |
servetable: |
dd sys_drawwindow ; 0-DrawWindow |
dd syscall_setpixel ; 1-SetPixel |
dd sys_getkey ; 2-GetKey |
dd sys_clock ; 3-GetTime |
dd syscall_writetext ; 4-WriteText |
dd delay_hs ; 5-DelayHs |
dd syscall_openramdiskfile ; 6-OpenRamdiskFile |
dd syscall_putimage ; 7-PutImage |
dd sys_button ; 8-DefineButton |
dd sys_cpuusage ; 9-GetProcessInfo |
dd sys_waitforevent ; 10-WaitForEvent |
dd sys_getevent ; 11-CheckForEvent |
dd sys_redrawstat ; 12-BeginDraw and EndDraw |
dd syscall_drawrect ; 13-DrawRect |
dd syscall_getscreensize ; 14-GetScreenSize |
dd sys_background ; 15-bgr |
dd sys_cachetodiskette ; 16-FlushFloppyCache |
dd sys_getbutton ; 17-GetButton |
dd sys_system ; 18-System Services |
dd syscall_startapp ; 19-StartApp |
dd sys_midi ; 20-ResetMidi and OutputMidi |
dd sys_setup ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,. |
dd sys_settime ; 22-setting date,time,clock and alarm-clock |
dd sys_wait_event_timeout ; 23-TimeOutWaitForEvent |
dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist |
dd sys_sb16 ; 25-SetSb16 |
dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,. |
dd sys_wss ; 27-SetWssMainVol and SetWssCdVol |
dd sys_sb16II ; 28-SetSb16 |
dd sys_date ; 29-GetDate |
; dd syscall_readhd ; 30-ReadHd - obsolete <diamond> |
dd undefined_syscall ; 30-reserved |
; dd syscall_starthdapp ; 31-StartHdApp - obsolete <diamond> |
dd undefined_syscall ; 31-reserved |
dd syscall_delramdiskfile ; 32-DelRamdiskFile |
dd syscall_writeramdiskfile; 33-WriteRamdiskFile |
; dd read_floppy_file ; 34-ReadFloppyDrive - obsolete <diamond> |
dd undefined_syscall ; 34-reserved |
dd syscall_getpixel ; 35-GetPixel |
dd syscall_readstring ; 36-ReadString (not yet ready) |
dd readmousepos ; 37-GetMousePosition_ScreenRelative,. |
dd syscall_drawline ; 38-DrawLine |
dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,. |
dd set_app_param ; 40-WantEvents |
dd syscall_getirqowner ; 41-GetIrqOwner |
dd get_irq_data ; 42-ReadIrqData |
dd sys_outport ; 43-SendDeviceData |
dd sys_programirq ; 44-ProgramIrqs |
dd reserve_free_irq ; 45-ReserveIrq and FreeIrq |
dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea |
dd display_number ; 47-WriteNum |
dd display_settings ; 48-SetRedrawType and SetButtonType |
dd sys_apm ; 49-Advanced Power Management (APM) |
dd random_shaped_window ; 50-Window shape & scale |
dd syscall_threads ; 51-Threads |
dd stack_driver_stat ; 52-Stack driver status |
dd socket ; 53-Socket interface |
dd user_events ; 54-User events |
dd sound_interface ; 55-Sound interface |
dd write_to_hd ; 56-Write a file to hd |
; dd delete_from_hd ; 57-Delete a file from hd - obsolete <diamond> |
dd undefined_syscall ; 57-reserved |
dd file_system ; 58-Common file system interface |
dd sys_trace ; 59-System call trace |
dd new_sys_ipc ; 60-Inter Process Communication |
dd sys_gs ; 61-Direct graphics access |
dd sys_pci ; 62-PCI functions |
dd sys_msg_board ; 63-System message board |
dd sys_resize_app_memory ; 64-Resize application memory usage |
dd undefined_syscall ; 65-UTF |
dd sys_process_def ; 66-Process definitions - keyboard |
dd sys_window_move ; 67-Window move or resize |
dd sys_internal_services ; 68-Some internal services |
dd sys_debug_services ; 69-Debug |
dd file_system_lfn ; 70-Common file system interface, version 2 |
dd syscall_windowsettings ; 71-Window settings |
times 255 - ( ($-servetable) /4 ) dd undefined_syscall |
dd sys_end ; -1-end application |
endg |