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> 30*adc4cefaSAppana Durga Kedareswara rao#include <asm/xilinx_mb_manager.h> 31ca54502bSMichal Simek 32ca54502bSMichal Simek#include <linux/errno.h> 33ca54502bSMichal Simek#include <asm/signal.h> 3488707ebeSAppana Durga Kedareswara rao#include <asm/mmu.h> 35ca54502bSMichal Simek 3611d51360SMichal Simek#undef DEBUG 3711d51360SMichal Simek 38d8748e73SMichal Simek#ifdef DEBUG 39d8748e73SMichal Simek/* Create space for syscalls counting. */ 40d8748e73SMichal Simek.section .data 41d8748e73SMichal Simek.global syscall_debug_table 42d8748e73SMichal Simek.align 4 43d8748e73SMichal Simeksyscall_debug_table: 44d8748e73SMichal Simek .space (__NR_syscalls * 4) 45d8748e73SMichal Simek#endif /* DEBUG */ 46d8748e73SMichal Simek 47ca54502bSMichal Simek#define C_ENTRY(name) .globl name; .align 4; name 48ca54502bSMichal Simek 49ca54502bSMichal Simek/* 50ca54502bSMichal Simek * Various ways of setting and clearing BIP in flags reg. 51ca54502bSMichal Simek * This is mucky, but necessary using microblaze version that 52ca54502bSMichal Simek * allows msr ops to write to BIP 53ca54502bSMichal Simek */ 54ca54502bSMichal Simek#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR 55ca54502bSMichal Simek .macro clear_bip 5666f7de86SMichal Simek msrclr r0, MSR_BIP 57ca54502bSMichal Simek .endm 58ca54502bSMichal Simek 59ca54502bSMichal Simek .macro set_bip 6066f7de86SMichal Simek msrset r0, MSR_BIP 61ca54502bSMichal Simek .endm 62ca54502bSMichal Simek 63ca54502bSMichal Simek .macro clear_eip 6466f7de86SMichal Simek msrclr r0, MSR_EIP 65ca54502bSMichal Simek .endm 66ca54502bSMichal Simek 67ca54502bSMichal Simek .macro set_ee 6866f7de86SMichal Simek msrset r0, MSR_EE 69ca54502bSMichal Simek .endm 70ca54502bSMichal Simek 71ca54502bSMichal Simek .macro disable_irq 7266f7de86SMichal Simek msrclr r0, MSR_IE 73ca54502bSMichal Simek .endm 74ca54502bSMichal Simek 75ca54502bSMichal Simek .macro enable_irq 7666f7de86SMichal Simek msrset r0, MSR_IE 77ca54502bSMichal Simek .endm 78ca54502bSMichal Simek 79ca54502bSMichal Simek .macro set_ums 8066f7de86SMichal Simek msrset r0, MSR_UMS 8166f7de86SMichal Simek msrclr r0, MSR_VMS 82ca54502bSMichal Simek .endm 83ca54502bSMichal Simek 84ca54502bSMichal Simek .macro set_vms 8566f7de86SMichal Simek msrclr r0, MSR_UMS 8666f7de86SMichal Simek msrset r0, MSR_VMS 87ca54502bSMichal Simek .endm 88ca54502bSMichal Simek 89b318067eSMichal Simek .macro clear_ums 9066f7de86SMichal Simek msrclr r0, MSR_UMS 91b318067eSMichal Simek .endm 92b318067eSMichal Simek 93ca54502bSMichal Simek .macro clear_vms_ums 9466f7de86SMichal Simek msrclr r0, MSR_VMS | MSR_UMS 95ca54502bSMichal Simek .endm 96ca54502bSMichal Simek#else 97ca54502bSMichal Simek .macro clear_bip 98ca54502bSMichal Simek mfs r11, rmsr 99ca54502bSMichal Simek andi r11, r11, ~MSR_BIP 100ca54502bSMichal Simek mts rmsr, r11 101ca54502bSMichal Simek .endm 102ca54502bSMichal Simek 103ca54502bSMichal Simek .macro set_bip 104ca54502bSMichal Simek mfs r11, rmsr 105ca54502bSMichal Simek ori r11, r11, MSR_BIP 106ca54502bSMichal Simek mts rmsr, r11 107ca54502bSMichal Simek .endm 108ca54502bSMichal Simek 109ca54502bSMichal Simek .macro clear_eip 110ca54502bSMichal Simek mfs r11, rmsr 111ca54502bSMichal Simek andi r11, r11, ~MSR_EIP 112ca54502bSMichal Simek mts rmsr, r11 113ca54502bSMichal Simek .endm 114ca54502bSMichal Simek 115ca54502bSMichal Simek .macro set_ee 116ca54502bSMichal Simek mfs r11, rmsr 117ca54502bSMichal Simek ori r11, r11, MSR_EE 118ca54502bSMichal Simek mts rmsr, r11 119ca54502bSMichal Simek .endm 120ca54502bSMichal Simek 121ca54502bSMichal Simek .macro disable_irq 122ca54502bSMichal Simek mfs r11, rmsr 123ca54502bSMichal Simek andi r11, r11, ~MSR_IE 124ca54502bSMichal Simek mts rmsr, r11 125ca54502bSMichal Simek .endm 126ca54502bSMichal Simek 127ca54502bSMichal Simek .macro enable_irq 128ca54502bSMichal Simek mfs r11, rmsr 129ca54502bSMichal Simek ori r11, r11, MSR_IE 130ca54502bSMichal Simek mts rmsr, r11 131ca54502bSMichal Simek .endm 132ca54502bSMichal Simek 133ca54502bSMichal Simek .macro set_ums 134ca54502bSMichal Simek mfs r11, rmsr 135ca54502bSMichal Simek ori r11, r11, MSR_VMS 136ca54502bSMichal Simek andni r11, r11, MSR_UMS 137ca54502bSMichal Simek mts rmsr, r11 138ca54502bSMichal Simek .endm 139ca54502bSMichal Simek 140ca54502bSMichal Simek .macro set_vms 141ca54502bSMichal Simek mfs r11, rmsr 142ca54502bSMichal Simek ori r11, r11, MSR_VMS 143ca54502bSMichal Simek andni r11, r11, MSR_UMS 144ca54502bSMichal Simek mts rmsr, r11 145ca54502bSMichal Simek .endm 146ca54502bSMichal Simek 147b318067eSMichal Simek .macro clear_ums 148b318067eSMichal Simek mfs r11, rmsr 149b318067eSMichal Simek andni r11, r11, MSR_UMS 150b318067eSMichal Simek mts rmsr,r11 151b318067eSMichal Simek .endm 152b318067eSMichal Simek 153ca54502bSMichal Simek .macro clear_vms_ums 154ca54502bSMichal Simek mfs r11, rmsr 155ca54502bSMichal Simek andni r11, r11, (MSR_VMS|MSR_UMS) 156ca54502bSMichal Simek mts rmsr,r11 157ca54502bSMichal Simek .endm 158ca54502bSMichal Simek#endif 159ca54502bSMichal Simek 160ca54502bSMichal Simek/* Define how to call high-level functions. With MMU, virtual mode must be 161ca54502bSMichal Simek * enabled when calling the high-level function. Clobbers R11. 162ca54502bSMichal Simek * VM_ON, VM_OFF, DO_JUMP_BIPCLR, DO_CALL 163ca54502bSMichal Simek */ 164ca54502bSMichal Simek 165ca54502bSMichal Simek/* turn on virtual protected mode save */ 166ca54502bSMichal Simek#define VM_ON \ 167ca54502bSMichal Simek set_ums; \ 168ca54502bSMichal Simek rted r0, 2f; \ 169a4a94dbfSMichal Simek nop; \ 170a4a94dbfSMichal Simek2: 171ca54502bSMichal Simek 172ca54502bSMichal Simek/* turn off virtual protected mode save and user mode save*/ 173ca54502bSMichal Simek#define VM_OFF \ 174ca54502bSMichal Simek clear_vms_ums; \ 175ca54502bSMichal Simek rted r0, TOPHYS(1f); \ 176a4a94dbfSMichal Simek nop; \ 177a4a94dbfSMichal Simek1: 178ca54502bSMichal Simek 179ca54502bSMichal Simek#define SAVE_REGS \ 1806e83557cSMichal Simek swi r2, r1, PT_R2; /* Save SDA */ \ 1816e83557cSMichal Simek swi r3, r1, PT_R3; \ 1826e83557cSMichal Simek swi r4, r1, PT_R4; \ 1836e83557cSMichal Simek swi r5, r1, PT_R5; \ 1846e83557cSMichal Simek swi r6, r1, PT_R6; \ 1856e83557cSMichal Simek swi r7, r1, PT_R7; \ 1866e83557cSMichal Simek swi r8, r1, PT_R8; \ 1876e83557cSMichal Simek swi r9, r1, PT_R9; \ 1886e83557cSMichal Simek swi r10, r1, PT_R10; \ 1896e83557cSMichal Simek swi r11, r1, PT_R11; /* save clobbered regs after rval */\ 1906e83557cSMichal Simek swi r12, r1, PT_R12; \ 1916e83557cSMichal Simek swi r13, r1, PT_R13; /* Save SDA2 */ \ 1926e83557cSMichal Simek swi r14, r1, PT_PC; /* PC, before IRQ/trap */ \ 1936e83557cSMichal Simek swi r15, r1, PT_R15; /* Save LP */ \ 1946e83557cSMichal Simek swi r16, r1, PT_R16; \ 1956e83557cSMichal Simek swi r17, r1, PT_R17; \ 1966e83557cSMichal Simek swi r18, r1, PT_R18; /* Save asm scratch reg */ \ 1976e83557cSMichal Simek swi r19, r1, PT_R19; \ 1986e83557cSMichal Simek swi r20, r1, PT_R20; \ 1996e83557cSMichal Simek swi r21, r1, PT_R21; \ 2006e83557cSMichal Simek swi r22, r1, PT_R22; \ 2016e83557cSMichal Simek swi r23, r1, PT_R23; \ 2026e83557cSMichal Simek swi r24, r1, PT_R24; \ 2036e83557cSMichal Simek swi r25, r1, PT_R25; \ 2046e83557cSMichal Simek swi r26, r1, PT_R26; \ 2056e83557cSMichal Simek swi r27, r1, PT_R27; \ 2066e83557cSMichal Simek swi r28, r1, PT_R28; \ 2076e83557cSMichal Simek swi r29, r1, PT_R29; \ 2086e83557cSMichal Simek swi r30, r1, PT_R30; \ 2096e83557cSMichal Simek swi r31, r1, PT_R31; /* Save current task reg */ \ 210ca54502bSMichal Simek mfs r11, rmsr; /* save MSR */ \ 2116e83557cSMichal Simek swi r11, r1, PT_MSR; 212ca54502bSMichal Simek 213faf154cdSMichal Simek#define RESTORE_REGS_GP \ 2146e83557cSMichal Simek lwi r2, r1, PT_R2; /* restore SDA */ \ 2156e83557cSMichal Simek lwi r3, r1, PT_R3; \ 2166e83557cSMichal Simek lwi r4, r1, PT_R4; \ 2176e83557cSMichal Simek lwi r5, r1, PT_R5; \ 2186e83557cSMichal Simek lwi r6, r1, PT_R6; \ 2196e83557cSMichal Simek lwi r7, r1, PT_R7; \ 2206e83557cSMichal Simek lwi r8, r1, PT_R8; \ 2216e83557cSMichal Simek lwi r9, r1, PT_R9; \ 2226e83557cSMichal Simek lwi r10, r1, PT_R10; \ 2236e83557cSMichal Simek lwi r11, r1, PT_R11; /* restore clobbered regs after rval */\ 2246e83557cSMichal Simek lwi r12, r1, PT_R12; \ 2256e83557cSMichal Simek lwi r13, r1, PT_R13; /* restore SDA2 */ \ 2266e83557cSMichal Simek lwi r14, r1, PT_PC; /* RESTORE_LINK PC, before IRQ/trap */\ 2276e83557cSMichal Simek lwi r15, r1, PT_R15; /* restore LP */ \ 2286e83557cSMichal Simek lwi r16, r1, PT_R16; \ 2296e83557cSMichal Simek lwi r17, r1, PT_R17; \ 2306e83557cSMichal Simek lwi r18, r1, PT_R18; /* restore asm scratch reg */ \ 2316e83557cSMichal Simek lwi r19, r1, PT_R19; \ 2326e83557cSMichal Simek lwi r20, r1, PT_R20; \ 2336e83557cSMichal Simek lwi r21, r1, PT_R21; \ 2346e83557cSMichal Simek lwi r22, r1, PT_R22; \ 2356e83557cSMichal Simek lwi r23, r1, PT_R23; \ 2366e83557cSMichal Simek lwi r24, r1, PT_R24; \ 2376e83557cSMichal Simek lwi r25, r1, PT_R25; \ 2386e83557cSMichal Simek lwi r26, r1, PT_R26; \ 2396e83557cSMichal Simek lwi r27, r1, PT_R27; \ 2406e83557cSMichal Simek lwi r28, r1, PT_R28; \ 2416e83557cSMichal Simek lwi r29, r1, PT_R29; \ 2426e83557cSMichal Simek lwi r30, r1, PT_R30; \ 2436e83557cSMichal Simek lwi r31, r1, PT_R31; /* Restore cur task reg */ 244ca54502bSMichal Simek 245faf154cdSMichal Simek#define RESTORE_REGS \ 246faf154cdSMichal Simek lwi r11, r1, PT_MSR; \ 247faf154cdSMichal Simek mts rmsr , r11; \ 248faf154cdSMichal Simek RESTORE_REGS_GP 249faf154cdSMichal Simek 25014ef905bSMichal Simek#define RESTORE_REGS_RTBD \ 25114ef905bSMichal Simek lwi r11, r1, PT_MSR; \ 25214ef905bSMichal Simek andni r11, r11, MSR_EIP; /* clear EIP */ \ 25314ef905bSMichal Simek ori r11, r11, MSR_EE | MSR_BIP; /* set EE and BIP */ \ 25414ef905bSMichal Simek mts rmsr , r11; \ 25514ef905bSMichal Simek RESTORE_REGS_GP 25614ef905bSMichal Simek 257e5d2af2bSMichal Simek#define SAVE_STATE \ 258e5d2af2bSMichal Simek swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */ \ 259e5d2af2bSMichal Simek /* See if already in kernel mode.*/ \ 260e5d2af2bSMichal Simek mfs r1, rmsr; \ 261e5d2af2bSMichal Simek andi r1, r1, MSR_UMS; \ 262e5d2af2bSMichal Simek bnei r1, 1f; \ 263e5d2af2bSMichal Simek /* Kernel-mode state save. */ \ 264e5d2af2bSMichal Simek /* Reload kernel stack-ptr. */ \ 265e5d2af2bSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ 266287503faSMichal Simek /* FIXME: I can add these two lines to one */ \ 267287503faSMichal Simek /* tophys(r1,r1); */ \ 2686e83557cSMichal Simek /* addik r1, r1, -PT_SIZE; */ \ 2696e83557cSMichal Simek addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \ 270e5d2af2bSMichal Simek SAVE_REGS \ 271e5d2af2bSMichal Simek brid 2f; \ 2726e83557cSMichal Simek swi r1, r1, PT_MODE; \ 273e5d2af2bSMichal Simek1: /* User-mode state save. */ \ 274e5d2af2bSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\ 275e5d2af2bSMichal Simek tophys(r1,r1); \ 276e5d2af2bSMichal Simek lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ \ 277287503faSMichal Simek /* MS these three instructions can be added to one */ \ 278287503faSMichal Simek /* addik r1, r1, THREAD_SIZE; */ \ 279287503faSMichal Simek /* tophys(r1,r1); */ \ 2806e83557cSMichal Simek /* addik r1, r1, -PT_SIZE; */ \ 2816e83557cSMichal Simek addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \ 282e5d2af2bSMichal Simek SAVE_REGS \ 283e5d2af2bSMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); \ 2846e83557cSMichal Simek swi r11, r1, PT_R1; /* Store user SP. */ \ 2856e83557cSMichal Simek swi r0, r1, PT_MODE; /* Was in user-mode. */ \ 286e5d2af2bSMichal Simek /* MS: I am clearing UMS even in case when I come from kernel space */ \ 287e5d2af2bSMichal Simek clear_ums; \ 288e5d2af2bSMichal Simek2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 289e5d2af2bSMichal Simek 290ca54502bSMichal Simek.text 291ca54502bSMichal Simek 29288707ebeSAppana Durga Kedareswara rao.extern cpuinfo 29388707ebeSAppana Durga Kedareswara rao 29488707ebeSAppana Durga Kedareswara raoC_ENTRY(mb_flush_dcache): 29588707ebeSAppana Durga Kedareswara rao addik r1, r1, -PT_SIZE 29688707ebeSAppana Durga Kedareswara rao SAVE_REGS 29788707ebeSAppana Durga Kedareswara rao 29888707ebeSAppana Durga Kedareswara rao addik r3, r0, cpuinfo 29988707ebeSAppana Durga Kedareswara rao lwi r7, r3, CI_DCS 30088707ebeSAppana Durga Kedareswara rao lwi r8, r3, CI_DCL 30188707ebeSAppana Durga Kedareswara rao sub r9, r7, r8 30288707ebeSAppana Durga Kedareswara rao1: 30388707ebeSAppana Durga Kedareswara rao wdc.flush r9, r0 30488707ebeSAppana Durga Kedareswara rao bgtid r9, 1b 30588707ebeSAppana Durga Kedareswara rao addk r9, r9, r8 30688707ebeSAppana Durga Kedareswara rao 30788707ebeSAppana Durga Kedareswara rao RESTORE_REGS 30888707ebeSAppana Durga Kedareswara rao addik r1, r1, PT_SIZE 30988707ebeSAppana Durga Kedareswara rao rtsd r15, 8 31088707ebeSAppana Durga Kedareswara rao nop 31188707ebeSAppana Durga Kedareswara rao 31288707ebeSAppana Durga Kedareswara raoC_ENTRY(mb_invalidate_icache): 31388707ebeSAppana Durga Kedareswara rao addik r1, r1, -PT_SIZE 31488707ebeSAppana Durga Kedareswara rao SAVE_REGS 31588707ebeSAppana Durga Kedareswara rao 31688707ebeSAppana Durga Kedareswara rao addik r3, r0, cpuinfo 31788707ebeSAppana Durga Kedareswara rao lwi r7, r3, CI_ICS 31888707ebeSAppana Durga Kedareswara rao lwi r8, r3, CI_ICL 31988707ebeSAppana Durga Kedareswara rao sub r9, r7, r8 32088707ebeSAppana Durga Kedareswara rao1: 32188707ebeSAppana Durga Kedareswara rao wic r9, r0 32288707ebeSAppana Durga Kedareswara rao bgtid r9, 1b 32388707ebeSAppana Durga Kedareswara rao addk r9, r9, r8 32488707ebeSAppana Durga Kedareswara rao 32588707ebeSAppana Durga Kedareswara rao RESTORE_REGS 32688707ebeSAppana Durga Kedareswara rao addik r1, r1, PT_SIZE 32788707ebeSAppana Durga Kedareswara rao rtsd r15, 8 32888707ebeSAppana Durga Kedareswara rao nop 32988707ebeSAppana Durga Kedareswara rao 330ca54502bSMichal Simek/* 331ca54502bSMichal Simek * User trap. 332ca54502bSMichal Simek * 333ca54502bSMichal Simek * System calls are handled here. 334ca54502bSMichal Simek * 335ca54502bSMichal Simek * Syscall protocol: 336ca54502bSMichal Simek * Syscall number in r12, args in r5-r10 337ca54502bSMichal Simek * Return value in r3 338ca54502bSMichal Simek * 339ca54502bSMichal Simek * Trap entered via brki instruction, so BIP bit is set, and interrupts 340ca54502bSMichal Simek * are masked. This is nice, means we don't have to CLI before state save 341ca54502bSMichal Simek */ 342ca54502bSMichal SimekC_ENTRY(_user_exception): 3430e41c909SMichal Simek swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */ 3449da63458SMichal Simek addi r14, r14, 4 /* return address is 4 byte after call */ 345ca54502bSMichal Simek 346ca54502bSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ 347ca54502bSMichal Simek tophys(r1,r1); 348ca54502bSMichal Simek lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */ 3499da63458SMichal Simek/* calculate kernel stack pointer from task struct 8k */ 3509da63458SMichal Simek addik r1, r1, THREAD_SIZE; 3519da63458SMichal Simek tophys(r1,r1); 3529da63458SMichal Simek 3536e83557cSMichal Simek addik r1, r1, -PT_SIZE; /* Make room on the stack. */ 354ca54502bSMichal Simek SAVE_REGS 3556e83557cSMichal Simek swi r0, r1, PT_R3 3566e83557cSMichal Simek swi r0, r1, PT_R4 357ca54502bSMichal Simek 3586e83557cSMichal Simek swi r0, r1, PT_MODE; /* Was in user-mode. */ 359ca54502bSMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 3606e83557cSMichal Simek swi r11, r1, PT_R1; /* Store user SP. */ 36125f6e596SMichal Simek clear_ums; 3629da63458SMichal Simek2: lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 363ca54502bSMichal Simek /* Save away the syscall number. */ 3646e83557cSMichal Simek swi r12, r1, PT_R0; 365ca54502bSMichal Simek tovirt(r1,r1) 366ca54502bSMichal Simek 367ca54502bSMichal Simek/* where the trap should return need -8 to adjust for rtsd r15, 8*/ 368ca54502bSMichal Simek/* Jump to the appropriate function for the system call number in r12 369ca54502bSMichal Simek * (r12 is not preserved), or return an error if r12 is not valid. The LP 370ca54502bSMichal Simek * register should point to the location where 371ca54502bSMichal Simek * the called function should return. [note that MAKE_SYS_CALL uses label 1] */ 37223575483SMichal Simek 37325f6e596SMichal Simek /* Step into virtual mode */ 37425f6e596SMichal Simek rtbd r0, 3f 37523575483SMichal Simek nop 37623575483SMichal Simek3: 377b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO /* get thread info */ 37823575483SMichal Simek lwi r11, r11, TI_FLAGS /* get flags in thread info */ 37923575483SMichal Simek andi r11, r11, _TIF_WORK_SYSCALL_MASK 38023575483SMichal Simek beqi r11, 4f 38123575483SMichal Simek 38223575483SMichal Simek addik r3, r0, -ENOSYS 3836e83557cSMichal Simek swi r3, r1, PT_R3 38423575483SMichal Simek brlid r15, do_syscall_trace_enter 3856e83557cSMichal Simek addik r5, r1, PT_R0 38623575483SMichal Simek 38723575483SMichal Simek # do_syscall_trace_enter returns the new syscall nr. 38823575483SMichal Simek addk r12, r0, r3 3896e83557cSMichal Simek lwi r5, r1, PT_R5; 3906e83557cSMichal Simek lwi r6, r1, PT_R6; 3916e83557cSMichal Simek lwi r7, r1, PT_R7; 3926e83557cSMichal Simek lwi r8, r1, PT_R8; 3936e83557cSMichal Simek lwi r9, r1, PT_R9; 3946e83557cSMichal Simek lwi r10, r1, PT_R10; 39523575483SMichal Simek4: 39623575483SMichal Simek/* Jump to the appropriate function for the system call number in r12 39723575483SMichal Simek * (r12 is not preserved), or return an error if r12 is not valid. 39823575483SMichal Simek * The LP register should point to the location where the called function 39923575483SMichal Simek * should return. [note that MAKE_SYS_CALL uses label 1] */ 40023575483SMichal Simek /* See if the system call number is valid */ 401c2219edaSJamie Garside blti r12, 5f 402ca54502bSMichal Simek addi r11, r12, -__NR_syscalls; 40323575483SMichal Simek bgei r11, 5f; 404ca54502bSMichal Simek /* Figure out which function to use for this system call. */ 405ca54502bSMichal Simek /* Note Microblaze barrel shift is optional, so don't rely on it */ 406ca54502bSMichal Simek add r12, r12, r12; /* convert num -> ptr */ 407ca54502bSMichal Simek add r12, r12, r12; 4084de6ba68SMichal Simek addi r30, r0, 1 /* restarts allowed */ 409ca54502bSMichal Simek 41011d51360SMichal Simek#ifdef DEBUG 411d8748e73SMichal Simek /* Trac syscalls and stored them to syscall_debug_table */ 412d8748e73SMichal Simek /* The first syscall location stores total syscall number */ 413d8748e73SMichal Simek lwi r3, r0, syscall_debug_table 414ca54502bSMichal Simek addi r3, r3, 1 415d8748e73SMichal Simek swi r3, r0, syscall_debug_table 416d8748e73SMichal Simek lwi r3, r12, syscall_debug_table 417d8748e73SMichal Simek addi r3, r3, 1 418d8748e73SMichal Simek swi r3, r12, syscall_debug_table 41911d51360SMichal Simek#endif 420ca54502bSMichal Simek 42123575483SMichal Simek # Find and jump into the syscall handler. 42223575483SMichal Simek lwi r12, r12, sys_call_table 42323575483SMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 424b9ea77e2SMichal Simek addi r15, r0, ret_from_trap-8 42523575483SMichal Simek bra r12 42623575483SMichal Simek 427ca54502bSMichal Simek /* The syscall number is invalid, return an error. */ 42823575483SMichal Simek5: 429c2219edaSJamie Garside braid ret_from_trap 4309814cc11SMichal Simek addi r3, r0, -ENOSYS; 431ca54502bSMichal Simek 43223575483SMichal Simek/* Entry point used to return from a syscall/trap */ 433ca54502bSMichal Simek/* We re-enable BIP bit before state restore */ 434ca54502bSMichal SimekC_ENTRY(ret_from_trap): 4356e83557cSMichal Simek swi r3, r1, PT_R3 4366e83557cSMichal Simek swi r4, r1, PT_R4 437b1d70c62SMichal Simek 4386e83557cSMichal Simek lwi r11, r1, PT_MODE; 4399da63458SMichal Simek/* See if returning to kernel mode, if so, skip resched &c. */ 4409da63458SMichal Simek bnei r11, 2f; 441ca54502bSMichal Simek /* We're returning to user mode, so check for various conditions that 442ca54502bSMichal Simek * trigger rescheduling. */ 443b1d70c62SMichal Simek /* FIXME: Restructure all these flag checks. */ 444b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 44523575483SMichal Simek lwi r11, r11, TI_FLAGS; /* get flags in thread info */ 44623575483SMichal Simek andi r11, r11, _TIF_WORK_SYSCALL_MASK 44723575483SMichal Simek beqi r11, 1f 44823575483SMichal Simek 44923575483SMichal Simek brlid r15, do_syscall_trace_leave 4506e83557cSMichal Simek addik r5, r1, PT_R0 45123575483SMichal Simek1: 45223575483SMichal Simek /* We're returning to user mode, so check for various conditions that 45323575483SMichal Simek * trigger rescheduling. */ 454b1d70c62SMichal Simek /* get thread info from current task */ 455b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; 456e9f92526SAl Viro lwi r19, r11, TI_FLAGS; /* get flags in thread info */ 457e9f92526SAl Viro andi r11, r19, _TIF_NEED_RESCHED; 458ca54502bSMichal Simek beqi r11, 5f; 459ca54502bSMichal Simek 460ca54502bSMichal Simek bralid r15, schedule; /* Call scheduler */ 461ca54502bSMichal Simek nop; /* delay slot */ 462e9f92526SAl Viro bri 1b 463ca54502bSMichal Simek 464ca54502bSMichal Simek /* Maybe handle a signal */ 465e9f92526SAl Viro5: 466e9f92526SAl Viro andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; 467e9f92526SAl Viro beqi r11, 4f; /* Signals to handle, handle them */ 468ca54502bSMichal Simek 4696e83557cSMichal Simek addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 470969a9616SAl Viro bralid r15, do_notify_resume; /* Handle any signals */ 47114203e19SAl Viro add r6, r30, r0; /* Arg 2: int in_syscall */ 472e9f92526SAl Viro add r30, r0, r0 /* no more restarts */ 473e9f92526SAl Viro bri 1b 474b1d70c62SMichal Simek 475b1d70c62SMichal Simek/* Finally, return to user state. */ 476e9f92526SAl Viro4: set_bip; /* Ints masked for state restore */ 4778633bebcSMichal Simek swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ 478ca54502bSMichal Simek VM_OFF; 479ca54502bSMichal Simek tophys(r1,r1); 48014ef905bSMichal Simek RESTORE_REGS_RTBD; 4816e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space. */ 482ca54502bSMichal Simek lwi r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */ 4839da63458SMichal Simek bri 6f; 4849da63458SMichal Simek 4859da63458SMichal Simek/* Return to kernel state. */ 4869da63458SMichal Simek2: set_bip; /* Ints masked for state restore */ 4879da63458SMichal Simek VM_OFF; 4889da63458SMichal Simek tophys(r1,r1); 48914ef905bSMichal Simek RESTORE_REGS_RTBD; 4906e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space. */ 4919da63458SMichal Simek tovirt(r1,r1); 4929da63458SMichal Simek6: 493ca54502bSMichal SimekTRAP_return: /* Make global symbol for debugging */ 494ca54502bSMichal Simek rtbd r14, 0; /* Instructions to return from an IRQ */ 495ca54502bSMichal Simek nop; 496ca54502bSMichal Simek 497ca54502bSMichal Simek 498ca54502bSMichal Simek/* This the initial entry point for a new child thread, with an appropriate 4995b7d1d57SSlark Xiao stack in place that makes it look like the child is in the middle of a 500ca54502bSMichal Simek syscall. This function is actually `returned to' from switch_thread 501ca54502bSMichal Simek (copy_thread makes ret_from_fork the return address in each new thread's 502ca54502bSMichal Simek saved context). */ 503ca54502bSMichal SimekC_ENTRY(ret_from_fork): 504ca54502bSMichal Simek bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ 505fd11ff73SMichal Simek add r5, r3, r0; /* switch_thread returns the prev task */ 506ca54502bSMichal Simek /* ( in the delay slot ) */ 507ca54502bSMichal Simek brid ret_from_trap; /* Do normal trap return */ 5089814cc11SMichal Simek add r3, r0, r0; /* Child's fork call should return 0. */ 509ca54502bSMichal Simek 5102319295dSAl ViroC_ENTRY(ret_from_kernel_thread): 5112319295dSAl Viro bralid r15, schedule_tail; /* ...which is schedule_tail's arg */ 5122319295dSAl Viro add r5, r3, r0; /* switch_thread returns the prev task */ 5132319295dSAl Viro /* ( in the delay slot ) */ 5142319295dSAl Viro brald r15, r20 /* fn was left in r20 */ 5152319295dSAl Viro addk r5, r0, r19 /* ... and argument - in r19 */ 51699c59f60SAl Viro brid ret_from_trap 51799c59f60SAl Viro add r3, r0, r0 5182319295dSAl Viro 519ca54502bSMichal SimekC_ENTRY(sys_rt_sigreturn_wrapper): 52014203e19SAl Viro addik r30, r0, 0 /* no restarts */ 521791d0a16SMichal Simek brid sys_rt_sigreturn /* Do real work */ 5226e83557cSMichal Simek addik r5, r1, 0; /* add user context as 1st arg */ 523ca54502bSMichal Simek 524ca54502bSMichal Simek/* 525ca54502bSMichal Simek * HW EXCEPTION rutine start 526ca54502bSMichal Simek */ 527ca54502bSMichal SimekC_ENTRY(full_exception_trap): 528ca54502bSMichal Simek /* adjust exception address for privileged instruction 529ca54502bSMichal Simek * for finding where is it */ 530ca54502bSMichal Simek addik r17, r17, -4 531ca54502bSMichal Simek SAVE_STATE /* Save registers */ 53206a54604SMichal Simek /* PC, before IRQ/trap - this is one instruction above */ 5336e83557cSMichal Simek swi r17, r1, PT_PC; 53406a54604SMichal Simek tovirt(r1,r1) 535ca54502bSMichal Simek /* FIXME this can be store directly in PT_ESR reg. 536ca54502bSMichal Simek * I tested it but there is a fault */ 537ca54502bSMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 538b9ea77e2SMichal Simek addik r15, r0, ret_from_exc - 8 539ca54502bSMichal Simek mfs r6, resr 540ca54502bSMichal Simek mfs r7, rfsr; /* save FSR */ 541131e4e97SMichal Simek mts rfsr, r0; /* Clear sticky fsr */ 542c318d483SMichal Simek rted r0, full_exception 5436e83557cSMichal Simek addik r5, r1, 0 /* parameter struct pt_regs * regs */ 544ca54502bSMichal Simek 545ca54502bSMichal Simek/* 546ca54502bSMichal Simek * Unaligned data trap. 547ca54502bSMichal Simek * 548ca54502bSMichal Simek * Unaligned data trap last on 4k page is handled here. 549ca54502bSMichal Simek * 550ca54502bSMichal Simek * Trap entered via exception, so EE bit is set, and interrupts 551ca54502bSMichal Simek * are masked. This is nice, means we don't have to CLI before state save 552ca54502bSMichal Simek * 553ca54502bSMichal Simek * The assembler routine is in "arch/microblaze/kernel/hw_exception_handler.S" 554ca54502bSMichal Simek */ 555ca54502bSMichal SimekC_ENTRY(unaligned_data_trap): 5568b110d15SMichal Simek /* MS: I have to save r11 value and then restore it because 5578b110d15SMichal Simek * set_bit, clear_eip, set_ee use r11 as temp register if MSR 5588b110d15SMichal Simek * instructions are not used. We don't need to do if MSR instructions 5598b110d15SMichal Simek * are used and they use r0 instead of r11. 5608b110d15SMichal Simek * I am using ENTRY_SP which should be primary used only for stack 5618b110d15SMichal Simek * pointer saving. */ 5628b110d15SMichal Simek swi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 5638b110d15SMichal Simek set_bip; /* equalize initial state for all possible entries */ 5648b110d15SMichal Simek clear_eip; 5658b110d15SMichal Simek set_ee; 5668b110d15SMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 567ca54502bSMichal Simek SAVE_STATE /* Save registers.*/ 56806a54604SMichal Simek /* PC, before IRQ/trap - this is one instruction above */ 5696e83557cSMichal Simek swi r17, r1, PT_PC; 57006a54604SMichal Simek tovirt(r1,r1) 571ca54502bSMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 572b9ea77e2SMichal Simek addik r15, r0, ret_from_exc-8 573ca54502bSMichal Simek mfs r3, resr /* ESR */ 574ca54502bSMichal Simek mfs r4, rear /* EAR */ 575c318d483SMichal Simek rtbd r0, _unaligned_data_exception 5766e83557cSMichal Simek addik r7, r1, 0 /* parameter struct pt_regs * regs */ 577ca54502bSMichal Simek 578ca54502bSMichal Simek/* 579ca54502bSMichal Simek * Page fault traps. 580ca54502bSMichal Simek * 581ca54502bSMichal Simek * If the real exception handler (from hw_exception_handler.S) didn't find 582ca54502bSMichal Simek * the mapping for the process, then we're thrown here to handle such situation. 583ca54502bSMichal Simek * 584ca54502bSMichal Simek * Trap entered via exceptions, so EE bit is set, and interrupts 585ca54502bSMichal Simek * are masked. This is nice, means we don't have to CLI before state save 586ca54502bSMichal Simek * 587ca54502bSMichal Simek * Build a standard exception frame for TLB Access errors. All TLB exceptions 588ca54502bSMichal Simek * will bail out to this point if they can't resolve the lightweight TLB fault. 589ca54502bSMichal Simek * 590ca54502bSMichal Simek * The C function called is in "arch/microblaze/mm/fault.c", declared as: 591ca54502bSMichal Simek * void do_page_fault(struct pt_regs *regs, 592ca54502bSMichal Simek * unsigned long address, 593ca54502bSMichal Simek * unsigned long error_code) 594ca54502bSMichal Simek */ 595ca54502bSMichal Simek/* data and intruction trap - which is choose is resolved int fault.c */ 596ca54502bSMichal SimekC_ENTRY(page_fault_data_trap): 597ca54502bSMichal Simek SAVE_STATE /* Save registers.*/ 59806a54604SMichal Simek /* PC, before IRQ/trap - this is one instruction above */ 5996e83557cSMichal Simek swi r17, r1, PT_PC; 60006a54604SMichal Simek tovirt(r1,r1) 601ca54502bSMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 602b9ea77e2SMichal Simek addik r15, r0, ret_from_exc-8 603ca54502bSMichal Simek mfs r6, rear /* parameter unsigned long address */ 604ca54502bSMichal Simek mfs r7, resr /* parameter unsigned long error_code */ 605c318d483SMichal Simek rted r0, do_page_fault 6066e83557cSMichal Simek addik r5, r1, 0 /* parameter struct pt_regs * regs */ 607ca54502bSMichal Simek 608ca54502bSMichal SimekC_ENTRY(page_fault_instr_trap): 609ca54502bSMichal Simek SAVE_STATE /* Save registers.*/ 61006a54604SMichal Simek /* PC, before IRQ/trap - this is one instruction above */ 6116e83557cSMichal Simek swi r17, r1, PT_PC; 61206a54604SMichal Simek tovirt(r1,r1) 613ca54502bSMichal Simek /* where the trap should return need -8 to adjust for rtsd r15, 8 */ 614b9ea77e2SMichal Simek addik r15, r0, ret_from_exc-8 615ca54502bSMichal Simek mfs r6, rear /* parameter unsigned long address */ 616ca54502bSMichal Simek ori r7, r0, 0 /* parameter unsigned long error_code */ 6179814cc11SMichal Simek rted r0, do_page_fault 6186e83557cSMichal Simek addik r5, r1, 0 /* parameter struct pt_regs * regs */ 619ca54502bSMichal Simek 620ca54502bSMichal Simek/* Entry point used to return from an exception. */ 621ca54502bSMichal SimekC_ENTRY(ret_from_exc): 6226e83557cSMichal Simek lwi r11, r1, PT_MODE; 623ca54502bSMichal Simek bnei r11, 2f; /* See if returning to kernel mode, */ 624ca54502bSMichal Simek /* ... if so, skip resched &c. */ 625ca54502bSMichal Simek 626ca54502bSMichal Simek /* We're returning to user mode, so check for various conditions that 627ca54502bSMichal Simek trigger rescheduling. */ 628e9f92526SAl Viro1: 629b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 630e9f92526SAl Viro lwi r19, r11, TI_FLAGS; /* get flags in thread info */ 631e9f92526SAl Viro andi r11, r19, _TIF_NEED_RESCHED; 632ca54502bSMichal Simek beqi r11, 5f; 633ca54502bSMichal Simek 634ca54502bSMichal Simek/* Call the scheduler before returning from a syscall/trap. */ 635ca54502bSMichal Simek bralid r15, schedule; /* Call scheduler */ 636ca54502bSMichal Simek nop; /* delay slot */ 637e9f92526SAl Viro bri 1b 638ca54502bSMichal Simek 639ca54502bSMichal Simek /* Maybe handle a signal */ 640e9f92526SAl Viro5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; 641e9f92526SAl Viro beqi r11, 4f; /* Signals to handle, handle them */ 642ca54502bSMichal Simek 643ca54502bSMichal Simek /* 644ca54502bSMichal Simek * Handle a signal return; Pending signals should be in r18. 645ca54502bSMichal Simek * 646ca54502bSMichal Simek * Not all registers are saved by the normal trap/interrupt entry 647ca54502bSMichal Simek * points (for instance, call-saved registers (because the normal 648ca54502bSMichal Simek * C-compiler calling sequence in the kernel makes sure they're 649ca54502bSMichal Simek * preserved), and call-clobbered registers in the case of 650ca54502bSMichal Simek * traps), but signal handlers may want to examine or change the 651ca54502bSMichal Simek * complete register state. Here we save anything not saved by 652ca54502bSMichal Simek * the normal entry sequence, so that it may be safely restored 653969a9616SAl Viro * (in a possibly modified form) after do_notify_resume returns. */ 6546e83557cSMichal Simek addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 655969a9616SAl Viro bralid r15, do_notify_resume; /* Handle any signals */ 65683140191SAl Viro addi r6, r0, 0; /* Arg 2: int in_syscall */ 657e9f92526SAl Viro bri 1b 658ca54502bSMichal Simek 659ca54502bSMichal Simek/* Finally, return to user state. */ 660e9f92526SAl Viro4: set_bip; /* Ints masked for state restore */ 6618633bebcSMichal Simek swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ 662ca54502bSMichal Simek VM_OFF; 663ca54502bSMichal Simek tophys(r1,r1); 664ca54502bSMichal Simek 66514ef905bSMichal Simek RESTORE_REGS_RTBD; 6666e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space. */ 667ca54502bSMichal Simek 668ca54502bSMichal Simek lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */ 669ca54502bSMichal Simek bri 6f; 670ca54502bSMichal Simek/* Return to kernel state. */ 67196014cc3SMichal Simek2: set_bip; /* Ints masked for state restore */ 67296014cc3SMichal Simek VM_OFF; 673ca54502bSMichal Simek tophys(r1,r1); 67414ef905bSMichal Simek RESTORE_REGS_RTBD; 6756e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space. */ 676ca54502bSMichal Simek 677ca54502bSMichal Simek tovirt(r1,r1); 678ca54502bSMichal Simek6: 679ca54502bSMichal SimekEXC_return: /* Make global symbol for debugging */ 680ca54502bSMichal Simek rtbd r14, 0; /* Instructions to return from an IRQ */ 681ca54502bSMichal Simek nop; 682ca54502bSMichal Simek 683ca54502bSMichal Simek/* 684ca54502bSMichal Simek * HW EXCEPTION rutine end 685ca54502bSMichal Simek */ 686ca54502bSMichal Simek 687ca54502bSMichal Simek/* 688ca54502bSMichal Simek * Hardware maskable interrupts. 689ca54502bSMichal Simek * 690ca54502bSMichal Simek * The stack-pointer (r1) should have already been saved to the memory 691ca54502bSMichal Simek * location PER_CPU(ENTRY_SP). 692ca54502bSMichal Simek */ 693ca54502bSMichal SimekC_ENTRY(_interrupt): 694ca54502bSMichal Simek/* MS: we are in physical address */ 695ca54502bSMichal Simek/* Save registers, switch to proper stack, convert SP to virtual.*/ 696ca54502bSMichal Simek swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) 697ca54502bSMichal Simek /* MS: See if already in kernel mode. */ 698653e447eSMichal Simek mfs r1, rmsr 6995c0d72b1SMichal Simek nop 700653e447eSMichal Simek andi r1, r1, MSR_UMS 701653e447eSMichal Simek bnei r1, 1f 702ca54502bSMichal Simek 703ca54502bSMichal Simek/* Kernel-mode state save. */ 704653e447eSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) 705653e447eSMichal Simek tophys(r1,r1); /* MS: I have in r1 physical address where stack is */ 706ca54502bSMichal Simek /* save registers */ 707ca54502bSMichal Simek/* MS: Make room on the stack -> activation record */ 7086e83557cSMichal Simek addik r1, r1, -PT_SIZE; 709ca54502bSMichal Simek SAVE_REGS 710ca54502bSMichal Simek brid 2f; 7116e83557cSMichal Simek swi r1, r1, PT_MODE; /* 0 - user mode, 1 - kernel mode */ 712ca54502bSMichal Simek1: 713ca54502bSMichal Simek/* User-mode state save. */ 714ca54502bSMichal Simek /* MS: get the saved current */ 715ca54502bSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 716ca54502bSMichal Simek tophys(r1,r1); 717ca54502bSMichal Simek lwi r1, r1, TS_THREAD_INFO; 718ca54502bSMichal Simek addik r1, r1, THREAD_SIZE; 719ca54502bSMichal Simek tophys(r1,r1); 720ca54502bSMichal Simek /* save registers */ 7216e83557cSMichal Simek addik r1, r1, -PT_SIZE; 722ca54502bSMichal Simek SAVE_REGS 723ca54502bSMichal Simek /* calculate mode */ 7246e83557cSMichal Simek swi r0, r1, PT_MODE; 725ca54502bSMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 7266e83557cSMichal Simek swi r11, r1, PT_R1; 72780c5ff6bSMichal Simek clear_ums; 728ca54502bSMichal Simek2: 729b1d70c62SMichal Simek lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 730ca54502bSMichal Simek tovirt(r1,r1) 731b9ea77e2SMichal Simek addik r15, r0, irq_call; 73280c5ff6bSMichal Simekirq_call:rtbd r0, do_IRQ; 7336e83557cSMichal Simek addik r5, r1, 0; 734ca54502bSMichal Simek 735ca54502bSMichal Simek/* MS: we are in virtual mode */ 736ca54502bSMichal Simekret_from_irq: 7376e83557cSMichal Simek lwi r11, r1, PT_MODE; 738ca54502bSMichal Simek bnei r11, 2f; 739ca54502bSMichal Simek 740e9f92526SAl Viro1: 741b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; 742e9f92526SAl Viro lwi r19, r11, TI_FLAGS; /* MS: get flags from thread info */ 743e9f92526SAl Viro andi r11, r19, _TIF_NEED_RESCHED; 744ca54502bSMichal Simek beqi r11, 5f 745ca54502bSMichal Simek bralid r15, schedule; 746ca54502bSMichal Simek nop; /* delay slot */ 747e9f92526SAl Viro bri 1b 748ca54502bSMichal Simek 749ca54502bSMichal Simek /* Maybe handle a signal */ 750e9f92526SAl Viro5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; 751ca54502bSMichal Simek beqid r11, no_intr_resched 752ca54502bSMichal Simek/* Handle a signal return; Pending signals should be in r18. */ 7536e83557cSMichal Simek addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 754969a9616SAl Viro bralid r15, do_notify_resume; /* Handle any signals */ 75583140191SAl Viro addi r6, r0, 0; /* Arg 2: int in_syscall */ 756e9f92526SAl Viro bri 1b 757ca54502bSMichal Simek 758ca54502bSMichal Simek/* Finally, return to user state. */ 759ca54502bSMichal Simekno_intr_resched: 760ca54502bSMichal Simek /* Disable interrupts, we are now committed to the state restore */ 761ca54502bSMichal Simek disable_irq 7628633bebcSMichal Simek swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); 763ca54502bSMichal Simek VM_OFF; 764ca54502bSMichal Simek tophys(r1,r1); 765ca54502bSMichal Simek RESTORE_REGS 7666e83557cSMichal Simek addik r1, r1, PT_SIZE /* MS: Clean up stack space. */ 767ca54502bSMichal Simek lwi r1, r1, PT_R1 - PT_SIZE; 768ca54502bSMichal Simek bri 6f; 769ca54502bSMichal Simek/* MS: Return to kernel state. */ 77077753790SMichal Simek2: 77118803733SThomas Gleixner#ifdef CONFIG_PREEMPTION 772b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; 77377753790SMichal Simek /* MS: get preempt_count from thread info */ 77477753790SMichal Simek lwi r5, r11, TI_PREEMPT_COUNT; 77577753790SMichal Simek bgti r5, restore; 77677753790SMichal Simek 77777753790SMichal Simek lwi r5, r11, TI_FLAGS; /* get flags in thread info */ 77877753790SMichal Simek andi r5, r5, _TIF_NEED_RESCHED; 77977753790SMichal Simek beqi r5, restore /* if zero jump over */ 78077753790SMichal Simek 78177753790SMichal Simek /* interrupts are off that's why I am calling preempt_chedule_irq */ 78277753790SMichal Simek bralid r15, preempt_schedule_irq 78377753790SMichal Simek nop 78477753790SMichal Simekrestore: 78577753790SMichal Simek#endif 78677753790SMichal Simek VM_OFF /* MS: turn off MMU */ 787ca54502bSMichal Simek tophys(r1,r1) 788ca54502bSMichal Simek RESTORE_REGS 7896e83557cSMichal Simek addik r1, r1, PT_SIZE /* MS: Clean up stack space. */ 790ca54502bSMichal Simek tovirt(r1,r1); 791ca54502bSMichal Simek6: 792ca54502bSMichal SimekIRQ_return: /* MS: Make global symbol for debugging */ 793ca54502bSMichal Simek rtid r14, 0 794ca54502bSMichal Simek nop 795ca54502bSMichal Simek 79688707ebeSAppana Durga Kedareswara rao#ifdef CONFIG_MB_MANAGER 79788707ebeSAppana Durga Kedareswara rao 79888707ebeSAppana Durga Kedareswara rao#define PT_PID PT_SIZE 79988707ebeSAppana Durga Kedareswara rao#define PT_TLBI PT_SIZE + 4 80088707ebeSAppana Durga Kedareswara rao#define PT_ZPR PT_SIZE + 8 80188707ebeSAppana Durga Kedareswara rao#define PT_TLBL0 PT_SIZE + 12 80288707ebeSAppana Durga Kedareswara rao#define PT_TLBH0 PT_SIZE + 16 80388707ebeSAppana Durga Kedareswara rao 80488707ebeSAppana Durga Kedareswara raoC_ENTRY(_xtmr_manager_reset): 80588707ebeSAppana Durga Kedareswara rao lwi r1, r0, xmb_manager_stackpointer 80688707ebeSAppana Durga Kedareswara rao 80788707ebeSAppana Durga Kedareswara rao /* Restore MSR */ 80888707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_MSR 80988707ebeSAppana Durga Kedareswara rao mts rmsr, r2 81088707ebeSAppana Durga Kedareswara rao bri 4 81188707ebeSAppana Durga Kedareswara rao 81288707ebeSAppana Durga Kedareswara rao /* restore Special purpose registers */ 81388707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_PID 81488707ebeSAppana Durga Kedareswara rao mts rpid, r2 81588707ebeSAppana Durga Kedareswara rao 81688707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_TLBI 81788707ebeSAppana Durga Kedareswara rao mts rtlbx, r2 81888707ebeSAppana Durga Kedareswara rao 81988707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_ZPR 82088707ebeSAppana Durga Kedareswara rao mts rzpr, r2 82188707ebeSAppana Durga Kedareswara rao 82288707ebeSAppana Durga Kedareswara rao#if CONFIG_XILINX_MICROBLAZE0_USE_FPU 82388707ebeSAppana Durga Kedareswara rao lwi r2, r1, PT_FSR 82488707ebeSAppana Durga Kedareswara rao mts rfsr, r2 82588707ebeSAppana Durga Kedareswara rao#endif 82688707ebeSAppana Durga Kedareswara rao 82788707ebeSAppana Durga Kedareswara rao /* restore all the tlb's */ 82888707ebeSAppana Durga Kedareswara rao addik r3, r0, TOPHYS(tlb_skip) 82988707ebeSAppana Durga Kedareswara rao addik r6, r0, PT_TLBL0 83088707ebeSAppana Durga Kedareswara rao addik r7, r0, PT_TLBH0 83188707ebeSAppana Durga Kedareswara raorestore_tlb: 83288707ebeSAppana Durga Kedareswara rao add r6, r6, r1 83388707ebeSAppana Durga Kedareswara rao add r7, r7, r1 83488707ebeSAppana Durga Kedareswara rao lwi r2, r6, 0 83588707ebeSAppana Durga Kedareswara rao mts rtlblo, r2 83688707ebeSAppana Durga Kedareswara rao lwi r2, r7, 0 83788707ebeSAppana Durga Kedareswara rao mts rtlbhi, r2 83888707ebeSAppana Durga Kedareswara rao addik r6, r6, 4 83988707ebeSAppana Durga Kedareswara rao addik r7, r7, 4 84088707ebeSAppana Durga Kedareswara rao bgtid r3, restore_tlb 84188707ebeSAppana Durga Kedareswara rao addik r3, r3, -1 84288707ebeSAppana Durga Kedareswara rao 84388707ebeSAppana Durga Kedareswara rao lwi r5, r0, TOPHYS(xmb_manager_dev) 84488707ebeSAppana Durga Kedareswara rao lwi r8, r0, TOPHYS(xmb_manager_reset_callback) 84588707ebeSAppana Durga Kedareswara rao set_vms 84688707ebeSAppana Durga Kedareswara rao /* return from reset need -8 to adjust for rtsd r15, 8 */ 84788707ebeSAppana Durga Kedareswara rao addik r15, r0, ret_from_reset - 8 84888707ebeSAppana Durga Kedareswara rao rtbd r8, 0 84988707ebeSAppana Durga Kedareswara rao nop 85088707ebeSAppana Durga Kedareswara rao 85188707ebeSAppana Durga Kedareswara raoret_from_reset: 85288707ebeSAppana Durga Kedareswara rao set_bip /* Ints masked for state restore */ 85388707ebeSAppana Durga Kedareswara rao VM_OFF 85488707ebeSAppana Durga Kedareswara rao /* MS: Restore all regs */ 85588707ebeSAppana Durga Kedareswara rao RESTORE_REGS 85688707ebeSAppana Durga Kedareswara rao lwi r14, r1, PT_R14 85788707ebeSAppana Durga Kedareswara rao lwi r16, r1, PT_PC 85888707ebeSAppana Durga Kedareswara rao addik r1, r1, PT_SIZE + 36 85988707ebeSAppana Durga Kedareswara rao rtbd r16, 0 86088707ebeSAppana Durga Kedareswara rao nop 86188707ebeSAppana Durga Kedareswara rao 86288707ebeSAppana Durga Kedareswara rao/* 86388707ebeSAppana Durga Kedareswara rao * Break handler for MB Manager. Enter to _xmb_manager_break by 86488707ebeSAppana Durga Kedareswara rao * injecting fault in one of the TMR Microblaze core. 86588707ebeSAppana Durga Kedareswara rao * FIXME: This break handler supports getting 86688707ebeSAppana Durga Kedareswara rao * called from kernel space only. 86788707ebeSAppana Durga Kedareswara rao */ 86888707ebeSAppana Durga Kedareswara raoC_ENTRY(_xmb_manager_break): 86988707ebeSAppana Durga Kedareswara rao /* 87088707ebeSAppana Durga Kedareswara rao * Reserve memory in the stack for context store/restore 87188707ebeSAppana Durga Kedareswara rao * (which includes memory for storing tlbs (max two tlbs)) 87288707ebeSAppana Durga Kedareswara rao */ 87388707ebeSAppana Durga Kedareswara rao addik r1, r1, -PT_SIZE - 36 87488707ebeSAppana Durga Kedareswara rao swi r1, r0, xmb_manager_stackpointer 87588707ebeSAppana Durga Kedareswara rao SAVE_REGS 87688707ebeSAppana Durga Kedareswara rao swi r14, r1, PT_R14 /* rewrite saved R14 value */ 87788707ebeSAppana Durga Kedareswara rao swi r16, r1, PT_PC; /* PC and r16 are the same */ 87888707ebeSAppana Durga Kedareswara rao 87988707ebeSAppana Durga Kedareswara rao lwi r6, r0, TOPHYS(xmb_manager_baseaddr) 88088707ebeSAppana Durga Kedareswara rao lwi r7, r0, TOPHYS(xmb_manager_crval) 88188707ebeSAppana Durga Kedareswara rao /* 88288707ebeSAppana Durga Kedareswara rao * When the break vector gets asserted because of error injection, 88388707ebeSAppana Durga Kedareswara rao * the break signal must be blocked before exiting from the 88488707ebeSAppana Durga Kedareswara rao * break handler, below code configures the tmr manager 88588707ebeSAppana Durga Kedareswara rao * control register to block break signal. 88688707ebeSAppana Durga Kedareswara rao */ 88788707ebeSAppana Durga Kedareswara rao swi r7, r6, 0 88888707ebeSAppana Durga Kedareswara rao 88988707ebeSAppana Durga Kedareswara rao /* Save the special purpose registers */ 89088707ebeSAppana Durga Kedareswara rao mfs r2, rpid 89188707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_PID 89288707ebeSAppana Durga Kedareswara rao 89388707ebeSAppana Durga Kedareswara rao mfs r2, rtlbx 89488707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_TLBI 89588707ebeSAppana Durga Kedareswara rao 89688707ebeSAppana Durga Kedareswara rao mfs r2, rzpr 89788707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_ZPR 89888707ebeSAppana Durga Kedareswara rao 89988707ebeSAppana Durga Kedareswara rao#if CONFIG_XILINX_MICROBLAZE0_USE_FPU 90088707ebeSAppana Durga Kedareswara rao mfs r2, rfsr 90188707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_FSR 90288707ebeSAppana Durga Kedareswara rao#endif 90388707ebeSAppana Durga Kedareswara rao mfs r2, rmsr 90488707ebeSAppana Durga Kedareswara rao swi r2, r1, PT_MSR 90588707ebeSAppana Durga Kedareswara rao 90688707ebeSAppana Durga Kedareswara rao /* Save all the tlb's */ 90788707ebeSAppana Durga Kedareswara rao addik r3, r0, TOPHYS(tlb_skip) 90888707ebeSAppana Durga Kedareswara rao addik r6, r0, PT_TLBL0 90988707ebeSAppana Durga Kedareswara rao addik r7, r0, PT_TLBH0 91088707ebeSAppana Durga Kedareswara raosave_tlb: 91188707ebeSAppana Durga Kedareswara rao add r6, r6, r1 91288707ebeSAppana Durga Kedareswara rao add r7, r7, r1 91388707ebeSAppana Durga Kedareswara rao mfs r2, rtlblo 91488707ebeSAppana Durga Kedareswara rao swi r2, r6, 0 91588707ebeSAppana Durga Kedareswara rao mfs r2, rtlbhi 91688707ebeSAppana Durga Kedareswara rao swi r2, r7, 0 91788707ebeSAppana Durga Kedareswara rao addik r6, r6, 4 91888707ebeSAppana Durga Kedareswara rao addik r7, r7, 4 91988707ebeSAppana Durga Kedareswara rao bgtid r3, save_tlb 92088707ebeSAppana Durga Kedareswara rao addik r3, r3, -1 92188707ebeSAppana Durga Kedareswara rao 92288707ebeSAppana Durga Kedareswara rao lwi r5, r0, TOPHYS(xmb_manager_dev) 92388707ebeSAppana Durga Kedareswara rao lwi r8, r0, TOPHYS(xmb_manager_callback) 92488707ebeSAppana Durga Kedareswara rao /* return from break need -8 to adjust for rtsd r15, 8 */ 92588707ebeSAppana Durga Kedareswara rao addik r15, r0, ret_from_break - 8 92688707ebeSAppana Durga Kedareswara rao rtbd r8, 0 92788707ebeSAppana Durga Kedareswara rao nop 92888707ebeSAppana Durga Kedareswara rao 92988707ebeSAppana Durga Kedareswara raoret_from_break: 93088707ebeSAppana Durga Kedareswara rao /* flush the d-cache */ 93188707ebeSAppana Durga Kedareswara rao bralid r15, mb_flush_dcache 93288707ebeSAppana Durga Kedareswara rao nop 93388707ebeSAppana Durga Kedareswara rao 93488707ebeSAppana Durga Kedareswara rao /* 93588707ebeSAppana Durga Kedareswara rao * To make sure microblaze i-cache is in a proper state 93688707ebeSAppana Durga Kedareswara rao * invalidate the i-cache. 93788707ebeSAppana Durga Kedareswara rao */ 93888707ebeSAppana Durga Kedareswara rao bralid r15, mb_invalidate_icache 93988707ebeSAppana Durga Kedareswara rao nop 94088707ebeSAppana Durga Kedareswara rao 94188707ebeSAppana Durga Kedareswara rao set_bip; /* Ints masked for state restore */ 94288707ebeSAppana Durga Kedareswara rao VM_OFF; 94388707ebeSAppana Durga Kedareswara rao mbar 1 94488707ebeSAppana Durga Kedareswara rao mbar 2 94588707ebeSAppana Durga Kedareswara rao bri 4 94688707ebeSAppana Durga Kedareswara rao suspend 94788707ebeSAppana Durga Kedareswara rao nop 94888707ebeSAppana Durga Kedareswara rao#endif 94988707ebeSAppana Durga Kedareswara rao 950ca54502bSMichal Simek/* 9512d5973cbSMichal Simek * Debug trap for KGDB. Enter to _debug_exception by brki r16, 0x18 9522d5973cbSMichal Simek * and call handling function with saved pt_regs 953ca54502bSMichal Simek */ 954ca54502bSMichal SimekC_ENTRY(_debug_exception): 955ca54502bSMichal Simek /* BIP bit is set on entry, no interrupts can occur */ 956ca54502bSMichal Simek swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) 957ca54502bSMichal Simek 958653e447eSMichal Simek mfs r1, rmsr 9595c0d72b1SMichal Simek nop 960653e447eSMichal Simek andi r1, r1, MSR_UMS 961653e447eSMichal Simek bnei r1, 1f 9622d5973cbSMichal Simek/* MS: Kernel-mode state save - kgdb */ 963653e447eSMichal Simek lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/ 964ca54502bSMichal Simek 9652d5973cbSMichal Simek /* BIP bit is set on entry, no interrupts can occur */ 9666e83557cSMichal Simek addik r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; 967ca54502bSMichal Simek SAVE_REGS; 9682d5973cbSMichal Simek /* save all regs to pt_reg structure */ 9696e83557cSMichal Simek swi r0, r1, PT_R0; /* R0 must be saved too */ 9706e83557cSMichal Simek swi r14, r1, PT_R14 /* rewrite saved R14 value */ 9716e83557cSMichal Simek swi r16, r1, PT_PC; /* PC and r16 are the same */ 9722d5973cbSMichal Simek /* save special purpose registers to pt_regs */ 9732d5973cbSMichal Simek mfs r11, rear; 9746e83557cSMichal Simek swi r11, r1, PT_EAR; 9752d5973cbSMichal Simek mfs r11, resr; 9766e83557cSMichal Simek swi r11, r1, PT_ESR; 9772d5973cbSMichal Simek mfs r11, rfsr; 9786e83557cSMichal Simek swi r11, r1, PT_FSR; 979ca54502bSMichal Simek 9802d5973cbSMichal Simek /* stack pointer is in physical address at it is decrease 9816e83557cSMichal Simek * by PT_SIZE but we need to get correct R1 value */ 9826e83557cSMichal Simek addik r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + PT_SIZE; 9836e83557cSMichal Simek swi r11, r1, PT_R1 9842d5973cbSMichal Simek /* MS: r31 - current pointer isn't changed */ 9852d5973cbSMichal Simek tovirt(r1,r1) 9862d5973cbSMichal Simek#ifdef CONFIG_KGDB 9876e83557cSMichal Simek addi r5, r1, 0 /* pass pt_reg address as the first arg */ 988cd341577SMichal Simek addik r15, r0, dbtrap_call; /* return address */ 9892d5973cbSMichal Simek rtbd r0, microblaze_kgdb_break 9902d5973cbSMichal Simek nop; 9912d5973cbSMichal Simek#endif 9922d5973cbSMichal Simek /* MS: Place handler for brki from kernel space if KGDB is OFF. 9932d5973cbSMichal Simek * It is very unlikely that another brki instruction is called. */ 9942d5973cbSMichal Simek bri 0 9952d5973cbSMichal Simek 9962d5973cbSMichal Simek/* MS: User-mode state save - gdb */ 9972d5973cbSMichal Simek1: lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */ 998ca54502bSMichal Simek tophys(r1,r1); 999ca54502bSMichal Simek lwi r1, r1, TS_THREAD_INFO; /* get the thread info */ 1000ca54502bSMichal Simek addik r1, r1, THREAD_SIZE; /* calculate kernel stack pointer */ 1001ca54502bSMichal Simek tophys(r1,r1); 1002ca54502bSMichal Simek 10036e83557cSMichal Simek addik r1, r1, -PT_SIZE; /* Make room on the stack. */ 1004ca54502bSMichal Simek SAVE_REGS; 10056e83557cSMichal Simek swi r16, r1, PT_PC; /* Save LP */ 10066e83557cSMichal Simek swi r0, r1, PT_MODE; /* Was in user-mode. */ 1007ca54502bSMichal Simek lwi r11, r0, TOPHYS(PER_CPU(ENTRY_SP)); 10086e83557cSMichal Simek swi r11, r1, PT_R1; /* Store user SP. */ 10092d5973cbSMichal Simek lwi CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); 1010ca54502bSMichal Simek tovirt(r1,r1) 101106b28640SMichal Simek set_vms; 10126e83557cSMichal Simek addik r5, r1, 0; 1013b9ea77e2SMichal Simek addik r15, r0, dbtrap_call; 10142d5973cbSMichal Simekdbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ 1015751f1605SMichal Simek rtbd r0, sw_exception 1016751f1605SMichal Simek nop 1017ca54502bSMichal Simek 10182d5973cbSMichal Simek /* MS: The first instruction for the second part of the gdb/kgdb */ 1019ca54502bSMichal Simek set_bip; /* Ints masked for state restore */ 10206e83557cSMichal Simek lwi r11, r1, PT_MODE; 1021ca54502bSMichal Simek bnei r11, 2f; 10222d5973cbSMichal Simek/* MS: Return to user space - gdb */ 1023e9f92526SAl Viro1: 1024ca54502bSMichal Simek /* Get current task ptr into r11 */ 1025b1d70c62SMichal Simek lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ 1026e9f92526SAl Viro lwi r19, r11, TI_FLAGS; /* get flags in thread info */ 1027e9f92526SAl Viro andi r11, r19, _TIF_NEED_RESCHED; 1028ca54502bSMichal Simek beqi r11, 5f; 1029ca54502bSMichal Simek 1030ca54502bSMichal Simek /* Call the scheduler before returning from a syscall/trap. */ 1031ca54502bSMichal Simek bralid r15, schedule; /* Call scheduler */ 1032ca54502bSMichal Simek nop; /* delay slot */ 1033e9f92526SAl Viro bri 1b 1034ca54502bSMichal Simek 1035ca54502bSMichal Simek /* Maybe handle a signal */ 1036e9f92526SAl Viro5: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; 1037e9f92526SAl Viro beqi r11, 4f; /* Signals to handle, handle them */ 1038ca54502bSMichal Simek 10396e83557cSMichal Simek addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ 1040969a9616SAl Viro bralid r15, do_notify_resume; /* Handle any signals */ 104183140191SAl Viro addi r6, r0, 0; /* Arg 2: int in_syscall */ 1042e9f92526SAl Viro bri 1b 1043ca54502bSMichal Simek 1044ca54502bSMichal Simek/* Finally, return to user state. */ 1045e9f92526SAl Viro4: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ 1046ca54502bSMichal Simek VM_OFF; 1047ca54502bSMichal Simek tophys(r1,r1); 10482d5973cbSMichal Simek /* MS: Restore all regs */ 104914ef905bSMichal Simek RESTORE_REGS_RTBD 10506e83557cSMichal Simek addik r1, r1, PT_SIZE /* Clean up stack space */ 10512d5973cbSMichal Simek lwi r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */ 10522d5973cbSMichal SimekDBTRAP_return_user: /* MS: Make global symbol for debugging */ 10532d5973cbSMichal Simek rtbd r16, 0; /* MS: Instructions to return from a debug trap */ 10542d5973cbSMichal Simek nop; 1055ca54502bSMichal Simek 10562d5973cbSMichal Simek/* MS: Return to kernel state - kgdb */ 1057ca54502bSMichal Simek2: VM_OFF; 1058ca54502bSMichal Simek tophys(r1,r1); 10592d5973cbSMichal Simek /* MS: Restore all regs */ 106014ef905bSMichal Simek RESTORE_REGS_RTBD 10616e83557cSMichal Simek lwi r14, r1, PT_R14; 10626e83557cSMichal Simek lwi r16, r1, PT_PC; 10636e83557cSMichal Simek addik r1, r1, PT_SIZE; /* MS: Clean up stack space */ 1064ca54502bSMichal Simek tovirt(r1,r1); 10652d5973cbSMichal SimekDBTRAP_return_kernel: /* MS: Make global symbol for debugging */ 10662d5973cbSMichal Simek rtbd r16, 0; /* MS: Instructions to return from a debug trap */ 1067ca54502bSMichal Simek nop; 1068ca54502bSMichal Simek 1069ca54502bSMichal Simek 1070ca54502bSMichal SimekENTRY(_switch_to) 1071ca54502bSMichal Simek /* prepare return value */ 1072b1d70c62SMichal Simek addk r3, r0, CURRENT_TASK 1073ca54502bSMichal Simek 1074ca54502bSMichal Simek /* save registers in cpu_context */ 1075ca54502bSMichal Simek /* use r11 and r12, volatile registers, as temp register */ 1076ca54502bSMichal Simek /* give start of cpu_context for previous process */ 1077ca54502bSMichal Simek addik r11, r5, TI_CPU_CONTEXT 1078ca54502bSMichal Simek swi r1, r11, CC_R1 1079ca54502bSMichal Simek swi r2, r11, CC_R2 1080ca54502bSMichal Simek /* skip volatile registers. 1081ca54502bSMichal Simek * they are saved on stack when we jumped to _switch_to() */ 1082ca54502bSMichal Simek /* dedicated registers */ 1083ca54502bSMichal Simek swi r13, r11, CC_R13 1084ca54502bSMichal Simek swi r14, r11, CC_R14 1085ca54502bSMichal Simek swi r15, r11, CC_R15 1086ca54502bSMichal Simek swi r16, r11, CC_R16 1087ca54502bSMichal Simek swi r17, r11, CC_R17 1088ca54502bSMichal Simek swi r18, r11, CC_R18 1089ca54502bSMichal Simek /* save non-volatile registers */ 1090ca54502bSMichal Simek swi r19, r11, CC_R19 1091ca54502bSMichal Simek swi r20, r11, CC_R20 1092ca54502bSMichal Simek swi r21, r11, CC_R21 1093ca54502bSMichal Simek swi r22, r11, CC_R22 1094ca54502bSMichal Simek swi r23, r11, CC_R23 1095ca54502bSMichal Simek swi r24, r11, CC_R24 1096ca54502bSMichal Simek swi r25, r11, CC_R25 1097ca54502bSMichal Simek swi r26, r11, CC_R26 1098ca54502bSMichal Simek swi r27, r11, CC_R27 1099ca54502bSMichal Simek swi r28, r11, CC_R28 1100ca54502bSMichal Simek swi r29, r11, CC_R29 1101ca54502bSMichal Simek swi r30, r11, CC_R30 1102ca54502bSMichal Simek /* special purpose registers */ 1103ca54502bSMichal Simek mfs r12, rmsr 1104ca54502bSMichal Simek swi r12, r11, CC_MSR 1105ca54502bSMichal Simek mfs r12, rear 1106ca54502bSMichal Simek swi r12, r11, CC_EAR 1107ca54502bSMichal Simek mfs r12, resr 1108ca54502bSMichal Simek swi r12, r11, CC_ESR 1109ca54502bSMichal Simek mfs r12, rfsr 1110ca54502bSMichal Simek swi r12, r11, CC_FSR 1111ca54502bSMichal Simek 1112b1d70c62SMichal Simek /* update r31, the current-give me pointer to task which will be next */ 1113b1d70c62SMichal Simek lwi CURRENT_TASK, r6, TI_TASK 1114ca54502bSMichal Simek /* stored it to current_save too */ 1115b1d70c62SMichal Simek swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE) 1116ca54502bSMichal Simek 1117ca54502bSMichal Simek /* get new process' cpu context and restore */ 1118ca54502bSMichal Simek /* give me start where start context of next task */ 1119ca54502bSMichal Simek addik r11, r6, TI_CPU_CONTEXT 1120ca54502bSMichal Simek 1121ca54502bSMichal Simek /* non-volatile registers */ 1122ca54502bSMichal Simek lwi r30, r11, CC_R30 1123ca54502bSMichal Simek lwi r29, r11, CC_R29 1124ca54502bSMichal Simek lwi r28, r11, CC_R28 1125ca54502bSMichal Simek lwi r27, r11, CC_R27 1126ca54502bSMichal Simek lwi r26, r11, CC_R26 1127ca54502bSMichal Simek lwi r25, r11, CC_R25 1128ca54502bSMichal Simek lwi r24, r11, CC_R24 1129ca54502bSMichal Simek lwi r23, r11, CC_R23 1130ca54502bSMichal Simek lwi r22, r11, CC_R22 1131ca54502bSMichal Simek lwi r21, r11, CC_R21 1132ca54502bSMichal Simek lwi r20, r11, CC_R20 1133ca54502bSMichal Simek lwi r19, r11, CC_R19 1134ca54502bSMichal Simek /* dedicated registers */ 1135ca54502bSMichal Simek lwi r18, r11, CC_R18 1136ca54502bSMichal Simek lwi r17, r11, CC_R17 1137ca54502bSMichal Simek lwi r16, r11, CC_R16 1138ca54502bSMichal Simek lwi r15, r11, CC_R15 1139ca54502bSMichal Simek lwi r14, r11, CC_R14 1140ca54502bSMichal Simek lwi r13, r11, CC_R13 1141ca54502bSMichal Simek /* skip volatile registers */ 1142ca54502bSMichal Simek lwi r2, r11, CC_R2 1143ca54502bSMichal Simek lwi r1, r11, CC_R1 1144ca54502bSMichal Simek 1145ca54502bSMichal Simek /* special purpose registers */ 1146ca54502bSMichal Simek lwi r12, r11, CC_FSR 1147ca54502bSMichal Simek mts rfsr, r12 1148ca54502bSMichal Simek lwi r12, r11, CC_MSR 1149ca54502bSMichal Simek mts rmsr, r12 1150ca54502bSMichal Simek 1151ca54502bSMichal Simek rtsd r15, 8 1152ca54502bSMichal Simek nop 1153ca54502bSMichal Simek 1154a5e3aaa6SAppana Durga Kedareswara rao#ifdef CONFIG_MB_MANAGER 1155*adc4cefaSAppana Durga Kedareswara rao.global xmb_inject_err 1156*adc4cefaSAppana Durga Kedareswara rao.section .text 1157*adc4cefaSAppana Durga Kedareswara rao.align 2 1158*adc4cefaSAppana Durga Kedareswara rao.ent xmb_inject_err 1159*adc4cefaSAppana Durga Kedareswara rao.type xmb_inject_err, @function 1160*adc4cefaSAppana Durga Kedareswara raoxmb_inject_err: 1161*adc4cefaSAppana Durga Kedareswara rao addik r1, r1, -PT_SIZE 1162*adc4cefaSAppana Durga Kedareswara rao SAVE_REGS 1163*adc4cefaSAppana Durga Kedareswara rao 1164*adc4cefaSAppana Durga Kedareswara rao /* Switch to real mode */ 1165*adc4cefaSAppana Durga Kedareswara rao VM_OFF; 1166*adc4cefaSAppana Durga Kedareswara rao set_bip; 1167*adc4cefaSAppana Durga Kedareswara rao mbar 1 1168*adc4cefaSAppana Durga Kedareswara rao mbar 2 1169*adc4cefaSAppana Durga Kedareswara rao bralid r15, XMB_INJECT_ERR_OFFSET 1170*adc4cefaSAppana Durga Kedareswara rao nop; 1171*adc4cefaSAppana Durga Kedareswara rao 1172*adc4cefaSAppana Durga Kedareswara rao /* enable virtual mode */ 1173*adc4cefaSAppana Durga Kedareswara rao set_vms; 1174*adc4cefaSAppana Durga Kedareswara rao /* barrier for instructions and data accesses */ 1175*adc4cefaSAppana Durga Kedareswara rao mbar 1 1176*adc4cefaSAppana Durga Kedareswara rao mbar 2 1177*adc4cefaSAppana Durga Kedareswara rao /* 1178*adc4cefaSAppana Durga Kedareswara rao * Enable Interrupts, Virtual Protected Mode, equalize 1179*adc4cefaSAppana Durga Kedareswara rao * initial state for all possible entries. 1180*adc4cefaSAppana Durga Kedareswara rao */ 1181*adc4cefaSAppana Durga Kedareswara rao rtbd r0, 1f 1182*adc4cefaSAppana Durga Kedareswara rao nop; 1183*adc4cefaSAppana Durga Kedareswara rao1: 1184*adc4cefaSAppana Durga Kedareswara rao RESTORE_REGS 1185*adc4cefaSAppana Durga Kedareswara rao addik r1, r1, PT_SIZE 1186*adc4cefaSAppana Durga Kedareswara rao rtsd r15, 8; 1187*adc4cefaSAppana Durga Kedareswara rao nop; 1188*adc4cefaSAppana Durga Kedareswara rao.end xmb_inject_err 1189*adc4cefaSAppana Durga Kedareswara rao 1190a5e3aaa6SAppana Durga Kedareswara rao.section .data 1191a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_dev 1192a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_baseaddr 1193a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_crval 1194a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_callback 1195a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_reset_callback 119688707ebeSAppana Durga Kedareswara rao.global xmb_manager_stackpointer 1197a5e3aaa6SAppana Durga Kedareswara rao.align 4 1198a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_dev: 1199a5e3aaa6SAppana Durga Kedareswara rao .long 0 1200a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_baseaddr: 1201a5e3aaa6SAppana Durga Kedareswara rao .long 0 1202a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_crval: 1203a5e3aaa6SAppana Durga Kedareswara rao .long 0 1204a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_callback: 1205a5e3aaa6SAppana Durga Kedareswara rao .long 0 1206a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_reset_callback: 1207a5e3aaa6SAppana Durga Kedareswara rao .long 0 120888707ebeSAppana Durga Kedareswara raoxmb_manager_stackpointer: 120988707ebeSAppana Durga Kedareswara rao .long 0 1210a5e3aaa6SAppana Durga Kedareswara rao 1211a5e3aaa6SAppana Durga Kedareswara rao/* 1212a5e3aaa6SAppana Durga Kedareswara rao * When the break vector gets asserted because of error injection, 1213a5e3aaa6SAppana Durga Kedareswara rao * the break signal must be blocked before exiting from the 1214a5e3aaa6SAppana Durga Kedareswara rao * break handler, Below api updates the manager address and 1215a5e3aaa6SAppana Durga Kedareswara rao * control register and error count callback arguments, 1216a5e3aaa6SAppana Durga Kedareswara rao * which will be used by the break handler to block the 1217a5e3aaa6SAppana Durga Kedareswara rao * break and call the callback function. 1218a5e3aaa6SAppana Durga Kedareswara rao */ 1219a5e3aaa6SAppana Durga Kedareswara rao.global xmb_manager_register 1220a5e3aaa6SAppana Durga Kedareswara rao.section .text 1221a5e3aaa6SAppana Durga Kedareswara rao.align 2 1222a5e3aaa6SAppana Durga Kedareswara rao.ent xmb_manager_register 1223a5e3aaa6SAppana Durga Kedareswara rao.type xmb_manager_register, @function 1224a5e3aaa6SAppana Durga Kedareswara raoxmb_manager_register: 1225a5e3aaa6SAppana Durga Kedareswara rao swi r5, r0, xmb_manager_baseaddr 1226a5e3aaa6SAppana Durga Kedareswara rao swi r6, r0, xmb_manager_crval 1227a5e3aaa6SAppana Durga Kedareswara rao swi r7, r0, xmb_manager_callback 1228a5e3aaa6SAppana Durga Kedareswara rao swi r8, r0, xmb_manager_dev 1229a5e3aaa6SAppana Durga Kedareswara rao swi r9, r0, xmb_manager_reset_callback 1230a5e3aaa6SAppana Durga Kedareswara rao 1231a5e3aaa6SAppana Durga Kedareswara rao rtsd r15, 8; 1232a5e3aaa6SAppana Durga Kedareswara rao nop; 1233a5e3aaa6SAppana Durga Kedareswara rao.end xmb_manager_register 1234a5e3aaa6SAppana Durga Kedareswara rao#endif 1235a5e3aaa6SAppana Durga Kedareswara rao 1236ca54502bSMichal SimekENTRY(_reset) 12375119c418SMichal Simek VM_OFF 12387574349cSMichal Simek brai 0; /* Jump to reset vector */ 1239ca54502bSMichal Simek 1240ca54502bSMichal Simek /* These are compiled and loaded into high memory, then 1241ca54502bSMichal Simek * copied into place in mach_early_setup */ 1242ca54502bSMichal Simek .section .init.ivt, "ax" 124388707ebeSAppana Durga Kedareswara rao#if CONFIG_MANUAL_RESET_VECTOR && !defined(CONFIG_MB_MANAGER) 1244ca54502bSMichal Simek .org 0x0 12450b9b0200SMichal Simek brai CONFIG_MANUAL_RESET_VECTOR 124688707ebeSAppana Durga Kedareswara rao#elif defined(CONFIG_MB_MANAGER) 124788707ebeSAppana Durga Kedareswara rao .org 0x0 124888707ebeSAppana Durga Kedareswara rao brai TOPHYS(_xtmr_manager_reset); 12490b9b0200SMichal Simek#endif 1250626afa35SMichal Simek .org 0x8 1251ca54502bSMichal Simek brai TOPHYS(_user_exception); /* syscall handler */ 1252626afa35SMichal Simek .org 0x10 1253ca54502bSMichal Simek brai TOPHYS(_interrupt); /* Interrupt handler */ 125488707ebeSAppana Durga Kedareswara rao#ifdef CONFIG_MB_MANAGER 125588707ebeSAppana Durga Kedareswara rao .org 0x18 125688707ebeSAppana Durga Kedareswara rao brai TOPHYS(_xmb_manager_break); /* microblaze manager break handler */ 125788707ebeSAppana Durga Kedareswara rao#else 1258626afa35SMichal Simek .org 0x18 1259ca54502bSMichal Simek brai TOPHYS(_debug_exception); /* debug trap handler */ 126088707ebeSAppana Durga Kedareswara rao#endif 1261626afa35SMichal Simek .org 0x20 1262751f1605SMichal Simek brai TOPHYS(_hw_exception_handler); /* HW exception handler */ 1263ca54502bSMichal Simek 1264*adc4cefaSAppana Durga Kedareswara rao#ifdef CONFIG_MB_MANAGER 1265*adc4cefaSAppana Durga Kedareswara rao /* 1266*adc4cefaSAppana Durga Kedareswara rao * For TMR Inject API which injects the error should 1267*adc4cefaSAppana Durga Kedareswara rao * be executed from LMB. 1268*adc4cefaSAppana Durga Kedareswara rao * TMR Inject is programmed with address of 0x200 so that 1269*adc4cefaSAppana Durga Kedareswara rao * when program counter matches with this address error will 1270*adc4cefaSAppana Durga Kedareswara rao * be injected. 0x200 is expected to be next available bram 1271*adc4cefaSAppana Durga Kedareswara rao * offset, hence used for this api. 1272*adc4cefaSAppana Durga Kedareswara rao */ 1273*adc4cefaSAppana Durga Kedareswara rao .org XMB_INJECT_ERR_OFFSET 1274*adc4cefaSAppana Durga Kedareswara raoxmb_inject_error: 1275*adc4cefaSAppana Durga Kedareswara rao nop 1276*adc4cefaSAppana Durga Kedareswara rao rtsd r15, 8 1277*adc4cefaSAppana Durga Kedareswara rao nop 1278*adc4cefaSAppana Durga Kedareswara rao#endif 1279*adc4cefaSAppana Durga Kedareswara rao 1280ca54502bSMichal Simek.section .rodata,"a" 1281ca54502bSMichal Simek#include "syscall_table.S" 1282ca54502bSMichal Simek 1283ca54502bSMichal Simeksyscall_table_size=(.-sys_call_table) 1284ca54502bSMichal Simek 1285ce3266c0SSteven J. Magnanitype_SYSCALL: 1286ce3266c0SSteven J. Magnani .ascii "SYSCALL\0" 1287ce3266c0SSteven J. Magnanitype_IRQ: 1288ce3266c0SSteven J. Magnani .ascii "IRQ\0" 1289ce3266c0SSteven J. Magnanitype_IRQ_PREEMPT: 1290ce3266c0SSteven J. Magnani .ascii "IRQ (PREEMPTED)\0" 1291ce3266c0SSteven J. Magnanitype_SYSCALL_PREEMPT: 1292ce3266c0SSteven J. Magnani .ascii " SYSCALL (PREEMPTED)\0" 1293ce3266c0SSteven J. Magnani 1294ce3266c0SSteven J. Magnani /* 1295ce3266c0SSteven J. Magnani * Trap decoding for stack unwinder 1296ce3266c0SSteven J. Magnani * Tuples are (start addr, end addr, string) 1297ce3266c0SSteven J. Magnani * If return address lies on [start addr, end addr], 1298ce3266c0SSteven J. Magnani * unwinder displays 'string' 1299ce3266c0SSteven J. Magnani */ 1300ce3266c0SSteven J. Magnani 1301ce3266c0SSteven J. Magnani .align 4 1302ce3266c0SSteven J. Magnani.global microblaze_trap_handlers 1303ce3266c0SSteven J. Magnanimicroblaze_trap_handlers: 1304ce3266c0SSteven J. Magnani /* Exact matches come first */ 1305ce3266c0SSteven J. Magnani .word ret_from_trap; .word ret_from_trap ; .word type_SYSCALL 1306ce3266c0SSteven J. Magnani .word ret_from_irq ; .word ret_from_irq ; .word type_IRQ 1307ce3266c0SSteven J. Magnani /* Fuzzy matches go here */ 1308ce3266c0SSteven J. Magnani .word ret_from_irq ; .word no_intr_resched ; .word type_IRQ_PREEMPT 1309ce3266c0SSteven J. Magnani .word ret_from_trap; .word TRAP_return ; .word type_SYSCALL_PREEMPT 1310ce3266c0SSteven J. Magnani /* End of table */ 1311ce3266c0SSteven J. Magnani .word 0 ; .word 0 ; .word 0 1312