Page 1 of 1

Physical Memory

Posted: Thu Feb 25, 2010 5:57 pm
by osdnlo
Hi, first post. I need a way to retrieve the physical address of a variable, such as an array or struct. I have paging enabled. My first attempt was to use ld to get the physical address of global arrays, then I use that address to cause a page fault, that I resolve. My thought was that I would then have a physical address to use. I'm not sure if that was the case because when I offer that address to a device, the device remains unresponsive. My guess is that my physical address is not a physical address, but maybe an offset?

An example of what I tried would be, let's say array BUFFER is at location 0x01000000. I find that address from ld and I cause a page fault using that address. My fault handler catches it and resolves the fault by mapping it to address 0x9ad000 (for example). I tested the mapping by writing to 0x01000000 and reading from 0x9ad000 and the results are the same. So, shouldn't I be correct to offer the device 0x01000000 after the mapping or am I thinking about this all wrong?

I am really confused. If not using paging, how do I get the physical address of a variable, array, or struct? I could just calc the address, store the address, turn on paging, then map it right? But, how to calc address?

oSDN LO

Re: Physical Memory

Posted: Thu Feb 25, 2010 6:04 pm
by thepowersgang
Well, the first thing you could do is use the known physical base of your kernel (where GRUB loaded it) to get the physical base. Or you could write a method that walks the paging structures for you.

Re: Physical Memory

Posted: Thu Feb 25, 2010 6:11 pm
by osdnlo
thepowersgang wrote:Well, the first thing you could do is use the known physical base of your kernel (where GRUB loaded it) to get the physical base.
Does this apply for when paging is off? My loader loads the kernel at physical address 0x00100000. Do I use that as a base?

So, 0x00100000+&buffer = physical address? Assume that paging is turned off. Thanks.

Re: Physical Memory

Posted: Thu Feb 25, 2010 6:16 pm
by thepowersgang
No, when paging is enabled, your kernel is linked at a certain virtual address (say 0xC0100000), but it is loaded at a physical address (say 0x100000) to get the physical address of a page in the initial kernel binary, you subtract the difference between these values from the address ((uint)&symbol - (0xc0100000 - 0x100000))

Re: Physical Memory

Posted: Thu Feb 25, 2010 6:32 pm
by osdnlo
&buffer = 0x00105000

ADDROF = &buffer
PTE_BASE = 0xC0000000
PHY_BASE = 0x00100000

VRT_BASE = PTE_BASE+PHY_BASE

ADDROF - (VRT_BASE - PHY_BASE) = ?physical? = 0x40105000

Does that look right?

Re: Physical Memory

Posted: Thu Feb 25, 2010 6:42 pm
by Combuster
If you feed in a physical address where a virtual address is expected, it obviously does not work.

You should start with linking your kernel to the virtual address, not the physical address.

Re: Physical Memory

Posted: Thu Feb 25, 2010 7:09 pm
by osdnlo
Combuster wrote:You should start with linking your kernel to the virtual address, not the physical address.
Oh, I see. So, to clarify I should. Map 0x00105000 to 0xC0105000 and the math provided above basically works to strip it back down to 0x00105000 which is the physical address. Is that correct?

Re: Physical Memory

Posted: Fri Feb 26, 2010 1:53 pm
by osdnlo
I really have no idea if I am doing this right. I know that there is a mapping done between this 0xC0105000 and 0x00105000, because if I do this...

Code: Select all

char test[20]={0};
function test()
{
    uint *ptr=(uint *)0xC0105000;
    ptr[0]=0xDEADBEEF;
    printf("\nTEST[0]: %X",test[0]);
}
Answer: 0xDEADBEEF

Although when I offer either address (i.e., 0xC0105000 | 0x00105000), the device complains about a Host System Access Error. If I can access those addresses (R/W) then surely the device should too. What am I doing wrong here? Am I thinking of this wrong? Am I still not getting the correct physical address and maybe only a virtual to virtual mapping and not the physical to virtual mapping I expect?