OSDev.org

The Place to Start for Operating System Developers
It is currently Sun May 16, 2021 5:38 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Temporarily mapping RSDT problem [fixed]
PostPosted: Tue May 03, 2011 8:10 am 
Offline
Member
Member

Joined: Sat Oct 09, 2010 3:35 am
Posts: 272
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:
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:
           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)

_________________
http://shikhin.in/

Current status: Gandr.


Last edited by shikhin on Fri May 06, 2011 8:40 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Temporarily mapping RSDT problem
PostPosted: Wed May 04, 2011 3:46 am 
Offline
Member
Member

Joined: Sat Oct 09, 2010 3:35 am
Posts: 272
Hmm, I am running out of ideas. Anyone?

_________________
http://shikhin.in/

Current status: Gandr.


Top
 Profile  
 
 Post subject: Re: Temporarily mapping RSDT problem
PostPosted: Fri May 06, 2011 8:39 am 
Offline
Member
Member

Joined: Sat Oct 09, 2010 3:35 am
Posts: 272
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 14 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group