/kernel/tags/kolibri0.6.5.0/core/dll.inc |
---|
0,0 → 1,1047 |
DRV_ENTRY equ 1 |
DRV_EXIT equ -1 |
DRV_COMPAT equ 3 ;minimal required drivers version |
DRV_CURRENT equ 3 ;current drivers model version |
DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT |
align 4 |
proc attach_int_handler stdcall, irq:dword, handler:dword |
mov ebx, [irq] ;irq num |
test ebx, ebx |
jz .err |
mov eax, [handler] |
test eax, eax |
jz .err |
mov [irq_tab+ebx*4], eax |
stdcall enable_irq, [irq] |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc detach_int_handler |
ret |
endp |
align 4 |
proc enable_irq stdcall, irq_line:dword |
mov ebx, [irq_line] |
mov edx, 0x21 |
cmp ebx, 8 |
jb @F |
mov edx, 0xA1 |
sub ebx,8 |
@@: |
in al,dx |
btr eax, ebx |
out dx, al |
ret |
endp |
align 16 |
;; proc irq_serv |
irq_serv: |
.irq_1: |
push eax |
mov eax, 1 |
jmp .main |
align 4 |
.irq_2: |
push eax |
mov eax, 2 |
jmp .main |
align 4 |
.irq_3: |
push eax |
mov eax, 3 |
jmp .main |
align 4 |
.irq_4: |
push eax |
mov eax, 4 |
jmp .main |
align 4 |
.irq_5: |
push eax |
mov eax, 5 |
jmp .main |
align 4 |
.irq_6: |
push eax |
mov eax, 6 |
jmp .main |
align 4 |
.irq_7: |
push eax |
mov eax, 7 |
jmp .main |
align 4 |
.irq_8: |
push eax |
mov eax, 8 |
jmp .main |
align 4 |
.irq_9: |
push eax |
mov eax, 9 |
jmp .main |
align 4 |
.irq_10: |
push eax |
mov eax, 10 |
jmp .main |
align 4 |
.irq_11: |
push eax |
mov eax, 11 |
jmp .main |
align 4 |
.irq_12: |
push eax |
mov eax, 12 |
jmp .main |
align 4 |
.irq_13: |
push eax |
mov eax, 13 |
jmp .main |
align 4 |
.irq_14: |
push eax |
mov eax, 14 |
jmp .main |
align 4 |
.irq_15: |
push eax |
mov eax, 15 |
jmp .main |
align 16 |
.main: |
save_ring3_context |
mov bx, os_data |
mov ds, bx |
mov es, bx |
mov ebx, [irq_tab+eax*4] |
test ebx, ebx |
jz .exit |
call ebx |
.exit: |
restore_ring3_context |
cmp eax, 8 |
mov al, 0x20 |
jb @f |
out 0xa0, al |
@@: |
out 0x20, al |
pop eax |
iret |
align 4 |
proc get_notify stdcall, p_ev:dword |
.wait: |
mov ebx,[CURRENT_TASK] |
shl ebx,8 |
test dword [ebx+PROC_BASE+0xA8],EVENT_NOTIFY |
jz @f |
and dword [ebx+PROC_BASE+0xA8], not EVENT_NOTIFY |
mov edi, [p_ev] |
mov dword [edi], EV_INTR |
mov eax, [ebx+PROC_BASE+APPDATA.event] |
mov dword [edi+4], eax |
ret |
@@: |
call change_task |
jmp .wait |
endp |
align 4 |
proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 6 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
call pci_read_reg |
ret |
endp |
align 4 |
proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 4 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
call pci_read_reg |
ret |
endp |
align 4 |
proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword |
xor eax, eax |
xor ebx, ebx |
mov ah, byte [bus] |
mov al, 8 |
mov bh, byte [devfn] |
mov bl, byte [reg] |
mov ecx, [val] |
call pci_write_reg |
ret |
endp |
handle equ IOCTL.handle |
io_code equ IOCTL.io_code |
input equ IOCTL.input |
inp_size equ IOCTL.inp_size |
output equ IOCTL.output |
out_size equ IOCTL.out_size |
align 4 |
proc srv_handler stdcall, ioctl:dword |
mov esi, [ioctl] |
test esi, esi |
jz .err |
mov edi, [esi+handle] |
cmp [edi+SRV.magic], ' SRV' |
jne .fail |
cmp [edi+SRV.size], SRV_SIZE |
jne .fail |
stdcall [edi+SRV.srv_proc], esi |
ret |
.fail: |
xor eax, eax |
not eax |
mov [esi+output], eax |
mov [esi+out_size], 4 |
ret |
.err: |
xor eax, eax |
not eax |
ret |
endp |
align 4 |
proc srv_handlerEx stdcall, ioctl:dword |
mov esi, [ioctl] |
test esi, esi |
jz .err |
add esi, new_app_base |
mov edi, [esi+handle] |
cmp [edi+SRV.magic], ' SRV' |
jne .fail |
cmp [edi+SRV.size], SRV_SIZE |
jne .fail |
add [esi+input], new_app_base |
add [esi+output], new_app_base |
stdcall [edi+SRV.srv_proc], esi |
ret |
.fail: |
xor eax, eax |
not eax |
mov [esi+output], eax |
mov [esi+out_size], 4 |
ret |
.err: |
xor eax, eax |
not eax |
ret |
endp |
restore handle |
restore io_code |
restore input |
restore inp_size |
restore output |
restore out_size |
align 4 |
proc get_service stdcall, sz_name:dword |
mov eax, [sz_name] |
test eax, eax |
jnz @F |
ret |
@@: |
mov edx, [srv.fd] |
@@: |
cmp edx, srv.fd-SRV_FD_OFFSET |
je .not_load |
stdcall strncmp, edx, [sz_name], 16 |
test eax, eax |
je .ok |
mov edx, [edx+SRV.fd] |
jmp @B |
.not_load: |
pop ebp |
jmp load_driver |
.ok: |
mov eax, edx |
ret |
endp |
align 4 |
reg_service: |
.sz_name equ esp+4 |
.handler equ esp+8 |
mov eax, [.sz_name] |
test eax, eax |
jz .fail |
mov ebx, [.handler] |
test ebx, ebx |
jz .fail |
mov eax, SRV_SIZE |
call malloc ;call alloc_service |
test eax, eax |
jz .fail |
mov edi, eax |
mov esi, [.sz_name] |
mov ecx, 16/4 |
rep movsd |
mov [eax+SRV.magic], ' SRV' |
mov [eax+SRV.size], SRV_SIZE |
mov ebx, srv.fd-SRV_FD_OFFSET |
mov edx, [ebx+SRV.fd] |
mov [eax+SRV.fd], edx |
mov [eax+SRV.bk], ebx |
mov [ebx+SRV.fd], eax |
mov [edx+SRV.bk], eax |
mov ecx, [.handler] |
mov [eax+SRV.srv_proc], ecx |
ret 8 |
.fail: |
xor eax, eax |
ret 8 |
align 4 |
proc get_proc stdcall, exp:dword, sz_name:dword |
mov edx, [exp] |
.next: |
mov eax, [edx] |
test eax, eax |
jz .end |
push edx |
stdcall strncmp, eax, [sz_name], 16 |
pop edx |
test eax, eax |
jz .ok |
add edx,8 |
jmp .next |
.ok: |
mov eax, [edx+4] |
.end: |
ret |
endp |
align 4 |
proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword |
@@: |
stdcall strncmp, [pSym], [sz_sym], 8 |
test eax,eax |
jz .ok |
add [pSym], 18 |
dec [count] |
jnz @b |
xor eax, eax |
ret |
.ok: |
mov ebx, [pSym] |
mov eax, [ebx+8] |
ret |
endp |
align 4 |
proc get_curr_task |
mov eax,[CURRENT_TASK] |
shl eax, 8 |
ret |
endp |
align 4 |
proc get_fileinfo stdcall, file_name:dword, info:dword |
locals |
cmd dd ? |
offset dd ? |
dd ? |
count dd ? |
buff dd ? |
db ? |
name dd ? |
endl |
xor eax, eax |
mov ebx, [file_name] |
sub ebx, new_app_base |
mov ecx, [info] |
sub ecx, new_app_base |
mov [cmd], 5 |
mov [offset], eax |
mov [offset+4], eax |
mov [count], eax |
mov [buff], ecx |
mov byte [buff+4], al |
mov [name], ebx |
mov eax, 70 |
lea ebx, [cmd] |
sub ebx, new_app_base |
int 0x40 |
ret |
endp |
align 4 |
proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\ |
bytes:dword |
locals |
cmd dd ? |
offset dd ? |
dd ? |
count dd ? |
buff dd ? |
db ? |
name dd ? |
endl |
xor eax, eax |
mov ebx, [file_name] |
mov ecx, [off] |
mov edx, [bytes] |
mov esi, [buffer] |
sub ebx, new_app_base |
sub esi, new_app_base |
mov [cmd], eax |
mov [offset], ecx |
mov [offset+4], eax |
mov [count], edx |
mov [buff], esi |
mov byte [buff+4], al |
mov [name], ebx |
mov eax, 70 |
lea ebx, [cmd] |
sub ebx, new_app_base |
int 0x40 |
ret |
endp |
align 4 |
proc load_file stdcall, file_name:dword |
locals |
attr dd ? |
flags dd ? |
cr_time dd ? |
cr_date dd ? |
acc_time dd ? |
acc_date dd ? |
mod_time dd ? |
mod_date dd ? |
file_size dd ? |
file dd ? |
file2 dd ? |
endl |
lea eax, [attr] |
stdcall get_fileinfo, [file_name], eax |
test eax, eax |
jnz .fail |
mov eax, [file_size] |
cmp eax, 1024*1024*16 |
ja .fail |
stdcall kernel_alloc, [file_size] |
mov [file], eax |
stdcall read_file, [file_name], eax, dword 0, [file_size] |
cmp ebx, [file_size] |
jne .cleanup |
mov eax, [file] |
cmp dword [eax], 0x4B43504B |
jne .exit |
mov ebx, [eax+4] |
mov [file_size], ebx |
stdcall kernel_alloc, ebx |
test eax, eax |
jz .cleanup |
mov [file2], eax |
stdcall unpack, [file], eax |
stdcall kernel_free, [file] |
mov eax, [file2] |
mov ebx, [file_size] |
.exit: |
push eax |
lea edi, [eax+ebx] ;cleanup remain space |
mov ecx, ebx ;from file end |
add ecx, 4095 |
and ecx, not 4095 |
sub ecx, ebx |
xor eax, eax |
cld |
rep stosb |
pop eax |
ret |
.cleanup: |
stdcall kernel_free, [file] |
.fail: |
xor eax, eax |
xor ebx, ebx |
ret |
endp |
align 4 |
proc get_proc_ex stdcall, proc_name:dword, imports:dword |
.look_up: |
mov edx, [imports] |
test edx, edx |
jz .end |
mov edx, [edx] |
test edx, edx |
jz .end |
.next: |
mov eax, [edx] |
test eax, eax |
jz .next_table |
push edx |
stdcall strncmp, eax, [proc_name], 16 |
pop edx |
test eax, eax |
jz .ok |
add edx,8 |
jmp .next |
.next_table: |
add [imports], 4 |
jmp .look_up |
.ok: |
mov eax, [edx+4] |
ret |
.end: |
xor eax, eax |
ret |
endp |
align 4 |
proc fix_coff_symbols stdcall, sec:dword, symbols:dword,\ |
sym_count:dword, strings:dword, imports:dword |
locals |
retval dd ? |
endl |
mov edi, [symbols] |
mov [retval], 1 |
.fix: |
movzx ebx, [edi+CSYM.SectionNumber] |
test ebx, ebx |
jnz .internal |
mov eax, dword [edi+CSYM.Name] |
test eax, eax |
jnz @F |
mov edi, [edi+4] |
add edi, [strings] |
@@: |
push edi |
stdcall get_proc_ex, edi,[imports] |
pop edi |
xor ebx, ebx |
test eax, eax |
jnz @F |
mov esi, msg_unresolved |
call sys_msg_board_str |
mov esi, edi |
call sys_msg_board_str |
mov esi, msg_CR |
call sys_msg_board_str |
mov [retval],0 |
@@: |
mov edi, [symbols] |
mov [edi+CSYM.Value], eax |
jmp .next |
.internal: |
dec ebx |
shl ebx, 3 |
lea ebx, [ebx+ebx*4] |
add ebx, [sec] |
mov eax, [ebx+CFS.VirtualAddress] |
add [edi+CSYM.Value], eax |
.next: |
add edi, CSYM_SIZE |
mov [symbols], edi |
dec [sym_count] |
jnz .fix |
mov eax, [retval] |
ret |
endp |
align 4 |
proc fix_coff_relocs stdcall, coff:dword, sec:dword, sym:dword |
locals |
n_sec dd ? |
endl |
mov eax, [coff] |
movzx ebx, [eax+CFH.nSections] |
mov [n_sec], ebx |
.fix_sec: |
mov esi, [sec] |
mov edi, [esi+CFS.PtrReloc] |
add edi, [coff] |
movzx ecx, [esi+CFS.NumReloc] |
test ecx, ecx |
jz .next |
.next_reloc: |
mov ebx, [edi+CRELOC.SymIndex] |
add ebx,ebx |
lea ebx,[ebx+ebx*8] |
add ebx, [sym] |
mov edx, [ebx+CSYM.Value] |
cmp [edi+CRELOC.Type], 6 |
je .dir_32 |
cmp [edi+CRELOC.Type], 20 |
jne .next_reloc |
.rel_32: |
mov eax, [edi+CRELOC.VirtualAddress] |
add eax, [esi+CFS.VirtualAddress] |
sub edx, eax |
sub edx, 4 |
jmp .fix |
.dir_32: |
mov eax, [edi+CRELOC.VirtualAddress] |
add eax, [esi+CFS.VirtualAddress] |
.fix: |
add [eax], edx |
add edi, 10 |
dec ecx |
jnz .next_reloc |
.next: |
add [sec], COFF_SECTION_SIZE |
dec [n_sec] |
jnz .fix_sec |
.exit: |
ret |
endp |
align 4 |
proc load_driver stdcall, driver_name:dword |
locals |
coff dd ? |
sym dd ? |
strings dd ? |
img_size dd ? |
img_base dd ? |
start dd ? |
exports dd ? ;fake exports table |
dd ? |
file_name rb 14+16+4+1 ; '/rd/1/drivers/<up-to-16-chars>.obj' |
endl |
lea edx, [file_name] |
mov dword [edx], '/rd/' |
mov dword [edx+4], '1/dr' |
mov dword [edx+8], 'iver' |
mov word [edx+12], 's/' |
mov esi, [driver_name] |
lea edi, [edx+14] |
mov ecx, 16 |
@@: |
lodsb |
test al, al |
jz @f |
stosb |
loop @b |
@@: |
mov dword [edi], '.obj' |
mov byte [edi+4], 0 |
stdcall load_file, edx |
test eax, eax |
jz .exit |
mov [coff], eax |
movzx ecx, [eax+CFH.nSections] |
xor ebx, ebx |
lea edx, [eax+20] |
@@: |
add ebx, [edx+CFS.SizeOfRawData] |
add ebx, 15 |
and ebx, not 15 |
add edx, COFF_SECTION_SIZE |
dec ecx |
jnz @B |
mov [img_size], ebx |
stdcall kernel_alloc, ebx |
test eax, eax |
jz .fail |
mov [img_base], eax |
mov edi, eax |
xor eax, eax |
mov ecx, [img_size] |
add ecx, 4095 |
and ecx, not 4095 |
shr ecx, 2 |
cld |
rep stosd |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, [img_base] |
lea eax, [edx+20] |
@@: |
mov [eax+CFS.VirtualAddress], edi |
mov esi, [eax+CFS.PtrRawData] |
test esi, esi |
jnz .copy |
add edi, [eax+CFS.SizeOfRawData] |
jmp .next |
.copy: |
add esi, edx |
mov ecx, [eax+CFS.SizeOfRawData] |
cld |
rep movsb |
.next: |
add edi, 15 |
and edi, not 15 |
add eax, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
mov ebx, [edx+CFH.pSymTable] |
add ebx, edx |
mov [sym], ebx |
mov ecx, [edx+CFH.nSymbols] |
add ecx,ecx |
lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE |
add ecx, [sym] |
mov [strings], ecx |
lea ebx, [exports] |
mov dword [ebx], kernel_export |
mov dword [ebx+4], 0 |
lea eax, [edx+20] |
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\ |
[strings], ebx |
test eax, eax |
jz .link_fail |
mov ebx, [coff] |
add ebx, 20 |
stdcall fix_coff_relocs, [coff], ebx, [sym] |
mov ebx, [coff] |
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szVersion |
test eax, eax |
jz .link_fail |
mov eax, [eax] |
shr eax, 16 |
cmp eax, DRV_COMPAT |
jb .ver_fail |
cmp eax, DRV_CURRENT |
ja .ver_fail |
mov ebx, [coff] |
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szSTART |
mov [start], eax |
stdcall kernel_free, [coff] |
mov ebx, [start] |
stdcall ebx, DRV_ENTRY |
test eax, eax |
jnz .ok |
stdcall kernel_free, [img_base] |
xor eax, eax |
ret |
.ok: |
mov ebx, [img_base] |
mov [eax+SRV.base], ebx |
mov ecx, [start] |
mov [eax+SRV.entry], ecx |
ret |
.ver_fail: |
mov esi, msg_CR |
call sys_msg_board_str |
mov esi, [driver_name] |
call sys_msg_board_str |
mov esi, msg_CR |
call sys_msg_board_str |
mov esi, msg_version |
call sys_msg_board_str |
mov esi, msg_www |
call sys_msg_board_str |
jmp .cleanup |
.link_fail: |
mov esi, msg_module |
call sys_msg_board_str |
mov esi, [driver_name] |
call sys_msg_board_str |
mov esi, msg_CR |
call sys_msg_board_str |
.cleanup: |
stdcall kernel_free,[img_base] |
.fail: |
stdcall kernel_free, [coff] |
.exit: |
xor eax, eax |
ret |
endp |
align 4 |
proc load_library stdcall, file_name:dword |
locals |
coff dd ? |
sym dd ? |
strings dd ? |
img_size dd ? |
img_base dd ? |
exports dd ? |
endl |
cli |
stdcall load_file, [file_name] |
test eax, eax |
jz .fail |
mov [coff], eax |
movzx ecx, [eax+CFH.nSections] |
xor ebx, ebx |
lea edx, [eax+20] |
@@: |
add ebx, [edx+CFS.SizeOfRawData] |
add ebx, 15 |
and ebx, not 15 |
add edx, COFF_SECTION_SIZE |
dec ecx |
jnz @B |
mov [img_size], ebx |
call init_heap |
stdcall user_alloc, [img_size] |
test eax, eax |
jz .fail |
mov [img_base], eax |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, [img_base] |
lea eax, [edx+20] |
@@: |
mov [eax+CFS.VirtualAddress], edi |
mov esi, [eax+CFS.PtrRawData] |
test esi, esi |
jnz .copy |
add edi, [eax+CFS.SizeOfRawData] |
jmp .next |
.copy: |
add esi, edx |
add edi, new_app_base |
mov ecx, [eax+CFS.SizeOfRawData] |
cld |
rep movsb |
.next: |
add edi, 15-new_app_base |
and edi, not 15 |
add eax, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
mov ebx, [edx+CFH.pSymTable] |
add ebx, edx |
mov [sym], ebx |
mov ecx, [edx+CFH.nSymbols] |
add ecx,ecx |
lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE |
add ecx, [sym] |
mov [strings], ecx |
lea eax, [edx+20] |
stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\ |
[strings], dword 0 |
test eax, eax |
jnz @F |
@@: |
mov edx, [coff] |
movzx ebx, [edx+CFH.nSections] |
mov edi, new_app_base |
lea eax, [edx+20] |
@@: |
add [eax+CFS.VirtualAddress], edi ;patch user space offset |
add eax, COFF_SECTION_SIZE |
dec ebx |
jnz @B |
add edx, 20 |
stdcall fix_coff_relocs, [coff], edx, [sym] |
mov ebx, [coff] |
stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szEXPORTS |
mov [exports], eax |
stdcall kernel_free, [coff] |
mov eax, [exports] |
ret |
.fail: |
xor eax, eax |
ret |
endp |
align 4 |
proc stop_all_services |
mov edx, [srv.fd] |
.next: |
cmp edx, srv.fd-SRV_FD_OFFSET |
je .done |
cmp [edx+SRV.magic], ' SRV' |
jne .next |
cmp [edx+SRV.size], SRV_SIZE |
jne .next |
mov ebx, [edx+SRV.entry] |
mov edx, [edx+SRV.fd] |
push edx |
stdcall ebx, dword -1 |
pop edx |
jmp .next |
.done: |
ret |
endp |
; param |
; eax= size |
; ebx= pid |
align 4 |
create_kernel_object: |
push ebx |
call malloc |
pop ebx |
test eax, eax |
jz .fail |
mov ecx,[CURRENT_TASK] |
shl ecx,8 |
add ecx, PROC_BASE+APP_OBJ_OFFSET |
pushfd |
cli |
mov edx, [ecx+APPOBJ.fd] |
mov [eax+APPOBJ.fd], edx |
mov [eax+APPOBJ.bk], ecx |
mov [eax+APPOBJ.pid], ebx |
mov [ecx+APPOBJ.fd], eax |
mov [edx+APPOBJ.bk], eax |
popfd |
.fail: |
ret |
; param |
; eax= object |
align 4 |
destroy_kernel_object: |
pushfd |
cli |
mov ebx, [eax+APPOBJ.fd] |
mov ecx, [eax+APPOBJ.bk] |
mov [ebx+APPOBJ.bk], ecx |
mov [ecx+APPOBJ.fd], ebx |
popfd |
xor edx, edx ;clear common header |
mov [eax], edx |
mov [eax+4], edx |
mov [eax+8], edx |
mov [eax+12], edx |
mov [eax+16], edx |
call free ;release object memory |
ret |
;szSound db 'SOUND',0 |
;szInfinity db 'INFINITY',0 |
szHwMouse db 'ATI2D',0 |
szSTART db 'START',0 |
szEXPORTS db 'EXPORTS',0 |
szIMPORTS db 'IMPORTS',0 |
msg_unresolved db 'unresolved ',0 |
msg_module db 'in module ',0 |
msg_version db 'incompatible driver version',13,10,0 |
msg_www db 'please visit www.kolibrios.org',13,10,0 |
msg_CR db 13,10,0 |
align 4 |
create_cursor dd 0 |
set_hw_cursor dd 0 |
hw_restore dd 0 |
/kernel/tags/kolibri0.6.5.0/core/sys32.inc |
---|
0,0 → 1,933 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; MenuetOS process management, protected ring3 ;; |
;; ;; |
;; Distributed under GPL. See file COPYING for details. ;; |
;; Copyright 2003 Ville Turjanmaa ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
idtreg: |
dw 8*0x41-1 |
dd idts+8 |
;label idts at 0xB100-8 |
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 |
dd e4,e5,e6,e7 |
dd e8,e9,e10,e11 |
dd e12,e13,page_fault_handler,e15 |
dd except_16, e17,e18, except_19 |
times 12 dd unknown_interrupt |
dd irq0 , irq_serv.irq_1, p_irq2 , p_irq3 ;irq_serv.irq_3 |
dd p_irq4 ,irq_serv.irq_5,p_irq6,irq_serv.irq_7 |
dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10 |
dd irq_serv.irq_11,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, 18 |
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 |
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 |
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 |
p_irq14: |
save_ring3_context |
mov ax, os_data |
mov ds, ax |
mov es, ax |
call [irq14_func] |
call ready_for_next_irq_1 |
restore_ring3_context |
iret |
p_irq15: |
save_ring3_context |
mov ax, os_data |
mov ds, ax |
mov es, ax |
call [irq15_func] |
call ready_for_next_irq_1 |
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 |
stdcall new_mem_resize, ebx |
mov [esp+36], eax |
ret |
.no_application_mem_resize: |
ret |
if 0 |
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 |
; \begin{diamond}[20.08.2006] |
; sanity check (functions 19,58 load app_i_end bytes and that must |
; fit in allocated memory to prevent kernel faults) |
cmp eax,[app_i_end] |
jb no_01_header |
; \end{diamond}[20.08.2006] |
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 |
clc |
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 |
; \begin{diamond}[20.08.2006] |
cmp eax,[app_i_end] |
jb no_01_header |
; \end{diamond}[20.08.2006] |
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 |
clc |
ret |
no_01_header: |
pop eax |
stc |
ret |
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 |
endg |
end if |
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 |
msg_obj_destroy db 'K : destroy app object',13,10,0 |
endg |
; param |
; esi= slot |
terminate: ; terminate application |
.slot equ esp ;locals |
push esi ;save .slot |
shl esi, 8 |
cmp [PROC_BASE+esi+APPDATA.dir_table], 0 |
jne @F |
add esp, 4 |
ret |
@@: |
mov esi,process_terminating |
call sys_msg_board_str |
@@: |
cli |
cmp [application_table_status],0 |
je term9 |
sti |
call change_task |
jmp @b |
term9: |
call set_application_table_status |
mov esi, [.slot] |
shl esi,8 |
add esi, PROC_BASE+APP_OBJ_OFFSET |
@@: |
mov eax, [esi+APPOBJ.fd] |
test eax, eax |
jz @F |
cmp eax, esi |
je @F |
push esi |
call [eax+APPOBJ.destroy] |
mov esi, msg_obj_destroy |
call sys_msg_board_str |
pop esi |
jmp @B |
@@: |
mov eax, [.slot] |
shl eax, 8 |
mov eax,[PROC_BASE+eax+APPDATA.dir_table] |
stdcall destroy_app_space, eax |
;; mov esi, [.slot] |
pop esi ;restore stack |
cmp [fpu_owner],esi ; if user fpu last -> fpu user = 1 |
jne fpu_ok_1 |
mov [fpu_owner],1 |
mov eax, [256+PROC_BASE+APPDATA.fpu_state] |
bt [cpu_caps], CAPS_SSE |
clts |
jnc .no_SSE |
fxrstor [eax] |
jmp fpu_ok_1 |
.no_SSE: |
fnclex |
frstor [eax] |
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 |
xor eax, eax |
mov [esi+WDATA.box.left],eax |
mov [esi+WDATA.box.width],eax |
mov [esi+WDATA.box.top],eax |
mov [esi+WDATA.box.height],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 |
; \begin{diamond}[19.09.2006] |
; skip minimized windows |
test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED |
jnz .check_next_window |
; \end{diamond} |
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 |
call free_hd_channel |
mov [hd1_status], 0 |
@@: |
cmp [cd_status], esi |
jnz @f |
call free_cd_channel |
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 |
restore .slot |
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/tags/kolibri0.6.5.0/core/taskman.inc |
---|
0,0 → 1,1157 |
GREEDY_KERNEL equ 0 |
struc APP_HEADER_00 |
{ .banner dq ? |
.version dd ? ;+8 |
.start dd ? ;+12 |
.i_end dd ? ;+16 |
.mem_size dd ? ;+20 |
.i_param dd ? ;+24 |
} |
struc APP_HEADER_01 |
{ .banner dq ? |
.version dd ? ;+8 |
.start dd ? ;+12 |
.i_end dd ? ;+16 |
.mem_size dd ? ;+20 |
.stack_top dd ? ;+24 |
.i_param dd ? ;+28 |
.i_icon dd ? ;+32 |
} |
struc TSS |
{ |
._back rw 2 |
._esp0 rd 1 |
._ss0 rw 2 |
._esp1 rd 1 |
._ss1 rw 2 |
._esp2 rd 1 |
._ss2 rw 2 |
._cr3 rd 1 |
._eip rd 1 |
._eflags rd 1 |
._eax rd 1 |
._ecx rd 1 |
._edx rd 1 |
._ebx rd 1 |
._esp rd 1 |
._ebp rd 1 |
._esi rd 1 |
._edi rd 1 |
._es rw 2 |
._cs rw 2 |
._ss rw 2 |
._ds rw 2 |
._fs rw 2 |
._gs rw 2 |
._ldt rw 2 |
._trap rw 1 |
._io rw 1 |
} |
virtual at 0 |
TSS TSS |
end virtual |
struc APP_PARAMS |
{ .app_cmdline ;0x00 |
.app_path ;0x04 |
.app_eip ;0x08 |
.app_esp ;0x0C |
.app_mem ;0x10 |
} |
macro _clear_ op |
{ mov ecx, op/4 |
xor eax, eax |
cld |
rep stosd |
} |
align 4 |
proc fs_exec stdcall file_name:dword, cmd_line:dword, flags:dword |
locals |
save_cr3 dd ? |
slot dd ? |
slot_base dd ? |
file_base dd ? |
file_size dd ? |
app_cmdline dd ? ;0x00 |
app_path dd ? ;0x04 |
app_eip dd ? ;0x08 |
app_esp dd ? ;0x0C |
app_mem dd ? ;0x10 |
app_i_end dd ? ;0x14 |
endl |
stdcall load_file,[file_name] |
mov ecx, -ERROR_FILE_NOT_FOUND |
test eax, eax |
jz .err_file |
mov [file_base], eax |
mov [file_size], ebx |
lea ebx, [app_cmdline] |
call test_app_header |
mov ecx, -0x1F |
test eax, eax |
jz .err_hdr |
mov esi, new_process_loading |
call sys_msg_board_str ; write message to message board |
.wait_lock: |
cmp [application_table_status],0 |
je .get_lock |
call change_task |
jmp .wait_lock |
.get_lock: |
mov eax, 1 |
xchg eax, [application_table_status] |
cmp eax, 0 |
jne .wait_lock |
pushfd |
cli |
call set_application_table_status |
call get_new_process_place |
test eax, eax |
mov ecx, -0x20 ; too many processes |
jz .err |
mov [slot], eax |
shl eax, 8 |
add eax, PROC_BASE |
mov [slot_base], eax |
mov edi, eax |
_clear_ 256 ;clean extended information about process |
; write application name |
mov edi, [file_name] |
mov al, '/' |
call k_strrchr ; now eax points to name without path |
lea esi, [eax+1] |
test eax, eax |
jnz @F |
mov esi, [file_name] |
@@: |
mov ecx, 8 ; 8 chars for name |
mov edi, [slot_base] |
.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 ebx, cr3 |
mov [save_cr3], ebx |
stdcall create_app_space,[app_mem],[file_base],[file_size] |
test eax, eax |
jz .failed |
mov ebx,[slot_base] |
mov [ebx+APPDATA.dir_table],eax |
mov eax,[app_mem] |
mov [ebx+APPDATA.mem_size],eax |
if not GREEDY_KERNEL |
mov ecx, [app_mem] |
mov edi, [file_size] |
add edi, 4095 |
and edi, not 4095 |
sub ecx, edi |
jna @F |
xor eax, eax |
add edi, new_app_base |
cld |
rep stosb |
@@: |
end if |
; release only virtual space, not phisical memory |
stdcall free_kernel_space, [file_base] |
lea eax, [app_cmdline] |
stdcall set_app_params ,[slot],eax,[cmd_line],\ |
[file_name], [flags] |
mov eax, [save_cr3] |
call set_cr3 |
popfd |
xor ebx, ebx |
mov [application_table_status],ebx ;unlock application_table_status mutex |
mov eax,[process_number] ;set result |
ret |
.failed: |
mov eax, [save_cr3] |
call set_cr3 |
.err: |
popfd |
.err_hdr: |
stdcall kernel_free,[file_base] |
.err_file: |
xor eax, eax |
mov [application_table_status],eax |
mov eax, ecx |
ret |
endp |
align 4 |
test_app_header: |
virtual at eax |
APP_HEADER_00 APP_HEADER_00 |
end virtual |
virtual at eax |
APP_HEADER_01 APP_HEADER_01 |
end virtual |
cmp dword [eax], 'MENU' |
jne .fail |
cmp word [eax+4],'ET' |
jne .fail |
cmp [eax+6], word '00' |
jne .check_01_header |
mov ecx,[APP_HEADER_00.start] |
mov [ebx+0x08], ecx ;app_eip |
mov edx,[APP_HEADER_00.mem_size] |
mov [ebx+0x10], edx ;app_mem |
shr edx,1 |
sub edx,0x10 |
mov [ebx+0x0C], edx ;app_esp |
mov ecx,[APP_HEADER_00.i_param] |
mov [ebx], ecx ;app_cmdline |
mov [ebx+4], dword 0 ;app_path |
mov edx, [APP_HEADER_00.i_end] |
mov [ebx+0x14], edx |
ret |
.check_01_header: |
cmp [eax+6],word '01' |
jne .fail |
mov ecx,[APP_HEADER_01.start] |
mov [ebx+0x08], ecx ;app_eip |
mov edx,[APP_HEADER_01.mem_size] |
mov [ebx+0x10], edx ;app_mem |
mov ecx,[APP_HEADER_01.stack_top] |
mov [ebx+0x0C], ecx ;app_esp |
mov edx,[APP_HEADER_01.i_param] |
mov [ebx], edx ;app_cmdline |
mov ecx,[APP_HEADER_01.i_icon] |
mov [ebx+4], ecx ;app_path |
mov edx, [APP_HEADER_01.i_end] |
mov [ebx+0x14], edx |
ret |
.fail: |
xor eax, eax |
ret |
align 4 |
proc get_new_process_place |
;input: |
; none |
;result: |
; eax=[new_process_place]<>0 - ok |
; 0 - failed. |
;This function find least empty slot. |
;It doesn't increase [TASK_COUNT]! |
mov eax,CURRENT_TASK |
mov ebx,[TASK_COUNT] |
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+0xa],9 ;check process state, 9 means that process slot is empty |
jnz .newprocessplace |
.endnewprocessplace: |
mov ebx,eax |
sub eax,CURRENT_TASK |
shr eax,5 ;calculate slot index |
cmp eax,256 |
jge .failed ;it should be <256 |
mov word [ebx+0xa],9 ;set process state to 9 (for slot after hight boundary) |
; mov [new_process_place], eax |
ret |
.failed: |
xor eax,eax |
ret |
endp |
align 4 |
proc create_app_space stdcall, app_size:dword,img_base:dword,img_size:dword |
locals |
app_pages dd ? |
img_pages dd ? |
dir_addr dd ? |
app_tabs dd ? |
endl |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
xor eax, eax |
mov [dir_addr], eax |
mov eax, [app_size] |
add eax, 4095 |
and eax, NOT(4095) |
mov [app_size], eax |
mov ebx, eax |
shr eax, 12 |
mov [app_pages], eax |
add ebx, 0x3FFFFF |
and ebx, NOT(0x3FFFFF) |
shr ebx, 22 |
mov [app_tabs], ebx |
mov ecx, [img_size] |
add ecx, 4095 |
and ecx, NOT(4095) |
mov [img_size], ecx |
shr ecx, 12 |
mov [img_pages], ecx |
if GREEDY_KERNEL |
lea eax, [ecx+ebx+2] ;only image size |
else |
lea eax, [eax+ebx+2] ;all requested memory |
end if |
cmp eax, [pg_data.pages_free] |
ja .fail |
call alloc_page |
test eax, eax |
jz .fail |
mov [dir_addr], eax |
stdcall map_page,[tmp_task_pdir],eax,dword PG_SW |
mov esi, sys_pgdir |
mov edi, [tmp_task_pdir] |
mov ecx, 384 |
cld |
rep movsd |
mov ecx, 384 |
xor eax, eax |
cld |
rep stosd |
mov ecx, 256 |
mov esi, sys_pgdir+0xc00 |
rep movsd |
mov eax, [dir_addr] |
or eax, PG_SW |
mov ebx, [tmp_task_pdir] |
mov [ebx+0x600], eax |
mov eax, [dir_addr] |
call set_cr3 |
mov edx, [app_tabs] |
mov edi, new_app_base |
@@: |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page_table, edi, eax |
add edi, 0x00400000 |
dec edx |
jnz @B |
mov edi, new_app_base |
shr edi, 10 |
add edi, pages_tab |
mov ecx, [app_tabs] |
shl ecx, 10 |
xor eax, eax |
rep stosd |
mov ecx, [img_pages] |
mov ebx, PG_UW |
mov edx, new_app_base |
mov esi, [img_base] |
mov edi, new_app_base |
shr esi, 10 |
shr edi, 10 |
add esi, pages_tab |
add edi, pages_tab |
.remap: |
lodsd |
or eax, ebx ; force user level r/w access |
stosd |
add edx, 0x1000 |
dec [app_pages] |
dec ecx |
jnz .remap |
mov ecx, [app_pages] |
test ecx, ecx |
jz .done |
if GREEDY_KERNEL |
mov eax, 0x02 |
.reserve: |
stosd |
invlpg [edx] |
add edx, 4096 |
dec ecx |
jnz .reserve |
else |
.alloc: |
call alloc_page |
test eax, eax |
jz .fail |
stdcall map_page,edx,eax,dword PG_UW |
add edx, 0x1000 |
dec [app_pages] |
jnz .alloc |
end if |
.done: |
stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP |
dec [pg_data.pg_mutex] |
mov eax, [dir_addr] |
ret |
.fail: |
dec [pg_data.pg_mutex] |
cmp [dir_addr], 0 |
jz @f |
stdcall destroy_app_space, [dir_addr] |
@@: |
xor eax, eax |
ret |
endp |
align 4 |
set_cr3: |
mov esi, [CURRENT_TASK] |
mov ebx, esi |
shl esi,8 |
mov [PROC_BASE+esi+0xB8],eax |
imul ebx,tss_step |
add ebx,tss_data |
mov [ebx+28], eax |
mov cr3, eax |
ret |
align 4 |
proc destroy_page_table stdcall, pg_tab:dword |
push esi |
mov esi, [pg_tab] |
mov ecx, 1024 |
.free: |
mov eax, [esi] |
test eax, 1 |
jz .next |
call free_page |
.next: |
add esi, 4 |
dec ecx |
jnz .free |
pop esi |
ret |
endp |
align 4 |
proc destroy_app_space stdcall, pg_dir:dword |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
xor edx,edx |
mov eax,0x2 |
mov ebx, [pg_dir] |
.loop: |
;eax = current slot of process |
mov ecx,eax |
shl ecx,5 |
cmp byte [CURRENT_TASK+ecx+0xa],9 ;if process running? |
jz @f ;skip empty slots |
shl ecx,3 |
cmp [PROC_BASE+ecx+0xB8],ebx ;compare page directory addresses |
jnz @f |
inc edx ;thread found |
@@: |
inc eax |
cmp eax,[TASK_COUNT] ;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 .exit |
;if there isn't threads then clear memory. |
mov eax, [pg_dir] |
and eax, not 0xFFF |
stdcall map_page,[tmp_task_pdir],eax,dword PG_SW |
mov esi, [tmp_task_pdir] |
add esi, 0x604 |
mov edi, 383 |
.destroy: |
mov eax, [esi] |
test eax, 1 |
jz .next |
and eax, not 0xFFF |
stdcall map_page,[tmp_task_ptab],eax,dword PG_SW |
stdcall destroy_page_table, [tmp_task_ptab] |
mov eax, [esi] |
call free_page |
.next: |
add esi, 4 |
dec edi |
jnz .destroy |
mov eax, [pg_dir] |
call free_page |
.exit: |
stdcall map_page,[tmp_task_ptab],dword 0,dword PG_UNMAP |
stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP |
dec [pg_data.pg_mutex] |
ret |
endp |
align 4 |
proc fs_execute |
;fn_read:dword, file_size:dword, cluster:dword |
; ebx - cmdline |
; edx - flags |
; ebp - full filename |
; [esp+4] = procedure DoRead, [esp+8] = filesize & [esp+12]... - arguments for it |
locals |
cmdline dd ? |
flags dd ? |
filename dd ? |
retval dd ? |
endl |
pushad |
mov [cmdline], ebx |
mov [flags], edx |
mov eax, [ebp] |
mov [filename], eax |
mov ebx, pg_data.tmp_task_mutex |
call wait_mutex ;ebx |
mov edi, [tmp_task_data] |
mov ecx, (1024+256)/4 |
xor eax, eax |
rep stosd |
mov esi, [filename] |
mov edi, [tmp_task_data] |
mov ecx, 1024 |
rep movsb |
mov esi, [cmdline] |
test esi, esi |
jz @f |
mov ecx, 256 |
rep movsb |
@@: |
mov eax, [tmp_task_data] |
lea ebx, [eax+1024] ;cmd line |
stdcall fs_exec, eax, ebx, [flags] |
mov [retval], eax |
popad |
mov [pg_data.tmp_task_mutex], 0 |
mov eax, [retval] |
ret |
endp |
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,[TASK_COUNT] |
shl ebx,5 |
mov ecx,2*32 |
.loop: |
;ecx=offset of current process info entry |
;ebx=maximum permitted offset |
cmp byte [CURRENT_TASK+ecx+0xa],9 |
jz .endloop ;skip empty slots |
cmp [CURRENT_TASK+ecx+0x4],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 |
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,[CURRENT_TASK] |
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 [CURRENT_TASK+eax+0xa],0 |
jnz .failed |
shl eax,3 |
mov eax,[PROC_BASE+eax+0xb8] |
test eax,eax |
jz .failed |
mov eax,1 |
ret |
; 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 |
align 4 |
proc 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. |
locals |
slot dd ? |
buff dd ? |
r_count dd ? |
offset dd ? |
tmp_r_cnt dd ? |
endl |
mov [slot], eax |
mov [buff], ebx |
mov [r_count], ecx |
mov [tmp_r_cnt], ecx |
mov [offset], edx |
pushad |
.read_mem: |
mov edx, [offset] |
mov ebx, [tmp_r_cnt] |
mov ecx, 0x400000 |
and edx, 0x3FFFFF |
sub ecx, edx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
cmp ecx, 0x8000 |
jna @F |
mov ecx, 0x8000 |
@@: |
mov eax, [slot] |
shl eax,8 |
mov ebx, [offset] |
add ebx, new_app_base |
push ecx |
stdcall map_memEx, [proc_mem_map],\ |
[PROC_BASE+eax+0xB8],\ |
ebx, ecx |
pop ecx |
mov esi, [offset] |
and esi, 0xfff |
add esi, [proc_mem_map] |
mov edi, [buff] |
mov edx, ecx |
rep movsb |
add [offset], edx |
sub [tmp_r_cnt], edx |
jnz .read_mem |
popad |
mov eax, [r_count] |
ret |
endp |
align 4 |
proc 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 |
locals |
slot dd ? |
buff dd ? |
w_count dd ? |
offset dd ? |
tmp_w_cnt dd ? |
endl |
mov [slot], eax |
mov [buff], ebx |
mov [w_count], ecx |
mov [tmp_w_cnt], ecx |
mov [offset], edx |
pushad |
.read_mem: |
mov edx, [offset] |
mov ebx, [tmp_w_cnt] |
mov ecx, 0x400000 |
and edx, 0x3FFFFF |
sub ecx, edx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
cmp ecx, 0x8000 |
jna @F |
mov ecx, 0x8000 |
@@: |
mov eax, [slot] |
shl eax,8 |
mov ebx, [offset] |
add ebx, new_app_base |
push ecx |
stdcall map_memEx, [proc_mem_map],\ |
[PROC_BASE+eax+0xB8],\ |
ebx, ecx |
pop ecx |
mov edi, [offset] |
and edi, 0xfff |
add edi, [proc_mem_map] |
mov esi, [buff] |
mov edx, ecx |
rep movsb |
add [offset], edx |
sub [tmp_w_cnt], edx |
jnz .read_mem |
popad |
mov eax, [w_count] |
ret |
endp |
align 4 |
proc new_sys_threads |
locals |
slot dd ? |
app_cmdline dd ? ;0x00 |
app_path dd ? ;0x04 |
app_eip dd ? ;0x08 |
app_esp dd ? ;0x0C |
app_mem dd ? ;0x10 |
endl |
cmp eax,1 |
jne .failed ;other subfunctions |
xor eax,eax |
mov [app_cmdline], eax |
mov [app_path], eax |
mov [app_eip], ebx |
mov [app_esp], ecx |
mov esi,new_process_loading |
call sys_msg_board_str |
.wait_lock: |
cmp [application_table_status],0 |
je .get_lock |
call change_task |
jmp .wait_lock |
.get_lock: |
mov eax, 1 |
xchg eax, [application_table_status] |
cmp eax, 0 |
jne .wait_lock |
call set_application_table_status |
call get_new_process_place |
test eax, eax |
jz .failed |
mov [slot], eax |
mov esi,[CURRENT_TASK] |
shl esi,8 |
add esi,PROC_BASE |
mov ebx,esi ;ebx=esi - pointer to extended information about current thread |
mov edi, eax |
shl edi,8 |
add edi,PROC_BASE |
mov edx,edi ;edx=edi - pointer to extended infomation about new thread |
mov ecx,256/4 |
xor eax, eax |
cld |
rep stosd ;clean extended information about new thread |
mov esi,ebx |
mov edi,edx |
mov ecx,11 |
rep movsb ;copy process name |
mov eax,[ebx+APPDATA.heap_base] |
mov [edx+APPDATA.heap_base], eax |
mov ecx,[ebx+APPDATA.heap_top] |
mov [edx+APPDATA.heap_top], ecx |
mov eax,[ebx+APPDATA.mem_size] |
mov [edx+APPDATA.mem_size], eax |
mov ecx,[ebx+APPDATA.dir_table] |
mov [edx+APPDATA.dir_table],ecx ;copy page directory |
lea eax, [app_cmdline] |
stdcall set_app_params ,[slot],eax,dword 0,\ |
dword 0,dword 0 |
mov esi,new_process_running |
call sys_msg_board_str ;output information about succefull startup |
mov [application_table_status],0 ;unlock application_table_status mutex |
mov eax,[process_number] ;set result |
ret |
.failed: |
mov [application_table_status],0 |
mov eax,-1 |
ret |
endp |
; param |
; ebx=mutex |
align 4 |
wait_mutex: |
push eax |
push ebx |
.do_wait: |
cmp dword [ebx],0 |
je .get_lock |
call change_task |
jmp .do_wait |
.get_lock: |
mov eax, 1 |
xchg eax, [ebx] |
test eax, eax |
jnz .do_wait |
pop ebx |
pop eax |
ret |
align 4 |
proc set_app_params stdcall,slot:dword, params:dword,\ |
cmd_line:dword, app_path:dword, flags:dword |
mov edi, [slot] |
mov esi, [fpu_data] |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
shl edi, 8 |
mov eax, edi |
lea edi, [esi+edi*2] |
mov [eax+PROC_BASE+APPDATA.fpu_state], edi |
mov [eax+PROC_BASE+APPDATA.fpu_handler], 0 |
mov [eax+PROC_BASE+APPDATA.sse_handler], 0 |
mov ecx, 512/4 |
jmp @F |
.no_SSE: |
mov eax, edi |
shl eax, 8 |
mov ebx, edi |
shl edi, 7 |
shl ebx, 4 |
sub edi, ebx ;edi*=112 |
add edi, esi |
mov [eax+PROC_BASE+APPDATA.fpu_state], edi |
mov [eax+PROC_BASE+APPDATA.fpu_handler], 0 |
mov [eax+PROC_BASE+APPDATA.sse_handler], 0 |
mov ecx, 112/4 |
@@: |
rep movsd |
mov ebx,[slot] |
cmp ebx,[TASK_COUNT] |
jle .noinc |
inc dword [TASK_COUNT] ;update number of processes |
.noinc: |
shl ebx,8 |
lea edx, [ebx+PROC_BASE+APP_OBJ_OFFSET] |
mov [PROC_BASE+APPDATA.fd_obj+ebx],edx |
mov [PROC_BASE+APPDATA.bk_obj+ebx],edx |
mov ecx, [def_cursor] |
mov [PROC_BASE+APPDATA.cursor+ebx],ecx |
shr ebx,3 |
mov eax, new_app_base |
mov dword [CURRENT_TASK+ebx+0x10],eax |
.add_command_line: |
mov edx,[params] |
mov edx,[edx] ;app_cmdline |
test edx,edx |
jz @F ;application don't need parameters |
mov eax, edx |
add eax, 256 |
jc @f |
cmp eax, [PROC_BASE+APPDATA.mem_size+ebx*8] |
ja @f |
add edx, new_app_base |
stdcall k_strncpy, edx, [cmd_line], 256 |
@@: |
mov edx,[params] |
mov edx, [edx+4] ;app_path |
test edx,edx |
jz @F ;application don't need path of file |
mov eax, edx |
add eax, 1024 |
jc @f |
cmp eax, [PROC_BASE+APPDATA.mem_size+ebx*8] |
ja @f |
add edx, new_app_base |
stdcall k_strncpy, edx, [app_path], 1024 |
@@: |
mov ebx,[slot] |
mov eax,ebx |
shl ebx,5 |
; set window state to 'normal' (non-minimized/maximized/rolled-up) state |
mov [ebx+window_data+WDATA.fl_wstate], WSTATE_NORMAL |
mov [ebx+window_data+WDATA.fl_redraw], 1 |
add ebx,CURRENT_TASK ;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+4],eax ;set PID |
mov ecx,ebx |
add ecx,(draw_data-CURRENT_TASK) ;ecx - pointer to draw data |
;set draw data to full screen |
mov [ecx+0],dword 0 |
mov [ecx+4],dword 0 |
mov eax,[SCR_X_SIZE] |
mov [ecx+8],eax |
mov eax,[SCR_Y_SIZE] |
mov [ecx+12],eax |
mov edi,[slot] |
imul edi,tss_step |
add edi,tss_data |
mov ecx,128/4 |
xor eax, eax |
cld |
rep stosd |
;Add IO access table - bit array of permitted ports |
not eax |
mov ecx,2048 |
rep stosd ; access to 4096*8=65536 ports |
sub edi, tss_step |
;set cr3 register in TSS of application |
mov ecx, [slot] |
shl ecx, 8 |
mov eax,[PROC_BASE+ecx+APPDATA.dir_table] |
mov [edi+TSS._cr3],eax |
mov esi,[params] |
mov eax, [esi+0x08] ;app_eip |
mov [edi+TSS._eip],eax ;set eip in TSS |
mov eax, [esi+0x0C] ;app_esp |
mov [edi+TSS._esp],eax ;set stack in TSS |
mov [edi+TSS._eflags],dword 0x1202 |
mov [edi+TSS._cs],app_code ;selector of code segment |
mov [edi+TSS._ss],app_data |
mov [edi+TSS._ds],app_data |
mov [edi+TSS._es],app_data |
mov [edi+TSS._fs],app_data |
mov [edi+TSS._gs],graph_data ;selector of graphic segment |
mov [edi+TSS._io],word 128 |
mov [edi+TSS._ss0], os_data |
mov ebx,[slot] |
shl ebx,12 |
add ebx,sysint_stack_data+4096 |
mov [edi+TSS._esp0],ebx |
mov ecx, edi ;ecx - address of application TSS |
mov ebx,[slot] |
shl ebx,3 |
;set TSS descriptor |
mov [ebx+gdts+tss0+0],word tss_step ;limit (size) |
mov [ebx+gdts+tss0+2],cx ;part of offset |
shr ecx,16 |
mov [ebx+gdts+tss0+4],cl ;part of offset |
mov [ebx+gdts+tss0+7],ch ;part of offset |
mov [ebx+gdts+tss0+5],word 01010000b*256+11101001b ;system flags |
;flush keyboard and buttons queue |
mov [KEY_COUNT],byte 0 |
mov [BTN_COUNT],byte 0 |
mov edi,[slot] |
shl edi,5 |
add edi,window_data |
mov ebx,[slot] |
movzx esi,word [WIN_STACK+ebx*2] |
lea esi,[WIN_POS+esi*2] |
call windowactivate ;gui initialization |
mov ebx,[slot] |
shl ebx,5 |
mov [CURRENT_TASK+ebx+0xa],byte 0 ;set process state - running |
; set if debuggee |
mov eax, [flags] |
test byte [flags], 1 |
jz .no_debug |
mov [CURRENT_TASK+ebx+0xa],byte 1 ;set process state - suspended |
mov eax,[CURRENT_TASK] |
mov [PROC_BASE+ebx*8+0xac],eax ;set debugger PID - current |
.no_debug: |
mov esi,new_process_running |
call sys_msg_board_str ;output information about succefull startup |
ret |
endp |
include "debug.inc" |
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 |
/kernel/tags/kolibri0.6.5.0/core/memory.inc |
---|
0,0 → 1,1667 |
tmp_page_tab equ 0x00C00000 |
align 4 |
proc mem_test |
mov eax, cr0 |
and eax, not (CR0_CD+CR0_NW) |
or eax, CR0_CD ;disable caching |
mov cr0, eax |
wbinvd ;invalidate cache |
xor edi, edi |
mov ebx, 'TEST' |
@@: |
add edi, 0x400000 |
xchg ebx, dword [edi] |
cmp dword [edi], 'TEST' |
xchg ebx, dword [edi] |
je @b |
and eax, not (CR0_CD+CR0_NW) ;enable caching |
mov cr0, eax |
mov eax, edi |
mov [LFBSize], 0x00800000 |
ret |
endp |
align 4 |
proc init_memEx |
xor eax, eax |
mov edi, sys_pgdir |
mov ecx, 2048 |
rep stosd |
bt [cpu_caps], CAPS_PSE |
jnc .no_PSE |
mov ebx, cr4 |
or ebx, CR4_PSE |
mov eax, PG_LARGE+PG_SW |
bt [cpu_caps], CAPS_PGE |
jnc @F |
or eax, PG_GLOBAL |
or ebx, CR4_PGE |
@@: |
mov cr4, ebx |
mov dword [sys_pgdir], eax |
add eax, 0x00400000 |
mov dword [sys_pgdir+4], eax |
add eax, 0x00400000 |
mov dword [sys_pgdir+8], eax |
mov dword [sys_pgdir+0x600], sys_pgdir+PG_SW |
mov ecx, [pg_data.kernel_tables] |
sub ecx, 3 ;4 |
mov eax, tmp_page_tab+PG_SW |
mov edi, sys_pgdir+12 ;16 |
jmp .map_kernel_tabs |
.no_PSE: |
mov eax, PG_SW |
mov esi, tmp_page_tab |
mov ecx, 3072/4; 4096/4 ;0x0 - 0x00FFFFFF |
.map_low: |
mov [esi], eax |
add eax, 0x1000 |
mov [esi+4], eax |
add eax, 0x1000 |
mov [esi+8], eax |
add eax, 0x1000 |
mov [esi+12], eax |
add eax, 0x1000 |
add esi, 16 |
dec ecx |
jnz .map_low ;ÿäðî |
mov ecx, [pg_data.kernel_tables] |
mov eax, tmp_page_tab+PG_SW |
mov edi, sys_pgdir |
.map_kernel_tabs: |
mov [edi], eax |
add eax, 0x1000 |
add edi, 4 |
dec ecx |
jnz .map_kernel_tabs |
mov edi, tmp_page_tab |
bt [cpu_caps], CAPS_PSE |
jc @F |
add edi, 3072*4 ;4096*4 ;skip low kernel memory |
@@: |
mov ecx, [pg_data.kernel_tables] |
sub ecx, 3 |
shl ecx, 10 |
xor eax, eax |
cld |
rep stosd |
mov dword [sys_pgdir+0x600], sys_pgdir+PG_SW |
ret |
endp |
align 4 |
proc init_page_map |
mov edi, sys_pgmap |
mov ecx, 384/4 |
xor eax,eax |
cld |
rep stosd |
not eax |
mov ecx, [pg_data.pagemap_size] |
sub ecx, 384 |
shr ecx, 2 |
rep stosd |
mov edi, sys_pgmap+384 |
mov edx, [pg_data.pages_count] |
mov ecx, [pg_data.kernel_tables] |
bt [cpu_caps], CAPS_PSE |
jnc @f |
sub ecx, 3 |
@@: |
sub edx, 3072 |
sub edx, ecx |
mov [pg_data.pages_free], edx |
xor eax, eax |
mov ebx, ecx |
shr ecx, 5 |
rep stosd |
not eax |
mov ecx, ebx |
and ecx, 31 |
shl eax, cl |
stosd |
mov [page_start], sys_pgmap+384 |
mov ebx, sys_pgmap |
add ebx, [pg_data.pagemap_size] |
mov [page_end], ebx |
mov [pg_data.pg_mutex], 0 |
ret |
endp |
align 4 |
proc alloc_page |
pushfd |
cli |
mov ebx, [page_start] |
mov ecx, [page_end] |
.l1: |
bsf eax,[ebx]; |
jnz .found |
add ebx,4 |
cmp ebx, ecx |
jb .l1 |
popfd |
xor eax,eax |
ret |
.found: |
btr [ebx], eax |
mov [page_start],ebx |
sub ebx, sys_pgmap |
lea eax, [eax+ebx*8] |
shl eax, 12 |
dec [pg_data.pages_free] |
popfd |
ret |
endp |
align 4 |
proc alloc_pages stdcall, count:dword |
pushfd |
cli |
mov eax, [count] |
add eax, 7 |
shr eax, 3 |
mov [count], eax |
cmp eax, [pg_data.pages_free] |
ja .fail |
mov ecx, [page_start] |
mov ebx, [page_end] |
.find: |
mov edx, [count] |
mov edi, ecx |
.match: |
cmp byte [ecx], 0xFF |
jne .next |
dec edx |
jz .ok |
inc ecx |
cmp ecx,ebx |
jb .match |
.fail: xor eax, eax |
popfd |
ret |
.next: |
inc ecx |
cmp ecx, ebx |
jb .find |
popfd |
xor eax, eax |
ret |
.ok: |
sub ecx, edi |
inc ecx |
mov esi, edi |
xor eax, eax |
rep stosb |
sub esi, sys_pgmap |
shl esi, 3+12 |
mov eax, esi |
mov ebx, [count] |
shl ebx, 3 |
sub [pg_data.pages_free], ebx |
popfd |
ret |
endp |
align 4 |
proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword |
push ebx |
mov eax, [phis_addr] |
and eax, not 0xFFF |
or eax, [flags] |
mov ebx, [lin_addr] |
shr ebx, 12 |
mov [pages_tab+ebx*4], eax |
mov eax, [lin_addr] |
invlpg [eax] |
pop ebx |
ret |
endp |
align 4 |
map_space: ;not implemented |
ret |
align 4 |
proc free_page |
;arg: eax page address |
pushfd |
cli |
shr eax, 12 ;page index |
mov ebx, sys_pgmap |
bts [ebx], eax ;that's all! |
cmc |
adc [pg_data.pages_free], 0 |
shr eax, 3 |
and eax, not 3 ;dword offset from page_map |
add eax, ebx |
cmp [page_start], eax |
ja @f |
popfd |
ret |
@@: |
mov [page_start], eax |
popfd |
ret |
endp |
; param |
; eax= page base + page flags |
; ebx= liear address |
; ecx= count |
align 4 |
commit_pages: |
test ecx, ecx |
jz .fail |
mov edi, ebx |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
mov edx, 0x1000 |
mov ebx, edi |
shr ebx, 12 |
@@: |
mov [pages_tab+ebx*4], eax |
invlpg [edi] |
add edi, edx |
add eax, edx |
inc ebx |
dec ecx |
jnz @B |
mov [pg_data.pg_mutex],ecx |
.fail: |
ret |
; param |
; eax= base |
; ecx= count |
align 4 |
release_pages: |
pushad |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
mov esi, eax |
mov edi, eax |
shr esi, 10 |
add esi, pages_tab |
mov ebp, [pg_data.pages_free] |
mov ebx, [page_start] |
mov edx, sys_pgmap |
@@: |
xor eax, eax |
xchg eax, [esi] |
invlpg [edi] |
test eax, 1 |
jz .next |
shr eax, 12 |
bts [edx], eax |
cmc |
adc ebp, 0 |
shr eax, 3 |
and eax, -4 |
add eax, edx |
cmp eax, ebx |
jae .next |
mov ebx, eax |
.next: |
add edi, 0x1000 |
add esi, 4 |
dec ecx |
jnz @B |
mov [pg_data.pages_free], ebp |
and [pg_data.pg_mutex],0 |
popad |
ret |
align 4 |
proc map_page_table stdcall, lin_addr:dword, phis_addr:dword |
push ebx |
mov ebx, [lin_addr] |
shr ebx, 22 |
mov eax, [phis_addr] |
and eax, not 0xFFF |
or eax, PG_UW ;+PG_NOCACHE |
mov dword [current_pgdir+ebx*4], eax |
mov eax, [lin_addr] |
shr eax, 10 |
add eax, pages_tab |
invlpg [eax] |
pop ebx |
ret |
endp |
align 4 |
proc init_LFB |
cmp dword [LFBAddress], -1 |
jne @f |
mov [0x2f0000+0x901c],byte 2 |
stdcall kernel_alloc, 0x280000 |
mov [LFBAddress], eax |
ret |
@@: |
test [SCR_MODE],word 0100000000000000b |
jnz @f |
mov [0x2f0000+0x901c],byte 2 |
ret |
@@: |
call map_LFB |
ret |
endp |
align 4 |
proc map_LFB |
locals |
pg_count dd ? |
endl |
mov edi, [LFBSize] |
mov esi, [LFBAddress] |
mov dword [exp_lfb+4], esi |
shr edi, 12 |
mov [pg_count], edi |
shr edi, 10 |
bt [cpu_caps], CAPS_PSE |
jnc .map_page_tables |
mov ebx, esi |
or esi, PG_LARGE+PG_UW |
shr ebx, 20 |
mov ecx, ebx |
@@: |
mov [sys_pgdir+ebx], esi |
add ebx, 4 |
add esi, 0x00400000 |
dec edi |
jnz @B |
bt [cpu_caps], CAPS_PGE |
jnc @F |
or dword [sys_pgdir+ecx], PG_GLOBAL |
@@: |
mov eax, cr3 ;flush TLB |
mov cr3, eax |
ret |
.map_page_tables: |
@@: |
call alloc_page |
stdcall map_page_table, esi, eax |
add esi, 0x00400000 |
dec edi |
jnz @B |
mov eax, [LFBAddress] |
mov esi, eax |
shr esi, 10 |
add esi, pages_tab |
or eax, PG_UW |
mov ecx, [pg_count] |
shr ecx, 2 |
.map: |
mov [esi], eax |
add eax, 0x1000 |
mov [esi+4], eax |
add eax, 0x1000 |
mov [esi+8], eax |
add eax, 0x1000 |
mov [esi+12], eax |
add eax, 0x1000 |
add esi, 16 |
sub ecx, 1 |
jnz .map |
mov eax, cr3 ;flush TLB |
mov cr3, eax |
ret |
endp |
align 4 |
proc new_mem_resize stdcall, new_size:dword |
mov ebx, pg_data.pg_mutex |
call wait_mutex ;ebx |
mov edi, [new_size] |
add edi,4095 |
and edi,not 4095 |
mov [new_size], edi |
mov edx,[CURRENT_TASK] |
shl edx,8 |
cmp [PROC_BASE+APPDATA.heap_base+edx],0 |
jne .exit |
mov esi, [PROC_BASE+APPDATA.mem_size+edx] |
add esi, 4095 |
and esi, not 4095 |
cmp edi, esi |
jae .expand |
shr edi, 12 |
shr esi, 12 |
@@: |
mov eax, [pages_tab+0x00181000+edi*4] |
test eax, 1 |
jz .next |
mov dword [pages_tab+0x00181000+edi*4], 2 |
mov ebx, edi |
shl ebx, 12 |
invlpg [ebx+std_application_base_address] |
call free_page |
.next: add edi, 1 |
cmp edi, esi |
jb @B |
.update_size: |
mov ebx, [new_size] |
call update_mem_size |
xor eax, eax |
dec [pg_data.pg_mutex] |
ret |
.expand: |
add edi, new_app_base |
add esi, new_app_base |
push esi |
push edi |
add edi, 0x3FFFFF |
and edi, not(0x3FFFFF) |
add esi, 0x3FFFFF |
and esi, not(0x3FFFFF) |
cmp esi, edi |
jae .grow |
xchg esi, edi |
@@: |
call alloc_page |
test eax, eax |
jz .exit |
stdcall map_page_table, edi, eax |
push edi |
shr edi, 10 |
add edi, pages_tab |
mov ecx, 1024 |
xor eax, eax |
cld |
rep stosd |
pop edi |
add edi, 0x00400000 |
cmp edi, esi |
jb @B |
.grow: |
pop edi |
pop esi |
@@: |
call alloc_page |
test eax, eax |
jz .exit |
stdcall map_page,esi,eax,dword PG_UW |
push edi |
mov edi, esi |
xor eax, eax |
mov ecx, 1024 |
cld |
rep stosd |
pop edi |
add esi, 0x1000 |
cmp esi, edi |
jb @B |
jmp .update_size |
.exit: |
xor eax, eax |
inc eax |
dec [pg_data.pg_mutex] |
ret |
endp |
update_mem_size: |
; in: edx = slot shl 8 |
; ebx = new memory size |
; destroys eax,ecx,edx |
mov [PROC_BASE+APPDATA.mem_size+edx],ebx |
;search threads and update |
;application memory size infomation |
mov ecx,[PROC_BASE+APPDATA.dir_table+edx] |
mov eax,2 |
.search_threads: |
;eax = current slot |
;ebx = new memory size |
;ecx = page directory |
cmp eax,[TASK_COUNT] |
jg .search_threads_end |
mov edx,eax |
shl edx,5 |
cmp word [CURRENT_TASK+edx+TASKDATA.state],9 ;if slot empty? |
jz .search_threads_next |
shl edx,3 |
cmp [PROC_BASE+edx+APPDATA.dir_table],ecx ;if it is our thread? |
jnz .search_threads_next |
mov [PROC_BASE+edx+APPDATA.mem_size],ebx ;update memory size |
.search_threads_next: |
inc eax |
jmp .search_threads |
.search_threads_end: |
ret |
; param |
; eax= linear address |
; |
; retval |
; eax= phisical page address |
align 4 |
get_pg_addr: |
shr eax, 12 |
mov eax, [pages_tab+eax*4] |
and eax, 0xFFFFF000 |
ret |
align 4 |
proc page_fault_handler |
pushad |
mov ebp, esp |
mov eax, cr2 |
push eax |
push ds |
push es |
mov ax, 0x10 |
mov ds, ax |
mov es, ax |
inc [pg_data.pages_faults] |
mov ebx, [ebp-4] |
cmp ebx, 0xe0000000 |
jae .lfb_addr |
cmp ebx, 0x60400000 |
jae .user_space |
cmp ebx, master_tab+0x1000 |
jae .alloc |
cmp ebx, 0x60000000 |
jae .tab_space |
jmp .kernel_space |
.user_space: |
shr ebx, 12 |
mov ecx, ebx |
shr ecx, 10 |
mov edx, [master_tab+ecx*4] |
test edx, 1 |
jz .fail |
mov eax, [pages_tab+ebx*4] |
test eax, 2 |
jz .fail |
.alloc: |
call alloc_page |
and eax, eax |
jz .exit |
stdcall map_page,[ebp-4],eax,dword PG_UW |
mov edi, [ebp-4] |
and edi, 0xFFFFF000 |
mov ecx, 1024 |
xor eax, eax |
cld |
rep stosd |
.exit: |
pop es |
pop ds |
mov esp, ebp |
popad |
add esp, 4 |
iretd |
.fail: |
pop es |
pop ds |
mov esp, ebp |
popad |
add esp, 4 |
save_ring3_context ;debugger support |
mov bl, 14 |
jmp exc_c |
iretd |
.kernel_space: |
; shr ebx, 12 |
; mov eax, [pages_tab+ebx*4] |
; shr ebx, 10 |
; mov eax, [master_tab+ebx*4] |
jmp .exit |
.old_addr: |
; shr ebx, 12 |
; mov eax, [pages_tab+ebx*4] |
; shr ebx, 10 |
; mov eax, [master_tab+ebx*4] |
jmp .exit |
.lfb_addr: |
; shr ebx, 22 |
; ;mov ecx, [sys_page_dir] |
; mov eax, [master_tab+ebx*4] |
jmp .exit |
.tab_space: |
; shr ebx, 12 |
; mov eax, [pages_tab+ebx*4] |
; shr ebx, 10 |
; ;mov ecx, [sys_page_dir] |
; mov eax, [master_tab+ebx*4] |
jmp .exit |
endp |
align 4 |
proc map_mem stdcall, lin_addr:dword,pdir:dword,\ |
ofs:dword,buf_size:dword |
mov eax, [buf_size] |
test eax, eax |
jz .exit |
mov eax, [pdir] |
and eax, 0xFFFFF000 |
stdcall map_page,[ipc_pdir],eax,dword PG_UW |
mov ebx, [ofs] |
shr ebx, 22 |
mov esi, [ipc_pdir] |
mov edi, [ipc_ptab] |
mov eax, [esi+ebx*4] |
and eax, 0xFFFFF000 |
test eax, eax |
jz .exit |
stdcall map_page,edi,eax,dword PG_UW |
; inc ebx |
; add edi, 0x1000 |
; mov eax, [esi+ebx*4] |
; test eax, eax |
; jz @f |
; and eax, 0xFFFFF000 |
; stdcall map_page, edi, eax |
@@: mov edi, [lin_addr] |
and edi, 0xFFFFF000 |
mov ecx, [buf_size] |
add ecx, 4095 |
shr ecx, 12 |
inc ecx |
mov edx, [ofs] |
shr edx, 12 |
and edx, 0x3FF |
mov esi, [ipc_ptab] |
.map: mov eax, [esi+edx*4] |
and eax, 0xFFFFF000 |
test eax, eax |
jz .exit |
stdcall map_page,edi,eax,dword PG_UW |
add edi, 0x1000 |
inc edx |
dec ecx |
jnz .map |
.exit: |
ret |
endp |
align 4 |
proc map_memEx stdcall, lin_addr:dword,pdir:dword,\ |
ofs:dword,buf_size:dword |
mov eax, [buf_size] |
test eax, eax |
jz .exit |
mov eax, [pdir] |
and eax, 0xFFFFF000 |
stdcall map_page,[proc_mem_pdir],eax,dword PG_UW |
mov ebx, [ofs] |
shr ebx, 22 |
mov esi, [proc_mem_pdir] |
mov edi, [proc_mem_tab] |
mov eax, [esi+ebx*4] |
and eax, 0xFFFFF000 |
test eax, eax |
jz .exit |
stdcall map_page,edi,eax,dword PG_UW |
@@: mov edi, [lin_addr] |
and edi, 0xFFFFF000 |
mov ecx, [buf_size] |
add ecx, 4095 |
shr ecx, 12 |
inc ecx |
mov edx, [ofs] |
shr edx, 12 |
and edx, 0x3FF |
mov esi, [proc_mem_tab] |
.map: mov eax, [esi+edx*4] |
; and eax, 0xFFFFF000 |
; test eax, eax |
; jz .exit |
stdcall map_page,edi,eax,dword PG_UW |
add edi, 0x1000 |
inc edx |
dec ecx |
jnz .map |
.exit: |
ret |
endp |
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 |
jne @f |
call set_ipc_buff |
mov [esp+36], eax |
ret |
@@: |
cmp eax, 2 |
jne @f |
stdcall sys_ipc_send, ebx, ecx, edx |
mov [esp+36], eax |
ret |
@@: |
xor eax, eax |
not eax |
mov [esp+36], eax |
ret |
align 4 |
proc set_ipc_buff |
mov eax,[CURRENT_TASK] |
shl eax,8 |
add eax, PROC_BASE |
pushf |
cli |
mov [eax+0xA0],ebx ;set fields in extended information area |
mov [eax+0xA4],ecx |
add ebx, new_app_base |
add ecx, ebx |
add ecx, 4095 |
and ecx, not 4095 |
.touch: mov eax, [ebx] |
add ebx, 0x1000 |
cmp ebx, ecx |
jna .touch |
popf |
xor eax, eax |
ret |
endp |
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword |
locals |
dst_slot dd ? |
dst_offset dd ? |
buf_size dd ? |
endl |
pushf |
cli |
mov eax, [PID] |
call pid_to_slot |
test eax,eax |
jz .no_pid |
mov [dst_slot], eax |
shl eax,8 |
mov edi,[eax+PROC_BASE+0xa0] ;is ipc area defined? |
test edi,edi |
jz .no_ipc_area |
mov ebx, edi |
add edi, new_app_base |
and ebx, 0xFFF |
mov [dst_offset], ebx |
mov esi, [eax+PROC_BASE+0xa4] |
mov [buf_size], esi |
stdcall map_mem, [ipc_tmp], [PROC_BASE+eax+0xB8],\ |
edi, esi |
mov edi, [dst_offset] |
add edi, [ipc_tmp] |
cmp dword [edi], 0 |
jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now |
mov ebx, dword [edi+4] |
mov edx, ebx |
add ebx, 8 |
add ebx, [msg_size] |
cmp ebx, [buf_size] |
ja .buffer_overflow ;esi<0 - not enough memory in buffer |
mov dword [edi+4], ebx |
mov eax,[TASK_BASE] |
mov eax, [eax+0x04] ;eax - our PID |
mov edi, [dst_offset] |
add edi, [ipc_tmp] |
add edi, edx |
mov [edi], eax |
mov ecx, [msg_size] |
mov [edi+4], ecx |
add edi, 8 |
mov esi, [msg_addr] |
add esi, new_app_base |
cld |
rep movsb |
mov ebx, [ipc_tmp] |
mov edx, ebx |
shr ebx, 12 |
xor eax, eax |
mov [pages_tab+ebx*4], eax |
invlpg [edx] |
mov ebx, [ipc_pdir] |
mov edx, ebx |
shr ebx, 12 |
xor eax, eax |
mov [pages_tab+ebx*4], eax |
invlpg [edx] |
mov ebx, [ipc_ptab] |
mov edx, ebx |
shr ebx, 12 |
xor eax, eax |
mov [pages_tab+ebx*4], eax |
invlpg [edx] |
mov eax, [dst_slot] |
shl eax, 8 |
or [eax+PROC_BASE+0xA8],dword 0x40 |
cmp dword [check_idle_semaphore],20 |
jge .ipc_no_cis |
mov dword [check_idle_semaphore],5 |
.ipc_no_cis: |
popf |
xor eax, eax |
ret |
.no_pid: |
popf |
mov eax, 4 |
ret |
.no_ipc_area: |
popf |
xor eax, eax |
inc eax |
ret |
.ipc_blocked: |
popf |
mov eax, 2 |
ret |
.buffer_overflow: |
popf |
mov eax, 3 |
ret |
endp |
align 4 |
sysfn_meminfo: |
add ebx, new_app_base |
cmp ebx, new_app_base |
jb .fail |
mov eax, [pg_data.pages_count] |
mov [ebx], eax |
shl eax, 12 |
mov [esp+36], eax |
mov ecx, [pg_data.pages_free] |
mov [ebx+4], ecx |
mov edx, [pg_data.pages_faults] |
mov [ebx+8], edx |
mov esi, [heap_size] |
mov [ebx+12], esi |
mov edi, [heap_free] |
mov [ebx+16], edi |
mov eax, [heap_blocks] |
mov [ebx+20], eax |
mov ecx, [free_blocks] |
mov [ebx+24], ecx |
ret |
.fail: |
mov dword [esp+36], -1 |
ret |
align 4 |
new_services: |
cmp eax,4 |
jle sys_sheduler |
cmp eax, 11 |
jb .fail |
ja @f |
call init_heap |
mov [esp+36], eax |
ret |
@@: |
cmp eax, 12 |
ja @f |
stdcall user_alloc, ebx |
mov [esp+36], eax |
ret |
@@: |
cmp eax, 13 |
ja @f |
add ebx, new_app_base |
stdcall user_free, ebx |
mov [esp+36], eax |
ret |
@@: |
cmp eax, 14 |
ja @f |
add ebx, new_app_base |
cmp ebx, new_app_base |
jb .fail |
stdcall get_event_ex, ebx, ecx |
mov [esp+36], eax |
ret |
@@: |
cmp eax, 15 |
ja @f |
mov ecx, [CURRENT_TASK] |
shl ecx, 8 |
mov eax, [ecx+PROC_BASE+APPDATA.fpu_handler] |
mov [ecx+PROC_BASE+APPDATA.fpu_handler], ebx |
mov [esp+36], eax |
ret |
@@: |
cmp eax, 16 |
ja @f |
test ebx, ebx |
jz .fail |
add ebx, new_app_base |
cmp ebx, new_app_base |
jb .fail |
stdcall get_service, ebx |
mov [esp+36], eax |
ret |
@@: |
cmp eax, 17 |
ja @f |
stdcall srv_handlerEx, ebx |
mov [esp+36], eax |
ret |
@@: |
cmp eax, 18 |
ja @f |
mov ecx, [CURRENT_TASK] |
shl ecx, 8 |
mov eax, [ecx+PROC_BASE+APPDATA.sse_handler] |
mov [ecx+PROC_BASE+APPDATA.sse_handler], ebx |
mov [esp+36], eax |
ret |
@@: |
cmp eax, 19 |
ja .fail |
add ebx, new_app_base |
cmp ebx, new_app_base |
jb .fail |
stdcall load_library, ebx |
mov [esp+36], eax |
ret |
.fail: |
xor eax, eax |
mov [esp+36], eax |
ret |
align 4 |
proc strncmp stdcall, str1:dword, str2:dword, count:dword |
mov ecx,[count] |
jecxz .end |
mov ebx,ecx |
mov edi,[str1] |
mov esi,edi |
xor eax,eax |
repne scasb |
neg ecx ; cx = count - strlen |
add ecx,ebx ; strlen + count - strlen |
.okay: |
mov edi,esi |
mov esi,[str2] |
repe cmpsb |
mov al,[esi-1] |
xor ecx,ecx |
cmp al,[edi-1] |
ja .str2_big |
je .end |
.str1_big: |
sub ecx,2 |
.str2_big: |
not ecx |
.end: |
mov eax,ecx |
ret |
endp |
align 4 |
proc test_cpu |
locals |
cpu_type dd ? |
cpu_id dd ? |
cpu_Intel dd ? |
cpu_AMD dd ? |
endl |
mov [cpu_type], 0 |
xor eax, eax |
mov [cpu_caps], eax |
mov [cpu_caps+4], eax |
pushfd |
pop eax |
mov ecx, eax |
xor eax, 0x40000 |
push eax |
popfd |
pushfd |
pop eax |
xor eax, ecx |
mov [cpu_type], CPU_386 |
jz .end_cpuid |
push ecx |
popfd |
mov [cpu_type], CPU_486 |
mov eax, ecx |
xor eax, 0x200000 |
push eax |
popfd |
pushfd |
pop eax |
xor eax, ecx |
je .end_cpuid |
mov [cpu_id], 1 |
xor eax, eax |
cpuid |
mov [cpu_vendor], ebx |
mov [cpu_vendor+4], edx |
mov [cpu_vendor+8], ecx |
cmp ebx, dword [intel_str] |
jne .check_AMD |
cmp edx, dword [intel_str+4] |
jne .check_AMD |
cmp ecx, dword [intel_str+8] |
jne .check_AMD |
mov [cpu_Intel], 1 |
cmp eax, 1 |
jl .end_cpuid |
mov eax, 1 |
cpuid |
mov [cpu_sign], eax |
mov [cpu_info], ebx |
mov [cpu_caps], edx |
mov [cpu_caps+4],ecx |
shr eax, 8 |
and eax, 0x0f |
ret |
.end_cpuid: |
mov eax, [cpu_type] |
ret |
.check_AMD: |
cmp ebx, dword [AMD_str] |
jne .unknown |
cmp edx, dword [AMD_str+4] |
jne .unknown |
cmp ecx, dword [AMD_str+8] |
jne .unknown |
mov [cpu_AMD], 1 |
cmp eax, 1 |
jl .unknown |
mov eax, 1 |
cpuid |
mov [cpu_sign], eax |
mov [cpu_info], ebx |
mov [cpu_caps], edx |
mov [cpu_caps+4],ecx |
shr eax, 8 |
and eax, 0x0f |
ret |
.unknown: |
mov eax, 1 |
cpuid |
mov [cpu_sign], eax |
mov [cpu_info], ebx |
mov [cpu_caps], edx |
mov [cpu_caps+4],ecx |
shr eax, 8 |
and eax, 0x0f |
ret |
endp |
MEM_WB equ 6 ;write-back memory |
MEM_WC equ 1 ;write combined memory |
MEM_UC equ 0 ;uncached memory |
align 4 |
proc init_mtrr |
cmp [0x2f0000+0x901c],byte 2 |
je .exit |
bt [cpu_caps], CAPS_MTRR |
jnc .exit |
mov eax, cr0 |
or eax, 0x60000000 ;disable caching |
mov cr0, eax |
wbinvd ;invalidate cache |
mov ecx, 0x2FF |
rdmsr ; |
push eax |
xor edx, edx |
xor eax, eax |
mov ecx, 0x2FF |
wrmsr ;disable all MTRR |
stdcall set_mtrr, dword 0,dword 0,[MEM_AMOUNT],MEM_WB |
stdcall set_mtrr, dword 1,[LFBAddress],[LFBSize],MEM_WC |
xor edx, edx |
xor eax, eax |
mov ecx, 0x204 |
mov ebx, 6 |
@@: |
wrmsr ;disable unused MTRR |
inc ecx |
wrmsr |
inc ecx |
dec ebx |
jnz @b |
wbinvd ;again invalidate |
pop eax |
or eax, 0x800 ;set default memtype to UC |
and al, 0xF0 |
mov ecx, 0x2FF |
wrmsr ;and enable MTRR |
mov eax, cr0 |
and eax, not 0x60000000 |
mov cr0, eax ; enable caching |
.exit: |
ret |
endp |
align 4 |
proc set_mtrr stdcall, reg:dword,base:dword,size:dword,mem_type:dword |
xor edx, edx |
mov eax, [base] |
or eax, [mem_type] |
mov ecx, [reg] |
lea ecx, [0x200+ecx*2] |
wrmsr |
mov ebx, [size] |
dec ebx |
mov eax, 0xFFFFFFFF |
mov edx, 0x0000000F |
sub eax, ebx |
sbb edx, 0 |
or eax, 0x800 |
inc ecx |
wrmsr |
ret |
endp |
align 4 |
proc stall stdcall, delay:dword |
push ecx |
push edx |
push ebx |
push eax |
mov eax, [delay] |
mul [stall_mcs] |
mov ebx, eax ;low |
mov ecx, edx ;high |
rdtsc |
add ebx, eax |
adc ecx,edx |
@@: |
rdtsc |
sub eax, ebx |
sbb edx, ecx |
jb @B |
pop eax |
pop ebx |
pop edx |
pop ecx |
ret |
endp |
iglobal |
align 4 |
intel_str db "GenuineIntel",0 |
AMD_str db "AuthenticAMD",0 |
endg |
uglobal |
align 16 |
irq_tab rd 16 |
MEM_FreeSpace rd 1 |
ipc_tmp rd 1 |
ipc_pdir rd 1 |
ipc_ptab rd 1 |
proc_mem_map rd 1 |
proc_mem_pdir rd 1 |
proc_mem_tab rd 1 |
tmp_task_pdir rd 1 |
tmp_task_ptab rd 1 |
tmp_task_data rd 1 |
fpu_data rd 1 |
fdd_buff rd 1 |
LFBSize rd 1 |
stall_mcs rd 1 |
;;CPUID information |
cpu_vendor rd 3 |
cpu_sign rd 1 |
cpu_info rd 1 |
;;;;; cursors data |
align 16 |
cur_saved_data rb 4096 |
;cursors rb CURSOR_SIZE*64 |
;cursor_map rd 2 |
;cursor_start rd 1 |
;cursor_end rd 1 |
def_cursor rd 1 |
hw_cursor rd 1 |
scr_width rd 1 |
scr_height rd 1 |
cur_def_interl rd 1 |
cur_saved_base rd 1 |
cur_saved_interl rd 1 |
cur_saved_w rd 1 |
cur_saved_h rd 1 |
endg |
uglobal |
align 16 |
mst MEM_STATE |
; dll_tab rb 32*32 |
; srv_tab rb 36*32 |
mem_block_map rb 512 |
event_map rb 128 |
mem_block_list rd 64 |
mem_block_mask rd 2 |
; dll_map rd 1 |
; srv_map rd 1 |
srv.fd rd 1 |
srv.bk rd 1 |
mem_used_list rd 1 |
mem_block_arr rd 1 |
mem_block_start rd 1 |
mem_block_end rd 1 |
heap_mutex rd 1 |
heap_size rd 1 |
heap_free rd 1 |
heap_blocks rd 1 |
free_blocks rd 1 |
page_start rd 1 |
page_end rd 1 |
events rd 1 |
event_start rd 1 |
event_end rd 1 |
sys_page_map rd 1 |
endg |
if 0 |
push eax |
push edx |
mov edx, 0x400 ;bocsh |
mov al,0xff ;bocsh |
out dx, al ;bocsh |
pop edx |
pop eax |
end if |
align 4 |
k_strrchr: |
push eax |
xor eax,eax |
or ecx,-1 |
repne scasb |
add ecx,1 |
neg ecx |
sub edi,1 |
pop eax |
std |
repne scasb |
cld |
add edi,1 |
cmp [edi],al |
jne @F |
mov eax,edi |
ret |
@@: |
xor eax,eax |
ret |
align 4 |
proc k_strncpy stdcall, dest:dword, src:dword, maxlen:dword |
mov eax, [dest] |
mov esi, [src] |
mov ecx, [maxlen] |
test eax, eax |
jz .L9 |
test esi, esi |
jz .L9 |
test ecx, ecx |
jz .L9 |
sub esi, eax |
jmp .L1 |
align 4 |
.L2: |
mov edx, [esi+eax] |
mov [eax], dl |
test dl, dl |
jz .L7 |
mov [eax+1], dh |
test dh, dh |
jz .L6 |
shr edx, 16 |
mov [eax+2],dl |
test dl, dl |
jz .L5 |
mov [eax+3], dh |
test dh, dh |
jz .L4 |
add eax, 4 |
.L1: |
sub ecx, 4 |
jae .L2 |
add ecx, 4 |
jz .L9 |
mov dl, [eax+esi] |
mov [eax], dl |
test dl, dl |
jz .L3 |
inc eax |
dec ecx |
jz .L9 |
mov dl, [eax+esi] |
mov [eax], dl |
test dl, dl |
jz .L3 |
inc eax |
dec ecx |
jz .L9 |
mov dl, [eax+esi] |
mov [eax], dl |
test dl, dl |
jz .L3 |
inc eax |
jmp .L9 |
.L4: dec ecx |
inc eax |
.L5: dec ecx |
inc eax |
.L6: dec ecx |
inc eax |
.L7: |
add ecx,3 |
jz .L9 |
.L8: |
mov byte [ecx+eax], 0 |
.L3: |
dec ecx |
jnz .L8 |
.L9: |
ret |
endp |
if 0 |
magic equ 0xfefefeff |
k_strlen: |
mov eax,[esp+4] |
mov edx, 3 |
and edx, eax |
jz .L1 |
jp .L0 |
cmp dh, byte [eax] |
je .L2 |
inc eax |
cmp dh, byte [eax] |
je .L2 |
inc eax |
xor edx, 2 |
jz .L1 |
.L0: |
cmp dh, [eax] |
je .L2 |
inc eax |
xor edx, edx |
.L1: |
mov ecx, [eax] |
add eax, 4 |
sub edx, ecx |
add ecx, magic |
dec edx |
jnc .L3 |
xor edx, ecx |
and edx, not magic |
jne .L3 |
mov ecx, [eax] |
add eax, 4 |
sub edx, ecx |
add ecx, magic |
dec edx |
jnc .L3 |
xor edx, ecx |
and edx, not magic |
jne .L3 |
mov ecx, [eax] |
add eax, 4 |
sub edx, ecx |
add ecx, magic |
dec edx |
jnc .L3 |
xor edx, ecx |
and edx, not magic |
jne .L3 |
mov ecx, [eax] |
add eax, 4 |
sub edx, ecx |
add ecx, magic |
dec edx |
jnc .L3 |
xor edx, ecx |
and edx, not magic |
je .L1 |
.L3: sub eax ,4 |
sub ecx, magic |
cmp cl, 0 |
jz .L2 |
inc eax |
test ch, ch |
jz .L2 |
shr ecx, 16 |
inc eax |
cmp cl,0 |
jz .L2 |
inc eax |
.L2: |
sub eax, [esp+4] |
ret |
end if |
/kernel/tags/kolibri0.6.5.0/core/malloc.inc |
---|
0,0 → 1,993 |
; Small heap based on malloc/free/realloc written by Doug Lea |
; Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) |
; Source ftp://gee.cs.oswego.edu/pub/misc/malloc.c |
; License http://creativecommons.org/licenses/publicdomain. |
; eax= size |
; temp |
; esi= nb |
; ebx= idx |
; |
malloc: |
push esi |
; nb = ((size+7)&~7)+8; |
mov esi, eax ;size |
add esi, 7 |
and esi, -8 |
add esi, 8 |
mov ebx, mst.mutex |
call wait_mutex ;ebx |
cmp esi, 256 |
jae .large |
mov ecx, esi |
shr ecx, 3 |
or eax, -1 |
shl eax, cl |
and eax, [mst.smallmap] |
jz .small |
push ebp |
push edi |
bsf eax, eax |
mov ebx, eax |
; psize= idx<<3; |
; B = &ms.smallbins[idx]; |
; p = B->fd; |
; F = p->fd; |
; rsize= psize-nb; |
lea ebp, [eax*8] ;ebp= psize |
shl eax, 4 |
lea edi, [mst.smallbins+eax] ;edi= B |
mov edx, [edi+8] ;edx= p |
mov eax, [edx+8] ;eax= F |
mov ecx, ebp |
sub ecx, esi ;ecx= rsize |
; if (B == F) |
cmp edi, eax |
jne @F |
btr [mst.smallmap], ebx |
@@: |
; B->fd = F; |
; F->bk = B; |
; if(rsize<16) |
cmp ecx, 16 |
mov [edi+8], eax |
mov [eax+12], edi |
jae .split |
; p->head = psize|PINUSE_BIT|CINUSE_BIT; |
; (p + psize)->head |= PINUSE_BIT; |
lea eax, [edx+8] |
or dword [edx+ebp+4], 1 |
or ebp, 3 |
mov [edx+4], ebp |
pop edi |
pop ebp |
.done: |
pop esi |
mov [mst.mutex], 0 |
ret |
.split: |
lea ebx, [edx+8] ;ebx=mem |
; r = chunk_plus_offset(p, nb); |
; p->head = nb|PINUSE_BIT|CINUSE_BIT; |
; r->head = rsize|PINUSE_BIT; |
lea eax, [edx+esi] ;eax= r |
or esi, 3 |
mov [edx+4], esi |
mov edx, ecx |
or edx, 1 |
mov [eax+4], edx |
; (r + rsize)->prev_foot = rsize; |
mov [eax+ecx], ecx |
; I = rsize>>3; |
shr ecx, 3 |
; ms.smallmap |= 1<< I; |
bts [mst.smallmap], ecx |
; B = &ms.smallbins[I]; |
shl ecx, 4 |
pop edi |
pop ebp |
add ecx, mst.smallbins ;ecx= B |
mov edx, [ecx+8] ; F = B->fd; |
mov [ecx+8], eax ; B->fd = r; |
mov [edx+12], eax ; F->bk = r; |
mov [eax+8], edx ; r->fd = F; |
mov [eax+12], ecx ; r->bk = B; |
mov eax, ebx |
pop esi |
ret |
.small: |
; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0) |
cmp [mst.treemap], 0 |
je .from_top |
mov eax, esi |
call malloc_small |
test eax, eax |
jz .from_top |
pop esi |
and [mst.mutex], 0 |
ret |
.large: |
; if (ms.treemap != 0 && (mem = malloc_large(nb)) != 0) |
cmp [mst.treemap], 0 |
je .from_top |
call malloc_large ;esi= nb |
test eax, eax |
jne .done |
.from_top: |
; if (nb < ms.topsize) |
mov eax, [mst.topsize] |
cmp esi, eax |
jae .fail |
; rsize = ms.topsize -= nb; |
; p = ms.top; |
mov ecx, [mst.top] |
sub eax, esi |
mov [mst.topsize], eax |
; r = ms.top = chunk_plus_offset(p, nb); |
; r->head = rsize | PINUSE_BIT; |
; p->head = nb |PINUSE_BIT|CINUSE_BIT; |
lea edx, [ecx+esi] |
or eax, 1 |
mov [mst.top], edx |
or esi, 3 |
mov [edx+4], eax |
mov [ecx+4], esi |
lea eax, [ecx+8] |
pop esi |
and [mst.mutex], 0 |
ret |
.fail: |
xor eax, eax |
pop esi |
and [mst.mutex], 0 |
ret |
; param |
; eax= mem |
align 4 |
free: |
push edi |
mov edi, eax |
add edi, -8 |
; if(p->head & CINUSE_BIT) |
test byte [edi+4], 2 |
je .fail |
mov ebx, mst.mutex |
call wait_mutex ;ebx |
; psize = p->head & (~3); |
mov eax, [edi+4] |
push esi |
mov esi, eax |
and esi, -4 |
; next = chunk_plus_offset(p, psize); |
; if(!(p->head & PINUSE_BIT)) |
test al, 1 |
lea ebx, [esi+edi] |
jne .next |
; prevsize = p->prev_foot; |
; prev=p - prevsize; |
; psize += prevsize; |
; p = prev; |
mov ecx, [edi] ;ecx= prevsize |
add esi, ecx ;esi= psize |
sub edi, ecx ;edi= p |
; if (prevsize < 256) |
cmp ecx, 256 |
jae .unlink_large |
mov eax, [edi+8] ;F = p->fd; |
mov edx, [edi+12] ;B = p->bk; |
; if (F == B) |
; ms.smallmap &= ~(1<< I); |
shr ecx, 3 |
cmp eax, edx |
jne @F |
and [mst.smallmap], ecx |
@@: |
mov [eax+12], edx ;F->bk = B; |
mov [edx+8], eax ;B->fd = F |
jmp .next |
.unlink_large: |
mov edx, edi |
call unlink_large_chunk |
.next: |
; if(next->head & PINUSE_BIT) |
mov eax, [ebx+4] |
test al, 1 |
jz .fail2 |
; if (! (next->head & CINUSE_BIT)) |
test al, 2 |
jnz .fix_next |
; if (next == ms.top) |
cmp ebx, [mst.top] |
jne @F |
; tsize = ms.topsize += psize; |
mov eax, [mst.topsize] |
add eax, esi |
mov [mst.topsize], eax |
; ms.top = p; |
; p->head = tsize | PINUSE_BIT; |
or eax, 1 |
mov [mst.top], edi |
mov [edi+4], eax |
.fail2: |
and [mst.mutex], 0 |
pop esi |
.fail: |
pop edi |
ret |
@@: |
; nsize = next->head & ~INUSE_BITS; |
and eax, -4 |
add esi, eax ;psize += nsize; |
; if (nsize < 256) |
cmp eax, 256 |
jae .unl_large |
mov edx, [ebx+8] ;F = next->fd |
mov ebx, [ebx+12] ;B = next->bk |
; if (F == B) |
cmp edx, ebx |
jne @F |
mov ecx, eax |
shr ecx, 3 |
btr [mst.smallmap], ecx |
@@: |
mov [edx+12], ebx ;F->bk = B |
; p->head = psize|PINUSE_BIT; |
mov ecx, esi |
mov [ebx+8], edx |
or ecx, 1 |
mov [edi+4], ecx |
; (p+psize)->prev_foot = psize; |
mov [esi+edi], esi |
; insert_chunk(p,psize); |
mov eax, esi |
pop esi |
mov ecx, edi |
pop edi |
jmp insert_chunk |
.unl_large: |
; unlink_large_chunk((tchunkptr)next); |
mov edx, ebx |
call unlink_large_chunk |
; p->head = psize|PINUSE_BIT; |
mov ecx, esi |
or ecx, 1 |
mov [edi+4], ecx |
; (p+psize)->prev_foot = psize; |
mov [esi+edi], esi |
; insert_chunk(p,psize); |
mov eax, esi |
pop esi |
mov ecx, edi |
pop edi |
jmp insert_chunk |
.fix_next: |
; (p+psize)->prev_foot = psize; |
; next->head &= ~PINUSE_BIT; |
; p->head = psize|PINUSE_BIT; |
and eax, -2 |
mov edx, esi |
mov [ebx+4], eax |
or edx, 1 |
mov [edi+4], edx |
; (p+psize)->prev_foot = psize; |
mov [esi+edi], esi |
; insert_chunk(p,psize); |
mov eax, esi |
pop esi |
mov ecx, edi |
pop edi |
jmp insert_chunk |
; param |
; ecx = chunk |
; eax = size |
align 4 |
insert_chunk: |
cmp eax, 256 |
push esi |
mov esi, ecx |
jae .large |
; I = S>>3; |
; ms.smallmap |= 1<< I; |
shr eax, 3 |
bts [mst.smallmap], eax |
; B = &ms.smallbins[I]; |
shl eax, 4 |
add eax, mst.smallbins |
mov edx, [eax+8] ;F = B->fd |
mov [eax+8], esi ;B->fd = P |
mov [edx+12], esi ;F->bk = P |
mov [esi+8], edx ;P->fd = F |
mov [esi+12], eax ;P->bk = B |
pop esi |
and [mst.mutex], 0 |
ret |
.large: |
mov ebx, eax |
call insert_large_chunk |
pop esi |
and [mst.mutex], 0 |
ret |
align 4 |
; param |
; esi= chunk |
; ebx= size |
align 4 |
insert_large_chunk: |
; I = compute_tree_index(S); |
mov edx, ebx |
shr edx, 8 |
bsr eax, edx |
lea ecx, [eax+7] |
mov edx, ebx |
shr edx, cl |
and edx, 1 |
lea ecx, [edx+eax*2] |
; X->index = I; |
mov dword [esi+28], ecx |
; X->child[0] = X->child[1] = 0; |
and dword [esi+20], 0 |
and dword [esi+16], 0 |
; H = &ms.treebins[I]; |
mov eax, ecx |
lea edx, [mst.treebins+eax*4] |
; if (!(ms.treemap & 1<<I)) |
bt [mst.treemap], ecx |
jc .tree |
; ms.treemap |= 1<<I; |
bts [mst.treemap], ecx |
; *H = X; |
mov dword [edx], esi |
jmp .done |
.tree: |
; T = *H; |
mov edx, [edx] |
; K = S << leftshift_for_tree_index(I); |
mov eax, ecx |
shr eax, 1 |
sub ecx, 31 |
mov edi, 37 |
sub edi, eax |
neg ecx |
sbb ecx, ecx |
and ecx, edi |
mov eax, ebx |
shl eax, cl ;eax= K |
jmp .loop |
.not_eq_size: |
; C = &(T->child[(K >> 31) & 1]); |
mov ecx, eax |
shr ecx, 31 |
lea ecx, [edx+ecx*4+16] |
; K <<= 1; |
; if (*C != 0) |
mov edi, [ecx] |
add eax, eax |
test edi, edi |
jz .insert_child |
; T = *C; |
mov edx, edi |
.loop: |
; for (;;) |
; if ((T->head & ~INUSE_BITS) != S) |
mov ecx, [edx+4] |
and ecx, not 3 |
cmp ecx, ebx |
jne .not_eq_size |
; F = T->fd; |
mov eax, [edx+8] |
; T->fd = F->bk = X; |
mov [eax+12], esi |
mov [edx+8], esi |
; X->fd = F; |
; X->bk = T; |
; X->parent = 0; |
and dword [esi+24], 0 |
mov [esi+8], eax |
mov [esi+12], edx |
ret |
.insert_child: |
; *C = X; |
mov [ecx], esi |
.done: |
; X->parent = T; |
mov [esi+24], edx |
; X->fd = X->bk = X; |
mov [esi+12], esi |
mov [esi+8], esi |
ret |
; param |
; edx= chunk |
align 4 |
unlink_large_chunk: |
mov eax, [edx+12] |
cmp eax, edx |
push edi |
mov edi, [edx+24] |
je @F |
mov ecx, [edx+8] ;F = X->fd |
mov [ecx+12], eax ;F->bk = R; |
mov [eax+8], ecx ;R->fd = F |
jmp .parent |
@@: |
mov eax, [edx+20] |
test eax, eax |
push esi |
lea esi, [edx+20] |
jne .loop |
mov eax, [edx+16] |
test eax, eax |
lea esi, [edx+16] |
je .l2 |
.loop: |
cmp dword [eax+20], 0 |
lea ecx, [eax+20] |
jne @F |
cmp dword [eax+16], 0 |
lea ecx, [eax+16] |
je .l1 |
@@: |
mov eax, [ecx] |
mov esi, ecx |
jmp .loop |
.l1: |
mov dword [esi], 0 |
.l2: |
pop esi |
.parent: |
test edi, edi |
je .done |
mov ecx, [edx+28] |
cmp edx, [mst.treebins+ecx*4] |
lea ecx, [mst.treebins+ecx*4] |
jne .l3 |
test eax, eax |
mov [ecx], eax |
jne .l5 |
mov ecx, [edx+28] |
btr [mst.treemap], ecx |
pop edi |
ret |
.l3: |
cmp [edi+16], edx |
jne @F |
mov [edi+16], eax |
jmp .l4 |
@@: |
mov [edi+20], eax |
.l4: |
test eax, eax |
je .done |
.l5: |
mov [eax+24], edi |
mov ecx, [edx+16] |
test ecx, ecx |
je .l6 |
mov [eax+16], ecx |
mov [ecx+24], eax |
.l6: |
mov edx, [edx+20] |
test edx, edx |
je .done |
mov [eax+20], edx |
mov [edx+24], eax |
.done: |
pop edi |
ret |
; param |
; esi= nb |
align 4 |
malloc_small: |
push ebp |
mov ebp, esi |
push edi |
bsf eax,[mst.treemap] |
mov ecx, [mst.treebins+eax*4] |
; rsize = (t->head & ~INUSE_BITS) - nb; |
mov edi, [ecx+4] |
and edi, -4 |
sub edi, esi |
.loop: |
mov ebx, ecx |
.loop_1: |
; while ((t = leftmost_child(t)) != 0) |
mov eax, [ecx+16] |
test eax, eax |
jz @F |
mov ecx, eax |
jmp .l1 |
@@: |
mov ecx, [ecx+20] |
.l1: |
test ecx, ecx |
jz .unlink |
; trem = (t->head & ~INUSE_BITS) - nb; |
mov eax, [ecx+4] |
and eax, -4 |
sub eax, ebp |
; if (trem < rsize) |
cmp eax, edi |
jae .loop_1 |
; rsize = trem; |
mov edi, eax |
jmp .loop |
.unlink: |
; r = chunk_plus_offset((mchunkptr)v, nb); |
; unlink_large_chunk(v); |
mov edx, ebx |
lea esi, [ebx+ebp] |
call unlink_large_chunk |
; if (rsize < 16) |
cmp edi, 16 |
jae .split |
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; |
lea ecx, [edi+ebp] |
; (v+rsize + nb)->head |= PINUSE_BIT; |
add edi, ebx |
lea eax, [edi+ebp+4] |
pop edi |
or ecx, 3 |
mov [ebx+4], ecx |
or dword [eax], 1 |
pop ebp |
lea eax, [ebx+8] |
ret |
.split: |
; v->head = nb|PINUSE_BIT|CINUSE_BIT; |
; r->head = rsize|PINUSE_BIT; |
; (r+rsize)->prev_foot = rsize; |
or ebp, 3 |
mov edx, edi |
or edx, 1 |
cmp edi, 256 |
mov [ebx+4], ebp |
mov [esi+4], edx |
mov [esi+edi], edi |
jae .large |
shr edi, 3 |
bts [mst.smallmap], edi |
mov eax, edi |
shl eax, 4 |
add eax, mst.smallbins |
mov edx, [eax+8] |
mov [eax+8], esi |
mov [edx+12], esi |
pop edi |
mov [esi+12], eax |
mov [esi+8], edx |
pop ebp |
lea eax, [ebx+8] |
ret |
.large: |
lea eax, [ebx+8] |
push eax |
mov ebx, edi |
call insert_large_chunk |
pop eax |
pop edi |
pop ebp |
ret |
; param |
; esi= nb |
align 4 |
malloc_large: |
.idx equ esp+4 |
.rst equ esp |
push ebp |
push edi |
sub esp, 8 |
; v = 0; |
; rsize = -nb; |
mov edi, esi |
mov ebx, esi |
xor ebp, ebp |
neg edi |
; idx = compute_tree_index(nb); |
mov edx, esi |
shr edx, 8 |
bsr eax, edx |
lea ecx, [eax+7] |
shr esi, cl |
and esi, 1 |
lea ecx, [esi+eax*2] |
mov [.idx], ecx |
; if ((t = ms.treebins[idx]) != 0) |
mov eax, [mst.treebins+ecx*4] |
test eax, eax |
jz .l3 |
; sizebits = nb << leftshift_for_tree_index(idx); |
cmp ecx, 31 |
jne @F |
xor ecx, ecx |
jmp .l1 |
@@: |
mov edx, ecx |
shr edx, 1 |
mov ecx, 37 |
sub ecx, edx |
.l1: |
mov edx, ebx |
shl edx, cl |
; rst = 0; |
mov [.rst], ebp |
.loop: |
; trem = (t->head & ~INUSE_BITS) - nb; |
mov ecx, [eax+4] |
and ecx, -4 |
sub ecx, ebx |
; if (trem < rsize) |
cmp ecx, edi |
jae @F |
; v = t; |
; if ((rsize = trem) == 0) |
test ecx, ecx |
mov ebp, eax |
mov edi, ecx |
je .l2 |
@@: |
; rt = t->child[1]; |
mov ecx, [eax+20] |
; t = t->child[(sizebits >> 31) & 1]; |
mov esi, edx |
shr esi, 31 |
; if (rt != 0 && rt != t) |
test ecx, ecx |
mov eax, [eax+esi*4+16] |
jz @F |
cmp ecx, eax |
jz @F |
; rst = rt; |
mov [.rst], ecx |
@@: |
; if (t == 0) |
test eax, eax |
jz @F |
; sizebits <<= 1; |
add edx, edx |
jmp .loop |
@@: |
; t = rst; |
mov eax, [.rst] |
.l2: |
; if (t == 0 && v == 0) |
test eax, eax |
jne .l4 |
test ebp, ebp |
jne .l7 |
mov ecx, [.idx] |
.l3: |
; leftbits = (-1<<idx) & ms.treemap; |
; if (leftbits != 0) |
or edx, -1 |
shl edx, cl |
and edx, [mst.treemap] |
jz @F |
bsf eax, edx |
; t = ms.treebins[i]; |
mov eax, [mst.treebins+eax*4] |
@@: |
; while (t != 0) |
test eax, eax |
jz .l5 |
.l4: |
; trem = (t->head & ~INUSE_BITS) - nb; |
mov ecx, [eax+4] |
and ecx, -4 |
sub ecx, ebx |
; if (trem < rsize) |
cmp ecx, edi |
jae @F |
; rsize = trem; |
mov edi, ecx |
; v = t; |
mov ebp, eax |
@@: |
; t = leftmost_child(t); |
mov ecx, [eax+16] |
test ecx, ecx |
je @F |
mov eax, ecx |
jmp .l6 |
@@: |
mov eax, [eax+20] |
.l6: |
; while (t != 0) |
test eax, eax |
jne .l4 |
.l5: |
; if (v != 0) |
test ebp, ebp |
jz .done |
.l7: |
; r = chunk_plus_offset((mchunkptr)v, nb); |
; unlink_large_chunk(v); |
mov edx, ebp |
lea esi, [ebx+ebp] |
call unlink_large_chunk |
; if (rsize < 16) |
cmp edi, 16 |
jae .large |
; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; |
lea ecx, [edi+ebx] |
; (v+rsize + nb)->head |= PINUSE_BIT; |
add edi, ebp |
lea eax, [edi+ebx+4] |
or ecx, 3 |
mov [ebp+4], ecx |
or dword [eax], 1 |
lea eax, [ebp+8] |
add esp, 8 |
pop edi |
pop ebp |
ret |
.large: |
; v->head = nb|PINUSE_BIT|CINUSE_BIT; |
; r->head = rsize|PINUSE_BIT; |
mov edx, edi |
or ebx, 3 |
mov [ebp+4], ebx |
or edx, 1 |
mov [esi+4], edx |
; (r+rsize)->prev_foot = rsize; |
; insert_large_chunk((tchunkptr)r, rsize); |
mov [esi+edi], edi |
mov eax, edi |
mov ecx, esi |
call insert_chunk |
lea eax, [ebp+8] |
add esp, 8 |
pop edi |
pop ebp |
ret |
.done: |
add esp, 8 |
pop edi |
pop ebp |
xor eax, eax |
ret |
align 4 |
init_malloc: |
stdcall kernel_alloc, 0x20000 |
mov [mst.top], eax |
mov [mst.topsize], 128*1024 |
mov dword [eax+4], (128*1024) or 1 |
mov eax, mst.smallbins |
@@: |
mov [eax+8], eax |
mov [eax+12], eax |
add eax, 16 |
cmp eax, mst.smallbins+512 |
jl @B |
ret |
/kernel/tags/kolibri0.6.5.0/core/heap.inc |
---|
0,0 → 1,833 |
HEAP_BASE equ 0x00C00000 |
;HEAP_SIZE equ 0x01000000 |
struc MEM_BLOCK |
{ .next_block dd ? |
.prev_block dd ? ;+4 |
.list_next dd ? ;+8 |
.list_prev dd ? ;+12 |
.base dd ? ;+16 |
.size dd ? ;+20 |
.flags dd ? ;+24 |
.handle dd ? ;+28 |
} |
FREE_BLOCK equ 4 |
USED_BLOCK equ 8 |
virtual at 0 |
MEM_BLOCK MEM_BLOCK |
end virtual |
MEM_BLOCK_SIZE equ 8*4 |
block_next equ MEM_BLOCK.next_block |
block_prev equ MEM_BLOCK.prev_block |
list_next equ MEM_BLOCK.list_next |
list_prev equ MEM_BLOCK.list_prev |
block_base equ MEM_BLOCK.base |
block_size equ MEM_BLOCK.size |
block_flags equ MEM_BLOCK.flags |
macro calc_index op |
{ shr op, 12 |
dec op |
cmp op, 63 |
jna @f |
mov op, 63 |
@@: |
} |
macro remove_from_list op |
{ mov edx, [op+list_next] |
mov ecx, [op+list_prev] |
test edx, edx |
jz @f |
mov [edx+list_prev], ecx |
@@: |
test ecx, ecx |
jz @f |
mov [ecx+list_next], edx |
@@: |
mov [op+list_next],0 |
mov [op+list_prev],0 |
} |
macro remove_from_free op |
{ |
remove_from_list op |
mov eax, [op+block_size] |
calc_index eax |
cmp [mem_block_list+eax*4], op |
jne @f |
mov [mem_block_list+eax*4], edx |
@@: |
cmp [mem_block_list+eax*4], 0 |
jne @f |
btr [mem_block_mask], eax |
@@: |
} |
macro remove_from_used op |
{ |
remove_from_list op |
cmp [mem_used_list], op |
jne @f |
mov [mem_used_list], edx |
@@: |
} |
align 4 |
proc init_kernel_heap |
mov ecx, 64/4 |
mov edi, mem_block_list |
xor eax, eax |
cld |
rep stosd |
mov ecx, 512/4 |
mov edi, mem_block_map |
not eax |
rep stosd |
mov [mem_block_start], mem_block_map |
mov [mem_block_end], mem_block_map+512 |
mov [mem_block_arr], HEAP_BASE |
stdcall alloc_pages, dword 32 |
mov ecx, 32 |
mov edx, eax |
mov edi, HEAP_BASE |
.l1: |
stdcall map_page,edi,edx,PG_SW |
add edi, 0x1000 |
add edx, 0x1000 |
dec ecx |
jnz .l1 |
mov edi, HEAP_BASE |
mov ebx, edi |
add ebx, MEM_BLOCK_SIZE |
xor eax, eax |
mov [edi+block_next], ebx |
mov [edi+block_prev], eax |
mov [edi+list_next], eax |
mov [edi+list_prev], eax |
mov [edi+block_base], HEAP_BASE |
mov [edi+block_size], 4096*MEM_BLOCK_SIZE |
mov [edi+block_flags], USED_BLOCK |
mov [ebx+block_next], eax |
mov [ebx+block_prev], eax |
mov [ebx+list_next], eax |
mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK_SIZE |
mov ecx, [MEM_AMOUNT] |
sub ecx, HEAP_BASE + 4096*MEM_BLOCK_SIZE |
mov [heap_size], ecx |
mov [heap_free], ecx |
mov [ebx+block_size], ecx |
mov [ebx+block_flags], FREE_BLOCK |
mov [mem_block_mask], eax |
mov [mem_block_mask+4],0x80000000 |
mov [mem_used_list], eax |
mov [mem_block_list+63*4], ebx |
mov byte [mem_block_map], 0xFC |
and [heap_mutex], 0 |
mov [heap_blocks], 4095 |
mov [free_blocks], 4095 |
ret |
endp |
align 4 |
proc get_block stdcall, index:dword |
mov eax, 63 |
mov ecx, [index] |
cmp ecx, eax |
jna @f |
;cmova ecx, eax |
mov ecx, eax |
@@: |
xor esi, esi |
xor ebx, ebx |
xor edx, edx |
not edx |
cmp ecx, 32 |
jb .bit_test |
sub ecx, 32 |
add ebx, 32 |
add esi, 4 |
.bit_test: |
shl edx, cl |
and edx, [mem_block_mask+esi] |
jz .high_mask |
bsf eax, edx |
add ebx, eax |
mov eax, [mem_block_list+ebx*4] |
ret |
.high_mask: |
add esi, 4 |
add ebx, 32 |
test esi, 0xFFFFFFF8 |
jnz .big_error |
mov edx, [mem_block_mask+esi] |
and edx, edx |
jz .high_mask |
bsf eax, edx |
add ebx, eax |
mov eax, [mem_block_list+ebx*4] |
ret |
.big_error: |
xor eax, eax |
ret |
endp |
align 4 |
proc alloc_mem_block |
mov ebx, [mem_block_start] |
mov ecx, [mem_block_end] |
.l1: |
bsf eax,[ebx]; |
jnz found |
add ebx,4 |
cmp ebx, ecx |
jb .l1 |
xor eax,eax |
ret |
found: |
btr [ebx], eax |
mov [mem_block_start],ebx |
sub ebx, mem_block_map |
lea eax,[eax+ebx*8] |
shl eax, 5 |
add eax, [mem_block_arr] |
dec [free_blocks] |
ret |
endp |
proc free_mem_block |
sub eax, [mem_block_arr] |
shr eax, 5 |
mov ebx, mem_block_map |
bts [ebx], eax |
inc [free_blocks] |
shr eax, 3 |
and eax, not 3 |
add eax, ebx |
cmp [mem_block_start], eax |
ja @f |
ret |
@@: |
mov [mem_block_start], eax |
ret |
.err: |
xor eax, eax |
ret |
endp |
align 4 |
proc alloc_kernel_space stdcall, size:dword |
local block_ind:DWORD |
mov eax, [size] |
add eax, 4095 |
and eax, not 4095 |
mov [size], eax |
mov ebx, heap_mutex |
call wait_mutex ;ebx |
cmp eax, [heap_free] |
ja .error |
shr eax, 12 |
sub eax, 1 |
mov [block_ind], eax |
stdcall get_block, eax |
test eax, eax |
jz .error |
mov edi, eax ;edi - pBlock |
cmp [edi+block_flags], FREE_BLOCK |
jne .error |
mov [block_ind], ebx ;index of allocated block |
mov eax, [edi+block_size] |
cmp eax, [size] |
je .m_eq_size |
call alloc_mem_block |
and eax, eax |
jz .error |
mov esi, eax ;esi - splitted block |
mov [esi+block_next], edi |
mov eax, [edi+block_prev] |
mov [esi+block_prev], eax |
mov [edi+block_prev], esi |
mov [esi+list_next], 0 |
mov [esi+list_prev], 0 |
and eax, eax |
jz @f |
mov [eax+block_next], esi |
@@: |
mov ebx, [edi+block_base] |
mov [esi+block_base], ebx |
mov edx, [size] |
mov [esi+block_size], edx |
add [edi+block_base], edx |
sub [edi+block_size], edx |
mov eax, [edi+block_size] |
shr eax, 12 |
sub eax, 1 |
cmp eax, 63 |
jna @f |
mov eax, 63 |
@@: |
cmp eax, [block_ind] |
je .m_eq_ind |
remove_from_list edi |
mov ecx, [block_ind] |
mov [mem_block_list+ecx*4], edx |
test edx, edx |
jnz @f |
btr [mem_block_mask], ecx |
@@: |
mov edx, [mem_block_list+eax*4] |
mov [edi+list_next], edx |
test edx, edx |
jz @f |
mov [edx+list_prev], edi |
@@: |
mov [mem_block_list+eax*4], edi |
bts [mem_block_mask], eax |
.m_eq_ind: |
mov ebx, [mem_used_list] |
mov [esi+list_next], ebx |
test ebx, ebx |
jz @f |
mov [ebx+list_prev], esi |
@@: |
mov [esi+block_flags], USED_BLOCK |
mov [mem_used_list], esi |
mov eax, [esi+block_base] |
mov ebx, [size] |
sub [heap_free], ebx |
and [heap_mutex], 0 |
ret |
.m_eq_size: |
remove_from_list edi |
mov [mem_block_list+ebx*4], edx |
and edx, edx |
jnz @f |
btr [mem_block_mask], ebx |
@@: |
mov ecx, [mem_used_list] |
mov [edi+list_next], ecx |
test ecx, ecx |
jnz @f |
mov [ecx+list_prev], edi |
@@: |
mov [mem_used_list], edi |
mov [edi+block_flags], USED_BLOCK |
mov eax, [edi+block_base] |
mov ebx, [size] |
sub [heap_free], ebx |
and [heap_mutex], 0 |
ret |
.error: |
xor eax, eax |
mov [heap_mutex], eax |
ret |
endp |
align 4 |
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword |
mov ebx, heap_mutex |
call wait_mutex ;ebx |
mov eax, [base] |
mov esi, [mem_used_list] |
@@: |
test esi, esi |
jz .fail |
cmp [esi+block_base], eax |
je .found |
mov esi, [esi+list_next] |
jmp @b |
.found: |
cmp [esi+block_flags], USED_BLOCK |
jne .fail |
mov eax, [esi+block_size] |
add [heap_free], eax |
mov edi, [esi+block_next] |
test edi, edi |
jz .prev |
cmp [edi+block_flags], FREE_BLOCK |
jne .prev |
remove_from_free edi |
mov edx, [edi+block_next] |
mov [esi+block_next], edx |
test edx, edx |
jz @f |
mov [edx+block_prev], esi |
@@: |
mov ecx, [edi+block_size] |
add [esi+block_size], ecx |
mov eax, edi |
call free_mem_block |
.prev: |
mov edi, [esi+block_prev] |
test edi, edi |
jz .insert |
cmp [edi+block_flags], FREE_BLOCK |
jne .insert |
remove_from_used esi |
mov edx, [esi+block_next] |
mov [edi+block_next], edx |
test edx, edx |
jz @f |
mov [edx+block_prev], edi |
@@: |
mov eax, esi |
call free_mem_block |
mov ecx, [edi+block_size] |
mov eax, [esi+block_size] |
add eax, ecx |
mov [edi+block_size], eax |
calc_index eax |
calc_index ecx |
cmp eax, ecx |
je .m_eq |
push ecx |
remove_from_list edi |
pop ecx |
cmp [mem_block_list+ecx*4], edi |
jne @f |
mov [mem_block_list+ecx*4], edx |
@@: |
cmp [mem_block_list+ecx*4], 0 |
jne @f |
btr [mem_block_mask], ecx |
@@: |
mov esi, [mem_block_list+eax*4] |
mov [mem_block_list+eax*4], edi |
mov [edi+list_next], esi |
test esi, esi |
jz @f |
mov [esi+list_prev], edi |
@@: |
bts [mem_block_mask], eax |
.m_eq: |
xor eax, eax |
mov [heap_mutex], eax |
dec eax |
ret |
.insert: |
remove_from_used esi |
mov eax, [esi+block_size] |
calc_index eax |
mov edi, [mem_block_list+eax*4] |
mov [mem_block_list+eax*4], esi |
mov [esi+list_next], edi |
test edi, edi |
jz @f |
mov [edi+list_prev], esi |
@@: |
bts [mem_block_mask], eax |
mov [esi+block_flags],FREE_BLOCK |
xor eax, eax |
mov [heap_mutex], eax |
dec eax |
ret |
.fail: |
xor eax, eax |
mov [heap_mutex], eax |
ret |
endp |
align 4 |
proc kernel_alloc stdcall, size:dword |
locals |
lin_addr dd ? |
pages_count dd ? |
endl |
mov eax, [size] |
add eax, 4095 |
and eax, not 4095; |
mov [size], eax |
and eax, eax |
jz .error |
mov ebx, eax |
shr ebx, 12 |
mov [pages_count], ebx |
stdcall alloc_kernel_space, eax |
and eax, eax |
jz .error |
mov [lin_addr], eax |
mov ecx, [pages_count] |
mov edx, eax |
mov ebx, ecx |
shr ecx, 3 |
jz .next |
and ebx, not 7 |
push ebx |
stdcall alloc_pages, ebx |
pop ecx ; yes ecx!!! |
and eax, eax |
jz .error |
mov edi, eax |
mov edx, [lin_addr] |
@@: |
stdcall map_page,edx,edi,dword PG_SW |
add edx, 0x1000 |
add edi, 0x1000 |
dec ecx |
jnz @B |
.next: |
mov ecx, [pages_count] |
and ecx, 7 |
jz .end |
@@: push ecx |
call alloc_page |
pop ecx |
test eax, eax |
jz .error |
stdcall map_page,edx,eax,dword PG_SW |
add edx, 0x1000 |
dec ecx |
jnz @B |
.end: |
mov eax, [lin_addr] |
ret |
.error: |
xor eax, eax |
ret |
endp |
align 4 |
proc kernel_free stdcall, base:dword |
push ebx esi |
mov ebx, heap_mutex |
call wait_mutex ;ebx |
mov eax, [base] |
mov esi, [mem_used_list] |
@@: |
test esi, esi |
jz .fail |
cmp [esi+block_base], eax |
je .found |
mov esi, [esi+list_next] |
jmp @b |
.found: |
cmp [esi+block_flags], USED_BLOCK |
jne .fail |
and [heap_mutex], 0 |
push ecx |
mov ecx, [esi+block_size]; |
shr ecx, 12 |
call release_pages ;eax, ecx |
pop ecx |
stdcall free_kernel_space, [base] |
pop esi ebx |
ret |
.fail: |
and [heap_mutex], 0 |
pop esi ebx |
ret |
endp |
restore block_next |
restore block_prev |
restore block_list |
restore block_base |
restore block_size |
restore block_flags |
;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;; |
HEAP_TOP equ 0x5FC00000 |
align 4 |
proc init_heap |
mov ebx,[CURRENT_TASK] |
shl ebx,8 |
mov eax, [PROC_BASE+APPDATA.heap_top+ebx] |
test eax, eax |
jz @F |
sub eax,[PROC_BASE+APPDATA.heap_base+ebx] |
sub eax, 4096 |
ret |
@@: |
mov esi, [PROC_BASE+APPDATA.mem_size+ebx] |
add esi, 4095 |
and esi, not 4095 |
mov [PROC_BASE+APPDATA.mem_size+ebx], esi |
mov eax, HEAP_TOP |
mov [PROC_BASE+APPDATA.heap_base+ebx], esi |
mov [PROC_BASE+APPDATA.heap_top+ebx], eax |
sub eax, esi |
add esi, new_app_base |
shr esi, 10 |
mov ecx, eax |
sub eax, 4096 |
or ecx, FREE_BLOCK |
mov [pages_tab+esi], ecx |
ret |
.exit: |
xor eax, eax |
ret |
endp |
align 4 |
proc user_alloc stdcall, alloc_size:dword |
mov ecx, [alloc_size] |
add ecx, (4095+4096) |
and ecx, not 4095 |
mov ebx, [CURRENT_TASK] |
shl ebx, 8 |
mov esi, dword [ebx+PROC_BASE+APPDATA.heap_base]; heap_base |
mov edi, dword [ebx+PROC_BASE+APPDATA.heap_top]; heap_top |
add esi, new_app_base |
add edi, new_app_base |
l_0: |
cmp esi, edi |
jae m_exit |
mov ebx, esi |
shr ebx, 12 |
mov eax, [pages_tab+ebx*4] |
test eax, FREE_BLOCK |
jz test_used |
and eax, 0xFFFFF000 |
cmp eax, ecx ;alloc_size |
jb m_next |
jz @f |
mov edx, esi |
add edx, ecx |
sub eax, ecx; |
or eax, FREE_BLOCK |
shr edx, 12 |
mov [pages_tab+edx*4], eax |
@@: |
or ecx, USED_BLOCK |
mov [pages_tab+ebx*4], ecx |
shr ecx, 12 |
dec ecx |
inc ebx |
@@: |
mov dword [pages_tab+ebx*4], 2 |
inc ebx |
dec ecx |
jnz @B |
mov edx, [CURRENT_TASK] |
shl edx, 8 |
mov ebx, [alloc_size] |
add ebx, 0xFFF |
and ebx, not 0xFFF |
add ebx, [PROC_BASE+APPDATA.mem_size+edx] |
call update_mem_size |
mov eax, esi |
add eax, 4096 |
sub eax, new_app_base |
ret |
m_next: |
add esi, eax |
jmp l_0 |
test_used: |
test eax, USED_BLOCK |
jz m_exit |
and eax, 0xFFFFF000 |
add esi, eax |
jmp l_0 |
m_exit: |
xor eax, eax |
ret |
endp |
align 4 |
proc user_free stdcall, base:dword |
mov esi, [base] |
test esi, esi |
jz .exit |
xor ebx, ebx |
sub esi, 4096 |
shr esi, 12 |
mov eax, [pages_tab+esi*4] |
test eax, USED_BLOCK |
jz .not_used |
and eax, not 4095 |
mov ecx, eax |
or eax, FREE_BLOCK |
mov [pages_tab+esi*4], eax |
inc esi |
sub ecx, 4096 |
shr ecx, 12 |
mov ebx, ecx |
.release: |
xor eax, eax |
xchg eax, [pages_tab+esi*4] |
test eax, 1 |
jz @F |
call free_page |
@@: |
inc esi |
dec ecx |
jnz .release |
.not_used: |
mov edx, [CURRENT_TASK] |
shl edx, 8 |
mov esi, dword [edx+PROC_BASE+APPDATA.heap_base]; heap_base |
mov edi, dword [edx+PROC_BASE+APPDATA.heap_top]; heap_top |
sub ebx, [edx+PROC_BASE+APPDATA.mem_size] |
neg ebx |
call update_mem_size |
add esi, new_app_base |
add edi, new_app_base |
shr esi, 12 |
shr edi, 12 |
@@: |
mov eax, [pages_tab+esi*4] |
test eax, USED_BLOCK |
jz .test_free |
shr eax, 12 |
add esi, eax |
jmp @B |
.test_free: |
test eax, FREE_BLOCK |
jz .err |
mov edx, eax |
shr edx, 12 |
add edx, esi |
cmp edx, edi |
jae .exit |
mov ebx, [pages_tab+edx*4] |
test ebx, USED_BLOCK |
jz .next_free |
shr ebx, 12 |
add edx, ebx |
mov esi, edx |
jmp @B |
.next_free: |
test ebx, FREE_BLOCK |
jz .err |
and dword [pages_tab+edx*4], 0 |
add eax, ebx |
and eax, not 4095 |
or eax, FREE_BLOCK |
mov [pages_tab+esi*4], eax |
jmp @B |
.exit: |
xor eax, eax |
inc eax |
ret |
.err: |
xor eax, eax |
ret |
endp |
if 0 |
align 4 |
proc alloc_dll |
pushf |
cli |
bsf eax, [dll_map] |
jnz .find |
popf |
xor eax, eax |
ret |
.find: |
btr [dll_map], eax |
popf |
shl eax, 5 |
add eax, dll_tab |
ret |
endp |
align 4 |
proc alloc_service |
pushf |
cli |
bsf eax, [srv_map] |
jnz .find |
popf |
xor eax, eax |
ret |
.find: |
btr [srv_map], eax |
popf |
shl eax,0x02 |
lea eax,[srv_tab+eax+eax*8] ;srv_tab+eax*36 |
ret |
endp |
end if |
/kernel/tags/kolibri0.6.5.0/core/syscall.inc |
---|
0,0 → 1,122 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; SYSTEM CALL ENTRY ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
align 32 |
i40: |
push ds es |
pushad |
cld |
mov ax,word os_data |
mov ds,ax |
mov es,ax |
; load all registers in crossed order |
mov eax, ebx |
mov ebx, ecx |
mov ecx, edx |
mov edx, esi |
mov esi, edi |
mov edi, [esp+28] |
; 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 |
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 undefined_syscall ; 19-reserved |
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 undefined_syscall ; 27-reserved |
dd sys_sb16II ; 28-SetSb16 |
dd sys_date ; 29-GetDate |
dd undefined_syscall ; 30-reserved |
dd undefined_syscall ; 31-reserved |
dd syscall_delramdiskfile ; 32-DelRamdiskFile |
dd syscall_writeramdiskfile; 33-WriteRamdiskFile |
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 undefined_syscall ; 56-reserved |
dd undefined_syscall ; 57-reserved |
dd file_system ; 58-Common file system interface |
dd undefined_syscall ; 59-reserved |
dd 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 syscall_putimage_palette; 65-PutImagePalette |
dd sys_process_def ; 66-Process definitions - keyboard |
dd sys_window_move ; 67-Window move or resize |
dd new_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 |
/kernel/tags/kolibri0.6.5.0/core/exports.inc |
---|
0,0 → 1,100 |
iglobal |
szKernel db 'KERNEL', 0 |
szVersion db 'version',0 |
szRegService db 'RegService',0 |
szGetService db 'GetService',0 |
szServiceHandler db 'ServiceHandler',0 |
szAttachIntHandler db 'AttachIntHandler',0 |
szFpuSave db 'FpuSave',0 |
szFpuRestore db 'FpuRestore',0 |
szPciApi db 'PciApi', 0 |
szPciRead32 db 'PciRead32', 0 |
szPciRead8 db 'PciRead8', 0 |
szPciWrite8 db 'PciWrite8',0 |
szAllocPage db 'AllocPage',0 |
szAllocPages db 'AllocPages',0 |
szFreePage db 'FreePage',0 |
szGetPgAddr db 'GetPgAddr',0 |
szMapPage db 'MapPage',0 |
szMapSpace db 'MapSpace',0 |
szCommitPages db 'CommitPages',0 |
szReleasePages db 'ReleasePages',0 |
szAllocKernelSpace db 'AllocKernelSpace',0 |
szFreeKernelSpace db 'FreeKernelSpace',0 |
szKernelAlloc db 'KernelAlloc',0 |
szKernelFree db 'KernelFree',0 |
szUserAlloc db 'UserAlloc',0 |
szUserFree db 'UserFree',0 |
szKmalloc db 'Kmalloc',0 |
szKfree db 'Kfree',0 |
szCreateObject db 'CreateObject',0 |
szDestroyObject db 'DestroyObject',0 |
szLoadCursor db 'LoadCursor',0 |
szSetHwCursor db 'SetHwCursor',0 |
szHwCursorRestore db 'HwCursorRestore', 0 |
szHwCursorCreate db 'HwCursorCreate', 0 |
szSysMsgBoardStr db 'SysMsgBoardStr', 0 |
szGetCurrentTask db 'GetCurrentTask',0 |
szLFBAddress db 'LFBAddress',0 |
szLoadFile db 'LoadFile',0 |
szSendEvent db 'SendEvent',0 |
align 16 |
kernel_export: |
dd szRegService , reg_service |
dd szGetService , get_service |
dd szServiceHandler , srv_handler |
dd szAttachIntHandler, attach_int_handler |
dd szFpuSave , fpu_save |
dd szFpuRestore , fpu_restore |
dd szPciApi , pci_api |
dd szPciRead32 , pci_read32 |
dd szPciRead8 , pci_read8 |
dd szPciWrite8 , pci_write8 |
dd szAllocPage , alloc_page |
dd szAllocPages , alloc_pages |
dd szFreePage , free_page |
dd szMapPage , map_page |
dd szMapSpace , map_space |
dd szGetPgAddr , get_pg_addr |
dd szCommitPages , commit_pages ;not implemented |
dd szReleasePages , release_pages |
dd szAllocKernelSpace, alloc_kernel_space |
dd szFreeKernelSpace , free_kernel_space |
dd szKernelAlloc , kernel_alloc |
dd szKernelFree , kernel_free |
dd szUserAlloc , user_alloc |
dd szUserFree , user_free |
dd szKmalloc , malloc |
dd szKfree , free |
dd szCreateObject , create_kernel_object |
dd szDestroyObject , destroy_kernel_object |
dd szLoadCursor , load_cursor |
dd szSetHwCursor , set_hw_cursor |
dd szHwCursorRestore , hw_restore |
dd szHwCursorCreate , create_cursor |
dd szSysMsgBoardStr , sys_msg_board_str |
dd szGetCurrentTask , get_curr_task |
dd szLoadFile , load_file |
dd szSendEvent , send_event |
exp_lfb: |
dd szLFBAddress , 0 |
dd 0 |
endg |
/kernel/tags/kolibri0.6.5.0/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 [eax+TSS._cs], app_code |
jnz .ring0 |
lea esi, [eax+TSS._eip] |
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, [eax+TSS._esp0] |
; 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 [eax+TSS._cs], app_code |
jnz .ring0 |
lea edi, [eax+TSS._eip] |
shr ecx, 2 |
rep movsd |
jmp .stiret |
.ring0: |
mov edi, [eax+TSS._esp0] |
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 + TSS._trap], 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 + TSS._trap], 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/tags/kolibri0.6.5.0/core/fpu.inc |
---|
0,0 → 1,223 |
init_fpu: |
clts |
fninit |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
stdcall kernel_alloc, 512*256 |
mov [fpu_data], eax |
mov ebx, cr4 |
mov ecx, cr0 |
or ebx, CR4_OSFXSR+CR4_OSXMMEXPT |
mov cr4, ebx |
and ecx, not (CR0_MP+CR0_EM) |
or ecx, CR0_NE |
mov cr0, ecx |
mov dword [esp-4], SSE_INIT |
ldmxcsr [esp-4] |
xorps xmm0, xmm0 |
xorps xmm1, xmm1 |
xorps xmm2, xmm2 |
xorps xmm3, xmm3 |
xorps xmm4, xmm4 |
xorps xmm5, xmm5 |
xorps xmm6, xmm6 |
xorps xmm7, xmm7 |
fxsave [eax] |
ret |
.no_SSE: |
stdcall kernel_alloc, 112*256 |
mov [fpu_data], eax |
mov ecx, cr0 |
and ecx, not CR0_EM |
or ecx, CR0_MP+CR0_NE |
mov cr0, ecx |
fnsave [eax] |
ret |
align 4 |
proc fpu_save |
clts |
mov ebx, [fpu_owner] |
shl ebx, 8 |
mov eax, [ebx+PROC_BASE+0x10] |
mov ebx, [CURRENT_TASK] |
mov [fpu_owner], ebx |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxsave [eax] |
fninit ;re-init fpu |
ret |
.no_SSE: |
fnsave [eax] |
ret |
endp |
align 4 |
proc fpu_restore |
mov ebx, [CURRENT_TASK] |
shl ebx, 8 |
mov eax, [ebx+PROC_BASE+0x10] |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxrstor [eax] |
ret |
.no_SSE: |
fnclex ;fix possible problems |
frstor [eax] |
ret |
endp |
align 4 |
e7: ;#NM exception handler |
save_ring3_context |
clts |
mov ax, os_data |
mov ds, ax |
mov es, ax |
mov ebx, [fpu_owner] |
cmp ebx, [CURRENT_TASK] |
je .exit |
shl ebx, 8 |
mov eax, [ebx+PROC_BASE+APPDATA.fpu_state] |
bt [cpu_caps], CAPS_SSE |
jnc .no_SSE |
fxsave [eax] |
mov ebx, [CURRENT_TASK] |
mov [fpu_owner], ebx |
shl ebx, 8 |
mov eax, [ebx+PROC_BASE+APPDATA.fpu_state] |
fxrstor [eax] |
.exit: |
restore_ring3_context |
iret |
.no_SSE: |
fnsave [eax] |
mov ebx, [CURRENT_TASK] |
mov [fpu_owner], ebx |
shl ebx, 8 |
mov eax, [ebx+PROC_BASE+APPDATA.fpu_state] |
frstor [eax] |
restore_ring3_context |
iret |
iglobal |
fpu_owner dd 1 |
endg |
reg_eip equ ebp+4 |
reg_cs equ ebp+8 |
reg_eflags equ ebp+12 |
reg_esp equ ebp+16 |
reg_ss equ ebp+20 |
align 4 |
except_16: ;fpu native exceptions handler |
push ebp |
mov ebp, esp |
push eax |
push ebx |
push ecx |
push edx |
mov ebx, [ss:CURRENT_TASK] |
shl ebx, 8 |
mov eax, [ss:ebx+PROC_BASE+APPDATA.fpu_handler] |
test eax, eax |
jz .default |
mov ecx, [reg_eip] |
mov edx, [reg_esp] |
sub edx, 4 |
mov [ss:edx+new_app_base], ecx |
mov [reg_esp], edx |
mov dword [reg_eip], eax |
pop edx |
pop ecx |
pop ebx |
pop eax |
leave |
iretd |
.default: |
pop edx |
pop ecx |
pop ebx |
pop eax |
leave |
save_ring3_context ;debugger support |
mov bl, 16 |
jmp exc_c |
align 4 |
except_19: ;sse exceptions handler |
push ebp |
mov ebp, esp |
push eax |
push ebx |
push ecx |
push edx |
mov ebx, [ss:CURRENT_TASK] |
shl ebx, 8 |
mov eax, [ss:ebx+PROC_BASE+APPDATA.sse_handler] |
test eax, eax |
jz .default |
mov ecx, [reg_eip] |
mov edx, [reg_esp] |
sub edx, 4 |
mov [ss:edx+new_app_base], ecx |
mov [reg_esp], edx |
mov dword [reg_eip], eax |
pop edx |
pop ecx |
pop ebx |
pop eax |
leave |
iretd |
.default: |
pop edx |
pop ecx |
pop ebx |
pop eax |
leave |
save_ring3_context ;debugger support |
mov bl, 19 |
jmp exc_c |
restore reg_eip |
restore reg_cs |
restore reg_eflags |
restore reg_esp |
restore reg_ss |
/kernel/tags/kolibri0.6.5.0/core/sched.inc |
---|
0,0 → 1,204 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; 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 |
; \begin{Mario79} |
cmp [dma_task_switched], 1 |
jne .find_next_task |
mov [dma_task_switched], 0 |
mov ebx, [dma_process] |
cmp [0x3000], ebx |
je .return |
mov edi, [dma_slot_ptr] |
mov [0x3000], ebx |
mov [0x3010], edi |
jmp @f |
.find_next_task: |
; \end{Mario79} |
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/tags/kolibri0.6.5.0/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 |