(candy) modules & drivers.
Posted: Tue Dec 23, 2003 8:49 am
Initial post in another thread (leaving undefined references by LD ...) by Candy.
The Place to Start for Operating System Developers
http://f.osdev.org/
No way I didn't. There are still a lot of things about it that I didn't work out yet, it's just that I thought it out to the point where it is now. And as far as my module system is working now, it's sufficient. As Tim would put it, it's a design made by somebody that didn't do something like that before, so it's probably wrong.Adek336 wrote: Candy: I see you have designed your method in every aspect!
Must admit that I never thought "Hey let's make a microkernel", just like you. The concept of message-passing including making the kernel a pure message-passer (amoeba etc) seems like an oversimplification of the kernel, as in, it might look nice and if you optimize it like **** it might be faster than a normal monolithic kernel (as they call 'em) but I don't see any reason to do so. Or, like Einstein put it, make it as simple as it can be, but no simpler (quote from book of Tanenbaum himself, page where he describes amoeba).At this moment I'll be trying to make it as simple as possible but, I will think about all those nifty features. What do you think of a system where all modules are in kernel space and none in user? Something like Linux, I don't like the microkernel design very much.
Hmm ... so conceptually, you're walking the list of available modules, looking for modules whose dependency graph is only made of loaded modules, then load them and look for further "ready" modules.Candy wrote: After this loading phase, the memory allocator frees all init memory (still to be implemented, just found out how thanks to Chris Giese) and then it starts loading modules that either have no objects they depend on, or whose depending objects are present.
That probe-section thing is interresting... I have myself tried to do something alike and come to a design with roughly 3 modules per driver:It loads only the probe-section (.probe.text, .probe.data and .probe.bss) that can only probe for the device. If it returns with success, the rest of the module is loaded, called to init, then init and probe are removed again (so you can use some detected info from the probe to the module).
Do you mean the loader should be able to make the same binary loaded either at kernel or at user level ?Thinking about this, it would be best if you relocated every module before running it, and then according to user settings decided whether it would be kernel mode or user mode.
If you're sure that the target of a communication do not change once the modules have been installed, what you can do is, at load time, decide whether a direct component connection is available or if a proxy/stub (hiding the cross-domain communication) must be used.I was thinking about linking the modules through a highspeed kernel call something that all modules call to call other modules. Still wondering about any better ways, since this would require all kernel-only modules to communicate through that path too, thus becoming a lagpoint.
That's true. Also note that all of the modules must be completely written for reentrancy, as will the kernel. As far as possible, multiple modules will be probed simultaneously (so slow probes do not slow down the boot by themselves). There will be a kernel level module admin thread that does all the adminning and decides what to try (something like the intelligence of the system), and then posts messages (no I'm still not going microkernel) to the worker threads, that then call those functions.Pype.Clicker wrote: Hmm ... so conceptually, you're walking the list of available modules, looking for modules whose dependency graph is only made of loaded modules, then load them and look for further "ready" modules.
Well, the compiler helps you a lot. Since the gnu compiler (as the gnu linker) do not remove any relocations until the final relocation step, which I do myself, I have all relocation info (strip is forbidden), and can thus check for every symbol whether it is in one or another section. If I thus find a relocation in either probe or core that links to a symbol of the other, that'll be obviously wrong.That probe-section thing is interresting... I have myself tried to do something alike and come to a design with roughly 3 modules per driver:
- the "xyzCore" module that contains helper functions required by both the probing and the running code.
- the "xyzBusdriver" that is responsible for scanning hardware and loading the requested modules for the available devices.
- the "xyzDeviceDrivers" modules that will actually do the useful job.
Once the busdriver has been installing the device drivers, it could theorically be unloaded...
One thing that remain obscure to me with those "probe" section is how much the compiler can help you detecting probe code that calls non-probe code or non-probe data.
No, as a matter of fact, I was thinking about a method with a number of macros to wrap around those module calls in a shared header, and to let them function somewhat like the PLT in ELF files. That is, code that modifies itself but only in that place. It is still something I'm not sure about, so correct me if this is a really stupid idea.Do you mean the loader should be able to make the same binary loaded either at kernel or at user level ?
I suppose you'll use something like a dynamically linked (and generated ?) library to provide "trampolines" to system calls when needed (like, calling INT $82 instead of calling kprint directly).
Well, I don't do timeouts that way, honestly... Still, your point is taken, and I must admit, didn't think about that. I'll think about it some tonight.One thing i wonder is how you'll deal with "objects" or pointer to data structures that must be kept within the kernel ... Let's say for instance you need to trampoline to kDelay* setupTimeout(int millis) and need the return value for later cancelTimeout(kDelay* delay) but you do not want user-level code to give you "forged" nor "stolen" timeout structures ? ...
Please, let your conceptual ideas out. If all we can only learn from them and point you to obvious flaws, as you yourself do with all the others here, including me.I have ideas on my own for that kind of flexible communication, but they're still in the sketchbook and need further study before i can express them clearly ...
Hum. Well, i'll try -- note that i'm rather inclined to idea-sharing, but this one is still at a *very* draft level ... I'll give it a try thoughCandy wrote: Please, let your conceptual ideas out. If all we can only learn from them and point you to obvious flaws, as you yourself do with all the others here, including me.
Hum. I fear after all this time i've lost the thread a bit ... what everything do you wish to copy exactly ? ...Candy wrote: just for kicks...
What about the method that is fully possible for me but absolutely out of the question for you? Copying everything?
by not allowing those modules to allocate kernel space-address space, in the first place. If it was a bad module, it could request too much, thus not good (Also, why would the address space have to be in the kernel? it has its own address space when in user space). So, the function itself maps to a different set of memory pages for user or kernel mode.Pype.Clicker wrote: Hum. I fear after all this time i've lost the thread a bit ... what everything do you wish to copy exactly ? ...
I don't think creating copies of driver-to-kernel calls parameters will solve everything.
Let's take the following example: a disk driver need to send the content of a user data page to a disk sector ... In order to do this, it performs the following when in kernel mode:
- request for a 4K free system area (just virtual memory) and receive the vaddr_t for it
- maps the page frame provided by the "syscall decoder" to the newly allocated vaddr_t
- reads the user data and send them to the disk with I/O opcodes (that your kernel will have allowed through a proper I/O bitmap)
How would the 'copy everything' handle the fact that only the returned vaddr_t and the syscall-decoded frame_t may be given to the pgMap service ?
It is more or less impossible to do so. You can only expect it not to take random frame_t's but if it does it's in its own space, it misbehaves, user notices, kills driver. Still, I don't expect many people to write this kind of driver, I was thinking more in the lines of utility drivers, where it is obvious that it doesn't work anymore (video card drivers, sound card drivers, fs system drivers etc).Once you'll have allowed PCI dma, how will you still check things, as there will no longer be any kind of pgMap service involved, but rather frame_t stuff directly fed to the ultradma PCI configuration space ? ...