Enabling Long Mode [fixed]
Posted: Mon Mar 12, 2007 2:27 pm
Before this code, the following things have been set up, and are working:
1. GDT
2. IDT with handlers
3. Interrupts enabled
main.cpp:
All I'm doing (I think) is creating the 4-level paging structures at 10MB. The code as shown will triple-fault and reset the system. If I comment out the call to enablePaging(), the kernel reaches the for(;;); and hangs like you'd expect.
So, what's wrong here?
1. GDT
2. IDT with handlers
3. Interrupts enabled
main.cpp:
Code: Select all
inline void disableInterrupts()
{
asm("cli");
}
inline void enablePAE()
{
asm("mov %cr4, %eax");
asm("or $0x20, %eax");
asm("mov %eax, %cr4");
}
inline void installPaging()
{
asm("mov $0xA00000, %eax");
asm("mov %eax, %cr3");
}
inline void enableLongMode()
{
asm("mov $0xC0000080, %ecx");
asm("rdmsr");
asm("bts $8, %eax");
asm("wrmsr");
}
inline void enablePaging()
{
asm("mov %cr0, %eax");
asm("bts $31, %eax");
asm("mov %eax, %cr0");
}
//Create the bottom level page table at 'address' and identity map 2MB of pages
void makePageTable(addr64_t address, addr64_t start)
{
addr64_t* entries = (addr64_t*)address;
//Mask out the bottom twelve bits of start
start = start & 0x000FFFFFFFFFF000LL;
int i=0;
while(i < 512)
{
//Set entry to start, with read/write and present bits on
entries[i] = start | 0x3;
start += 0x1000;
i++;
}
screen.printf("%i: %X\n",511,entries[511]);
}
void makePageDir(addr64_t address)
{
addr64_t* entries = (addr64_t*)address;
int i=0;
while(i < 512)
{
entries[i] = 0LL;
i++;
}
}
void makePageDirEntry(addr64_t address, uint32_t lowbit, addr64_t entry)
{
addr64_t* entries = (addr64_t*)address;
uint32_t index = (address >> lowbit) & 0x1FFL;
if(index < 512)
{
//Mask out the last 12 bits
entry = entry & 0x000FFFFFFFFFF000LL;
//Set entry, and turn on read/write and present bits
entries[index] = entry | 0x3;
}
else
screen.println("Big error!");
}
extern "C" void _main()
{
screen.clear();
screen.println("Welcome to my OS64!\n");
screen.printf("%x\n",idt);
screen.println("Disabling Interrupts...");
disableInterrupts();
screen.println("Enabling Physical Address Extensions...");
enablePAE();
screen.println("Creating Page Tables...");
//Create 8MB of identity mapped page tables
makePageTable(0xA03000,0x000000);
makePageTable(0xA04000,0x200000);
makePageTable(0xA05000,0x400000);
makePageTable(0xA06000,0x600000);
//Make the L2 page directory
makePageDir(0xA02000);
makePageDirEntry(0xA02000, 21,0xA03000);
makePageDirEntry(0xA02000, 21,0xA04000);
makePageDirEntry(0xA02000, 21,0xA05000);
makePageDirEntry(0xA02000, 21,0xA06000);
//Make the L3 page directory
makePageDir(0xA01000);
makePageDirEntry(0xA01000, 30,0xA02000);
//Make the L4 page directory
makePageDir(0xA00000);
makePageDirEntry(0xA00000, 39,0xA01000);
screen.println("Installing Page Tables...");
installPaging();
screen.println("Enabling Long Mode...");
enableLongMode();
screen.println("Enabling Paging...");
enablePaging();
for(;;);
}
So, what's wrong here?