The problem is that it doesn't work.When I run the code in QEMU it exits with the following error "qemu: fatal: Trying to execute code outside RAM or ROM at 0x0010066c".When I tested it on a real PC it rebooted.The code is relocated at the first MB.
I've read the Intel's manuals and searched the web a coulpe of times but couldn't found anything related to this problem.Any clues what I'm missing?
Here are the functions I use to initialise the page dir:
Code: Select all
volatile struct pg_dir_t *kpg_dir=NULL;
for(i=0;i<PG_DIR_ENT_NUM;i++)
{
// Set page not present.
kpg_dir[i].p=0;
/* If the page is within the real memory then set it present.'i' shifted 22 bits left then divided by 1024 is equal to only 12 shifts left.
*/
if( mb_info->mem_upper>=(i<<12) ) kpg_dir[i].p=1;
kpg_dir[i].r_w=1;
kpg_dir[i].u_s=0;
kpg_dir[i].pwt=1;
kpg_dir[i].pcd=0;
kpg_dir[i].a=0;
kpg_dir[i].d=0;
kpg_dir[i].ps=1;
kpg_dir[i].g=0;
kpg_dir[i].avl=0;
kpg_dir[i].res_low=0;
kpg_dir[i].res_high=0;
// 'i' is the physical page address.
kpg_dir[i].base_addr=i;
};
Code: Select all
u_int cr0=GET_CR0(),cr4=GET_CR4();
cr4|=CR4_PSE;
SET_CR4(cr4);
SET_CR3(kpg_dir);
cr0|=CR0_PG;
SET_CR0(cr0);
for(;;);
Code: Select all
struct pg_dir_t
{
u_int p:1;
u_int r_w:1;
u_int u_s:1;
u_int pwt:1;
u_int pcd:1;
u_int a:1;
u_int d:1;
u_int ps:1;
u_int g:1;
u_int avl:3;
u_int res_low:4;
u_int res_high:6;
u_int base_addr:10;
}__attribute__((__packed__));
#define PG_DIR_ENT_NUM 0x400
/**
* Get and return CR0 register
*/
#define GET_CR0()\
({\
u_int cr0;\
__asm__ __volatile__("mov %0,%%cr0":"=r"(cr0):);\
cr0;\
})
/**
* Set CR0 register
*/
#define SET_CR0(cr0)\
({\
__asm__ __volatile__("mov %%cr0,%0"::"r"((u_int)cr0));\
})
/**
* Set CR3 register
*/
#define SET_CR3(cr3)\
({\
__asm__ __volatile__("mov %%cr3,%0"::"r"((u_int)cr3));\
})
/**
* Get and return CR4 register
*/
#define GET_CR4()\
({\
u_int cr4;\
__asm__ __volatile__("mov %0,%%cr4":"=r"(cr4):);\
cr4;\
})
/**
* Set CR4 register
*/
#define SET_CR4(cr4)\
({\
__asm__ __volatile__("mov %%cr4,%0"::"r"((u_int)cr4));\
})