1/1

|
Naive thoughts on interrupts and processes
by Unknown on Apr 18, 2008 |
Not available! | ||
|
Hi folks,
a few naive thoughs about interrupts and process switching
from an software-only (but embedded experienced) guy ...
First, I'd rather choose a more abstract name: exceptions.
I see two major reasons why an exception can happen:
a) internal: access violations, page faults, syscalls, preemtion
b) external: periphery signals data ready or data request, etc
What should happen in these cases ?
* page fault:
-> jump into kernel (hypervisor), so it can handle the fault
(eg. swapping in).
-> kernel doesn't need access to process' address space
* access violation:
-> jump into kernel to, so it can handle this violation (eg.
sending signal to process or even simulating successful access)
-> access to process' address space might be necessary
* preemtion:
-> jump into kernel, so it can find the next process in queue
and switch to it.
-> kernel doesn't need process' address space
* syscall:
-> jump into kernel, so it can handle the syscall.
-> kernel needs access to process' address space
* signal from periphery:
-> jump into kernel to handle the event (at least critical parts)
-> kernel needs process' address space.
Obviously the most vital (and performance critical) point seems to
be safely switching to kernel privileges, blocking further exceptions
and saving the processor status (registers, etc). Ideally this should
work in ony cycle.
Proposed solution:
* the current process has several access privile flags, which define
allowed operations (eg. accessing privileged registers)
* the (process visible) register space is bank switched (eg. 4 banks)
* an interrupt causes an primitive kind of context switch:
* blocking further interrupts
* switching register bank (including privilege flags)
* loading IP w/ handler vector
* loading some working registers with interrupt type, etc
* the RETI instruction swiches the whole thing back, restores the
privilege and cleares the interrupt block.
This approach (IMHO) has the big advantage that whole switch is quite
cheap and safe (kernel doesn't have to safe, init and later restore
registers) and easily manipulate the process' status, including
emulating privileged operations. To make nesting OS'es easier, the
process visible privilege register(s) could also be virtualized:
userland's access from the goes to userland register bank and writes
can be catched by exceptions. So it should be possible to stack
dozens of OS'es together, without them even noticing it.
How to do preemtion:
There could be some (privileged) TTL counter register, which goes
down with each cycle. Reaching zero causes the preemt exception.
This way, the kernel can easily specify the exact interval for the
next process. For realtime processes, even some exceptions (eg.
periphery signals) could be blocked and explictly checked at the
preemtion point.
Syscalls and kernel processes:
Of course, it should also be easy to make large parts of the kernel
(at least syscalls) preemtible / interruptible by exception.
As in my design the syscalls happen through exceptions, the best
way (IMHO) is that the syscall exception handler just coordinates
the switch to kernelspace (switching registers, etc) and return to
"normal" (non-exception) mode.
The CPU design can assist here by having more than just two register
banks. So we had eg. these banks:
#0 HYPERVISOR: normally exceptions run here
#1 MCP: here the kernelspace stuff runs (syscalls, etc)
#2 PRIVILEGED: reserved for nested OS kernel or maybe some drivers
#3 USER: plain user processes run here
IMHO it's wise that these banks are technically equal, just limited
in their privileges by their privilege register.
For an massive multicore system we could even go some bits further:
* the registers live in an separate cache memory
* each core's register space is mapped to their own minipage to
their own cache minipage (by an simple mux).
* same with working memory, which is mapped by an separate MMU
* reg-mux and mmu are configured via memory an area (through MMU ;-P)
* exceptions are processed via an special exception multiplexer,
which can wakeup an configured core.
* at least one core is dedicated to the MCP. (for automatic
failover there could be multiple ones and an watchdog mechanism)
* the MCP does the whole work of context switching and exception
handling for all user cores, eg. by switching their register mapping.
What do you think about these ideas ?
cu
--
---------------------------------------------------------------------
Enrico Weigelt == metux IT service - http://www.metux.de/
---------------------------------------------------------------------
Please visit the OpenSource QM Taskforce:
http://wiki.metux.de/public/OpenSource_QM_Taskforce
Patches / Fixes for a lot dozens of packages in dozens of versions:
http://patches.metux.de/
---------------------------------------------------------------------
|
|||
1/1

