Temporarily mapping RSDT problem [fixed]
Posted: Tue May 03, 2011 8:10 am
Hello,
In my design, an Intermediate Loader is loaded by GRUB, which then loads the Kernel. The Intermediate Loader is expected to perform a number of tasks, and relocating the ACPI, MPS and SMBIOS tables is one of them.
I started by relocating the ACPI tables, and it worked as a charm on Bochs. I further tried on QEMU and it also worked smoothly over there. However, when I tried on my laptop (which is a VAIO machine) I got a problem. I need to temporarily map the RSDT to 0xF0000000 so that I can find its length, map the further areas (which are above 0xF0000FFF) and then memcpy it. The problem was that the temporarily mapped RSDT contain garbage values. I decided to investigate further, and found out the following facts:
Here is where I map the RSDT and find out the INCORRECT signature:
A point to note is that every time, the incorrect signature is the same, which means that the problem isn't random. If anyone required more piece of code, I'd surely give it up.
Hope someone helps.
Regards,
Shikhin
In my design, an Intermediate Loader is loaded by GRUB, which then loads the Kernel. The Intermediate Loader is expected to perform a number of tasks, and relocating the ACPI, MPS and SMBIOS tables is one of them.
I started by relocating the ACPI tables, and it worked as a charm on Bochs. I further tried on QEMU and it also worked smoothly over there. However, when I tried on my laptop (which is a VAIO machine) I got a problem. I need to temporarily map the RSDT to 0xF0000000 so that I can find its length, map the further areas (which are above 0xF0000FFF) and then memcpy it. The problem was that the temporarily mapped RSDT contain garbage values. I decided to investigate further, and found out the following facts:
- Before even enabling paging, I checked the contents of the RSDT. All the values were nice and good.
- The above fact led me to the conclusion that either I was messing up the RSDT somewhere or the mapping wasn't happening correctly.
- Just to check whether I was changing the values of the RSDT somewhere, I first enabled paging, printed it's values out, then disabled paging and again printed it's values out. When paging was enabled, the values were wrong, while when paging was disabled, the values were correct.
- This lead me to the idea that I was messing up the mappings. I printed out the mapping value using the self mapped tables (SelfMappedTablePae->PageTable[3][384].Page[0]).
- The RSDT is at 0xBFDF60AC and the value of the above is 0xBFDF6001 which means it is correctly mapped. P.S. I use 0xF00000AC as the RSDT address and that is NOT a problem.
- This verified it is correctly mapped, leading me to nowhere. I was out of clues and decided to post about it here (after talking a lot on IRC).
Code: Select all
void vmmPaeMapFrame(uint32_t address, uint32_t user, uint32_t rw, uint64_t physAddress)
{
address &= 0xFFFFF000;
physAddress -= (physAddress % 0x1000);
uint32_t flags = 0x1 + (rw << 1) + (user << 2);
uint32_t pdpt = address >> 30;
uint32_t dir = (address << 2) >> 23;
uint32_t table = (address << 11) >> 23;
uint64_t *page;
pageDirPae_t *pageDir = (pageDirPae_t*)(0xFFFFF000 - 0x3000);
uint32_t flushpd;
if((kernelPdpt->pageDir[pdpt] & 0x1) == 0)
{
uint64_t tmp;
tmp = pmmAllocFrame();
kernelPdpt->pageDir[pdpt] = (uint64_t)(tmp | 1);
SelfMappedTablePae->pageTable[3][507].page[508+pdpt] = (uint64_t)(kernelPdpt->pageDir[pdpt] | 0x3);
memset((void*)&pageDir[pdpt], 0, 0x1000);
pageDir[3].pageTable[508+pdpt] = (uint64_t)(kernelPdpt->pageDir[pdpt] | 0x3);
}
if((pageDir[pdpt].pageTable[dir] & 0x1) == 0)
{
uint64_t tmp;
tmp = pmmAllocFrame();
pageDir[pdpt].pageTable[dir] = tmp | 0x3;
asm volatile("mov %%cr3, %0" : "=r" (flushpd));
asm volatile("mov %0, %%cr3" : : "r" (flushpd));
memset((void*)&SelfMappedTablePae->pageTable[pdpt][dir], 0, 0x1000);
}
page = (uint64_t*)&SelfMappedTablePae->pageTable[pdpt][dir].page[table];
*page = (uint64_t)(physAddress | flags);
pmmSetFrame(physAddress);
vmmFlushTlb(address);
}
Code: Select all
vmmMapFrame(0xF0000000, 0, 0, (uint32_t)RSDT & 0xFFFFF000);
kprintf("Mapped to: %x\n", SelfMappedTablePae->pageTable[3][384].page[0]);
RSDT = (RSDT_t*)(0xF0000000 + ((uint32_t)RSDT & 0xFFF));
kprintf("\nRSDT: %x\n", (uint32_t)RSDT);
for(i = 0; i < 4; i++)
kprintf("%c", RSDT->Header.Signature[i]);
Hope someone helps.
Regards,
Shikhin