OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Apr 29, 2024 10:31 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: GDT/Paging Kernel into Higher Half
PostPosted: Thu Sep 22, 2005 7:46 pm 
Hello everybody, I need some help big time please, I've been banging my head against this for nearly 30 hours this week!

Grub loads my kernel code at physical location of 0x00101000 but it is linked to be at virtual address of 0xC0000000

I had my kernel working when it was linked as virtual=physical but I want to move it up the the 3GB mark. I've used Tims trick to use a GDT with segment offsets that give me 0xC0000000 + 0x40101000 = 0x00101000. This works fine and I jump into my kernel code.

Now I want to setup and enable paging and then load new linear code/data segments and continue on with things.

Setting up the linear segments is fine but my paging code triple faults Bochs. (paging seemed to work when linked to virtual=physical). My code is on SourceForge and I would be eternally gratefull if somebody could have a look through it and spot the problem(s). My heads spinning and fresh eyes are definatly needed :)

loader.asm sets up the GDT with the special base's and jumps into the kernel address space (0xC0000000) which inturn calls main() in kernel.c. Here we setup paging in paging.c and then back in kernel.c the newly created page directory is installed and then the linear code/data descriptors will be put inplace. It triple faults around loadind cr3 with the page directory in kernel.c. I've tried following all similar threads about this topic but no joy.

LOADER.ASM http://cvs.sourceforge.net/viewcvs.py/osamos/AMOS/src/kernel/loader.asm?view=markup

KERNEL.C http://cvs.sourceforge.net/viewcvs.py/osamos/AMOS/src/kernel/kernel.c?view=markup

PAGING.C http://cvs.sourceforge.net/viewcvs.py/osamos/AMOS/src/kernel/mm/paging.c?view=markup

This code in kernel.c was for testing as 0x00000000 = *pagedirectory
Code:
   // Enable Paging...
   __asm__ __volatile__ ( "movl %%eax, %%cr3" : : "a" ( 0x00000000 ) );

As 0x00000000 is the first address physical_pageAlloc() will give out and setting up the pagedirectory is the first call to physical_pageAlloc().

Any and all help greatly appreciated, cheers :)


Top
  
 
 Post subject: Re:GDT/Paging Kernel into Higher Half
PostPosted: Thu Sep 22, 2005 9:32 pm 
Not absolutely sure about this, but...
Code:
struct PAGE_DIRECTORY_ENTRY
  35 :                {
  36 :                unsigned int present:1;
  37 :                unsigned int readwrite:1;
  38 :                unsigned int user:1;
  39 :                unsigned int writethrough:1;
  40 :                unsigned int cachedisabled:1;
  41 :                unsigned int accessed:1;
  42 :                unsigned int reserved:1;
  43 :                unsigned int pagesize:1;
  44 :                unsigned int globalpage:1;
  45 :                unsigned int available:3;
  46 :                unsigned int address:20;
  47 :                } PACKED;
  48 :              
  49 :                struct PAGE_TABLE_ENTRY
  50 :                {
  51 :                unsigned int present:1;
  52 :                unsigned int readwrite:1;
  53 :                unsigned int user:1;
  54 :                unsigned int writethrough:1;
  55 :                unsigned int cachedisabled:1;
  56 :                unsigned int accessed:1;
  57 :                unsigned int dirty:1;
  58 :                unsigned int attributeindex:1;
  59 :                unsigned int globalpage:1;
  60 :                unsigned int available:3;
  61 :                unsigned int address:20;
  62 :                } PACKED;


