2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2025-01-09 06:25:55 +01:00

perf: dont use recursion for build_prp_list + remove redundant calls

This commit is contained in:
Abdur-Rahman Mansoor 2024-07-11 13:37:05 -04:00
parent 1f5815351c
commit 8101007350

View File

@ -452,7 +452,7 @@ proc get_log_page stdcall, pci:dword, dptr:dword, lid:byte
endp endp
proc free_prp_list stdcall, prp_list_ptr:dword, nprps:dword, recursive:byte proc free_prp_list stdcall, prp_list_ptr:dword, nprps:dword
push edi push edi
mov edi, [prp_list_ptr] mov edi, [prp_list_ptr]
@ -482,69 +482,96 @@ endp
proc build_prp_list stdcall, nprps:dword proc build_prp_list stdcall, nprps:dword
push esi ebx edi push esi ebx edi
sub esp, 16
; here, we store the pointer to the very first
; PRP list so that free_prp_list can free the
; entire PRP list if something goes wrong, it
; also serves as our return value placeholder
mov dword [esp], 0
; store the number of PRPs here, we need to
; cache the result here since we'll subtract
; nprps regularly. If we don't we will lose
; the value.
mov eax, [nprps]
mov dword [esp + 4], eax
; store consecutive PRP list buffer here, since
; we'll increment the PRP list pointer continuously
; its important to cache the value
mov dword [esp + 12], 0
xor edi, edi xor edi, edi
xor esi, esi xor esi, esi
mov ecx, [nprps] mov ecx, [nprps]
mov ebx, ecx mov ebx, ecx
shl ecx, 3 shl ecx, 3
; we'll store consecutive PRP list buffers here, for example
; given 2 PRP lists, we allocate 2 continuous pages
invoke KernelAlloc, ecx ; store pointers to the PRP entries here invoke KernelAlloc, ecx ; store pointers to the PRP entries here
test eax, eax test eax, eax
jz .err jz .err
mov dword [esp + 12], eax
mov edi, eax mov edi, eax
.build_prp_list:
mov ecx, ebx mov ecx, ebx
cmp ecx, PAGE_SIZE / 8
jne @f
mov ecx, PAGE_SIZE / 8
@@:
imul ecx, PAGE_SIZE imul ecx, PAGE_SIZE
; allocate a massive buffer for the PRPs themselves
invoke KernelAlloc, ecx invoke KernelAlloc, ecx
test eax, eax test eax, eax
jz .err jz .err
invoke GetPhysAddr
mov esi, eax mov esi, eax
xor ecx, ecx xor ecx, ecx
push esi cmp dword [esp], 0
jz @f
.loop: ; we need to store the pointer of the newly allocated
; check if we need to build another PRP list ; PRP list to the previous PRP list last slot
mov eax, ebx mov eax, dword [esp + 8]
sub eax, PAGE_SIZE mov dword [eax + PAGE_SIZE - 8], esi
; is this the last entry in the list? If so, build yet another PRP list here mov dword [eax + PAGE_SIZE - 4], 0
cmp ecx, PAGE_SIZE / 8 - 1
jne @f
push ecx
stdcall build_prp_list, eax, TRUE
pop ecx
test eax, eax
jz .cleanup_prp_list
invoke GetPhysAddr
mov dword [edi + ecx * 4], eax
mov dword [edi + ecx * 4 + 4], 0
jmp .success
@@: @@:
mov eax, esi mov dword [esp], esi
push ecx
invoke GetPhysAddr .loop:
pop ecx mov dword [edi + ecx * 4], esi
mov dword [edi + ecx * 4], eax
mov dword [edi + ecx * 4 + 4], 0 mov dword [edi + ecx * 4 + 4], 0
add esi, PAGE_SIZE add esi, PAGE_SIZE
inc ecx inc ecx
cmp ecx, ebx cmp ecx, ebx
jb .loop jne .loop
; check if we we need to build another PRP list
.success: mov dword [esp + 8], edi
mov eax, edi mov ebx, [nprps]
pop esi cmp ebx, PAGE_SIZE / 8
pop edi ebx esi je .build_prp_list
ret
.cleanup_prp_list:
pop esi
invoke KernelFree, esi
.err: .err:
test edi, edi mov esi, dword [esp]
test esi, esi
jz @f jz @f
invoke KernelFree, edi sub [nprps], PAGE_SIZE / 8
add edi, PAGE_SIZE
stdcall free_prp_list, esi, [esp + 4]
@@: @@:
mov eax, dword [esp + 12]
test eax, eax
jz @f
invoke KernelFree, eax
@@:
add esp, 16
pop edi ebx esi pop edi ebx esi
xor eax, eax xor eax, eax
ret ret
@ -575,7 +602,6 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, numsectors:dword
cmp edx, eax cmp edx, eax
jae @f jae @f
DEBUGF DBG_INFO, "Allocating single entry for PRP2\n"
; allocate a single PRP entry for PRP2 ; allocate a single PRP entry for PRP2
invoke AllocPage invoke AllocPage
test eax, eax test eax, eax