1ca54502bSMichal Simek/* 2ca54502bSMichal Simek * Low-level system-call handling, trap handlers and context-switching 3ca54502bSMichal Simek * 4ca54502bSMichal Simek * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> 5ca54502bSMichal Simek * Copyright (C) 2008-2009 PetaLogix 6ca54502bSMichal Simek * Copyright (C) 2003 John Williams <jwilliams@itee.uq.edu.au> 7ca54502bSMichal Simek * Copyright (C) 2001,2002 NEC Corporation 8ca54502bSMichal Simek * Copyright (C) 2001,2002 Miles Bader <miles@gnu.org> 9ca54502bSMichal Simek * 10ca54502bSMichal Simek * This file is subject to the terms and conditions of the GNU General 11ca54502bSMichal Simek * Public License. See the file COPYING in the main directory of this 12ca54502bSMichal Simek * archive for more details. 13ca54502bSMichal Simek * 14ca54502bSMichal Simek * Written by Miles Bader <miles@gnu.org> 15ca54502bSMichal Simek * Heavily modified by John Williams for Microblaze 16ca54502bSMichal Simek */ 17ca54502bSMichal Simek 18ca54502bSMichal Simek#include <linux/sys.h> 19ca54502bSMichal Simek#include <linux/linkage.h> 20ca54502bSMichal Simek 21ca54502bSMichal Simek#include <asm/entry.h> 22ca54502bSMichal Simek#include <asm/current.h> 23ca54502bSMichal Simek#include <asm/processor.h> 24ca54502bSMichal Simek#include <asm/exceptions.h> 25ca54502bSMichal Simek#include <asm/asm-offsets.h> 26ca54502bSMichal Simek#include <asm/thread_info.h> 27ca54502bSMichal Simek 28ca54502bSMichal Simek#include <asm/page.h> 29ca54502bSMichal Simek#include <asm/unistd.h> 30ca54502bSMichal Simek 31ca54502bSMichal Simek#include <linux/errno.h> 32ca54502bSMichal Simek#include <asm/signal.h> 33*88707ebeSAppana Durga Kedareswara rao#include <asm/mmu.h> 34ca54502bSMichal Simek 3511d51360SMichal Simek#undef DEBUG 3611d51360SMichal Simek 37d8748e73SMichal Simek#ifdef DEBUG 38d8748e73SMichal Simek/* Create space for syscalls counting. */ 39d8748e73SMichal Simek.section .data 40d8748e73SMichal Simek.global syscall_debug_table 41d8748e73SMichal Simek.align 4 42d8748e73SMichal Simeksyscall_debug_table: 43d8748e73SMichal Simek .space (__NR_syscalls * 4) 44d8748e73SMichal Simek#endif /* DEBUG */ 45d8748e73SMichal Simek 46ca54502bSMichal Simek#define C_ENTRY(name) .globl name; .align 4; name 47ca54502bSMichal Simek 48ca54502bSMichal Simek/* 49ca54502bSMichal Simek * Various ways of setting and clearing BIP in flags reg. 50ca54502bSMichal Simek * This is mucky, but necessary using microblaze version that 51ca54502bSMichal Simek * allows msr ops to write to BIP 52ca54502bSMichal Simek */ 53ca54502bSMichal Simek#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 54ca54502bSMichal Simek .macro clear_bip 5566f7de86SMichal Simek msrclr r0, MSR_BIP 56ca54502bSMichal Simek .endm 57ca54502bSMichal Simek 58ca54502bSMichal Simek .macro set_bip 5966f7de86SMichal Simek msrset r0, MSR_BIP 60ca54502bSMichal Simek .endm 61ca54502bSMichal Simek 62ca54502bSMichal Simek .macro clear_eip 6366f7de86SMichal Simek msrclr r0, MSR_EIP 64ca54502bSMichal Simek .endm 65ca54502bSMichal Simek 66ca54502bSMichal Simek .macro set_ee 6766f7de86SMichal Simek msrset r0, MSR_EE 68ca54502bSMichal Simek .endm 69ca54502bSMichal Simek 70ca54502bSMichal Simek .macro disable_irq 7166f7de86SMichal Simek msrclr r0, MSR_IE 72ca54502bSMichal Simek .endm 73ca54502bSMichal Simek 74ca54502bSMichal Simek .macro enable_irq 7566f7de86SMichal Simek msrset r0, MSR_IE 76ca54502bSMichal Simek .endm 77ca54502bSMichal Simek 78ca54502bSMichal Simek .macro set_ums 7966f7de86SMichal Simek msrset r0, MSR_UMS 8066f7de86SMichal Simek msrclr r0, MSR_VMS 81ca54502bSMichal Simek .endm 82ca54502bSMichal Simek 83ca54502bSMichal Simek .macro set_vms 8466f7de86SMichal Simek msrclr r0, MSR_UMS 8566f7de86SMichal Simek msrset r0, MSR_VMS 86ca54502bSMichal Simek .endm 87ca54502bSMichal Simek 88b318067eSMichal Simek .macro clear_ums 8966f7de86SMichal Simek msrclr r0, MSR_UMS 90b318067eSMichal Simek .endm 91b318067eSMichal Simek 92ca54502bSMichal Simek .macro clear_vms_ums 9366f7de86SMichal Simek msrclr r0, MSR_VMS | MSR_UMS 94ca54502bSMichal Simek .endm 95ca54502bSMichal Simek#else 96ca54502bSMichal Simek .macro clear_bip 97ca54502bSMichal Simek mfs r11, rmsr 98ca54502bSMichal Simek andi r11, r11, ~MSR_BIP 99ca54502bSMichal Simek mts rmsr, r11 100ca54502bSMichal Simek .endm 101ca54502bSMichal Simek 102ca54502bSMichal Simek .macro set_bip 103ca54502bSMichal Simek mfs r11, rmsr 104ca54502bSMichal Simek ori r11, r11, MSR_BIP 105ca54502bSMichal Simek mts rmsr, r11 106ca54502bSMichal Simek .endm 107ca54502bSMichal Simek 108ca54502bSMichal Simek .macro clear_eip 109ca54502bSMichal Simek mfs r11, rmsr 110ca54502bSMichal Simek andi r11, r11, ~MSR_EIP 111ca54502bSMichal Simek mts rmsr, r11 112ca54502bSMichal Simek .endm 113ca54502bSMichal Simek 114ca54502bSMichal Simek .macro set_ee 115ca54502bSMichal Simek mfs r11, rmsr 116ca54502bSMichal Simek ori r11, r11, MSR_EE 117ca54502bSMichal Simek mts rmsr, r11 118ca54502bSMichal Simek .endm 119ca54502bSMichal Simek 120ca54502bSMichal Simek .macro disable_irq 121ca54502bSMichal Simek mfs r11, rmsr 122ca54502bSMichal Simek andi r11, r11, ~MSR_IE 123ca54502bSMichal Simek mts rmsr, r11 124ca54502bSMichal Simek .endm 125ca54502bSMichal Simek 126ca54502bSMichal Simek .macro enable_irq 127ca54502bSMichal Simek mfs r11, rmsr 128ca54502bSMichal Simek ori r11, r11, MSR_IE 129ca54502bSMichal Simek mts rmsr, r11 130ca54502bSMichal Simek .endm 131ca54502bSMichal Simek 132ca54502bSMichal Simek .macro set_ums 133ca54502bSMichal Simek mfs r11, rmsr 134ca54502bSMichal Simek ori r11, r11, MSR_VMS 135ca54502bSMichal Simek andni r11, r11, MSR_UMS 136ca54502bSMichal Simek mts rmsr, r11 137ca54502bSMichal Simek .endm 138ca54502bSMichal Simek 139ca54502bSMichal Simek .macro set_vms 140ca54502bSMichal Simek mfs r11, rmsr 141ca54502bSMichal Simek ori r11, r11, MSR_VMS 142ca54502bSMichal Simek andni r11, r11, MSR_UMS 143ca54502bSMichal Simek mts rmsr, r11 144ca54502bSMichal Simek .endm 145ca54502bSMichal Simek 146b318067eSMichal Simek .macro clear_ums 147b318067eSMichal Simek mfs r11, rmsr 148b318067eSMichal Simek andni r11, r11, MSR_UMS 149b318067eSMichal Simek mts rmsr,r11 150b318067eSMichal Simek .endm 151b318067eSMichal Simek 152ca54502bSMichal Simek .macro clear_vms_ums 153ca54502bSMichal Simek mfs r11, rmsr 154ca54502bSMichal Simek andni r11, r11, (MSR_VMS|MSR_UMS) 155ca54502bSMichal Simek mts rmsr,r11 156ca54502bSMichal Simek .endm 157ca54502bSMichal Simek#endif 158ca54502bSMichal Simek 159ca54502bSMichal Simek/* Define how to call high-level functions. With MMU, virtual mode must be 160ca54502bSMichal Simek * enabled when calling the high-level function. Clobbers R11. 161ca54502bSMichal Simek * VM_ON, VM_OFF, DO_JUMP_BIPCLR, DO_CALL 162ca54502bSMichal Simek */ 163ca54502bSMichal Simek 164ca54502bSMichal Simek/* turn on virtual protected mode save */ 165ca54502bSMichal Simek#define VM_ON \ 166ca54502bSMichal Simek set_ums; \ 167ca54502bSMichal Simek rted r0, 2f; \ 168a4a94dbfSMichal Simek nop; \ 169a4a94dbfSMichal Simek2: 170ca54502bSMichal Simek 171ca54502bSMichal Simek/* turn off virtual protected mode save and user mode save*/ 172ca54502bSMichal Simek#define VM_OFF \ 173ca54502bSMichal Simek clear_vms_ums; \ 174ca54502bSMichal Simek rted r0, TOPHYS(1f); \ 175a4a94dbfSMichal Simek nop; \ 176a4a94dbfSMichal Simek1: 177ca54502bSMichal Simek 178ca54502bSMichal Simek#define SAVE_REGS \ 1796e83557cSMichal Simek swi r2, r1, PT_R2; /* Save SDA */ \ 1806e83557cSMichal Simek swi r3, r1, PT_R3; \ 1816e83557cSMichal Simek swi r4, r1, PT_R4; \ 1826e83557cSMichal Simek swi r5, r1, PT_R5; \ 1836e83557cSMichal Simek swi r6, r1, PT_R6; \ 1846e83557cSMichal Simek swi r7, r1, PT_R7; \ 1856e83557cSMichal Simek swi r8, r1, PT_R8; \ 1866e83557cSMichal Simek swi r9, r1, PT_R9; \ 1876e83557cSMichal Simek swi r10, r1, PT_R10; \ 1886e83557cSMichal Simek swi r11, r1, PT_R11; /* save clobbered regs after rval */\ 1896e83557cSMichal Simek swi r12, r1, PT_R12; \ 1906e83557cSMichal Simek swi r13, r1, PT_R13; /* Save SDA2 */ \ 1916e83557cSMichal Simek swi r14, r1, PT_PC; /* PC, before IRQ/trap */ \ 1926e83557cSMichal Simek swi r15, r1, PT_R15; /* Save LP */ \ 1936e83557cSMichal Simek swi r16, r1, PT_R16; \ 1946e83557cSMichal Simek swi r17, r1, PT_R17; \ 1956e83557cSMichal Simek swi r18, r1, PT_R18; /* Save asm scratch reg */ \ 1966e83557cSMichal Simek swi r19, r1, PT_R19; \ 1976e83557cSMichal Simek swi r20, r1, PT_R20; \ 1986e83557cSMichal Simek swi r21, r1, PT_R21; \ 1996e83557cSMichal Simek swi r22, r1, PT_R22; \ 2006e83557cSMichal Simek swi r23, r1, PT_R23; \ 2016e83557cSMichal Simek swi r24, r1, PT_R24; \ 2026e83557cSMichal Simek swi r25, r1, PT_R25; \ 2036e83557cSMichal Simek swi r26, r1, PT_R26; \ 2046e83557cSMichal Simek swi r27, r1, PT_R27; \ 2056e83557cSMichal Simek swi r28, r1, PT_R28; \ 2066e83557cSMichal Simek swi r29, r1, PT_R29; \ 2076e83557cSMichal Simek swi r30, r1, PT_R30; \ 2086e83557cSMichal Simek swi r31, r1, PT_R31; /* Save current task reg */ \ 209ca54502bSMichal Simek mfs r11, rmsr; /* save MSR */ \ 2106e83557cSMichal Simek swi r11, r1, PT_MSR; 211ca54502bSMichal Simek 212faf154cdSMichal Simek#define RESTORE_REGS_GP \ 2136e83557cSMichal Simek lwi r2, r1, PT_R2; /* restore SDA */ \ 2146e83557cSMichal Simek lwi r3, r1, PT_R3; \ 2156e83557cSMichal Simek lwi r4, r1, PT_R4; \ 2166e83557cSMichal Simek lwi r5, r1, PT_R5; \ 2176e83557cSMichal Simek lwi r6, r1, PT_R6; \ 2186e83557cSMichal Simek lwi r7, r1, PT_R7; \ 2196e83557cSMichal Simek lwi r8, r1, PT_R8; \ 2206e83557cSMichal Simek lwi r9, r1, PT_R9; \ 2216e83557cSMichal Simek lwi r10, r1, PT_R10; \ 2226e83557cSMichal Simek lwi r11, r1, PT_R11; /* restore clobbered regs after rval */\ 2236e83557cSMichal Simek lwi r12, r1, PT_R12; \ 2246e83557cSMichal Simek lwi r13, r1, PT_R13; /* restore SDA2 */ \ 2256e83557cSMichal Simek lwi r14, r1, PT_PC; /* RESTORE_LINK PC, before IRQ/trap */\ 2266e83557cSMichal Simek lwi r15, r1, PT_R15; /* restore LP */ \ 2276e83557cSMichal Simek lwi r16, r1, PT_R16; \ 2286e83557cSMichal Simek lwi r17, r1, PT_R17; \ 2296e83557cSMichal Simek lwi r18, r1, PT_R18; /* restore asm scratch reg */ \ 2306e83557cSMichal Simek lwi r19, r1, PT_R19; \ 2316e83557cSMichal Simek lwi r20, r1, PT_R20; \ 2326e83557cSMichal Simek lwi r21, r1, PT_R21; \ 2336e83557cSMichal Simek lwi r22, r1, PT_R22; \ 2346e83557cSMichal Simek lwi r23, r1, PT_R23; \ 2356e83557cSMichal Simek lwi r24, r1, PT_R24; \ 2366e83557cSMichal Simek lwi r25, r1, PT_R25; \ 2376e83557cSMichal Simek lwi r26, r1, PT_R26; \ 2386e83557cSMichal Simek lwi r27, r1, PT_R27; \ 2396e83557cSMichal Simek lwi r28, r1, PT_R28; \ 2406e83557cSMichal Simek lwi r29, r1, PT_R29; \ 2416e83557cSMichal Simek lwi r30, r1, PT_R30; \ 2426e83557cSMichal Simek lwi r31, r1, PT_R31; /* Restore cur task reg */ 243ca54502bSMichal Simek 244faf154cdSMichal Simek#define RESTORE_REGS \ 245faf154cdSMichal Simek lwi r11, r1, PT_MSR; \ 246faf154cdSMichal Simek mts rmsr , r11; \ 247faf154cdSMichal Simek RESTORE_REGS_GP 248faf154cdSMichal Simek 24914ef905bSMichal Simek#define RESTORE_REGS_RTBD \ 25014ef905bSMichal Simek lwi r11, r1, PT_MSR; \ 25114ef905bSMichal Simek andni r11, r11, MSR_EIP; /* clear EIP */ \ 25214ef905bSMichal Simek ori r11, r11, MSR_EE | MSR_BIP; /* set EE and BIP */ \ 25314ef905bSMichal Simek mts rmsr , r11; \ 25414ef905bSMichal Simek RESTORE_REGS_GP 25514ef905bSMichal Simek 256e5d2af2bSMichal Simek#define SAVE_STATE \ 257e5d2af2bSMichal Simek swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */ \ 258e5d2af2bSMichal Simek /* See if already in kernel mode.*/ \ 259e5d2af2bSMichal Simek mfs r1, rmsr; \ 260e5d2af2bSMichal Simek andi r1, r1, MSR_UMS; \ 261e5d2af2bSMichal Simek bnei r1, 1f; \ 262e5d2af2bSMichal Simek /* Kernel-mode state save. */ \ 263e5d2af2bSMichal Simek /* Reload kernel stack-ptr. */ \ 264e5d2af2bSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ 265287503faSMichal Simek /* FIXME: I can add these two lines to one */ \ 266287503faSMichal Simek /* tophys(r1,r1); */ \ 2676e83557cSMichal Simek /* addik r1, r1, -PT_SIZE; */ \ 2686e83557cSMichal Simek addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \ 269e5d2af2bSMichal Simek SAVE_REGS \ 270e5d2af2bSMichal Simek brid 2f; \ 2716e83557cSMichal Simek swi r1, r1, PT_MODE; \ 272e5d2af2bSMichal Simek1: /* User-mode state save. */ \ 273e5d2af2bSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\ 274e5d2af2bSMichal Simek tophys(r1,r1); \ 275e5d2af2bSMichal Simek lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ \ 276287503faSMichal Simek /* MS these three instructions can be added to one */ \ 277287503faSMichal Simek /* addik r1, r1, THREAD_SIZE; */ \ 278287503faSMichal Simek /* tophys(r1,r1); */ \ 2796e83557cSMichal Simek /* addik r1, r1, -PT_SIZE; */ \ 2806e83557cSMichal Simek addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \ 281e5d2af2bSMichal Simek SAVE_REGS \ 282e5d2af2bSMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ 2836e83557cSMichal Simek swi r11, r1, PT_R1; /* Store user SP. */ \ 2846e83557cSMichal Simek swi r0, r1, PT_MODE; /* Was in user-mode. */ \ 285e5d2af2bSMichal Simek /* MS: I am clearing UMS even in case when I come from kernel space */ \ 286e5d2af2bSMichal Simek clear_ums; \ 287e5d2af2bSMichal Simek2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 288e5d2af2bSMichal Simek 289ca54502bSMichal Simek.text 290ca54502bSMichal Simek 291*88707ebeSAppana Durga Kedareswara rao.extern cpuinfo 292*88707ebeSAppana Durga Kedareswara rao 293*88707ebeSAppana Durga Kedareswara raoC_ENTRY(mb_flush_dcache): 294*88707ebeSAppana Durga Kedareswara rao addik r1, r1, -PT_SIZE 295*88707ebeSAppana Durga Kedareswara rao SAVE_REGS 296*88707ebeSAppana Durga Kedareswara rao 297*88707ebeSAppana Durga Kedareswara rao addik r3, r0, cpuinfo 298*88707ebeSAppana Durga Kedareswara rao lwi r7, r3, CI_DCS 299*88707ebeSAppana Durga Kedareswara rao lwi r8, r3, CI_DCL 300*88707ebeSAppana Durga Kedareswara rao sub r9, r7, r8 301*88707ebeSAppana Durga Kedareswara rao1: 302*88707ebeSAppana Durga Kedareswara rao wdc.flush r9, r0 303*88707ebeSAppana Durga Kedareswara rao bgtid r9, 1b 304*88707ebeSAppana Durga Kedareswara rao addk r9, r9, r8 305*88707ebeSAppana Durga Kedareswara rao 306*88707ebeSAppana Durga Kedareswara rao RESTORE_REGS 307*88707ebeSAppana Durga Kedareswara rao addik r1, r1, PT_SIZE 308*88707ebeSAppana Durga Kedareswara rao rtsd r15, 8 309*88707ebeSAppana Durga Kedareswara rao nop 310*88707ebeSAppana Durga Kedareswara rao 311*88707ebeSAppana Durga Kedareswara raoC_ENTRY(mb_invalidate_icache): 312*88707ebeSAppana Durga Kedareswara rao addik r1, r1, -PT_SIZE 313*88707ebeSAppana Durga Kedareswara rao SAVE_REGS 314*88707ebeSAppana Durga Kedareswara rao 315*88707ebeSAppana Durga Kedareswara rao addik r3, r0, cpuinfo 316*88707ebeSAppana Durga Kedareswara rao lwi r7, r3, CI_ICS 317*88707ebeSAppana Durga Kedareswara rao lwi r8, r3, CI_ICL 318*88707ebeSAppana Durga Kedareswara rao sub r9, r7, r8 319*88707ebeSAppana Durga Kedareswara rao1: 320*88707ebeSAppana Durga Kedareswara rao wic r9, r0 321*88707ebeSAppana Durga Kedareswara rao bgtid r9, 1b 322*88707ebeSAppana Durga Kedareswara rao addk r9, r9, r8 323*88707ebeSAppana Durga Kedareswara rao 324*88707ebeSAppana Durga Kedareswara rao RESTORE_REGS 325*88707ebeSAppana Durga Kedareswara rao addik r1, r1, PT_SIZE 326*88707ebeSAppana Durga Kedareswara rao rtsd r15, 8 327*88707ebeSAppana Durga Kedareswara rao nop 328*88707ebeSAppana Durga Kedareswara rao 329ca54502bSMichal Simek/* 330ca54502bSMichal Simek * User trap. 331ca54502bSMichal Simek * 332ca54502bSMichal Simek * System calls are handled here. 333ca54502bSMichal Simek * 334ca54502bSMichal Simek * Syscall protocol: 335ca54502bSMichal Simek * Syscall number in r12, args in r5-r10 336ca54502bSMichal Simek * Return value in r3 337ca54502bSMichal Simek * 338ca54502bSMichal Simek * Trap entered via brki instruction, so BIP bit is set, and interrupts 339ca54502bSMichal Simek * are masked. This is nice, means we don't have to CLI before state save 340ca54502bSMichal Simek */ 341ca54502bSMichal SimekC_ENTRY(_user_exception): 3420e41c909SMichal Simek swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ 3439da63458SMichal Simek addi r14, r14, 4 /* return address is 4 byte after call */ 344ca54502bSMichal Simek 345ca54502bSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ 346ca54502bSMichal Simek tophys(r1,r1); 347ca54502bSMichal Simek lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ 3489da63458SMichal Simek/* calculate kernel stack pointer from task struct 8k */ 3499da63458SMichal Simek addik r1, r1, THREAD_SIZE; 3509da63458SMichal Simek tophys(r1,r1); 3519da63458SMichal Simek 3526e83557cSMichal Simek addik r1, r1, -PT_SIZE; /* Make room on the stack. */ 353ca54502bSMichal Simek SAVE_REGS 3546e83557cSMichal Simek swi r0, r1, PT_R3 3556e83557cSMichal Simek swi r0, r1, PT_R4 356ca54502bSMichal Simek 3576e83557cSMichal Simek swi r0, r1, PT_MODE; /* Was in user-mode. */ 358ca54502bSMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 3596e83557cSMichal Simek swi r11, r1, PT_R1; /* Store user SP. */ 36025f6e596SMichal Simek clear_ums; 3619da63458SMichal Simek2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 362ca54502bSMichal Simek /* Save away the syscall number. */ 3636e83557cSMichal Simek swi r12, r1, PT_R0; 364ca54502bSMichal Simek tovirt(r1,r1) 365ca54502bSMichal Simek 366ca54502bSMichal Simek/* where the trap should return need -8 to adjust for rtsd r15, 8*/ 367ca54502bSMichal Simek/* Jump to the appropriate function for the system call number in r12 368ca54502bSMichal Simek * (r12 is not preserved), or return an error if r12 is not valid. The LP 369ca54502bSMichal Simek * register should point to the location where 370ca54502bSMichal Simek * the called function should return. [note that MAKE_SYS_CALL uses label 1] */ 37123575483SMichal Simek 37225f6e596SMichal Simek /* Step into virtual mode */ 37325f6e596SMichal Simek rtbd r0, 3f 37423575483SMichal Simek nop 37523575483SMichal Simek3: 376b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */ 37723575483SMichal Simek lwi r11, r11, TI_FLAGS /* get flags in thread info */ 37823575483SMichal Simek andi r11, r11, _TIF_WORK_SYSCALL_MASK 37923575483SMichal Simek beqi r11, 4f 38023575483SMichal Simek 38123575483SMichal Simek addik r3, r0, -ENOSYS 3826e83557cSMichal Simek swi r3, r1, PT_R3 38323575483SMichal Simek brlid r15, do_syscall_trace_enter 3846e83557cSMichal Simek addik r5, r1, PT_R0 38523575483SMichal Simek 38623575483SMichal Simek # do_syscall_trace_enter returns the new syscall nr. 38723575483SMichal Simek addk r12, r0, r3 3886e83557cSMichal Simek lwi r5, r1, PT_R5; 3896e83557cSMichal Simek lwi r6, r1, PT_R6; 3906e83557cSMichal Simek lwi r7, r1, PT_R7; 3916e83557cSMichal Simek lwi r8, r1, PT_R8; 3926e83557cSMichal Simek lwi r9, r1, PT_R9; 3936e83557cSMichal Simek lwi r10, r1, PT_R10; 39423575483SMichal Simek4: 39523575483SMichal Simek/* Jump to the appropriate function for the system call number in r12 39623575483SMichal Simek * (r12 is not preserved), or return an error if r12 is not valid. 39723575483SMichal Simek * The LP register should point to the location where the called function 39823575483SMichal Simek * should return. [note that MAKE_SYS_CALL uses label 1] */ 39923575483SMichal Simek /* See if the system call number is valid */ 400c2219edaSJamie Garside blti r12, 5f 401ca54502bSMichal Simek addi r11, r12, -__NR_syscalls; 40223575483SMichal Simek bgei r11, 5f; 403ca54502bSMichal Simek /* Figure out which function to use for this system call. */ 404ca54502bSMichal Simek /* Note Microblaze barrel shift is optional, so don't rely on it */ 405ca54502bSMichal Simek add r12, r12, r12; /* convert num -> ptr */ 406ca54502bSMichal Simek add r12, r12, r12; 4074de6ba68SMichal Simek addi r30, r0, 1 /* restarts allowed */ 408ca54502bSMichal Simek 40911d51360SMichal Simek#ifdef DEBUG 410d8748e73SMichal Simek /* Trac syscalls and stored them to syscall_debug_table */ 411d8748e73SMichal Simek /* The first syscall location stores total syscall number */ 412d8748e73SMichal Simek lwi r3, r0, syscall_debug_table 413ca54502bSMichal Simek addi r3, r3, 1 414d8748e73SMichal Simek swi r3, r0, syscall_debug_table 415d8748e73SMichal Simek lwi r3, r12, syscall_debug_table 416d8748e73SMichal Simek addi r3, r3, 1 417d8748e73SMichal Simek swi r3, r12, syscall_debug_table 41811d51360SMichal Simek#endif 419ca54502bSMichal Simek 42023575483SMichal Simek # Find and jump into the syscall handler. 42123575483SMichal Simek lwi r12, r12, sys_call_table 42223575483SMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 423b9ea77e2SMichal Simek addi r15, r0, ret_from_trap-8 42423575483SMichal Simek bra r12 42523575483SMichal Simek 426ca54502bSMichal Simek /* The syscall number is invalid, return an error. */ 42723575483SMichal Simek5: 428c2219edaSJamie Garside braid ret_from_trap 4299814cc11SMichal Simek addi r3, r0, -ENOSYS; 430ca54502bSMichal Simek 43123575483SMichal Simek/* Entry point used to return from a syscall/trap */ 432ca54502bSMichal Simek/* We re-enable BIP bit before state restore */ 433ca54502bSMichal SimekC_ENTRY(ret_from_trap): 4346e83557cSMichal Simek swi r3, r1, PT_R3 4356e83557cSMichal Simek swi r4, r1, PT_R4 436b1d70c62SMichal Simek 4376e83557cSMichal Simek lwi r11, r1, PT_MODE; 4389da63458SMichal Simek/* See if returning to kernel mode, if so, skip resched &c. */ 4399da63458SMichal Simek bnei r11, 2f; 440ca54502bSMichal Simek /* We're returning to user mode, so check for various conditions that 441ca54502bSMichal Simek * trigger rescheduling. */ 442b1d70c62SMichal Simek /* FIXME: Restructure all these flag checks. */ 443b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 44423575483SMichal Simek lwi r11, r11, TI_FLAGS; /* get flags in thread info */ 44523575483SMichal Simek andi r11, r11, _TIF_WORK_SYSCALL_MASK 44623575483SMichal Simek beqi r11, 1f 44723575483SMichal Simek 44823575483SMichal Simek brlid r15, do_syscall_trace_leave 4496e83557cSMichal Simek addik r5, r1, PT_R0 45023575483SMichal Simek1: 45123575483SMichal Simek /* We're returning to user mode, so check for various conditions that 45223575483SMichal Simek * trigger rescheduling. */ 453b1d70c62SMichal Simek /* get thread info from current task */ 454b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; 455e9f92526SAl Viro lwi r19, r11, TI_FLAGS; /* get flags in thread info */ 456e9f92526SAl Viro andi r11, r19, _TIF_NEED_RESCHED; 457ca54502bSMichal Simek beqi r11, 5f; 458ca54502bSMichal Simek 459ca54502bSMichal Simek bralid r15, schedule; /* Call scheduler */ 460ca54502bSMichal Simek nop; /* delay slot */ 461e9f92526SAl Viro bri 1b 462ca54502bSMichal Simek 463ca54502bSMichal Simek /* Maybe handle a signal */ 464e9f92526SAl Viro5: 465e9f92526SAl Viro andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; 466e9f92526SAl Viro beqi r11, 4f; /* Signals to handle, handle them */ 467ca54502bSMichal Simek 4686e83557cSMichal Simek addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 469969a9616SAl Viro bralid r15, do_notify_resume; /* Handle any signals */ 47014203e19SAl Viro add r6, r30, r0; /* Arg 2: int in_syscall */ 471e9f92526SAl Viro add r30, r0, r0 /* no more restarts */ 472e9f92526SAl Viro bri 1b 473b1d70c62SMichal Simek 474b1d70c62SMichal Simek/* Finally, return to user state. */ 475e9f92526SAl Viro4: set_bip; /* Ints masked for state restore */ 4768633bebcSMichal Simek swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ 477ca54502bSMichal Simek VM_OFF; 478ca54502bSMichal Simek tophys(r1,r1); 47914ef905bSMichal Simek RESTORE_REGS_RTBD; 4806e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space. */ 481ca54502bSMichal Simek lwi r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */ 4829da63458SMichal Simek bri 6f; 4839da63458SMichal Simek 4849da63458SMichal Simek/* Return to kernel state. */ 4859da63458SMichal Simek2: set_bip; /* Ints masked for state restore */ 4869da63458SMichal Simek VM_OFF; 4879da63458SMichal Simek tophys(r1,r1); 48814ef905bSMichal Simek RESTORE_REGS_RTBD; 4896e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space. */ 4909da63458SMichal Simek tovirt(r1,r1); 4919da63458SMichal Simek6: 492ca54502bSMichal SimekTRAP_return: /* Make global symbol for debugging */ 493ca54502bSMichal Simek rtbd r14, 0; /* Instructions to return from an IRQ */ 494ca54502bSMichal Simek nop; 495ca54502bSMichal Simek 496ca54502bSMichal Simek 497ca54502bSMichal Simek/* This the initial entry point for a new child thread, with an appropriate 4985b7d1d57SSlark Xiao stack in place that makes it look like the child is in the middle of a 499ca54502bSMichal Simek syscall. This function is actually `returned to' from switch_thread 500ca54502bSMichal Simek (copy_thread makes ret_from_fork the return address in each new thread's 501ca54502bSMichal Simek saved context). */ 502ca54502bSMichal SimekC_ENTRY(ret_from_fork): 503ca54502bSMichal Simek bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ 504fd11ff73SMichal Simek add r5, r3, r0; /* switch_thread returns the prev task */ 505ca54502bSMichal Simek /* ( in the delay slot ) */ 506ca54502bSMichal Simek brid ret_from_trap; /* Do normal trap return */ 5079814cc11SMichal Simek add r3, r0, r0; /* Child's fork call should return 0. */ 508ca54502bSMichal Simek 5092319295dSAl ViroC_ENTRY(ret_from_kernel_thread): 5102319295dSAl Viro bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ 5112319295dSAl Viro add r5, r3, r0; /* switch_thread returns the prev task */ 5122319295dSAl Viro /* ( in the delay slot ) */ 5132319295dSAl Viro brald r15, r20 /* fn was left in r20 */ 5142319295dSAl Viro addk r5, r0, r19 /* ... and argument - in r19 */ 51599c59f60SAl Viro brid ret_from_trap 51699c59f60SAl Viro add r3, r0, r0 5172319295dSAl Viro 518ca54502bSMichal SimekC_ENTRY(sys_rt_sigreturn_wrapper): 51914203e19SAl Viro addik r30, r0, 0 /* no restarts */ 520791d0a16SMichal Simek brid sys_rt_sigreturn /* Do real work */ 5216e83557cSMichal Simek addik r5, r1, 0; /* add user context as 1st arg */ 522ca54502bSMichal Simek 523ca54502bSMichal Simek/* 524ca54502bSMichal Simek * HW EXCEPTION rutine start 525ca54502bSMichal Simek */ 526ca54502bSMichal SimekC_ENTRY(full_exception_trap): 527ca54502bSMichal Simek /* adjust exception address for privileged instruction 528ca54502bSMichal Simek * for finding where is it */ 529ca54502bSMichal Simek addik r17, r17, -4 530ca54502bSMichal Simek SAVE_STATE /* Save registers */ 53106a54604SMichal Simek /* PC, before IRQ/trap - this is one instruction above */ 5326e83557cSMichal Simek swi r17, r1, PT_PC; 53306a54604SMichal Simek tovirt(r1,r1) 534ca54502bSMichal Simek /* FIXME this can be store directly in PT_ESR reg. 535ca54502bSMichal Simek * I tested it but there is a fault */ 536ca54502bSMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 537b9ea77e2SMichal Simek addik r15, r0, ret_from_exc - 8 538ca54502bSMichal Simek mfs r6, resr 539ca54502bSMichal Simek mfs r7, rfsr; /* save FSR */ 540131e4e97SMichal Simek mts rfsr, r0; /* Clear sticky fsr */ 541c318d483SMichal Simek rted r0, full_exception 5426e83557cSMichal Simek addik r5, r1, 0 /* parameter struct pt_regs * regs */ 543ca54502bSMichal Simek 544ca54502bSMichal Simek/* 545ca54502bSMichal Simek * Unaligned data trap. 546ca54502bSMichal Simek * 547ca54502bSMichal Simek * Unaligned data trap last on 4k page is handled here. 548ca54502bSMichal Simek * 549ca54502bSMichal Simek * Trap entered via exception, so EE bit is set, and interrupts 550ca54502bSMichal Simek * are masked. This is nice, means we don't have to CLI before state save 551ca54502bSMichal Simek * 552ca54502bSMichal Simek * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S" 553ca54502bSMichal Simek */ 554ca54502bSMichal SimekC_ENTRY(unaligned_data_trap): 5558b110d15SMichal Simek /* MS: I have to save r11 value and then restore it because 5568b110d15SMichal Simek * set_bit, clear_eip, set_ee use r11 as temp register if MSR 5578b110d15SMichal Simek * instructions are not used. We don't need to do if MSR instructions 5588b110d15SMichal Simek * are used and they use r0 instead of r11. 5598b110d15SMichal Simek * I am using ENTRY_SP which should be primary used only for stack 5608b110d15SMichal Simek * pointer saving. */ 5618b110d15SMichal Simek swi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 5628b110d15SMichal Simek set_bip; /* equalize initial state for all possible entries */ 5638b110d15SMichal Simek clear_eip; 5648b110d15SMichal Simek set_ee; 5658b110d15SMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 566ca54502bSMichal Simek SAVE_STATE /* Save registers.*/ 56706a54604SMichal Simek /* PC, before IRQ/trap - this is one instruction above */ 5686e83557cSMichal Simek swi r17, r1, PT_PC; 56906a54604SMichal Simek tovirt(r1,r1) 570ca54502bSMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 571b9ea77e2SMichal Simek addik r15, r0, ret_from_exc-8 572ca54502bSMichal Simek mfs r3, resr /* ESR */ 573ca54502bSMichal Simek mfs r4, rear /* EAR */ 574c318d483SMichal Simek rtbd r0, _unaligned_data_exception 5756e83557cSMichal Simek addik r7, r1, 0 /* parameter struct pt_regs * regs */ 576ca54502bSMichal Simek 577ca54502bSMichal Simek/* 578ca54502bSMichal Simek * Page fault traps. 579ca54502bSMichal Simek * 580ca54502bSMichal Simek * If the real exception handler (from hw_exception_handler.S) didn't find 581ca54502bSMichal Simek * the mapping for the process, then we're thrown here to handle such situation. 582ca54502bSMichal Simek * 583ca54502bSMichal Simek * Trap entered via exceptions, so EE bit is set, and interrupts 584ca54502bSMichal Simek * are masked. This is nice, means we don't have to CLI before state save 585ca54502bSMichal Simek * 586ca54502bSMichal Simek * Build a standard exception frame for TLB Access errors. All TLB exceptions 587ca54502bSMichal Simek * will bail out to this point if they can't resolve the lightweight TLB fault. 588ca54502bSMichal Simek * 589ca54502bSMichal Simek * The C function called is in "arch/microblaze/mm/fault.c", declared as: 590ca54502bSMichal Simek * void do_page_fault(struct pt_regs *regs, 591ca54502bSMichal Simek * unsigned long address, 592ca54502bSMichal Simek * unsigned long error_code) 593ca54502bSMichal Simek */ 594ca54502bSMichal Simek/* data and intruction trap - which is choose is resolved int fault.c */ 595ca54502bSMichal SimekC_ENTRY(page_fault_data_trap): 596ca54502bSMichal Simek SAVE_STATE /* Save registers.*/ 59706a54604SMichal Simek /* PC, before IRQ/trap - this is one instruction above */ 5986e83557cSMichal Simek swi r17, r1, PT_PC; 59906a54604SMichal Simek tovirt(r1,r1) 600ca54502bSMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 601b9ea77e2SMichal Simek addik r15, r0, ret_from_exc-8 602ca54502bSMichal Simek mfs r6, rear /* parameter unsigned long address */ 603ca54502bSMichal Simek mfs r7, resr /* parameter unsigned long error_code */ 604c318d483SMichal Simek rted r0, do_page_fault 6056e83557cSMichal Simek addik r5, r1, 0 /* parameter struct pt_regs * regs */ 606ca54502bSMichal Simek 607ca54502bSMichal SimekC_ENTRY(page_fault_instr_trap): 608ca54502bSMichal Simek SAVE_STATE /* Save registers.*/ 60906a54604SMichal Simek /* PC, before IRQ/trap - this is one instruction above */ 6106e83557cSMichal Simek swi r17, r1, PT_PC; 61106a54604SMichal Simek tovirt(r1,r1) 612ca54502bSMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 613b9ea77e2SMichal Simek addik r15, r0, ret_from_exc-8 614ca54502bSMichal Simek mfs r6, rear /* parameter unsigned long address */ 615ca54502bSMichal Simek ori r7, r0, 0 /* parameter unsigned long error_code */ 6169814cc11SMichal Simek rted r0, do_page_fault 6176e83557cSMichal Simek addik r5, r1, 0 /* parameter struct pt_regs * regs */ 618ca54502bSMichal Simek 619ca54502bSMichal Simek/* Entry point used to return from an exception. */ 620ca54502bSMichal SimekC_ENTRY(ret_from_exc): 6216e83557cSMichal Simek lwi r11, r1, PT_MODE; 622ca54502bSMichal Simek bnei r11, 2f; /* See if returning to kernel mode, */ 623ca54502bSMichal Simek /* ... if so, skip resched &c. */ 624ca54502bSMichal Simek 625ca54502bSMichal Simek /* We're returning to user mode, so check for various conditions that 626ca54502bSMichal Simek trigger rescheduling. */ 627e9f92526SAl Viro1: 628b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 629e9f92526SAl Viro lwi r19, r11, TI_FLAGS; /* get flags in thread info */ 630e9f92526SAl Viro andi r11, r19, _TIF_NEED_RESCHED; 631ca54502bSMichal Simek beqi r11, 5f; 632ca54502bSMichal Simek 633ca54502bSMichal Simek/* Call the scheduler before returning from a syscall/trap. */ 634ca54502bSMichal Simek bralid r15, schedule; /* Call scheduler */ 635ca54502bSMichal Simek nop; /* delay slot */ 636e9f92526SAl Viro bri 1b 637ca54502bSMichal Simek 638ca54502bSMichal Simek /* Maybe handle a signal */ 639e9f92526SAl Viro5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; 640e9f92526SAl Viro beqi r11, 4f; /* Signals to handle, handle them */ 641ca54502bSMichal Simek 642ca54502bSMichal Simek /* 643ca54502bSMichal Simek * Handle a signal return; Pending signals should be in r18. 644ca54502bSMichal Simek * 645ca54502bSMichal Simek * Not all registers are saved by the normal trap/interrupt entry 646ca54502bSMichal Simek * points (for instance, call-saved registers (because the normal 647ca54502bSMichal Simek * C-compiler calling sequence in the kernel makes sure they're 648ca54502bSMichal Simek * preserved), and call-clobbered registers in the case of 649ca54502bSMichal Simek * traps), but signal handlers may want to examine or change the 650ca54502bSMichal Simek * complete register state. Here we save anything not saved by 651ca54502bSMichal Simek * the normal entry sequence, so that it may be safely restored 652969a9616SAl Viro * (in a possibly modified form) after do_notify_resume returns. */ 6536e83557cSMichal Simek addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 654969a9616SAl Viro bralid r15, do_notify_resume; /* Handle any signals */ 65583140191SAl Viro addi r6, r0, 0; /* Arg 2: int in_syscall */ 656e9f92526SAl Viro bri 1b 657ca54502bSMichal Simek 658ca54502bSMichal Simek/* Finally, return to user state. */ 659e9f92526SAl Viro4: set_bip; /* Ints masked for state restore */ 6608633bebcSMichal Simek swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ 661ca54502bSMichal Simek VM_OFF; 662ca54502bSMichal Simek tophys(r1,r1); 663ca54502bSMichal Simek 66414ef905bSMichal Simek RESTORE_REGS_RTBD; 6656e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space. */ 666ca54502bSMichal Simek 667ca54502bSMichal Simek lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */ 668ca54502bSMichal Simek bri 6f; 669ca54502bSMichal Simek/* Return to kernel state. */ 67096014cc3SMichal Simek2: set_bip; /* Ints masked for state restore */ 67196014cc3SMichal Simek VM_OFF; 672ca54502bSMichal Simek tophys(r1,r1); 67314ef905bSMichal Simek RESTORE_REGS_RTBD; 6746e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space. */ 675ca54502bSMichal Simek 676ca54502bSMichal Simek tovirt(r1,r1); 677ca54502bSMichal Simek6: 678ca54502bSMichal SimekEXC_return: /* Make global symbol for debugging */ 679ca54502bSMichal Simek rtbd r14, 0; /* Instructions to return from an IRQ */ 680ca54502bSMichal Simek nop; 681ca54502bSMichal Simek 682ca54502bSMichal Simek/* 683ca54502bSMichal Simek * HW EXCEPTION rutine end 684ca54502bSMichal Simek */ 685ca54502bSMichal Simek 686ca54502bSMichal Simek/* 687ca54502bSMichal Simek * Hardware maskable interrupts. 688ca54502bSMichal Simek * 689ca54502bSMichal Simek * The stack-pointer (r1) should have already been saved to the memory 690ca54502bSMichal Simek * location PER_CPU(ENTRY_SP). 691ca54502bSMichal Simek */ 692ca54502bSMichal SimekC_ENTRY(_interrupt): 693ca54502bSMichal Simek/* MS: we are in physical address */ 694ca54502bSMichal Simek/* Save registers, switch to proper stack, convert SP to virtual.*/ 695ca54502bSMichal Simek swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) 696ca54502bSMichal Simek /* MS: See if already in kernel mode. */ 697653e447eSMichal Simek mfs r1, rmsr 6985c0d72b1SMichal Simek nop 699653e447eSMichal Simek andi r1, r1, MSR_UMS 700653e447eSMichal Simek bnei r1, 1f 701ca54502bSMichal Simek 702ca54502bSMichal Simek/* Kernel-mode state save. */ 703653e447eSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) 704653e447eSMichal Simek tophys(r1,r1); /* MS: I have in r1 physical address where stack is */ 705ca54502bSMichal Simek /* save registers */ 706ca54502bSMichal Simek/* MS: Make room on the stack -> activation record */ 7076e83557cSMichal Simek addik r1, r1, -PT_SIZE; 708ca54502bSMichal Simek SAVE_REGS 709ca54502bSMichal Simek brid 2f; 7106e83557cSMichal Simek swi r1, r1, PT_MODE; /* 0 - user mode, 1 - kernel mode */ 711ca54502bSMichal Simek1: 712ca54502bSMichal Simek/* User-mode state save. */ 713ca54502bSMichal Simek /* MS: get the saved current */ 714ca54502bSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 715ca54502bSMichal Simek tophys(r1,r1); 716ca54502bSMichal Simek lwi r1, r1, TS_THREAD_INFO; 717ca54502bSMichal Simek addik r1, r1, THREAD_SIZE; 718ca54502bSMichal Simek tophys(r1,r1); 719ca54502bSMichal Simek /* save registers */ 7206e83557cSMichal Simek addik r1, r1, -PT_SIZE; 721ca54502bSMichal Simek SAVE_REGS 722ca54502bSMichal Simek /* calculate mode */ 7236e83557cSMichal Simek swi r0, r1, PT_MODE; 724ca54502bSMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 7256e83557cSMichal Simek swi r11, r1, PT_R1; 72680c5ff6bSMichal Simek clear_ums; 727ca54502bSMichal Simek2: 728b1d70c62SMichal Simek lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 729ca54502bSMichal Simek tovirt(r1,r1) 730b9ea77e2SMichal Simek addik r15, r0, irq_call; 73180c5ff6bSMichal Simekirq_call:rtbd r0, do_IRQ; 7326e83557cSMichal Simek addik r5, r1, 0; 733ca54502bSMichal Simek 734ca54502bSMichal Simek/* MS: we are in virtual mode */ 735ca54502bSMichal Simekret_from_irq: 7366e83557cSMichal Simek lwi r11, r1, PT_MODE; 737ca54502bSMichal Simek bnei r11, 2f; 738ca54502bSMichal Simek 739e9f92526SAl Viro1: 740b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; 741e9f92526SAl Viro lwi r19, r11, TI_FLAGS; /* MS: get flags from thread info */ 742e9f92526SAl Viro andi r11, r19, _TIF_NEED_RESCHED; 743ca54502bSMichal Simek beqi r11, 5f 744ca54502bSMichal Simek bralid r15, schedule; 745ca54502bSMichal Simek nop; /* delay slot */ 746e9f92526SAl Viro bri 1b 747ca54502bSMichal Simek 748ca54502bSMichal Simek /* Maybe handle a signal */ 749e9f92526SAl Viro5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; 750ca54502bSMichal Simek beqid r11, no_intr_resched 751ca54502bSMichal Simek/* Handle a signal return; Pending signals should be in r18. */ 7526e83557cSMichal Simek addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 753969a9616SAl Viro bralid r15, do_notify_resume; /* Handle any signals */ 75483140191SAl Viro addi r6, r0, 0; /* Arg 2: int in_syscall */ 755e9f92526SAl Viro bri 1b 756ca54502bSMichal Simek 757ca54502bSMichal Simek/* Finally, return to user state. */ 758ca54502bSMichal Simekno_intr_resched: 759ca54502bSMichal Simek /* Disable interrupts, we are now committed to the state restore */ 760ca54502bSMichal Simek disable_irq 7618633bebcSMichal Simek swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); 762ca54502bSMichal Simek VM_OFF; 763ca54502bSMichal Simek tophys(r1,r1); 764ca54502bSMichal Simek RESTORE_REGS 7656e83557cSMichal Simek addik r1, r1, PT_SIZE /* MS: Clean up stack space. */ 766ca54502bSMichal Simek lwi r1, r1, PT_R1 - PT_SIZE; 767ca54502bSMichal Simek bri 6f; 768ca54502bSMichal Simek/* MS: Return to kernel state. */ 76977753790SMichal Simek2: 77018803733SThomas Gleixner#ifdef CONFIG_PREEMPTION 771b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; 77277753790SMichal Simek /* MS: get preempt_count from thread info */ 77377753790SMichal Simek lwi r5, r11, TI_PREEMPT_COUNT; 77477753790SMichal Simek bgti r5, restore; 77577753790SMichal Simek 77677753790SMichal Simek lwi r5, r11, TI_FLAGS; /* get flags in thread info */ 77777753790SMichal Simek andi r5, r5, _TIF_NEED_RESCHED; 77877753790SMichal Simek beqi r5, restore /* if zero jump over */ 77977753790SMichal Simek 78077753790SMichal Simek /* interrupts are off that's why I am calling preempt_chedule_irq */ 78177753790SMichal Simek bralid r15, preempt_schedule_irq 78277753790SMichal Simek nop 78377753790SMichal Simekrestore: 78477753790SMichal Simek#endif 78577753790SMichal Simek VM_OFF /* MS: turn off MMU */ 786ca54502bSMichal Simek tophys(r1,r1) 787ca54502bSMichal Simek RESTORE_REGS 7886e83557cSMichal Simek addik r1, r1, PT_SIZE /* MS: Clean up stack space. */ 789ca54502bSMichal Simek tovirt(r1,r1); 790ca54502bSMichal Simek6: 791ca54502bSMichal SimekIRQ_return: /* MS: Make global symbol for debugging */ 792ca54502bSMichal Simek rtid r14, 0 793ca54502bSMichal Simek nop 794ca54502bSMichal Simek 795*88707ebeSAppana Durga Kedareswara rao#ifdef CONFIG_MB_MANAGER 796*88707ebeSAppana Durga Kedareswara rao 797*88707ebeSAppana Durga Kedareswara rao#define PT_PID PT_SIZE 798*88707ebeSAppana Durga Kedareswara rao#define PT_TLBI PT_SIZE + 4 799*88707ebeSAppana Durga Kedareswara rao#define PT_ZPR PT_SIZE + 8 800*88707ebeSAppana Durga Kedareswara rao#define PT_TLBL0 PT_SIZE + 12 801*88707ebeSAppana Durga Kedareswara rao#define PT_TLBH0 PT_SIZE + 16 802*88707ebeSAppana Durga Kedareswara rao 803*88707ebeSAppana Durga Kedareswara raoC_ENTRY(_xtmr_manager_reset): 804*88707ebeSAppana Durga Kedareswara rao lwi r1, r0, xmb_manager_stackpointer 805*88707ebeSAppana Durga Kedareswara rao 806*88707ebeSAppana Durga Kedareswara rao /* Restore MSR */ 807*88707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_MSR 808*88707ebeSAppana Durga Kedareswara rao mts rmsr, r2 809*88707ebeSAppana Durga Kedareswara rao bri 4 810*88707ebeSAppana Durga Kedareswara rao 811*88707ebeSAppana Durga Kedareswara rao /* restore Special purpose registers */ 812*88707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_PID 813*88707ebeSAppana Durga Kedareswara rao mts rpid, r2 814*88707ebeSAppana Durga Kedareswara rao 815*88707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_TLBI 816*88707ebeSAppana Durga Kedareswara rao mts rtlbx, r2 817*88707ebeSAppana Durga Kedareswara rao 818*88707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_ZPR 819*88707ebeSAppana Durga Kedareswara rao mts rzpr, r2 820*88707ebeSAppana Durga Kedareswara rao 821*88707ebeSAppana Durga Kedareswara rao#if CONFIG_XILINX_MICROBLAZE0_USE_FPU 822*88707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_FSR 823*88707ebeSAppana Durga Kedareswara rao mts rfsr, r2 824*88707ebeSAppana Durga Kedareswara rao#endif 825*88707ebeSAppana Durga Kedareswara rao 826*88707ebeSAppana Durga Kedareswara rao /* restore all the tlb's */ 827*88707ebeSAppana Durga Kedareswara rao addik r3, r0, TOPHYS(tlb_skip) 828*88707ebeSAppana Durga Kedareswara rao addik r6, r0, PT_TLBL0 829*88707ebeSAppana Durga Kedareswara rao addik r7, r0, PT_TLBH0 830*88707ebeSAppana Durga Kedareswara raorestore_tlb: 831*88707ebeSAppana Durga Kedareswara rao add r6, r6, r1 832*88707ebeSAppana Durga Kedareswara rao add r7, r7, r1 833*88707ebeSAppana Durga Kedareswara rao lwi r2, r6, 0 834*88707ebeSAppana Durga Kedareswara rao mts rtlblo, r2 835*88707ebeSAppana Durga Kedareswara rao lwi r2, r7, 0 836*88707ebeSAppana Durga Kedareswara rao mts rtlbhi, r2 837*88707ebeSAppana Durga Kedareswara rao addik r6, r6, 4 838*88707ebeSAppana Durga Kedareswara rao addik r7, r7, 4 839*88707ebeSAppana Durga Kedareswara rao bgtid r3, restore_tlb 840*88707ebeSAppana Durga Kedareswara rao addik r3, r3, -1 841*88707ebeSAppana Durga Kedareswara rao 842*88707ebeSAppana Durga Kedareswara rao lwi r5, r0, TOPHYS(xmb_manager_dev) 843*88707ebeSAppana Durga Kedareswara rao lwi r8, r0, TOPHYS(xmb_manager_reset_callback) 844*88707ebeSAppana Durga Kedareswara rao set_vms 845*88707ebeSAppana Durga Kedareswara rao /* return from reset need -8 to adjust for rtsd r15, 8 */ 846*88707ebeSAppana Durga Kedareswara rao addik r15, r0, ret_from_reset - 8 847*88707ebeSAppana Durga Kedareswara rao rtbd r8, 0 848*88707ebeSAppana Durga Kedareswara rao nop 849*88707ebeSAppana Durga Kedareswara rao 850*88707ebeSAppana Durga Kedareswara raoret_from_reset: 851*88707ebeSAppana Durga Kedareswara rao set_bip /* Ints masked for state restore */ 852*88707ebeSAppana Durga Kedareswara rao VM_OFF 853*88707ebeSAppana Durga Kedareswara rao /* MS: Restore all regs */ 854*88707ebeSAppana Durga Kedareswara rao RESTORE_REGS 855*88707ebeSAppana Durga Kedareswara rao lwi r14, r1, PT_R14 856*88707ebeSAppana Durga Kedareswara rao lwi r16, r1, PT_PC 857*88707ebeSAppana Durga Kedareswara rao addik r1, r1, PT_SIZE + 36 858*88707ebeSAppana Durga Kedareswara rao rtbd r16, 0 859*88707ebeSAppana Durga Kedareswara rao nop 860*88707ebeSAppana Durga Kedareswara rao 861*88707ebeSAppana Durga Kedareswara rao/* 862*88707ebeSAppana Durga Kedareswara rao * Break handler for MB Manager. Enter to _xmb_manager_break by 863*88707ebeSAppana Durga Kedareswara rao * injecting fault in one of the TMR Microblaze core. 864*88707ebeSAppana Durga Kedareswara rao * FIXME: This break handler supports getting 865*88707ebeSAppana Durga Kedareswara rao * called from kernel space only. 866*88707ebeSAppana Durga Kedareswara rao */ 867*88707ebeSAppana Durga Kedareswara raoC_ENTRY(_xmb_manager_break): 868*88707ebeSAppana Durga Kedareswara rao /* 869*88707ebeSAppana Durga Kedareswara rao * Reserve memory in the stack for context store/restore 870*88707ebeSAppana Durga Kedareswara rao * (which includes memory for storing tlbs (max two tlbs)) 871*88707ebeSAppana Durga Kedareswara rao */ 872*88707ebeSAppana Durga Kedareswara rao addik r1, r1, -PT_SIZE - 36 873*88707ebeSAppana Durga Kedareswara rao swi r1, r0, xmb_manager_stackpointer 874*88707ebeSAppana Durga Kedareswara rao SAVE_REGS 875*88707ebeSAppana Durga Kedareswara rao swi r14, r1, PT_R14 /* rewrite saved R14 value */ 876*88707ebeSAppana Durga Kedareswara rao swi r16, r1, PT_PC; /* PC and r16 are the same */ 877*88707ebeSAppana Durga Kedareswara rao 878*88707ebeSAppana Durga Kedareswara rao lwi r6, r0, TOPHYS(xmb_manager_baseaddr) 879*88707ebeSAppana Durga Kedareswara rao lwi r7, r0, TOPHYS(xmb_manager_crval) 880*88707ebeSAppana Durga Kedareswara rao /* 881*88707ebeSAppana Durga Kedareswara rao * When the break vector gets asserted because of error injection, 882*88707ebeSAppana Durga Kedareswara rao * the break signal must be blocked before exiting from the 883*88707ebeSAppana Durga Kedareswara rao * break handler, below code configures the tmr manager 884*88707ebeSAppana Durga Kedareswara rao * control register to block break signal. 885*88707ebeSAppana Durga Kedareswara rao */ 886*88707ebeSAppana Durga Kedareswara rao swi r7, r6, 0 887*88707ebeSAppana Durga Kedareswara rao 888*88707ebeSAppana Durga Kedareswara rao /* Save the special purpose registers */ 889*88707ebeSAppana Durga Kedareswara rao mfs r2, rpid 890*88707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_PID 891*88707ebeSAppana Durga Kedareswara rao 892*88707ebeSAppana Durga Kedareswara rao mfs r2, rtlbx 893*88707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_TLBI 894*88707ebeSAppana Durga Kedareswara rao 895*88707ebeSAppana Durga Kedareswara rao mfs r2, rzpr 896*88707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_ZPR 897*88707ebeSAppana Durga Kedareswara rao 898*88707ebeSAppana Durga Kedareswara rao#if CONFIG_XILINX_MICROBLAZE0_USE_FPU 899*88707ebeSAppana Durga Kedareswara rao mfs r2, rfsr 900*88707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_FSR 901*88707ebeSAppana Durga Kedareswara rao#endif 902*88707ebeSAppana Durga Kedareswara rao mfs r2, rmsr 903*88707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_MSR 904*88707ebeSAppana Durga Kedareswara rao 905*88707ebeSAppana Durga Kedareswara rao /* Save all the tlb's */ 906*88707ebeSAppana Durga Kedareswara rao addik r3, r0, TOPHYS(tlb_skip) 907*88707ebeSAppana Durga Kedareswara rao addik r6, r0, PT_TLBL0 908*88707ebeSAppana Durga Kedareswara rao addik r7, r0, PT_TLBH0 909*88707ebeSAppana Durga Kedareswara raosave_tlb: 910*88707ebeSAppana Durga Kedareswara rao add r6, r6, r1 911*88707ebeSAppana Durga Kedareswara rao add r7, r7, r1 912*88707ebeSAppana Durga Kedareswara rao mfs r2, rtlblo 913*88707ebeSAppana Durga Kedareswara rao swi r2, r6, 0 914*88707ebeSAppana Durga Kedareswara rao mfs r2, rtlbhi 915*88707ebeSAppana Durga Kedareswara rao swi r2, r7, 0 916*88707ebeSAppana Durga Kedareswara rao addik r6, r6, 4 917*88707ebeSAppana Durga Kedareswara rao addik r7, r7, 4 918*88707ebeSAppana Durga Kedareswara rao bgtid r3, save_tlb 919*88707ebeSAppana Durga Kedareswara rao addik r3, r3, -1 920*88707ebeSAppana Durga Kedareswara rao 921*88707ebeSAppana Durga Kedareswara rao lwi r5, r0, TOPHYS(xmb_manager_dev) 922*88707ebeSAppana Durga Kedareswara rao lwi r8, r0, TOPHYS(xmb_manager_callback) 923*88707ebeSAppana Durga Kedareswara rao /* return from break need -8 to adjust for rtsd r15, 8 */ 924*88707ebeSAppana Durga Kedareswara rao addik r15, r0, ret_from_break - 8 925*88707ebeSAppana Durga Kedareswara rao rtbd r8, 0 926*88707ebeSAppana Durga Kedareswara rao nop 927*88707ebeSAppana Durga Kedareswara rao 928*88707ebeSAppana Durga Kedareswara raoret_from_break: 929*88707ebeSAppana Durga Kedareswara rao /* flush the d-cache */ 930*88707ebeSAppana Durga Kedareswara rao bralid r15, mb_flush_dcache 931*88707ebeSAppana Durga Kedareswara rao nop 932*88707ebeSAppana Durga Kedareswara rao 933*88707ebeSAppana Durga Kedareswara rao /* 934*88707ebeSAppana Durga Kedareswara rao * To make sure microblaze i-cache is in a proper state 935*88707ebeSAppana Durga Kedareswara rao * invalidate the i-cache. 936*88707ebeSAppana Durga Kedareswara rao */ 937*88707ebeSAppana Durga Kedareswara rao bralid r15, mb_invalidate_icache 938*88707ebeSAppana Durga Kedareswara rao nop 939*88707ebeSAppana Durga Kedareswara rao 940*88707ebeSAppana Durga Kedareswara rao set_bip; /* Ints masked for state restore */ 941*88707ebeSAppana Durga Kedareswara rao VM_OFF; 942*88707ebeSAppana Durga Kedareswara rao mbar 1 943*88707ebeSAppana Durga Kedareswara rao mbar 2 944*88707ebeSAppana Durga Kedareswara rao bri 4 945*88707ebeSAppana Durga Kedareswara rao suspend 946*88707ebeSAppana Durga Kedareswara rao nop 947*88707ebeSAppana Durga Kedareswara rao#endif 948*88707ebeSAppana Durga Kedareswara rao 949ca54502bSMichal Simek/* 9502d5973cbSMichal Simek * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18 9512d5973cbSMichal Simek * and call handling function with saved pt_regs 952ca54502bSMichal Simek */ 953ca54502bSMichal SimekC_ENTRY(_debug_exception): 954ca54502bSMichal Simek /* BIP bit is set on entry, no interrupts can occur */ 955ca54502bSMichal Simek swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) 956ca54502bSMichal Simek 957653e447eSMichal Simek mfs r1, rmsr 9585c0d72b1SMichal Simek nop 959653e447eSMichal Simek andi r1, r1, MSR_UMS 960653e447eSMichal Simek bnei r1, 1f 9612d5973cbSMichal Simek/* MS: Kernel-mode state save - kgdb */ 962653e447eSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ 963ca54502bSMichal Simek 9642d5973cbSMichal Simek /* BIP bit is set on entry, no interrupts can occur */ 9656e83557cSMichal Simek addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; 966ca54502bSMichal Simek SAVE_REGS; 9672d5973cbSMichal Simek /* save all regs to pt_reg structure */ 9686e83557cSMichal Simek swi r0, r1, PT_R0; /* R0 must be saved too */ 9696e83557cSMichal Simek swi r14, r1, PT_R14 /* rewrite saved R14 value */ 9706e83557cSMichal Simek swi r16, r1, PT_PC; /* PC and r16 are the same */ 9712d5973cbSMichal Simek /* save special purpose registers to pt_regs */ 9722d5973cbSMichal Simek mfs r11, rear; 9736e83557cSMichal Simek swi r11, r1, PT_EAR; 9742d5973cbSMichal Simek mfs r11, resr; 9756e83557cSMichal Simek swi r11, r1, PT_ESR; 9762d5973cbSMichal Simek mfs r11, rfsr; 9776e83557cSMichal Simek swi r11, r1, PT_FSR; 978ca54502bSMichal Simek 9792d5973cbSMichal Simek /* stack pointer is in physical address at it is decrease 9806e83557cSMichal Simek * by PT_SIZE but we need to get correct R1 value */ 9816e83557cSMichal Simek addik r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + PT_SIZE; 9826e83557cSMichal Simek swi r11, r1, PT_R1 9832d5973cbSMichal Simek /* MS: r31 - current pointer isn't changed */ 9842d5973cbSMichal Simek tovirt(r1,r1) 9852d5973cbSMichal Simek#ifdef CONFIG_KGDB 9866e83557cSMichal Simek addi r5, r1, 0 /* pass pt_reg address as the first arg */ 987cd341577SMichal Simek addik r15, r0, dbtrap_call; /* return address */ 9882d5973cbSMichal Simek rtbd r0, microblaze_kgdb_break 9892d5973cbSMichal Simek nop; 9902d5973cbSMichal Simek#endif 9912d5973cbSMichal Simek /* MS: Place handler for brki from kernel space if KGDB is OFF. 9922d5973cbSMichal Simek * It is very unlikely that another brki instruction is called. */ 9932d5973cbSMichal Simek bri 0 9942d5973cbSMichal Simek 9952d5973cbSMichal Simek/* MS: User-mode state save - gdb */ 9962d5973cbSMichal Simek1: lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ 997ca54502bSMichal Simek tophys(r1,r1); 998ca54502bSMichal Simek lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ 999ca54502bSMichal Simek addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */ 1000ca54502bSMichal Simek tophys(r1,r1); 1001ca54502bSMichal Simek 10026e83557cSMichal Simek addik r1, r1, -PT_SIZE; /* Make room on the stack. */ 1003ca54502bSMichal Simek SAVE_REGS; 10046e83557cSMichal Simek swi r16, r1, PT_PC; /* Save LP */ 10056e83557cSMichal Simek swi r0, r1, PT_MODE; /* Was in user-mode. */ 1006ca54502bSMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 10076e83557cSMichal Simek swi r11, r1, PT_R1; /* Store user SP. */ 10082d5973cbSMichal Simek lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 1009ca54502bSMichal Simek tovirt(r1,r1) 101006b28640SMichal Simek set_vms; 10116e83557cSMichal Simek addik r5, r1, 0; 1012b9ea77e2SMichal Simek addik r15, r0, dbtrap_call; 10132d5973cbSMichal Simekdbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ 1014751f1605SMichal Simek rtbd r0, sw_exception 1015751f1605SMichal Simek nop 1016ca54502bSMichal Simek 10172d5973cbSMichal Simek /* MS: The first instruction for the second part of the gdb/kgdb */ 1018ca54502bSMichal Simek set_bip; /* Ints masked for state restore */ 10196e83557cSMichal Simek lwi r11, r1, PT_MODE; 1020ca54502bSMichal Simek bnei r11, 2f; 10212d5973cbSMichal Simek/* MS: Return to user space - gdb */ 1022e9f92526SAl Viro1: 1023ca54502bSMichal Simek /* Get current task ptr into r11 */ 1024b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 1025e9f92526SAl Viro lwi r19, r11, TI_FLAGS; /* get flags in thread info */ 1026e9f92526SAl Viro andi r11, r19, _TIF_NEED_RESCHED; 1027ca54502bSMichal Simek beqi r11, 5f; 1028ca54502bSMichal Simek 1029ca54502bSMichal Simek /* Call the scheduler before returning from a syscall/trap. */ 1030ca54502bSMichal Simek bralid r15, schedule; /* Call scheduler */ 1031ca54502bSMichal Simek nop; /* delay slot */ 1032e9f92526SAl Viro bri 1b 1033ca54502bSMichal Simek 1034ca54502bSMichal Simek /* Maybe handle a signal */ 1035e9f92526SAl Viro5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; 1036e9f92526SAl Viro beqi r11, 4f; /* Signals to handle, handle them */ 1037ca54502bSMichal Simek 10386e83557cSMichal Simek addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 1039969a9616SAl Viro bralid r15, do_notify_resume; /* Handle any signals */ 104083140191SAl Viro addi r6, r0, 0; /* Arg 2: int in_syscall */ 1041e9f92526SAl Viro bri 1b 1042ca54502bSMichal Simek 1043ca54502bSMichal Simek/* Finally, return to user state. */ 1044e9f92526SAl Viro4: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ 1045ca54502bSMichal Simek VM_OFF; 1046ca54502bSMichal Simek tophys(r1,r1); 10472d5973cbSMichal Simek /* MS: Restore all regs */ 104814ef905bSMichal Simek RESTORE_REGS_RTBD 10496e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space */ 10502d5973cbSMichal Simek lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */ 10512d5973cbSMichal SimekDBTRAP_return_user: /* MS: Make global symbol for debugging */ 10522d5973cbSMichal Simek rtbd r16, 0; /* MS: Instructions to return from a debug trap */ 10532d5973cbSMichal Simek nop; 1054ca54502bSMichal Simek 10552d5973cbSMichal Simek/* MS: Return to kernel state - kgdb */ 1056ca54502bSMichal Simek2: VM_OFF; 1057ca54502bSMichal Simek tophys(r1,r1); 10582d5973cbSMichal Simek /* MS: Restore all regs */ 105914ef905bSMichal Simek RESTORE_REGS_RTBD 10606e83557cSMichal Simek lwi r14, r1, PT_R14; 10616e83557cSMichal Simek lwi r16, r1, PT_PC; 10626e83557cSMichal Simek addik r1, r1, PT_SIZE; /* MS: Clean up stack space */ 1063ca54502bSMichal Simek tovirt(r1,r1); 10642d5973cbSMichal SimekDBTRAP_return_kernel: /* MS: Make global symbol for debugging */ 10652d5973cbSMichal Simek rtbd r16, 0; /* MS: Instructions to return from a debug trap */ 1066ca54502bSMichal Simek nop; 1067ca54502bSMichal Simek 1068ca54502bSMichal Simek 1069ca54502bSMichal SimekENTRY(_switch_to) 1070ca54502bSMichal Simek /* prepare return value */ 1071b1d70c62SMichal Simek addk r3, r0, CURRENT_TASK 1072ca54502bSMichal Simek 1073ca54502bSMichal Simek /* save registers in cpu_context */ 1074ca54502bSMichal Simek /* use r11 and r12, volatile registers, as temp register */ 1075ca54502bSMichal Simek /* give start of cpu_context for previous process */ 1076ca54502bSMichal Simek addik r11, r5, TI_CPU_CONTEXT 1077ca54502bSMichal Simek swi r1, r11, CC_R1 1078ca54502bSMichal Simek swi r2, r11, CC_R2 1079ca54502bSMichal Simek /* skip volatile registers. 1080ca54502bSMichal Simek * they are saved on stack when we jumped to _switch_to() */ 1081ca54502bSMichal Simek /* dedicated registers */ 1082ca54502bSMichal Simek swi r13, r11, CC_R13 1083ca54502bSMichal Simek swi r14, r11, CC_R14 1084ca54502bSMichal Simek swi r15, r11, CC_R15 1085ca54502bSMichal Simek swi r16, r11, CC_R16 1086ca54502bSMichal Simek swi r17, r11, CC_R17 1087ca54502bSMichal Simek swi r18, r11, CC_R18 1088ca54502bSMichal Simek /* save non-volatile registers */ 1089ca54502bSMichal Simek swi r19, r11, CC_R19 1090ca54502bSMichal Simek swi r20, r11, CC_R20 1091ca54502bSMichal Simek swi r21, r11, CC_R21 1092ca54502bSMichal Simek swi r22, r11, CC_R22 1093ca54502bSMichal Simek swi r23, r11, CC_R23 1094ca54502bSMichal Simek swi r24, r11, CC_R24 1095ca54502bSMichal Simek swi r25, r11, CC_R25 1096ca54502bSMichal Simek swi r26, r11, CC_R26 1097ca54502bSMichal Simek swi r27, r11, CC_R27 1098ca54502bSMichal Simek swi r28, r11, CC_R28 1099ca54502bSMichal Simek swi r29, r11, CC_R29 1100ca54502bSMichal Simek swi r30, r11, CC_R30 1101ca54502bSMichal Simek /* special purpose registers */ 1102ca54502bSMichal Simek mfs r12, rmsr 1103ca54502bSMichal Simek swi r12, r11, CC_MSR 1104ca54502bSMichal Simek mfs r12, rear 1105ca54502bSMichal Simek swi r12, r11, CC_EAR 1106ca54502bSMichal Simek mfs r12, resr 1107ca54502bSMichal Simek swi r12, r11, CC_ESR 1108ca54502bSMichal Simek mfs r12, rfsr 1109ca54502bSMichal Simek swi r12, r11, CC_FSR 1110ca54502bSMichal Simek 1111b1d70c62SMichal Simek /* update r31, the current-give me pointer to task which will be next */ 1112b1d70c62SMichal Simek lwi CURRENT_TASK, r6, TI_TASK 1113ca54502bSMichal Simek /* stored it to current_save too */ 1114b1d70c62SMichal Simek swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE) 1115ca54502bSMichal Simek 1116ca54502bSMichal Simek /* get new process' cpu context and restore */ 1117ca54502bSMichal Simek /* give me start where start context of next task */ 1118ca54502bSMichal Simek addik r11, r6, TI_CPU_CONTEXT 1119ca54502bSMichal Simek 1120ca54502bSMichal Simek /* non-volatile registers */ 1121ca54502bSMichal Simek lwi r30, r11, CC_R30 1122ca54502bSMichal Simek lwi r29, r11, CC_R29 1123ca54502bSMichal Simek lwi r28, r11, CC_R28 1124ca54502bSMichal Simek lwi r27, r11, CC_R27 1125ca54502bSMichal Simek lwi r26, r11, CC_R26 1126ca54502bSMichal Simek lwi r25, r11, CC_R25 1127ca54502bSMichal Simek lwi r24, r11, CC_R24 1128ca54502bSMichal Simek lwi r23, r11, CC_R23 1129ca54502bSMichal Simek lwi r22, r11, CC_R22 1130ca54502bSMichal Simek lwi r21, r11, CC_R21 1131ca54502bSMichal Simek lwi r20, r11, CC_R20 1132ca54502bSMichal Simek lwi r19, r11, CC_R19 1133ca54502bSMichal Simek /* dedicated registers */ 1134ca54502bSMichal Simek lwi r18, r11, CC_R18 1135ca54502bSMichal Simek lwi r17, r11, CC_R17 1136ca54502bSMichal Simek lwi r16, r11, CC_R16 1137ca54502bSMichal Simek lwi r15, r11, CC_R15 1138ca54502bSMichal Simek lwi r14, r11, CC_R14 1139ca54502bSMichal Simek lwi r13, r11, CC_R13 1140ca54502bSMichal Simek /* skip volatile registers */ 1141ca54502bSMichal Simek lwi r2, r11, CC_R2 1142ca54502bSMichal Simek lwi r1, r11, CC_R1 1143ca54502bSMichal Simek 1144ca54502bSMichal Simek /* special purpose registers */ 1145ca54502bSMichal Simek lwi r12, r11, CC_FSR 1146ca54502bSMichal Simek mts rfsr, r12 1147ca54502bSMichal Simek lwi r12, r11, CC_MSR 1148ca54502bSMichal Simek mts rmsr, r12 1149ca54502bSMichal Simek 1150ca54502bSMichal Simek rtsd r15, 8 1151ca54502bSMichal Simek nop 1152ca54502bSMichal Simek 1153a5e3aaa6SAppana Durga Kedareswara rao#ifdef CONFIG_MB_MANAGER 1154a5e3aaa6SAppana Durga Kedareswara rao.section .data 1155a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_dev 1156a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_baseaddr 1157a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_crval 1158a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_callback 1159a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_reset_callback 1160*88707ebeSAppana Durga Kedareswara rao.global xmb_manager_stackpointer 1161a5e3aaa6SAppana Durga Kedareswara rao.align 4 1162a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_dev: 1163a5e3aaa6SAppana Durga Kedareswara rao .long 0 1164a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_baseaddr: 1165a5e3aaa6SAppana Durga Kedareswara rao .long 0 1166a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_crval: 1167a5e3aaa6SAppana Durga Kedareswara rao .long 0 1168a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_callback: 1169a5e3aaa6SAppana Durga Kedareswara rao .long 0 1170a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_reset_callback: 1171a5e3aaa6SAppana Durga Kedareswara rao .long 0 1172*88707ebeSAppana Durga Kedareswara raoxmb_manager_stackpointer: 1173*88707ebeSAppana Durga Kedareswara rao .long 0 1174a5e3aaa6SAppana Durga Kedareswara rao 1175a5e3aaa6SAppana Durga Kedareswara rao/* 1176a5e3aaa6SAppana Durga Kedareswara rao * When the break vector gets asserted because of error injection, 1177a5e3aaa6SAppana Durga Kedareswara rao * the break signal must be blocked before exiting from the 1178a5e3aaa6SAppana Durga Kedareswara rao * break handler, Below api updates the manager address and 1179a5e3aaa6SAppana Durga Kedareswara rao * control register and error count callback arguments, 1180a5e3aaa6SAppana Durga Kedareswara rao * which will be used by the break handler to block the 1181a5e3aaa6SAppana Durga Kedareswara rao * break and call the callback function. 1182a5e3aaa6SAppana Durga Kedareswara rao */ 1183a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_register 1184a5e3aaa6SAppana Durga Kedareswara rao.section .text 1185a5e3aaa6SAppana Durga Kedareswara rao.align 2 1186a5e3aaa6SAppana Durga Kedareswara rao.ent xmb_manager_register 1187a5e3aaa6SAppana Durga Kedareswara rao.type xmb_manager_register, @function 1188a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_register: 1189a5e3aaa6SAppana Durga Kedareswara rao swi r5, r0, xmb_manager_baseaddr 1190a5e3aaa6SAppana Durga Kedareswara rao swi r6, r0, xmb_manager_crval 1191a5e3aaa6SAppana Durga Kedareswara rao swi r7, r0, xmb_manager_callback 1192a5e3aaa6SAppana Durga Kedareswara rao swi r8, r0, xmb_manager_dev 1193a5e3aaa6SAppana Durga Kedareswara rao swi r9, r0, xmb_manager_reset_callback 1194a5e3aaa6SAppana Durga Kedareswara rao 1195a5e3aaa6SAppana Durga Kedareswara rao rtsd r15, 8; 1196a5e3aaa6SAppana Durga Kedareswara rao nop; 1197a5e3aaa6SAppana Durga Kedareswara rao.end xmb_manager_register 1198a5e3aaa6SAppana Durga Kedareswara rao#endif 1199a5e3aaa6SAppana Durga Kedareswara rao 1200ca54502bSMichal SimekENTRY(_reset) 12015119c418SMichal Simek VM_OFF 12027574349cSMichal Simek brai 0; /* Jump to reset vector */ 1203ca54502bSMichal Simek 1204ca54502bSMichal Simek /* These are compiled and loaded into high memory, then 1205ca54502bSMichal Simek * copied into place in mach_early_setup */ 1206ca54502bSMichal Simek .section .init.ivt, "ax" 1207*88707ebeSAppana Durga Kedareswara rao#if CONFIG_MANUAL_RESET_VECTOR && !defined(CONFIG_MB_MANAGER) 1208ca54502bSMichal Simek .org 0x0 12090b9b0200SMichal Simek brai CONFIG_MANUAL_RESET_VECTOR 1210*88707ebeSAppana Durga Kedareswara rao#elif defined(CONFIG_MB_MANAGER) 1211*88707ebeSAppana Durga Kedareswara rao .org 0x0 1212*88707ebeSAppana Durga Kedareswara rao brai TOPHYS(_xtmr_manager_reset); 12130b9b0200SMichal Simek#endif 1214626afa35SMichal Simek .org 0x8 1215ca54502bSMichal Simek brai TOPHYS(_user_exception); /* syscall handler */ 1216626afa35SMichal Simek .org 0x10 1217ca54502bSMichal Simek brai TOPHYS(_interrupt); /* Interrupt handler */ 1218*88707ebeSAppana Durga Kedareswara rao#ifdef CONFIG_MB_MANAGER 1219*88707ebeSAppana Durga Kedareswara rao .org 0x18 1220*88707ebeSAppana Durga Kedareswara rao brai TOPHYS(_xmb_manager_break); /* microblaze manager break handler */ 1221*88707ebeSAppana Durga Kedareswara rao#else 1222626afa35SMichal Simek .org 0x18 1223ca54502bSMichal Simek brai TOPHYS(_debug_exception); /* debug trap handler */ 1224*88707ebeSAppana Durga Kedareswara rao#endif 1225626afa35SMichal Simek .org 0x20 1226751f1605SMichal Simek brai TOPHYS(_hw_exception_handler); /* HW exception handler */ 1227ca54502bSMichal Simek 1228ca54502bSMichal Simek.section .rodata,"a" 1229ca54502bSMichal Simek#include "syscall_table.S" 1230ca54502bSMichal Simek 1231ca54502bSMichal Simeksyscall_table_size=(.-sys_call_table) 1232ca54502bSMichal Simek 1233ce3266c0SSteven J. Magnanitype_SYSCALL: 1234ce3266c0SSteven J. Magnani .ascii "SYSCALL\0" 1235ce3266c0SSteven J. Magnanitype_IRQ: 1236ce3266c0SSteven J. Magnani .ascii "IRQ\0" 1237ce3266c0SSteven J. Magnanitype_IRQ_PREEMPT: 1238ce3266c0SSteven J. Magnani .ascii "IRQ (PREEMPTED)\0" 1239ce3266c0SSteven J. Magnanitype_SYSCALL_PREEMPT: 1240ce3266c0SSteven J. Magnani .ascii " SYSCALL (PREEMPTED)\0" 1241ce3266c0SSteven J. Magnani 1242ce3266c0SSteven J. Magnani /* 1243ce3266c0SSteven J. Magnani * Trap decoding for stack unwinder 1244ce3266c0SSteven J. Magnani * Tuples are (start addr, end addr, string) 1245ce3266c0SSteven J. Magnani * If return address lies on [start addr, end addr], 1246ce3266c0SSteven J. Magnani * unwinder displays 'string' 1247ce3266c0SSteven J. Magnani */ 1248ce3266c0SSteven J. Magnani 1249ce3266c0SSteven J. Magnani .align 4 1250ce3266c0SSteven J. Magnani.global microblaze_trap_handlers 1251ce3266c0SSteven J. Magnanimicroblaze_trap_handlers: 1252ce3266c0SSteven J. Magnani /* Exact matches come first */ 1253ce3266c0SSteven J. Magnani .word ret_from_trap; .word ret_from_trap ; .word type_SYSCALL 1254ce3266c0SSteven J. Magnani .word ret_from_irq ; .word ret_from_irq ; .word type_IRQ 1255ce3266c0SSteven J. Magnani /* Fuzzy matches go here */ 1256ce3266c0SSteven J. Magnani .word ret_from_irq ; .word no_intr_resched ; .word type_IRQ_PREEMPT 1257ce3266c0SSteven J. Magnani .word ret_from_trap; .word TRAP_return ; .word type_SYSCALL_PREEMPT 1258ce3266c0SSteven J. Magnani /* End of table */ 1259ce3266c0SSteven J. Magnani .word 0 ; .word 0 ; .word 0 1260