2
0
mirror of https://git.missingno.dev/kolibrios-nvme-driver/ synced 2024-12-22 22:08:47 +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
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
mov edi, [prp_list_ptr]
@ -482,69 +482,96 @@ endp
proc build_prp_list stdcall, nprps:dword
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 esi, esi
mov ecx, [nprps]
mov ebx, ecx
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
test eax, eax
jz .err
mov dword [esp + 12], eax
mov edi, eax
.build_prp_list:
mov ecx, ebx
cmp ecx, PAGE_SIZE / 8
jne @f
mov ecx, PAGE_SIZE / 8
@@:
imul ecx, PAGE_SIZE
; allocate a massive buffer for the PRPs themselves
invoke KernelAlloc, ecx
test eax, eax
jz .err
invoke GetPhysAddr
mov esi, eax
xor ecx, ecx
push esi
cmp dword [esp], 0
jz @f
.loop:
; check if we need to build another PRP list
mov eax, ebx
sub eax, PAGE_SIZE
; is this the last entry in the list? If so, build yet another PRP list here
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
; we need to store the pointer of the newly allocated
; PRP list to the previous PRP list last slot
mov eax, dword [esp + 8]
mov dword [eax + PAGE_SIZE - 8], esi
mov dword [eax + PAGE_SIZE - 4], 0
@@:
mov eax, esi
push ecx
invoke GetPhysAddr
pop ecx
mov dword [edi + ecx * 4], eax
mov dword [esp], esi
.loop:
mov dword [edi + ecx * 4], esi
mov dword [edi + ecx * 4 + 4], 0
add esi, PAGE_SIZE
inc ecx
cmp ecx, ebx
jb .loop
.success:
mov eax, edi
pop esi
pop edi ebx esi
ret
.cleanup_prp_list:
pop esi
invoke KernelFree, esi
jne .loop
; check if we we need to build another PRP list
mov dword [esp + 8], edi
mov ebx, [nprps]
cmp ebx, PAGE_SIZE / 8
je .build_prp_list
.err:
test edi, edi
mov esi, dword [esp]
test esi, esi
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
xor eax, eax
ret
@ -575,7 +602,6 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, numsectors:dword
cmp edx, eax
jae @f
DEBUGF DBG_INFO, "Allocating single entry for PRP2\n"
; allocate a single PRP entry for PRP2
invoke AllocPage
test eax, eax