LOGIN   :::   RECOVER PASS   :::   GET ACCOUNT    
Browse
  • Projects
  • Code (CVS)
  • Forums
  • News
  • Articles
  • Polls
  •  
    OpenCores
  • FAQ
  • CVS HowTo
  • Mission
  • Media
  • Tools
  • Sponsors
  • Mirrors
  • Logos
  • Contact us
  •  
    Tools
  • Search
      
  • Download Cores (CVSGet)
  •  
    More
  • Wishbone
  • Perlilog
  • EDA tools
  • OpenTech CD
  •  
    Navigation: All forums > Cores > Message List > Message Post

    Message

    Reply | Reply all
    Date Prev | Date Next | Thread Prev | Thread Next Date Index | Thread Index

    From: Enrico Weigelt<weigelt@m...>
    Date: Fri Apr 18 01:29:48 CEST 2008
    Subject: [oc] Naive thoughts on interrupts and processes
    Top

    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/ ---------------------------------------------------------------------

     
    Copyright (c) 1999 OPENCORES.ORG. All rights reserved.