AHCI Read hard disk sectors

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
iman
Member
Member
Posts: 84
Joined: Wed Feb 06, 2019 10:41 am
Libera.chat IRC: ImAn

AHCI Read hard disk sectors

Post by iman »

Dear.
In this link https://wiki.osdev.org/AHCI, which is the AHCI tutorial in OSDev wiki page, there is a whole explanation of the topic.
I could not find a clean explanation for why each PRDT.dbc field has been given 8KB size (and not more).

Code: Select all

// 8K bytes (16 sectors) per PRDT
	for (int i=0; i<cmdheader->prdtl-1; i++)
	{
		cmdtbl->prdt_entry[i].dba = (uint32_t) buf;
		cmdtbl->prdt_entry[i].dbc = 8*1024-1;	// 8K bytes (this value should always be set to 1 less than the actual value)
		cmdtbl->prdt_entry[i].i = 1;
		buf += 4*1024;	// 4K words
		count -= 16;	// 16 sectors
	}
	// Last entry
	cmdtbl->prdt_entry[i].dba = (uint32_t) buf;
	cmdtbl->prdt_entry[i].dbc = (count<<9)-1;	// 512 bytes per sector
	cmdtbl->prdt_entry[i].i = 1;
In my own OS implementation, I have a file as large as 100 KB. I tried to read the content of the file from the disk, once like above, with:

Code: Select all

dbc = 8*1024-1;
buf += 4*1024; 
count -= 16;
and once with new configuration:

Code: Select all

dbc = 32*1024-1;
buf += 16*1024; 
count -= 64;
In the second case, the total speed of reading was almost 50X slower than the first case.
This is where I got confused. I thought for a similar 100 KB file, once you increase the dbc of the PRDT, you would gain some more performance from your hard disk.
Am I wrong or is there a problem?

Best regards.
Iman.
Iman Abdollahzadeh
Github
Codeberg
User avatar
BenLunt
Member
Member
Posts: 1041
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: AHCI Read hard disk sectors

Post by BenLunt »

The DBC field is 22 bits in length. This gives a max value of 0x003FFFFF or 4Meg of data. i.e.: You can read up to 4Meg at a time using one PRD entry. This is not necessarily a coincidence. The Intel paging mechanism can use 4 Meg pages so this makes it quite easy to read to physical addresses when virtual addresses are given.

I don't know why you have a 50 times slower delay when reading more per PRD entry. I would bet it is not related to this code but maybe something else.

Ben
- http://www.fysnet.net/media_storage_devices.htm
User avatar
iman
Member
Member
Posts: 84
Joined: Wed Feb 06, 2019 10:41 am
Libera.chat IRC: ImAn

Re: AHCI Read hard disk sectors

Post by iman »

BenLunt wrote:You can read up to 4Meg at a time using one PRD entry
Dear Ben.
If I can read 4MB at a time, why would I use, instead, 8KB (in case of for example I have a file as large as 8MB)?
Does it make a difference to read 4MB data 2 times or read 8KB data 1024 times?
Thanks.
Iman.
Iman Abdollahzadeh
Github
Codeberg
User avatar
iocoder
Member
Member
Posts: 208
Joined: Sun Oct 18, 2009 5:47 pm
Libera.chat IRC: iocoder
Location: Alexandria, Egypt | Ottawa, Canada
Contact:

Re: AHCI Read hard disk sectors

Post by iocoder »

iman wrote:
BenLunt wrote:You can read up to 4Meg at a time using one PRD entry
Dear Ben.
If I can read 4MB at a time, why would I use, instead, 8KB (in case of for example I have a file as large as 8MB)?
Does it make a difference to read 4MB data 2 times or read 8KB data 1024 times?
Thanks.
Iman.
Because your virtual memory layout doesn't necessarily map to a contiguous region in RAM.

If a process wants to read a file which has size of 8MB, there is a high chance that the physical pages that are allocated by the process/OS are fragmented over physical memory, that's why AHCI, USB, NVRAM, etc. allow you to split the data into chunks.

If you don't use paging and you are not worried about physical RAM fragmentation, then surely you can use the maximum size in your PRDs.

There is a big difference between the process that the controller performs to read sectors from the disk (this is the one that affects performance), and the process that the controller uses in order to store the read data to RAM (DMA/PCIe). The purpose of the PRD table is to describe "where to store the data that the controller is already reading from the disk". RAM is a random-access storage medium, so storing data at different locations in memory shouldn't affect performance.

That being said, I can't see how changing the number of PRD entries would affect performance? I suggest you give us more information about your analysis.
User avatar
BenLunt
Member
Member
Posts: 1041
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: AHCI Read hard disk sectors

Post by BenLunt »

iocoder is correct. The reason for the multiple entries and to use lower valued transfers has to do with paging. For example, if you have 4k pages, you most likely will transfer 4k at a time.

Since the AHCI *must* use physical addresses, you have to place physical addresses in the PRD entries. However, the buffer to fill might be a linear virtual buffer. So that you don't have to read in the data to a temp buffer, then transfer it to the linear virtual buffer--a process that would take a big hit on performance--you simply calculate the physical address of every 4k block of your virtual buffer. For example:

Code: Select all

PTR = virtual address of MyLinearVirtualBuffer
i = 0
while not past end of buffer {
  PRD[i].address = physical address of PTR
  PTR = PTR + 4k
  i = i + 1
}
This allows a single read *directly* to your linear virtual buffer.

This is the reason for multiple PRD entries using small transfer values (4k normally). You can combine 4k pages if they fall consecutively after each other, physically in memory.

Ben
- http://www.fysnet.net/osdesign_book_series.htm
Post Reply