Hi,
gerryg400 wrote:
Brendan wrote:
A micro-kernel sacrifices some performance (due to IPC costs), and the only reason to do this is to avoid the need for "trusted drivers".
You should be able to download a "binary blob" device driver via. a Chinese peer to peer file sharing site (that was uploaded by a guy who calls himself "PawninU"), and use that driver on a server for an international bank without worrying about anything (other than the driver crashing or not working with the device) because you're using a micro-kernel.
When the blob says "I'm a keyboard driver, give me access to the IO ports related to the keyboard" how do you know to trust the blob?
You should be able to trust that the blob:
- Can't touch any kernel data
- Can't touch any IO ports, memory mapped areas, etc; that belong to other devices
- Can't touch any data that belongs to any other process (drivers, applications, etc)
- (Optionally/hopefully) Can't use networking
The only thing you can't be sure of is whether or not it handles the device properly; but if it doesn't then all other devices still work and it'd be obvious which device doesn't.
Note: Technically, keyboard driver would communicate with "PS/2 controller" driver, and keyboard driver itself wouldn't be given access to any IO ports. If "PS/2 controller driver" is dodgy it'd be able to interfere with data going to/from all PS/2 device drivers (keyboard, mouse, touchpad, bar-code scanner, etc).gerryg400 wrote:
Brendan wrote:
That information is trivial to obtain from PCI configuration space BARs. Of course I'd have a "device manager" process that does device enumeration, etc (and starts drivers, and tells kernel which driver should be allowed to use which resources).
It's also trivial to add a few fields to whatever the kernel uses as a "process data structure".
Of course, linked lists, bitmaps, dynamic memory management and the like are trivial. But so is setting up the IO bitmap. The point is that this method saves no complexity over the other methods.
My mistake - I thought you meant "harder than setting IOPL to 3 and not keeping track of which process can access which IO ports at all" (e.g. just an "all IO ports or no IO ports" flag for each process).
gerryg400 wrote:
And if IO is required to be done while processing an interrupt message (prior to sending the EOI at the end of processing) wouldn't there be a concern about the extra time taken to make all the system calls required to process the interrupt under this scheme. I'm really thinking that this method is probably unworkable.
Timing is all variable anyway, due to things like different computers being faster/slower, interrupts, task switching, power management, SMI/SMM, etc. There are no devices that have timing requirements that are so strict that it causes problems.
gerryg400 wrote:
And if IO is required to be done while processing an interrupt message (prior to sending the EOI at the end of processing) wouldn't there be a concern about the extra time taken to make all the system calls required to process the interrupt under this scheme. I'm really thinking that this method is probably unworkable.
Typically; the kernel's interrupt handler sends "IRQ occurred" messages out, causing (extremely high priority) "driver thread/s" to be unblocked, which ("immediately") preempt any (lower priority) threads that were running causing a task switch; then the thread/s examine the message they received, check if their device caused the interrupt and handle it if necessary, and call an "I finished with that IRQ" kernel function (and then block waiting for a message). While all this is going on interrupts are enabled and only lower priority IRQs (as determined by the interrupt controller's "IRQ priority" scheme) are blocked. The overhead of driver thread/s using a kernel function to access IO ports (within its interrupt handling) is negligible compared to the rest of it.
Note that my kernels typically have support for "batch kernel functions". Essentially; instead of doing one kernel function at a time (and paying the "CPL=3 -> CPL=0 -> CPL=3" switching cost for each function) you can build a list and ask kernel to process the list (and only pay the "CPL=3 -> CPL=0 -> CPL=3" switching cost once for the entire list). This means that (e.g.) a driver can ask kernel to write to an IO port, then send a message, then do the "I finished with the IRQ" and then do the "get message/block waiting for message"; all in a single "do this list" kernel function.
Cheers,
Brendan