From 78af4fb9964922c602c19c84f9d72dff41669548 Mon Sep 17 00:00:00 2001 From: Abdur-Rahman Mansoor Date: Sat, 25 May 2024 18:56:58 -0400 Subject: [PATCH] fix lots of nasty bugs! --- drivers/nvme/nvme.asm | 123 +++++++++++++++++------------------------- drivers/nvme/nvme.inc | 54 +++++++++---------- 2 files changed, 77 insertions(+), 100 deletions(-) diff --git a/drivers/nvme/nvme.asm b/drivers/nvme/nvme.asm index b0b3607..dde731d 100644 --- a/drivers/nvme/nvme.asm +++ b/drivers/nvme/nvme.asm @@ -42,13 +42,13 @@ proc START c, reason:dword test eax, eax jz .err xor ecx, ecx - mov ebx, eax .loop: - stdcall device_is_compat, dword [ebx + ecx * sizeof.pcidev] + mov ebx, dword [p_nvme_devices] + stdcall device_is_compat, ebx test eax, eax jz @f - stdcall nvme_init, dword [ebx + ecx * sizeof.pcidev] + stdcall nvme_init, ebx @@: inc ecx @@ -157,20 +157,23 @@ proc detect_nvme mov ebx, dword [p_nvme_devices] test ebx, ebx jnz @f - invoke KernelAlloc, TOTAL_PCIDEVS_MALLOC_SZ + invoke KernelAlloc, sizeof.pcidev test eax, eax jz .err_no_mem mov dword [p_nvme_devices], eax + DEBUGF DBG_INFO, "(NVMe) Allocated pcidev struct at 0x%x\n", [p_nvme_devices] @@: - mov ebx, dword [p_nvme_devices] mov ecx, dword [pcidevs_len] dec ecx pop eax + mov ebx, dword [p_nvme_devices] + movzx edx, byte [eax + PCIDEV.bus] - mov byte [ebx + ecx * sizeof.pcidev + pcidev.bus], dl + mov byte [ebx + pcidev.bus], dl movzx edx, byte [eax + PCIDEV.devfn] - mov byte [ebx + ecx * sizeof.pcidev + pcidev.devfn], dl + mov byte [ebx + pcidev.devfn], dl + pop edx jmp .next_dev @@ -188,44 +191,30 @@ endp proc device_is_compat stdcall, pci:dword - push ebx - invoke PciRead32, dword [pci + pcidev.bus], dword [pci + pcidev.devfn], PCI_header00.base_addr_0 + push ebx + mov ebx, [pci] + invoke PciRead32, dword [ebx + pcidev.bus], dword [ebx + pcidev.devfn], PCI_header00.base_addr_0 and eax, 0xfffffff0 test eax, eax jz .failure - invoke MapIoMem, eax, sizeof.NVME_REG_MAP, PG_SW+PG_NOCACHE + invoke MapIoMem, eax, sizeof.NVME_MMIO, PG_SW+PG_NOCACHE test eax, eax jz .failure - mov dword [pci + pcidev.mmio_ptr], eax - mov ebx, dword [eax + NVME_REG_MAP.VS] - - if __DEBUG__ - push ecx - mov ecx, ebx - shr ecx, 16 - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe controller version: %u.%u.%u\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], ecx, bh, bl - pop ecx - end if - - if 0 - cmp ebx, NVM_SUPPORTED_CONTROLLER_VERSION - jne .unsupported - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe controller version is supported\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn] - end if - + DEBUGF DBG_INFO, "(NVMe) MMIO allocated at: 0x%x\n", eax + mov ebx, [pci] + mov dword [ebx + pcidev.mmio_ptr], eax + mov eax, dword [eax + NVME_MMIO.VS] + DEBUGF DBG_INFO, "(NVMe) controller version: 0x%x\n", eax + pop ebx xor eax, eax inc eax - pop ebx ret -.unsupported: - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): unsupported controller version\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn] - .failure: - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): something went wrong checking NVMe device compatibility\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn] - xor eax, eax + PDEBUGF DBG_INFO, "PCI(%u.%u.%u): something went wrong checking NVMe device compatibility\n", byte [ebx + pcidev.bus], byte [ebx + pcidev.devfn] pop ebx + xor eax, eax ret endp @@ -233,81 +222,69 @@ endp ; nvme_init: Initializes the NVMe controller proc nvme_init stdcall, pci:dword - push ebx ecx - mov eax, dword [pci + pcidev.mmio_ptr] - mov bx, word [eax + NVME_REG_MAP.CAP] - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe maximum queue entries supported: %u\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], bx + push ebx + mov eax, dword [pci] + mov eax, dword [eax + pcidev.mmio_ptr] + mov ebx, dword [eax + NVME_MMIO.CAP] test ebx, CAP_CQR jz .cqr_not_req - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe contiguous queues required\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn] .cqr_not_req: ; For some reason, bit 7 (No I/O command set supported) is also set to 1 despite bit 0 (NVM command set) ; being set to 1.. so I am not sure if bit 7 should be checked at all.. investigate later. - mov ebx, dword [eax + NVME_REG_MAP.CAP + 4] + mov ebx, dword [eax + NVME_MMIO.CAP + 4] test ebx, CAP_CSS_NVM_CMDSET jz .exit_fail - if __DEBUG__ - mov ecx, ebx - and ebx, CAP_MPSMIN - and ecx, CAP_MPSMAX - shr ebx, 16 - shr ecx, 16 - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe memory page size minimum: %u\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], ebx - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe memory page size maximum: %u\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], ecx - end if - ; Reset controller - mov ebx, dword [eax + NVME_REG_MAP.CC] - stdcall nvme_controller_reset, [pci] + stdcall nvme_controller_reset, [pci] xor eax, eax inc eax - pop ecx ebx + pop ebx ret .exit_fail: PDEBUGF DBG_INFO, "PCI(%u.%u.%u): failed to initialize NVMe controller\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn] xor eax, eax - pop ecx ebx + pop ebx ret endp proc nvme_controller_reset stdcall, pci:dword + DEBUGF DBG_INFO, "(NVMe) Resetting Controller...\n" push ebx - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): Resetting NVMe controller\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn] - mov eax, dword [pci + pcidev.mmio_ptr] - mov ebx, dword [eax + NVME_REG_MAP.CSTS] + mov ebx, dword [pci] + mov ebx, dword [ebx + pcidev.mmio_ptr] + mov eax, dword [ebx + NVME_MMIO.CC] + and eax, 0xfffffffe ; CC.EN = 0 + mov dword [ebx + NVME_MMIO.CC], eax + stdcall nvme_wait, [pci] ; Wait for controller to be brought to idle state, CSTS.RDY should be cleared to 0 when this happens .wait: - test ebx, CSTS_RDY + mov eax, dword [ebx + NVME_MMIO.CSTS] + test eax, CSTS_RDY jnz .wait - mov ebx, dword [eax + NVME_REG_MAP.CC] - PDEBUGF DBG_INFO, "PCI(%u.%u.%u): NVMe.CC = 0x%x\n", byte [pci + pcidev.bus], byte [pci + pcidev.devfn], ebx - and ebx, 0xfffffffe - mov dword [eax + NVME_REG_MAP.CC], ebx - stdcall nvme_wait, [pci] + DEBUGF DBG_INFO, "(NVMe) Successfully reset controller...\n" pop ebx ret endp +; Should be called only after the value of CC.EN has changed proc nvme_wait stdcall, pci:dword - push esi - mov eax, dword [pci + pcidev.mmio_ptr] - mov eax, dword [eax + NVME_REG_MAP.CAP] + mov eax, [pci] + mov eax, [eax + pcidev.mmio_ptr] + mov eax, dword [eax + NVME_MMIO.CAP] and eax, CAP_TO shr eax, 24 - DEBUGF DBG_INFO, "CSTS.TO = %u\n", eax mov esi, eax - ;imul esi, 500 - ;invoke Sleep - pop esi + imul esi, 50 + invoke Sleep ret endp @@ -316,17 +293,17 @@ proc nvme_cleanup DEBUGF DBG_INFO, "(NVMe): Cleaning up...\n" push ecx - xor ecx, ecx mov eax, dword [p_nvme_devices] + mov ecx, eax test eax, eax jnz .loop ret .loop: ;invoke KernelFree, dword [p_nvme_devices + ecx * sizeof.pcidev + pcidev.ident_ptr] - inc ecx - cmp ecx, dword [pcidevs_len] - jne .loop + dec ecx + test ecx, ecx + jnz .loop invoke KernelFree, dword [p_nvme_devices] pop ecx ret diff --git a/drivers/nvme/nvme.inc b/drivers/nvme/nvme.inc index 86ba5d7..152cdc3 100644 --- a/drivers/nvme/nvme.inc +++ b/drivers/nvme/nvme.inc @@ -163,41 +163,41 @@ CSTS_SHST = (1 shl 2) or (1 shl 3) CSTS_NSSRO = 1 shl 4 CSTS_PP = 1 shl 5 -struct NVME_REG_MAP - CAP rq 1 ; Controller Capabilities - VS rd 1 ; Version - INTMS rd 1 ; Interrupt Mask Set - INTMC rd 1 ; Interrupt Mask Clear - CC rd 1 ; Controller Configuration - rd 1 ; Reserved - CSTS rd 1 ; Controller Status - NSSR rd 1 ; NVM Subsystem Reset - AQA rd 1 ; Admin Queue Attributes - ASQ rq 1 ; Admin Submission Queue Base Address - ACQ rq 1 ; Admin Completion Queue Base Address - CMBLOC rd 1 ; Controller Memory Buffer Location +struct NVME_MMIO + CAP dq ? ; Controller Capabilities + VS dd ? ; Version + INTMS dd ? ; Interrupt Mask Set + INTMC dd ? ; Interrupt Mask Clear + CC dd ? ; Controller Configuration + dd ? ; Reserved + CSTS dd ? ; Controller Status + NSSR dd ? ; NVM Subsystem Reset + AQA dd ? ; Admin Queue Attributes + ASQ dq ? ; Admin Submission Queue Base Address + ACQ dq ? ; Admin Completion Queue Base Address + CMBLOC dd ? ; Controller Memory Buffer Location ends ; Submission Queue Entry (64 bytes) struct SQ_ENTRY - cdw0 rd 1 - nsid rd 1 - cdw2 rd 1 - cdw3 rd 1 - mptr rq 1 - dptr rq 1 - cdw10 rd 1 - cdw11 rd 1 - cdw12 rd 1 - cdw13 rd 1 - cdw14 rd 1 - cdw15 rd 1 + cdw0 dd ? + nsid dd ? + cdw2 dd ? + cdw3 dd ? + mptr dq ? + dptr dq ? + cdw10 dd ? + cdw11 dd ? + cdw12 dd ? + cdw13 dd ? + cdw14 dd ? + cdw15 dd ? ends ; Completion Queue Entry (16 bytes) struct CQ_ENTRY cdw0 dd ? - dd ? ; reserved + rd 1 ; reserved sqhd dw ? sqid dw ? cid dw ? @@ -207,7 +207,7 @@ ends struct pcidev bus db ? devfn db ? - dw ? + rw 1 mmio_ptr dd ? ends TOTAL_PCIDEVS = 4