I have no idea how you decided to do shifts like that. I am assuming you did not take the time to debug the function and see what the values were.
(virt_page>>12), should have easily went well over the value
1023 for a index - most likely right off into some memory and corrupted something.
Code: Select all
/* Map virt_addr onto phys_addr */
void pmman_map(uint32 dir, uint32 phys_addr, uint32 virt_addr, uint32 flags)
{
uint32 phys_page, virt_page;
uint32 *directory;
uint32 *table;
/* Get page boundary below address */
phys_page = phys_addr & 0xfffff000;
virt_page = virt_addr & 0xfffff000;
/* Get PDE */
directory = (uint32*)dir;
if(directory[virt_addr>>22] == 0)
{
/* Table not even here? */
directory[virt_addr>>22] = ALLOCATE_4096_KB_PAGE() | PAGE_USER_RW;
}
/* If directory table not present, set it */
if (!(directory[virt_addr>>22] & PAGE_PRESENT))
{
directory[virt_addr>>22] |= PAGE_USER_RW;
}
/* Set page table entry */
table = (uint32*)(directory[virt_addr>>22] & ~0xFFF);
table[virt_addr<<10>>10>>12] = phys_addr | flags;
}
(bit31)......(bit22) (bit21)......(bit12) (bit11.......bit0)
[-------PDE------] [------PTE--------] [------FLAGS-----]
If you notice
bit11 to
bit0 make twelve bits. Lets inspect the maximum value of twelve bits:
0xFFF = 4095. Each
0xF is a nibble which is
4bits. So we have three
Fs which is three times four equals twelve. Since 0x0
000 starts counting at zero we can note that once we have 0x0
FFF which is
4095 we actually have
4096 counts. So using
0xFFF we can represent a memory address from
0 to
4095. Notice, how they almost make
4096.
The next bit which is
bit11 will make the value
4096 like:
0x1000 = 4096. If you notice this bit with a value of one is in the
PTE slot (above). Lets count them
0xF=4, 0xFF=8, 0xFFF=12, 0x1000=13. That is
bit13 instead of
bit12, right? Nope. My depiction above starts at
bit0 so subtract one from
bit13 and you get
bit12 which is the first bit of the
PTE.
The
PTE has
10bits. The maximum value of
10bits is
0x3FF which is
1023. That makes a total of
1024 PTEs per table since we start counting at zero:
0x000 to
0x3FF. The page directory is exactly the same way which means that the directory has
1024 PDEs (starting at
0 and ending at
1023), and
each table has
1024 PTEs (starting at
0 and ending at
1023).
To extract the bits you use shifts:
(phy_addr>>22): There are
22bits if you count them that make up the
PTE and
FLAGS (12 + 10 = 22). We shift them to the right where they disappear and are replaced by zeros on the left.
(phy_addr>>12 & 0x3FF): This removes the
FLAGS part which is
12bits. The problem is the
PDE is still at the end giving us a crazy value if we tried to use it. So we
AND by
0x3FF which chops the ending off since if you remember
0x3FF is really
10bits.
phy_addr........ =
1011011100 0101011111 011111010101
phy_addr>>12 =
000000000000 1011011100 0101011111
0x3FF = .............
000000000000 0000000000 1111111111
phy_addr>>12 & 0x3FF =
(below - one line)[/i]
..........................000000000000 0000000000 0101011111