You see those unsigned ints? Whenever you assign to one of those an entire 32 bits of data (all zeroed out except one because you're assigning the number one) is moved to the correct location, overriding other bits. In other words, you're treating a single unsigned int as many, thus making the entire thing's final value 1 = 0x00000001 = 00000000000000000000000000000001 in binary. I remember C as having a datatype called a "bitfield" that might allow you to do what you want, or you might just have to use ORs and shifts.

Again, not exactly sure this is The Problem You Asked About, but it's certainly a bug unless my C is rusty. Somebody please let me know if my C is rusty.


Top
  
 
 Post subject: Re:GDT/Paging Kernel into Higher Half
PostPosted: Thu Sep 22, 2005 10:27 pm 
The colon with a number after the end declares a bitfield of "number" bits. unsigned int present:1 = 1bit, they are automatically packed apparently but I assume PACKED is defined as __attribute__((packed)) which should make sure it's packed.

Paging is under segmentation, you need to map the kernel at both 0x00101000 and 0xC0000000, once you load a flat segment you can remove the 0x00101000 mapping.


Top
  
 
 Post subject: Re:GDT/Paging Kernel into Higher Half
PostPosted: Fri Sep 23, 2005 4:49 am 
Hello, thanks for the quick replys :)
AR wrote:
I assume PACKED is defined as __attribute__((packed)) which should make sure it's packed.
yup PACKED is defined in sys/types.h as #define PACKED __attribute__( (packed) )

I'm nearly sure that the paging code is ok as it seemed to work when the kernel was linked to run at its physical address, e.g. I could map the video memory to some high location and successfully write to the console at that point.

AR wrote:
Paging is under segmentation, you need to map the kernel at both 0x00101000 and 0xC0000000, once you load a flat segment you can remove the 0x00101000 mapping.


Ya im guessing that as im trying to do this under segmentation with a base of 0x40101000 that its causing problems. From PAGING.C:
Code:
   // identity map bottom 4MB's
   for( physicalAddress=0L ; physicalAddress<(1024*SIZE_4KB) ; physicalAddress+=SIZE_4KB )
      paging_setPageTableEntry( physicalAddress, physicalAddress, TRUE );      

   // map the kernel's virtual address to its physical memory location
   linearAddress = 0xC0000000;
   // 0x00101000 = &start (start in loader.asm which is the kernel entry point)
   for( physicalAddress=(DWORD)0x00101000; physicalAddress<(DWORD)(0x00101000+(1024*SIZE_4KB)) ; physicalAddress+=SIZE_4KB )
   {
      paging_setPageTableEntry( linearAddress, physicalAddress, TRUE );
      linearAddress += SIZE_4KB;      
   }


I think this does what you said though, the bottom 4MB's includes the kernel and then I also map it to its new virtual location of 0xC000000


Top
  
 
 Post subject: Re:GDT/Paging Kernel into Higher Half
PostPosted: Fri Sep 23, 2005 9:01 am 
What you appear to be doing is identity mapping the kernel to both its physical address AND its new virtual address in order to make paging work before you can change the segments. This should work. Do you have IRQs enabled, or any other sort of interrupt enabled that could be firing after paging is enabled?


Top
  
 
 Post subject: Re:GDT/Paging Kernel into Higher Half
PostPosted: Fri Sep 23, 2005 9:08 am 
no I havnt setup IRQ's yet and I perform a CLI instruction to disable maskable interrupts before I setup/enable paging ...boy am I stumped on this one! ???


Top
  
 
 Post subject: Re:GDT/Paging Kernel into Higher Half
PostPosted: Fri Sep 23, 2005 2:18 pm 
Do you have exceptions set up?


Top
  
 
 Post subject: Re:GDT/Paging Kernel into Higher Half
PostPosted: Mon Sep 26, 2005 3:28 am 
No I have disabled my code for exceptions until I have this sorted out, that wouldnt make a difference though would it? If I enable my exception code it doesnt help either ...I'm spending the rest of the day at this so hopefully I will figure it out :)

[edit ...a day later]

arrgg! so I dumped the idea of trying to get the gdt trick working, instead I setup a simple page directory & 2 tables in my setup routine called by Grub. maping the kernel into the higher half and jump into my kernel from their. soo much easier and it works and took only a few hours compared to the week of my life i spent to get the other way working! :P

Anyways thanks for helping me out :)


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 16 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