From 1e315791fbeb402157f818a7c42e82d424e150df Mon Sep 17 00:00:00 2001 From: Abdur-Rahman Mansoor Date: Thu, 18 Jul 2024 17:01:26 -0400 Subject: [PATCH] fix: PRP list allocation --- drivers/nvme/nvme.asm | 75 ++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/drivers/nvme/nvme.asm b/drivers/nvme/nvme.asm index 3197aa2..a56e380 100644 --- a/drivers/nvme/nvme.asm +++ b/drivers/nvme/nvme.asm @@ -454,29 +454,19 @@ proc get_log_page stdcall, pci:dword, prp1:dword, lid:byte endp -proc build_prp_list stdcall, nprps:dword, buf_physical:dword, prp_list_ptr:dword +proc build_prp_list stdcall, nprps:dword, buf:dword, prp_list_ptr:dword push esi ebx edi - sub esp, 16 + sub esp, 4 + ; stack: + ; [esp]: virtual pointer to first PRP list ; 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] @@ -484,16 +474,20 @@ proc build_prp_list stdcall, nprps:dword, buf_physical:dword, prp_list_ptr:dword ; we'll store consecutive PRP list buffers here, for example ; given 2 PRP lists, we allocate 2 continuous pages + push ecx invoke KernelAlloc, ecx ; store pointers to the PRP entries here + pop ecx test eax, eax jz .err - mov dword [esp + 12], eax + mov dword [esp], eax mov edi, eax mov eax, [prp_list_ptr] mov dword [eax], edi + shr ecx, 1 + stdcall memsetdz, edi, ecx - ; note we assume buf_physical is page-aligned - mov esi, [buf_physical] + ; note we assume buf is page-aligned + mov esi, [buf] .build_prp_list: ; ensure we don't cross a page boundary @@ -505,40 +499,41 @@ proc build_prp_list stdcall, nprps:dword, buf_physical:dword, prp_list_ptr:dword @@: xor ecx, ecx - cmp dword [esp], 0 - jz @f + cmp dword [esp], edi + je .loop - ; 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 - jmp .loop - -@@: - mov dword [esp], esi + ; we need to store the pointer of the next + ; PRP list to the previous PRP list last entry + mov eax, edi + invoke GetPhysAddr + mov dword [edi - 8], eax + mov dword [edi - 4], 0 .loop: - mov dword [edi + ecx * 4], esi + mov eax, esi + invoke GetPhysAddr + mov dword [edi + ecx * 4], eax mov dword [edi + ecx * 4 + 4], 0 - DEBUGF DBG_INFO, "PRP: %x\n", esi + DEBUGF DBG_INFO, "PRP: %x\n", eax add esi, PAGE_SIZE inc ecx cmp ecx, ebx jne .loop + ; check if we we need to build another PRP list - mov dword [esp + 8], edi add edi, PAGE_SIZE cmp ebx, PAGE_SIZE / 8 je .build_prp_list + + ; PRP list successfully created mov eax, dword [esp] invoke GetPhysAddr - add esp, 16 + add esp, 4 pop edi ebx esi ret .err: - add esp, 16 + add esp, 4 pop edi ebx esi xor eax, eax ret @@ -607,12 +602,9 @@ proc alloc_dptr stdcall, ns:dword, prps_ptr:dword, numsectors:dword, prp_list_pt inc eax @@: - mov edx, dword [buf] - and edx, not (PAGE_SIZE - 1) - add edx, PAGE_SIZE - xchg eax, edx - ; push edx? - invoke GetPhysAddr + mov eax, [buf] + and eax, not (PAGE_SIZE - 1) + add eax, PAGE_SIZE stdcall build_prp_list, edx, eax, [prp_list_ptr] test eax, eax jz .err @@ -1092,11 +1084,12 @@ proc nvme_init stdcall, pci:dword test eax, eax jz .exit_fail mov edx, NVM_CMD_READ - mov dword [eax], 1 - add edi, 4094 + mov dword [eax], 17 + ;add edi, 4094 stdcall nvme_readwrite, [esi + pcidev.nsinfo], edi, 0, 0, eax test eax, eax jz .exit_fail + add edi, PAGE_SIZE DEBUGF DBG_INFO, "STRING: %s\n", edi end if DEBUGF DBG_INFO, "nvme%u: Successfully initialized driver\n", [esi + pcidev.num]