Update: OK, so no progress at all. Also, for some odd reason my OS keeps page faulting and I can't figure out why. (My VGA output gets spurious and weird too by the time this happens.) This is what it looks like:
Kernel control a comm »@ ole (KC3)
Type 'he for ¦@ of commands
*** WA NG * ¦@ re currently oper ng i ¦@ mode. Remember t wit ¦@ comes
responsibil , an ¦@ e responsible for y da ¦@ at arise out of y
mis ¦@ his console, your shan +@ devices and port your +@ to
follow docume tion ¦@
3> Page fault: (empty)
Caused by read from memory address VirtAddr(0x10)
Stack frame: InterruptStackFrame {
instruction_pointer: VirtAddr(0x20a07d),
code_segment: 8,
cpu_flags: 0x2,
stack_pointer: VirtAddr(0x10000201210),
stack_segment: 0,
}
Registers:
RAX = 100002010A0 RBX = 1
RCX = 1 RDX = 23C313
RSI = 0 RDI = 100002010A0
RSP = 10000200578 RBP = 10
R8 = 0 R9 = 1
R10 = 10000200F38 R11 = 2490B0
R12 = 1 R13 = 24D060
R14 = 10000201238 R15 = 10000201530
RFLAGS = 12 CR0 = 80010613
CR2 = 10 CR3 = 1000
CR4 = 620 CR8 = 0
EFER = 0
Segments:
CS = 8 DS = 10
SS = 0 ES = 10
FS = 0 GS= 0
FSBASE = 0 GSBASE = 0
KERNELGSBASE = 0
This is incredibly confusing since my code does not print any symbols whatsoever (only ASCII characters). At first I thought that the page fault was because I enabled Spectre mitigation's via retpoline, but it does that even after I turn the features off. I've also debugged my kernel multiple times now and get the same output; my ATA read function appears to be working fine. The error, I think, is when the system is trying to access the data that the disk returns. I thought about dumping the memory and uploading it here but I don't think that would be very useful to anyone. I don't have memory analysis tools or skills myself -- at least, not of that kind.
I also thought that the strange output could be because the SMBIOS code was enabled (which might've been causing the page fault), but I've removed that completely and it still happens. The memory address is random too: I've seen it try to read to address 0x10 and 0x50. Though I have intel HDA code and SB16 code, the SB16 code is not integrated into the build yet and the HDA code does nothing useful right now. I'm not really sure what to try next... am I misunderstanding the way AHCI works? Am I misinterpreting the wiki and/or the specification?
Edit: just tried to map 0x1000-0x1200, but the kernel indicates that the pages for that address range are already mapped. I thought that since CR3 indicated 1000h I should try to map it but it appears that's already been done for me.
Edit 2: OK, so I just moved the HBA write/read buffer to the range 0x1000000-0x100c350. Then I forgot that I was allocating the buffer in paged memory space. I moved it to physical mappings and now I'm getting all zeros (I was getting all zeros before I moved it from paged to physical but after the move to the new address space). I raised the sector/LBA count to 64 to see if I wasn't catching the boot information at the immediate start of the disk but am still getting nothing. (I'm still reading only 512 bytes from the start of the buffer because I don't know my disk geometry and don't know how I'd even go about detecting that.) I also was reading the information on the Read DMA Ext command (INCITS 452-2009: AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS), section 7.25). In case the one on the wiki and this one differ, this one says:
7.25 READ DMA EXT - 25h, DMA
7.25.1 Feature Set
This 48-bit command is mandatory for devices implementing the 48-bit Address feature set.
7.25.2 Description
The READ DMA EXT command allows the host to read data using the DMA data transfer protocol.
7.25.3 Inputs
Name | Description
Feature | Reserved
Count | The number of logical sectors to be transferred. A value of 0000h indicates that 65,536 logical sectors are to be transferred
LBA | LBA of first logical sector to be transferred
Device |
Bit | Description
7 | Obsolete
6 | Shall be set to one
5 | Obsolete
4 | Transport Dependent - See 6.2.11
3:0 | Reserved
Command | 7:0 25h
7.25.4 Normal Outputs
See table 111.
7.25.5 Error Outputs
If an unrecoverable error occurs while the device is processing this command, then the device shall return command completion with the Error bit set to one and the LBA field set to the LBA of the logical sector where the first unrecoverable error occurred. The validity of the data transferred is indeterminate. See table 131.
I don't think the device is returning an error status (TFD doesn't say so) so...
So... I'm kinda stuck here. What should I try next?