Page 1 of 1

A20 + GDT + Paging = mess

Posted: Mon Aug 15, 2005 12:08 pm
by GLneo
hi all, ok, i used the gdt trick to get my kernel to think it is a 0xc0000000, it starts fine but when i set a20 or paging, EIP goes to 0xFFFFFFFF??? my a20 is:

Code: Select all

a20:
            call    empty
            mov     al, 0xd1
            out     0x64,al
            call    empty
            mov     al, 0xdf
            out     0x60,al
            call    empty
            jmp gdt

    empty:
            call    delay
            in      al, 0x64
            test    al, 2
            jnz     empty
            ret

    delay:
            nop
            ret
and my paging is:

Code: Select all

#define nonsuplev 4
#define read_write 2
#define present 1

unsigned long page_directory[1024];
unsigned long page_table[1024];
unsigned long page_table2[1024];

int read_cr0()
{
    int cr0;
    asm("movl %%cr0, %0":"=r"(cr0));
    return cr0;
}

void write_cr0(int cr0)
{
    asm("movl %0, %%cr0"::"r"(cr0));
}

int read_cr3()
{
    int cr3;
    asm("movl %%cr3, %0":"=r"(cr3));
    return cr3;
}

void write_cr3(int cr3)
{
    asm("movl %0, %%cr3"::"r"(cr3));
}

void idpage(unsigned long *ptable, unsigned long from, int size)
{
   from = from & 0xfffff000; 
   for(; size; from += 4096, ptable++, size--)
      *ptable = from | read_write | present;     // mark page present.
}

void set_paging()
{
    int x;
    unsigned long physaddr = 0x0;
    idpage(page_table, physaddr, 1024);
    for(x = 0; x < 1024; x++) // fill directory with nonpresent pages
    {
        page_directory[x] = 0 | read_write;
    }
    page_directory[0x0] = (int)page_table | read_write | present; // set test table to 0x0 in directory  
    page_directory[0x300] = (int)page_table | read_write | present; // set test table to 0xC0000000 in directory
    write_cr3((int)0x9D000); // write pointer to cr3
    write_cr0(read_cr0() | 0x80000000); // set paging bit
}
and bochs says:

Code: Select all

00002419057i[CPU  ] write_virtual_checks(): write beyond limit, r/w
00002419057e[CPU  ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
i have no clue, any thing obvious?, thx :)

Re:A20 + GDT + Paging = mess

Posted: Mon Aug 15, 2005 12:55 pm
by Kim
Don't forget the GDT is on top of paging, make sure the address loaded in the gdtr is mapped at the same virtual address.

Normally if you are using the gdt trick, paging shouldn't be a reason why it crashes.

ADDRESS
0xC0000000
GDT BASE
0x40100000
NEW ADDRESS
0x100000
PAGING IDENTITY MAPPING
FINAL ADDRESS
0x100000

If you correct the gdt base (set it to 0) then you have to make sure you mapped 0xC0000000 to the physical start of the kernel.

Please make sure these are page aligned:

unsigned long page_directory[1024];
unsigned long page_table[1024];
unsigned long page_table2[1024];

CR3 should point to your page_directory:

EDIT: forgot that page_directory was some pointer over the 3gb :)
write_cr3((int)&page_directory + 0x40100000);

Re:A20 + GDT + Paging = mess

Posted: Mon Aug 15, 2005 12:57 pm
by QuiTeVexat
GLneo wrote:

Code: Select all

unsigned long page_directory[1024];
unsigned long page_table[1024];
unsigned long page_table2[1024];
These need to be page-aligned, and declaring them like this is unlikely to do that for you.

Another thing is that you seem not to be distinguishing between virtual and physical addresses in your code. When you perform operations on the data from your C code, you need to be using the virtual addresses, but the pointers themselves in page tables/directories and cr3 need to be physical.

Re:A20 + GDT + Paging = mess

Posted: Mon Aug 15, 2005 1:05 pm
by GLneo
thx, but how do i page aligne my tables, and how do i distinguishing between virtual and physical addresses?, but thx

Re:A20 + GDT + Paging = mess

Posted: Mon Aug 15, 2005 1:18 pm
by Kim
unsigned long page_directory[1024] __attribute__ ((aligned (4096)));
unsigned long page_table[1024] __attribute__ ((aligned (4096)));
unsigned long page_table2[1024] __attribute__ ((aligned (4096)));

Iam not sure it works.

Re:A20 + GDT + Paging = mess

Posted: Mon Aug 15, 2005 3:16 pm
by GLneo
ok, i tryed setting data in the gdt to 0x0 and code to 0xc0000000 but that didnt work for some reson, probly too simple :), then i made some macros:

Code: Select all

#define???VER(X) (X + 0xBFFFF000)
#define???PHY(X) (X - 0xBFFFF000)
but i still get problems righting to video memory???

Re:A20 + GDT + Paging = mess

Posted: Tue Aug 16, 2005 1:26 am
by Kim
Try this:

Code: Select all

#define nonsuplev 4
#define read_write 2
#define present 1

unsigned long page_directory[1024] __attribute__ ((aligned (4096)));
unsigned long page_table[1024] __attribute__ ((aligned (4096)));
unsigned long page_table2[1024] __attribute__ ((aligned (4096)));

int read_cr0()
{
    int cr0;
    asm("movl %%cr0, %0":"=r"(cr0));
    return cr0;
}

void write_cr0(int cr0)
{
    asm("movl %0, %%cr0"::"r"(cr0));
}

int read_cr3()
{
    int cr3;
    asm("movl %%cr3, %0":"=r"(cr3));
    return cr3;
}

void write_cr3(int cr3)
{
    asm("movl %0, %%cr3"::"r"(cr3));
}

void idpage(unsigned long *ptable, unsigned long from, int size)
{
  from = from & 0xfffff000;
  for(; size; from += 4096, ptable++, size--)
      *ptable = from | read_write | present;
}

void set_paging()
{
    int x;
    unsigned long physaddr = 0x0;
    idpage(page_table, physaddr, 1024);
    for(x = 0; x < 1024; x++)
    {
        page_directory[x] = 0;
    }
    page_directory[0x0] = ((int)page_table + 0x40100000) | read_write | present;
    page_directory[0x300] = ((int)page_table + 0x40100000) | read_write | present;
    write_cr3((int)page_directory + 0x40100000);
    write_cr0(read_cr0() | 0x80000000);
}