Using Paging

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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Using Paging

Post by Brendan »

Hi,
Colonel Kernel wrote:What is the advantage of your scheme...? Conversely, what is the disadvantage of my scheme? For that matter, which is more conventional?
I guess both schemes are just different ways to make sure that things that need to be done before a task switch are done before a task switch. My scheme might give better performance in some cases, while your scheme might be simpler in some cases.

As for which is more conventional, I've got no idea - I've never actually studied any other OS properly - I just do what I think is best at the time until I find a better way, which isn't recommended but after many years it can work (if you've got many years to spare ;) ).
Colonel Kernel wrote:
At the time I had (unrelated) design problems with level triggered interrupts, and (more recently) interrupt latency problems that caused IRQ8 to be missed on some computers which led to the OS locking up/waiting forever (although this could be attributed to setting the RTC periodic timer's frequency too fast).
Did allowing nested interrupts fix this? If so, how? I briefly forgot that the kernel itself ought to deal with the timer in its own ISRs. :D


Allowing nested interrupts didn't fix the IRQ8 problems, as the kernel allows IRQ8 to be handled immediately (unless interrupts are disabled) anyway. The problem was caused by the high frequency of the RTC periodic interrupt combined with disabling interrupts for too long. The only place the kernel disables interrupts for more than a few instructions is during the "find a next thread to run" code and the "switch to the selected thread" code.

The "find the next thread to run" code was the main problem, as it used "O(2 * N)" algorithms where the more threads there are the longer it disables interrupts for. My plan was to change all scheduling algorithms to "O(1)" and make the "switch to the selected thread" code interruptable, but at the time I was in the middle of other things and chose to reduce the frequency of the RTC periodic interrupt instead.

I tried fixing the scheduler properly afterwards, but it's a complex thing (multi-CPU, domains and sub-domains, CPU affinity, 4 policy levels with different scheduling algorithms for each policy, etc) and it's not seperated from other parts of the kernel very well. This is one of the reasons I'm converting the kernel into seperate modules (so the scheduler itself is a seperate binary with a clearly documented interface between it and other parts of the kernel, and can be replaced with a different "scheduler module" during boot).

It's a little funny, because "clearly seperated parts" was one of the reasons I chose not to write a monolithic kernel - to have the same problem within a micro-kernel was a surprise (my previous kernels were single-CPU only, which is much much simpler).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
iammisc

Re:Using Paging

Post by iammisc »

Back to the topic of paging. Once all the addresses are virtual when I enable paging, how do I get the virtual address of a given physical address? And how do I change the Page Directory?
Ushma

Re:Using Paging

Post by Ushma »

Map the page directory into itself, so some 4 meg portion of the virtual address space consists of all the page tables. Then you can map as needed. Physical memory that you map will be where you put it. Finding a mapped page would involve searching all page table entries for the physical address.

Changing the page directory is as easy as setting up a new valid page directory, and loading cr3 with its address.
iammisc

Re:Using Paging

Post by iammisc »

When I said change i meant modify the page directory.
AR

Re:Using Paging

Post by AR »

iammisc wrote: When I said change i meant modify the page directory.
Ushma wrote: Map the page directory into itself, so some 4 meg portion of the virtual address space consists of all the page tables. Then you can map as needed. Physical memory that you map will be where you put it. Finding a mapped page would involve searching all page table entries for the physical address.
iammisc

Re:Using Paging

Post by iammisc »

Okay but then, how am I going to change all my interrupts to virtual addresses. I though of just paging the start of the vga memory(0xA000) to 0xA000 and doing the same for all the pages all the way to the end of my kernel. Is that okay?
That way I don't change the physical addresses. Okay, another question how do I load an app onto a specific page? I should page the app's page directory to my page directory right? or is there another way? Sorry for the many questions.

PS. [OFFTOPIC] Is it hard to get a project on SourceForge?

[edit]
When my timer interrupt is called, it changes a global var. So when the timer interrupt is called do I have to change cr3 to my new page directory? Can I enable inside my kernel code?
AR

Re:Using Paging

Post by AR »

Mapping physical addresses to the same virtual addresses is called "Identity Mapping"

There is no special procedure to load an anything (apps have special needs - initalization but apart from that it's the same as loading anything else), you just grab a page add it to the relevant page table, execute INVLPG then just write to the virtual location. To modify a second page directory other than the current one then just add the page directory to the current page directory which will map all page tables in for you to access as a linear array.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Using Paging

Post by Brendan »

Hi,
iammisc wrote: Okay but then, how am I going to change all my interrupts to virtual addresses. I though of just paging the start of the vga memory(0xA000) to 0xA000 and doing the same for all the pages all the way to the end of my kernel. Is that okay?
That way I don't change the physical addresses.


That might be okay - but it depends on your OS. If you intended to allow more than one virtual 8086 task, then it won't work because they would all need to use addresses from 0x00000000 to 0x00100000. If you make the video use a linear frame buffer (e.g. 32 MB at 0xE0000000) then that couldn't be identity mapped either.

iammisc wrote:Okay, another question how do I load an app onto a specific page? I should page the app's page directory to my page directory right? or is there another way? Sorry for the many questions.


Loading a new process/application would go something like this:
  • Create a new page directory
    Add all the kernel's page tables to the new page directory
    Spawn a new task/thread for the new page directory
    Return
Then the new task starts running the kernel's "load a process" code (allocate some memory for the application, open the file, read the file into memory, etc). This step depends on your application - if it is in ELF format then you need to read it's header to see where to put it, if you support several formats then you'd need different "load a process" code for each, if you support memory mapped files then you'd only associate the memory areas with the file and wouldn't load much from the file system.

Once it is loaded (or mapped) into memory you'd switch to CPL=3 and start running it, so that the task/thread you spawned becomes the process/application's first thread.

iammisc wrote:PS. [OFFTOPIC] Is it hard to get a project on SourceForge?

[edit]
When my timer interrupt is called, it changes a global var. So when the timer interrupt is called do I have to change cr3 to my new page directory? Can I enable inside my kernel code?


Your kernel's code should be in every address space (ie. the same set of "kernel page tables" are re-used), so that your global variable (and all of the kernel's code and data) can always be accessed, regardless of what CR3 contains.

BTW not sure about SourceForge - I don't think it's too hard (but could be wrong). Best way to find out would be to try to get your project on SourceForge :).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
iammisc

Re:Using Paging

Post by iammisc »

Okay! I got it I think I will start paging from my kernel start (0x100000) to my kernel finish and then I will have a function which maps the desired physical location to a new virtual location so I know the virtual address. Then I will map the vga address to something different so I can do stuff for that. Okay! Thanks for all your help!
Post Reply