Physical Memory

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
osdnlo
Member
Member
Posts: 136
Joined: Thu Feb 25, 2010 5:39 pm

Physical Memory

Post 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
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
User avatar
thepowersgang
Member
Member
Posts: 734
Joined: Tue Dec 25, 2007 6:03 am
Libera.chat IRC: thePowersGang
Location: Perth, Western Australia
Contact:

Re: Physical Memory

Post 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.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
User avatar
osdnlo
Member
Member
Posts: 136
Joined: Thu Feb 25, 2010 5:39 pm

Re: Physical Memory

Post 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.
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
User avatar
thepowersgang
Member
Member
Posts: 734
Joined: Tue Dec 25, 2007 6:03 am
Libera.chat IRC: thePowersGang
Location: Perth, Western Australia
Contact:

Re: Physical Memory

Post 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))
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
User avatar
osdnlo
Member
Member
Posts: 136
Joined: Thu Feb 25, 2010 5:39 pm

Re: Physical Memory

Post 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?
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Physical Memory

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
osdnlo
Member
Member
Posts: 136
Joined: Thu Feb 25, 2010 5:39 pm

Re: Physical Memory

Post 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?
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
User avatar
osdnlo
Member
Member
Posts: 136
Joined: Thu Feb 25, 2010 5:39 pm

Re: Physical Memory

Post 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?
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
Post Reply