linux/arch/mips/kernel/smtc-asm.S
<<
>>
Prefs
   1/*
   2 * Assembly Language Functions for MIPS MT SMTC support
   3 */
   4
   5/*
   6 * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */
   7
   8#include <asm/regdef.h>
   9#include <asm/asmmacro.h>
  10#include <asm/stackframe.h>
  11#include <asm/irqflags.h>
  12
  13/*
  14 * "Software Interrupt" linkage.
  15 *
  16 * This is invoked when an "Interrupt" is sent from one TC to another,
  17 * where the TC to be interrupted is halted, has it's Restart address
  18 * and Status values saved by the "remote control" thread, then modified
  19 * to cause execution to begin here, in kenel mode. This code then
  20 * disguises the TC state as that of an exception and transfers
  21 * control to the general exception or vectored interrupt handler.
  22 */
  23        .set noreorder
  24
  25/*
  26The __smtc_ipi_vector would use k0 and k1 as temporaries and
  271) Set EXL (this is per-VPE, so this can't be done by proxy!)
  282) Restore the K/CU and IXMT bits to the pre "exception" state
  29   (EXL means no interrupts and access to the kernel map).
  303) Set EPC to be the saved value of TCRestart.
  314) Jump to the exception handler entry point passed by the sender.
  32
  33CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED??
  34*/
  35
  36/*
  37 * Reviled and slandered vision: Set EXL and restore K/CU/IXMT
  38 * state of pre-halt thread, then save everything and call
  39 * thought some function pointer to imaginary_exception, which
  40 * will parse a register value or memory message queue to
  41 * deliver things like interprocessor interrupts. On return
  42 * from that function, jump to the global ret_from_irq code
  43 * to invoke the scheduler and return as appropriate.
  44 */
  45
  46#define PT_PADSLOT4 (PT_R0-8)
  47#define PT_PADSLOT5 (PT_R0-4)
  48
  49        .text
  50        .align 5
  51FEXPORT(__smtc_ipi_vector)
  52        .set    noat
  53        /* Disable thread scheduling to make Status update atomic */
  54        DMT     27                                      # dmt   k1
  55        _ehb
  56        /* Set EXL */
  57        mfc0    k0,CP0_STATUS
  58        ori     k0,k0,ST0_EXL
  59        mtc0    k0,CP0_STATUS
  60        _ehb
  61        /* Thread scheduling now inhibited by EXL. Restore TE state. */
  62        andi    k1,k1,VPECONTROL_TE
  63        beqz    k1,1f
  64        emt
  651:
  66        /*
  67         * The IPI sender has put some information on the anticipated
  68         * kernel stack frame.  If we were in user mode, this will be
  69         * built above the saved kernel SP.  If we were already in the
  70         * kernel, it will be built above the current CPU SP.
  71         *
  72         * Were we in kernel mode, as indicated by CU0?
  73         */
  74        sll     k1,k0,3
  75        .set noreorder
  76        bltz    k1,2f
  77        move    k1,sp
  78        .set reorder
  79        /*
  80         * If previously in user mode, set CU0 and use kernel stack.
  81         */
  82        li      k1,ST0_CU0
  83        or      k1,k1,k0
  84        mtc0    k1,CP0_STATUS
  85        _ehb
  86        get_saved_sp
  87        /* Interrupting TC will have pre-set values in slots in the new frame */
  882:      subu    k1,k1,PT_SIZE
  89        /* Load TCStatus Value */
  90        lw      k0,PT_TCSTATUS(k1)
  91        /* Write it to TCStatus to restore CU/KSU/IXMT state */
  92        mtc0    k0,$2,1
  93        _ehb
  94        lw      k0,PT_EPC(k1)
  95        mtc0    k0,CP0_EPC
  96        /* Save all will redundantly recompute the SP, but use it for now */
  97        SAVE_ALL
  98        CLI
  99        TRACE_IRQS_OFF
 100        /* Function to be invoked passed stack pad slot 5 */
 101        lw      t0,PT_PADSLOT5(sp)
 102        /* Argument from sender passed in stack pad slot 4 */
 103        lw      a0,PT_PADSLOT4(sp)
 104        LONG_L  s0, TI_REGS($28)
 105        LONG_S  sp, TI_REGS($28)
 106        PTR_LA  ra, ret_from_irq
 107        jr      t0
 108
 109/*
 110 * Called from idle loop to provoke processing of queued IPIs
 111 * First IPI message in queue passed as argument.
 112 */
 113
 114LEAF(self_ipi)
 115        /* Before anything else, block interrupts */
 116        mfc0    t0,CP0_TCSTATUS
 117        ori     t1,t0,TCSTATUS_IXMT
 118        mtc0    t1,CP0_TCSTATUS
 119        _ehb
 120        /* We know we're in kernel mode, so prepare stack frame */
 121        subu    t1,sp,PT_SIZE
 122        sw      ra,PT_EPC(t1)
 123        sw      a0,PT_PADSLOT4(t1)
 124        la      t2,ipi_decode
 125        sw      t2,PT_PADSLOT5(t1)
 126        /* Save pre-disable value of TCStatus */
 127        sw      t0,PT_TCSTATUS(t1)
 128        j       __smtc_ipi_vector
 129        nop
 130END(self_ipi)
 131
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.