Hello everyone,
After thinking a bit about how the boot drivers can be called by the kernel only when needed, I came up with a solution that I wanted to share for suggestions, comments, and maybe help give some insight on other microkernel developers here. A boot driver, in my case, is a driver loaded along with the kernel by the OS loading program into kernel space.
The basic idea I have is to provide a system call that can be called by drivers (using an INT instruction, like Linux's int 0x80). The system call can be used to install a system interrupt call thus allowing the driver to install its own system interrupt call.
For an example, lets say this system interrupt service is KeSysRead, for reading data from a disk into a buffer. The driver calls the kernel's system interrupt service to install this interrupt to a function of the system interrupt (like, int 0x80 function 2). This will overwrite any existing interrupt in the kernels system call table of course. So, now, whenever INT 0x80 function 2 is called to read data from disk, it will automatically call the drivers interrupt handler.
If the kernel provides a system call that returns the current system interrupt routine, this allows the driver to obtain a pointer to the previous interrupt handler for that function. ie, the driver can obtain the last interrupt handler for int 0x80 function 2, store it somewhere, and install its own.
From here, whenever the drivers interrupt handler is called, using interrupt chaining it can call the last installed handler. Thus allowing the kernels default routines to be called, and any other driver of the same type to have a chance at the request before returning.
This design only applies to drivers needing to be called on system call events. Other drivers do not need to do this. This method also makes it so most system calls will be handled in external libraries or drivers.
---
What do you think? Are there any problems with this method that I may have overlooked? I am looking for comments, suggestions, basically anything for this idea. And who knows - if it is a good one it might help other microkernel system designers here as well.
If you are a microkernel developer, feel free to add your own set up if you like Im basically looking for different designs
Boot driver calling idea
Boot driver calling idea
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Re: Boot driver calling idea
Fancy that, this method is exactly how my OS works and btw the old DOS as well.
I've not had any issues with how it works. I do not however how a system stack, threads or execution protection mechanisms in place, so I'm not sure what the impact would be on this way of doing things should you need the aforementioned options in place.
One thing that did need special attention is the way the drivers are written and how they handle the return from the interrupt. I remember it needing some stack manipulation to work properly.
The way my drivers are loaded is as follows:
1. Tell grub in the .lst which modules to load (modules are normal executables that can be run at OS runtime after loading as well)
2. Once the kernel is booted, I iterate the multiboot list of modules and execute the inmemory images of the drivers. Each driver then terminates and stays resident.
3. The last driver to be loaded is the GUI/Shell that does not terminate and runs the main lop of the OS.
Hope this helped.
I've not had any issues with how it works. I do not however how a system stack, threads or execution protection mechanisms in place, so I'm not sure what the impact would be on this way of doing things should you need the aforementioned options in place.
One thing that did need special attention is the way the drivers are written and how they handle the return from the interrupt. I remember it needing some stack manipulation to work properly.
The way my drivers are loaded is as follows:
1. Tell grub in the .lst which modules to load (modules are normal executables that can be run at OS runtime after loading as well)
2. Once the kernel is booted, I iterate the multiboot list of modules and execute the inmemory images of the drivers. Each driver then terminates and stays resident.
3. The last driver to be loaded is the GUI/Shell that does not terminate and runs the main lop of the OS.
Hope this helped.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Boot driver calling idea
One of the problems here is that you will have to trust certain code enough to allow them to be run in kernel space (otherwise, the interrupt mechanism won't work), which is in violation of microkernel principles.
Of course you can simulate a similar calling scheme in userland.
Of course you can simulate a similar calling scheme in userland.
Re: Boot driver calling idea
Thanks for the responses
I have implemented the idea but with one modification: Not all system calls can be changed. This allows kernel-only system calls (that cannot be replaced) and takes the possibility of replacing the system call used to change system calls out.
mybura: My drivers are loaded in a similar way. My OS Loader program reads an lst file and loads all of the listed boot drivers in it, and passes the list of boot modules to the kernel. The kernel then goes through the boot module list and calls the entry points allowing them to initialize. Im intrigued by your idea of using the last driver to load to also be the GUI/Shell though but think I would prefer that not being a boot module.
Combuster: Very true. The original idea was specifically for boot modules that are loaded with the kernel. The kernel itself does just the most basic of tasks, everything else is currently done through external boot modules. The only boot modules that there should be are just enough to allow the kernel to load data from disk so the kernel can continue to load additional files as needed. This was the only solution that I can think of that would allow what I wanted...
*edit: Actually, with my current setup I might be able to turn the boot modules - disk driver and filesystem driver - into userland drivers. This seems like a hit on performance though.
I have implemented the idea but with one modification: Not all system calls can be changed. This allows kernel-only system calls (that cannot be replaced) and takes the possibility of replacing the system call used to change system calls out.
mybura: My drivers are loaded in a similar way. My OS Loader program reads an lst file and loads all of the listed boot drivers in it, and passes the list of boot modules to the kernel. The kernel then goes through the boot module list and calls the entry points allowing them to initialize. Im intrigued by your idea of using the last driver to load to also be the GUI/Shell though but think I would prefer that not being a boot module.
Combuster: Very true. The original idea was specifically for boot modules that are loaded with the kernel. The kernel itself does just the most basic of tasks, everything else is currently done through external boot modules. The only boot modules that there should be are just enough to allow the kernel to load data from disk so the kernel can continue to load additional files as needed. This was the only solution that I can think of that would allow what I wanted...
*edit: Actually, with my current setup I might be able to turn the boot modules - disk driver and filesystem driver - into userland drivers. This seems like a hit on performance though.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Boot driver calling idea
Yes, running drivers in userspace is slower. Yes it's safer. If you dump them in kernel space then we're technically talking about a modular kernel and no longer a microkernel. But that's a design choice you can start a holy war over.neon wrote:Combuster: Very true. The original idea was specifically for boot modules that are loaded with the kernel. The kernel itself does just the most basic of tasks, everything else is currently done through external boot modules. The only boot modules that there should be are just enough to allow the kernel to load data from disk so the kernel can continue to load additional files as needed. This was the only solution that I can think of that would allow what I wanted...
*edit: Actually, with my current setup I might be able to turn the boot modules - disk driver and filesystem driver - into userland drivers. This seems like a hit on performance though.
I'm doing an exokernel, yet my code largely runs in userspace like a microkernel. I load a bunch of modules at boot (currently in the form of a ramdisk since I haven't completed grub support) and pass them to the kernel which then starts one of them, passing the list of modules along (its called stage 4 in my case). From there, all data and execution is in userland, and from there other modules can be started, including disk services, which in turn allow more modules to be loaded from storage. Where that ends is up to you.