Please correct me if I am wrong anywhere here:
I have heard that in protected mode, you can create a memory space of each process. Each process has its own memory limitations and it cannot (legally) break the limit. Additionally it cannot change its own code or data segments to affect the other processes even though it is in the same ring as the other processes.... That is one of the main reasons one would want memory protection.
Is there any way to do this with the ring always being 0? All that I want to do is stop the processes from accidentally overwriting each other. They should be able to do everything else, like CLI, HLT, IO commands, etc. I understand that "HLT" can only be done in ring 0, and I would like the processes to be able to use this opcode without having to transfer to the kernel.
So far I was not able to do this. From what I understand a TSS would be required to do this however I don't know if it would be possible to it without switching the ring.
In short:
Is it possible for you to have a process in ring 0 that is restricted to some specific memory segment? ...So that it cannot switch to other code segments unless there is an interrupt?
Veniamin
A clarification of the abilities of protected mode
A clarification of the abilities of protected mode
Have a plan.
Re: A clarification of the abilities of protected mode
Hi,
If processes where in ring zero, then they could accidentally trash the kernel (where a trashed kernel might continue running and trash other things). There's no way to run the kernel in it's own address space (isolated from processes) - you must have (at a minimum) certain things in the same address space as the process (e.g. IRQ handlers/stubs, kernel API entry point, GDT, IDT, etc). Also, any process would be able to accidentally trash it's own page tables, etc, and then use these trashed page tables to trash anything in RAM (including the kernel and other processes); and any process could also accidentally use I/O ports to trash devices, where the devices could trash anything (for e.g. accidentally starting a DMA transfer, or accidentally turning off A20, or accidentally rebooting, or accidentally messing up the memory controller's configuration, or...).
Cheers,
Brendan
Correct.CPLH wrote:I have heard that in protected mode, you can create a memory space of each process. Each process has its own memory limitations and it cannot (legally) break the limit. Additionally it cannot change its own code or data segments to affect the other processes even though it is in the same ring as the other processes.... That is one of the main reasons one would want memory protection.
In protected mode, typically you'd use paging to isolate processes from each other (so that each process has it's own separate address space), and the kernel would be in part of every address space, and you'd use privilege levels to prevent processes from trashing the kernel.CPLH wrote:Is there any way to do this with the ring always being 0? All that I want to do is stop the processes from accidentally overwriting each other.
If processes where in ring zero, then they could accidentally trash the kernel (where a trashed kernel might continue running and trash other things). There's no way to run the kernel in it's own address space (isolated from processes) - you must have (at a minimum) certain things in the same address space as the process (e.g. IRQ handlers/stubs, kernel API entry point, GDT, IDT, etc). Also, any process would be able to accidentally trash it's own page tables, etc, and then use these trashed page tables to trash anything in RAM (including the kernel and other processes); and any process could also accidentally use I/O ports to trash devices, where the devices could trash anything (for e.g. accidentally starting a DMA transfer, or accidentally turning off A20, or accidentally rebooting, or accidentally messing up the memory controller's configuration, or...).
You can set the IOPL field in eflags to 3, so that the normal processes running in ring 3 can use CLI/STI, access I/O ports, etc. You could even do that selectively (so that some processes have access and some don't). HLT is different - no process should ever need to use it (including device drivers), and if a process needs to wait until an IRQ occurs then it should tell the scheduler to run other tasks until the IRQ occurs (and if the scheduler has no other tasks to run, it can use HLT itself).CPLH wrote:They should be able to do everything else, like CLI, HLT, IO commands, etc.
No - ring 0 code can always load any data segment, and can also modify the GDT and create it's own segments.CPLH wrote:In short:
Is it possible for you to have a process in ring 0 that is restricted to some specific memory segment? ...So that it cannot switch to other code segments unless there is an interrupt?
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.
-
- Member
- Posts: 368
- Joined: Sun Sep 23, 2007 4:52 am
Re: A clarification of the abilities of protected mode
The idle task needs to be able to use it.HLT is different - no process should ever need to use it (including device drivers)
If you have a non-preemptible kernel without kernel threads then you can't have HLT in your scheduler without adding special code somewhere to handle it (effectively making your kernel partially preemptible) because the stack of the irq handler will be wrong.
Re: A clarification of the abilities of protected mode
Thank you for your responses. They have cleared up a few things for me.
Now I (finally) successfully got into protected mode and transfered the code and data segments to ring 3.
I have found that while in ring 3, I cannot access ring 0 without an interrupt. However I can access other segments that are at ring 3. What do I do to stop the ring 3 code from being able to access any other segments that do not belong to it? ..once again I'm trying to implement memory protection, so no two programs can access each other. (My best guess is to use a TSS.. I'm still trying to find a good tutorial on it.. most of the time they talk about multitasking, which is something I am currently not working on.)
Now I (finally) successfully got into protected mode and transfered the code and data segments to ring 3.
I have found that while in ring 3, I cannot access ring 0 without an interrupt. However I can access other segments that are at ring 3. What do I do to stop the ring 3 code from being able to access any other segments that do not belong to it? ..once again I'm trying to implement memory protection, so no two programs can access each other. (My best guess is to use a TSS.. I'm still trying to find a good tutorial on it.. most of the time they talk about multitasking, which is something I am currently not working on.)
Have a plan.
Re: A clarification of the abilities of protected mode
Hi,
The second method is segmentation, where the OS can prevent one piece of ring 3 code from accessing segments that belong to other pieces of ring 3 code by making those segments unusable. For example, either mark those segments as temporarily "not present" in the GDT, or have a different LDT for each piece of ring 3 code.
The last method is software isolation, where the hardware isn't used to prevent processes from trashing each other, but the OS forces everyone to use the same compiler and the compiler makes sure that processes don't try to access something they shouldn't. This is probably a good idea in theory, but in practice it's hard enough writing an OS without also writing a compiler.
Cheers,
Brendan
There's also exceptions, call gates and for newer CPUs there's special instructions (SYSENTER and SYSCALL). Any of these could be used to switch from ring 3 to ring 0.CPLH wrote:I have found that while in ring 3, I cannot access ring 0 without an interrupt.
There's only 3 possible ways that can be used to prevent ring 3 code accessing data that belongs to other ring 3 code. The first method is paging, which is what almost all modern OSs use, where different pieces of ring 3 code (processes) are in completely separate virtual address spaces. There's other benefits from using paging too (not just protection).CPLH wrote:However I can access other segments that are at ring 3. What do I do to stop the ring 3 code from being able to access any other segments that do not belong to it? ..once again I'm trying to implement memory protection, so no two programs can access each other. (My best guess is to use a TSS.. I'm still trying to find a good tutorial on it.. most of the time they talk about multitasking, which is something I am currently not working on.)
The second method is segmentation, where the OS can prevent one piece of ring 3 code from accessing segments that belong to other pieces of ring 3 code by making those segments unusable. For example, either mark those segments as temporarily "not present" in the GDT, or have a different LDT for each piece of ring 3 code.
The last method is software isolation, where the hardware isn't used to prevent processes from trashing each other, but the OS forces everyone to use the same compiler and the compiler makes sure that processes don't try to access something they shouldn't. This is probably a good idea in theory, but in practice it's hard enough writing an OS without also writing a compiler.
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.
Re: A clarification of the abilities of protected mode
Thank you, Brendan, for your post.
Currently I am using segmentation because most tutorials and sample codes ignore paging. I would like to use paging, but don't know the specifics well enough yet. (I understand the general theory of it though)...
I understood the technique in segmentation for setting the "Not Present" flag.
However, in paging, although you have a flat memory model, which stops you from being able to get to a "limited" area of the memory, while in paging mode, can't a user program still switch it's "DS" to something else that is of ring 3? Do you use the "Not Present" flag technique here too?
I have heard that Linux uses only one code segment and one data segment for all ring 3 processes. However this seems kind of inefficient to me as it implies that every single time you switch to another process you have to update the virtual memory to point to the correct physical memory for the process...
....am I correct? Perhaps the switching is actually a bit faster than I think? Once again these are the "specifics" in paging that I don't know about.
Managing all of the virtual memory addresses seems kind of overwhelming.. I keep on thinking about how much memory all of these addresses would take up.. even though they are blocks of 4K.
Currently I am using segmentation because most tutorials and sample codes ignore paging. I would like to use paging, but don't know the specifics well enough yet. (I understand the general theory of it though)...
I understood the technique in segmentation for setting the "Not Present" flag.
However, in paging, although you have a flat memory model, which stops you from being able to get to a "limited" area of the memory, while in paging mode, can't a user program still switch it's "DS" to something else that is of ring 3? Do you use the "Not Present" flag technique here too?
I have heard that Linux uses only one code segment and one data segment for all ring 3 processes. However this seems kind of inefficient to me as it implies that every single time you switch to another process you have to update the virtual memory to point to the correct physical memory for the process...
....am I correct? Perhaps the switching is actually a bit faster than I think? Once again these are the "specifics" in paging that I don't know about.
Managing all of the virtual memory addresses seems kind of overwhelming.. I keep on thinking about how much memory all of these addresses would take up.. even though they are blocks of 4K.
Have a plan.
Re: A clarification of the abilities of protected mode
Hi,
When you switch from one virtual address space to another all you need to do is change one register (CR3).
It's more complex than that though, and paging does at a little overhead (TLB misses). However, without paging you'll need to handle physical memory fragmentation which can add a lot more overhead than paging does, and swapping RAM to/from disk becomes a nightmare, and you can't use common "virtual memory manager tricks" to improve performance and reduce RAM usage (like zeroed page optimizations, memory mapped files, shared memory, etc).
The amount of RAM used for paging (page directories, page tables, etc) is usually a very small amount of total RAM (less than 5%). This depends on a lot of things though...
Cheers,
Brendan
Normally there's only 3 segments (descriptors) that ring 3 code can use and none of them can be used to access any other ring 3 code's data, so you don't need to set any segments (descriptors) to "not present". Note: 3 segments (descriptors) means one for the code segment, one for the data segment, and the NULL descriptor (which is mostly useless, but can be loaded into a segment register).CPLH wrote:However, in paging, although you have a flat memory model, which stops you from being able to get to a "limited" area of the memory, while in paging mode, can't a user program still switch it's "DS" to something else that is of ring 3? Do you use the "Not Present" flag technique here too?
CPLH wrote:I have heard that Linux uses only one code segment and one data segment for all ring 3 processes. However this seems kind of inefficient to me as it implies that every single time you switch to another process you have to update the virtual memory to point to the correct physical memory for the process...
....am I correct? Perhaps the switching is actually a bit faster than I think? Once again these are the "specifics" in paging that I don't know about.
When you switch from one virtual address space to another all you need to do is change one register (CR3).
It's more complex than that though, and paging does at a little overhead (TLB misses). However, without paging you'll need to handle physical memory fragmentation which can add a lot more overhead than paging does, and swapping RAM to/from disk becomes a nightmare, and you can't use common "virtual memory manager tricks" to improve performance and reduce RAM usage (like zeroed page optimizations, memory mapped files, shared memory, etc).
[/quote]CPLH wrote:Managing all of the virtual memory addresses seems kind of overwhelming.. I keep on thinking about how much memory all of these addresses would take up.. even though they are blocks of 4K.
The amount of RAM used for paging (page directories, page tables, etc) is usually a very small amount of total RAM (less than 5%). This depends on a lot of things though...
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.
Re: A clarification of the abilities of protected mode
Eh, I do not want to have this post turned into a flame war of any type.
I thank you for your helpful posts. Last thing I want to ask, if anybody has the reference:
I usually learn best by example. So far I have found a few documentations on paging (including the wiki) but no sample codes. Does anybody have a reference to a really simple paging code? Note my emphesis on it being very simple.
...Preferably in assembly, if possible.
I thank you for your helpful posts. Last thing I want to ask, if anybody has the reference:
I usually learn best by example. So far I have found a few documentations on paging (including the wiki) but no sample codes. Does anybody have a reference to a really simple paging code? Note my emphesis on it being very simple.
...Preferably in assembly, if possible.
Have a plan.
Re: A clarification of the abilities of protected mode
Hi,
Cheers,
Brendan
CPLH wrote:Eh, I do not want to have this post turned into a flame war of any type.
The Virtual Memory Tutorial mentioned in this post looks like a very nice start. Even though the example code is in C the theory explains what's going on (and why), and you'll probably need to get used to reading some C now and then...CPLH wrote:I thank you for your helpful posts. Last thing I want to ask, if anybody has the reference:
I usually learn best by example. So far I have found a few documentations on paging (including the wiki) but no sample codes. Does anybody have a reference to a really simple paging code? Note my emphesis on it being very simple.
...Preferably in assembly, if possible.
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.