Confused in Long Mode

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.
Post Reply
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Confused in Long Mode

Post by sngskunk »

This is my first post but I have been reading around the forum and the wiki for months now and have just started writing my own kernel.

My kernel is in 64-bit Long Mode, not compatibility mode. To get into long mode I have to activate paging first.

Order of Operations:
(Stage 1)
1. Boots loads stage 2 from fat12 floppy (using bios interrupts)
(Stage 2)
2. Sets up GDT
3. Loads Kernel into memory (using bios interrupts)
4. Turn on PMode and far jump to it
5. Once in Pmode setup basic paging.
6. Far jumps to 64-bit Kernel

All above works. But what I am confused about is paging. Now that paging it on, is everything that I do have to be a virtual address? Example: like if i want to write to video memory do I have to make a page table to access it or can I write directly to the memory.

Thank you for any help you give,
Blake
User avatar
lukem95
Member
Member
Posts: 536
Joined: Fri Aug 03, 2007 6:03 am
Location: Cambridge, UK

Post by lukem95 »

your thread isn't to do with Long Mode, its more to do with paging.

try these:

http://www.jamesmolloy.co.uk/tutorial_h ... aging.html

http://www.osdever.net/

http://www.osdev.org/wiki/
~ Lukem95 [ Cake ]
Release: 0.08b
Image
Krox
Posts: 23
Joined: Fri Mar 21, 2008 3:52 am
Location: Germany

Post by Krox »

To answer your question: _nearly_ everthing has to be virutal addresses now. Every normal read-write access of cause, GDT/IDT/TSS and such stuff. Also Video-Memory, cause that behaves like normal RAM.
The only exception I found so far is the DMA Controller (you need it for Floppy access), which takes physical addresses cause it doesnt know anything about paging (or any processor-state at all)
21 is only half the truth...
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Post by sngskunk »

None of those links really covers long mode paging. Its 32-bit protected mode paging. I didn't know if long mode was different or not.

Its seems to be the same whether 32-bit or 64-bit only different is the page directory structure.

I am still a little confused how can you create a page table in memory if you have to write with a virtual address. Can i write to a physical address with paging enabled?
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

AFAIK, you can define any set of apps or drivers that you want to run in physical memory, rather than virtual memory. If you want your video driver code to run in physical memory, then your scheduler just needs to know that every time it schedules that task, it needs to turn off the "paging" bit in CR0. Even in long mode. It just needs to know where all the system video buffers are stored.

And ALL virtual memory maps to physical memory -- that is the point of virtual memory. You are in full control over which virtual addresses map to which physical addresses. You do that by setting up the page tables properly. The tutorials you already looked at tell you how to do that.
Last edited by bewing on Mon Mar 31, 2008 2:38 pm, edited 2 times in total.
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Post by sngskunk »

If you turn paging off then your no longer in long mode, so I would have to write code in 32-bit when paging is off and then 64-bit when paging is on, correct?
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

You can create an "identity mapping" for virtual memory, if you want to effectively turn it off, and just use physical memory (while stll leaving it on). You create one page table (with pages as big as possible), where all virtual memory maps to exactly the same physical memory address, all pages are marked as being "present" (no page faults, no swapping).
User avatar
karloathian
Posts: 22
Joined: Fri Mar 28, 2008 12:09 am

Post by karloathian »

Sorry for the noob question , but how do you switch into long mode ?

Do you have to compile your compile implicitly in 64 bits?
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Post by sngskunk »

Look at the AMD Programmers Guide Volume 2, it shows you how in there. It even gives you some example code.
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Post by sngskunk »

Okay got another question about page tables. Let say I have a page table setup, and paging is active. Then I want to create another page table, do I have to use the old page table to write teh new page table in memory?
User avatar
karloathian
Posts: 22
Joined: Fri Mar 28, 2008 12:09 am

Post by karloathian »

Thanx for the link, the AMD manuals are so much better than the Intel version as they are more explicit.

From the extent of my knowledge the new page table should be paged inside the old paged table, unless you create a new directory altogether.
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

To answer your first question - yes, everything you access in long mode is a virtual address. I would advise against doing a complete identity map, because later on you will most likely want a different memory space for each process
sngskunk wrote:Let say I have a page table setup, and paging is active. Then I want to create another page table, do I have to use the old page table to write teh new page table in memory?
I used a variation on a method used by lots of people with their 32 bit paging structures. This takes a bit of getting your head around - so concentrate :)

When I first set up my PML4, I identity map the area running the current code (required) and point the last PML4 entry to the physical address of the PML4 structure itself. This means that the last 0x4000000000 bytes of virtual RAM contain pointers to your paging structures. If you want to page in from 0x0000-0x1000, you therefore write a PTE to 0x7FC000000000. If you want to page in from 0x1000-0x2000, you write a PTE to 0x7FC000000008 and so on...

My paging in function, therefore looks like this:

Code: Select all

void page_in48(void *vptr, u16 flags)
{
   paging_in = true;
   uptr pte = ((uptr)vptr & 0xFFFFFFFFFFFF) / 0x1000;
		
   flags &= 0xFFF;
   if(!(ptbase[pte] & PAGE_PRESENT))
   ptbase[pte] = (uptr)pmalloc() | flags;
   paging_in = false;
}
The variable 'paging_in' is checked in the page fault exception handler. If true, the PFE handler will transparently handle a page fault in this area at the top of RAM. If false, it won't. 'ptbase' is an unsigned 64 bit integer pointer to 0x7FC000000000.

Suppose a page fault exception happens at 0x100000. This will cause a PFE at 0x100000, and we therefore attempt to write at:

Code: Select all

ptbase[0x100000/0x1000]
If the first page table does not yet exist, this itself will cause a PFE at the location of the page table in high RAM. Because paging_in is true, the PFE handler will try to create a page for the page table (PML1). If the page directory does not exist, a page will be paged in for this (PML2) and so on...

All this takes a little getting your head around, but once you've sorted it out, it's quite easy and just happens automatically.

If you havent already seen it, try this link which is a nice reference for when you can't remember the ranges covered by the various paging structures.

I hope your head doesn't hurt too much after reading that!

Cheers,
Adam
Post Reply