Temporarily mapping RSDT problem [fixed]

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
shikhin
Member
Member
Posts: 274
Joined: Sat Oct 09, 2010 3:35 am
Libera.chat IRC: shikhin
Contact:

Temporarily mapping RSDT problem [fixed]

Post by shikhin »

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:
  1. Before even enabling paging, I checked the contents of the RSDT. All the values were nice and good.
  2. The above fact led me to the conclusion that either I was messing up the RSDT somewhere or the mapping wasn't happening correctly.
  3. 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.
  4. 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]).
  5. 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.
  6. 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).
I would now like to post the relevant parts of the code. Here is the code which maps a page (vmmPaeMapFrame()). P.S. I know it doesn't invalidate everywhere required, and I need to rectify it. However, I even tried reloading CR3 after each and every line, and it doesn't fix the problem.

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);
}
Here is where I map the RSDT and find out the INCORRECT signature:

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]);
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 8)
Last edited by shikhin on Fri May 06, 2011 8:40 am, edited 1 time in total.
http://shikhin.in/

Current status: Gandr.
shikhin
Member
Member
Posts: 274
Joined: Sat Oct 09, 2010 3:35 am
Libera.chat IRC: shikhin
Contact:

Re: Temporarily mapping RSDT problem

Post by shikhin »

Hmm, I am running out of ideas. Anyone?
http://shikhin.in/

Current status: Gandr.
shikhin
Member
Member
Posts: 274
Joined: Sat Oct 09, 2010 3:35 am
Libera.chat IRC: shikhin
Contact:

Re: Temporarily mapping RSDT problem

Post by shikhin »

So finally, I fixed the problem. Seems like I was not invalidating the TLB well enough, leading to the same page being mapped through out (the RSDP one and not the RSDT one). Fixed the problem, with due thanks to Brendan. :D
http://shikhin.in/

Current status: Gandr.
Post Reply