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.
frank wrote:You have to set the user bit(4th bit) on all of the pages that the VM86 task is expected to access.
I've done this
page_table= address | 7 ;
now the page table is user read/write present,also I've done the
same with the first page directory entry,after that my virtual task
worked fine but after executing BIOS int and when tring to go back to pm
using IRET bochs panic this message:
task_switch: CS not valid executable seg
Thanx.
Just as a side note, you have to do the same for the page table's entry too.
void init_paging()
{
printf("enabling paging...");
page_directory = 0x4000;
page_table = 0x5000;
dword address=0;
dword i;
for(i=0;i<1024;i++)
{
page_table[i]= address | 7 ; //user ,read/write ,present
address= address+4096 ;
}
page_directory[0]= page_table;
page_directory[0]= page_directory[0] | 7;
for(i=1;i<1024;i++)
page_directory[i]= 0 | 2;
write_cr3(page_directory); // put that page directory address into CR3
write_cr0(read_cr0() | 0x80000000); // set the paging bit in CR0 to 1
printf("[Done]\n");
}
Please note my virtual mode monitor works fine but when I enable paging
I can't go back to pmode,I mean I execute bios int successfuly and after that
bochs panic that message,without paging everything works perfect.
I think we're getting closer to solve the problem,
I've changed the page_directory and page_table definition
from dword to unsigned long ....so after executing bios int
and when tring to go back I've got "bad Tss exception".
so here's my tss struct:
// tss type
typedef volatile struct __tagTSS_t {
unsigned short link;
unsigned short link_h;
unsigned int esp0;
unsigned short ss0;
unsigned short ss0_h;
unsigned int esp1;
unsigned short ss1;
unsigned short ss1_h;
unsigned int esp2;
unsigned short ss2;
unsigned short ss2_h;
unsigned int cr3;
unsigned int eip;
unsigned int eflags;
unsigned int eax;
unsigned int ecx;
unsigned int edx;
unsigned int ebx;
unsigned int esp;
unsigned int ebp;
unsigned int esi;
unsigned int edi;
unsigned short es;
unsigned short es_h;
unsigned short cs;
unsigned short cs_h;
unsigned short ss;
unsigned short ss_h;
unsigned short ds;
unsigned short ds_h;
unsigned short fs;
unsigned short fs_h;
unsigned short gs;
unsigned short gs_h;
unsigned short ldt;
unsigned short ldt_h;
unsigned short trap;
unsigned short iomap;
} __attribute((packed)) TSS_t ;
It looks to be pretty much the same as yours. I'm sorry, I can't help you any more - these waters are pretty much uncharted for me.
Have you got a page directory at 0x4000? If not, you'll get a page fault as there is no valid information to be read (or worse, will write to an unknown location).
I'd suggest that you use the kernel page directory for now. Once you've figured all this out you can then switch back to generating your own. Also - nothing for v86 has to be physically under 1 MB - the virtual addresses must be though.
You might try mapping then the IVT 1:1 and then 0x5000 (or something else) to other physical memory.
They are still under 1 MB (even though they don't need to be) and in a safe location.
One more thing: take a look at my kernel's source (here, syscore/paging.cc and reloc/reloc_elf.cc - the reloc_elf.cc file has an example of loading an ELF image and mapping it.)
One more thing... A page table's entry only addresses 4 kb of physical memory - one page table has 1024 entries which is 4 mb of physical memory. By the looks of it though this shouldn't be your problem.
You should also probably cast all pointers if you want their address. For example:
unsigned long* pagedir = (unsigned long*) 0x40000;
kprintf( "Page directory location is at 0x%x\n", (unsigned long) pagedir );
I'd do the above code with just the pointer (no cast) and then see if 0x40000 is still printed (not at my development PC so I can't test this for myself).