Page 1 of 1
AHCI Read hard disk sectors
Posted: Fri Dec 06, 2019 6:49 am
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.
Re: AHCI Read hard disk sectors
Posted: Fri Dec 06, 2019 6:25 pm
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
Re: AHCI Read hard disk sectors
Posted: Thu Dec 19, 2019 8:21 am
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.
Re: AHCI Read hard disk sectors
Posted: Thu Dec 19, 2019 9:53 am
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.
Re: AHCI Read hard disk sectors
Posted: Thu Dec 19, 2019 5:38 pm
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