18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Transactional memory support routines to reclaim and recheckpoint 48c2ecf20Sopenharmony_ci * transactional process state. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright 2012 Matt Evans & Michael Neuling, IBM Corporation. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 108c2ecf20Sopenharmony_ci#include <asm/ppc_asm.h> 118c2ecf20Sopenharmony_ci#include <asm/ppc-opcode.h> 128c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 138c2ecf20Sopenharmony_ci#include <asm/reg.h> 148c2ecf20Sopenharmony_ci#include <asm/bug.h> 158c2ecf20Sopenharmony_ci#include <asm/export.h> 168c2ecf20Sopenharmony_ci#include <asm/feature-fixups.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#ifdef CONFIG_VSX 198c2ecf20Sopenharmony_ci/* See fpu.S, this is borrowed from there */ 208c2ecf20Sopenharmony_ci#define __SAVE_32FPRS_VSRS(n,c,base) \ 218c2ecf20Sopenharmony_ciBEGIN_FTR_SECTION \ 228c2ecf20Sopenharmony_ci b 2f; \ 238c2ecf20Sopenharmony_ciEND_FTR_SECTION_IFSET(CPU_FTR_VSX); \ 248c2ecf20Sopenharmony_ci SAVE_32FPRS(n,base); \ 258c2ecf20Sopenharmony_ci b 3f; \ 268c2ecf20Sopenharmony_ci2: SAVE_32VSRS(n,c,base); \ 278c2ecf20Sopenharmony_ci3: 288c2ecf20Sopenharmony_ci#define __REST_32FPRS_VSRS(n,c,base) \ 298c2ecf20Sopenharmony_ciBEGIN_FTR_SECTION \ 308c2ecf20Sopenharmony_ci b 2f; \ 318c2ecf20Sopenharmony_ciEND_FTR_SECTION_IFSET(CPU_FTR_VSX); \ 328c2ecf20Sopenharmony_ci REST_32FPRS(n,base); \ 338c2ecf20Sopenharmony_ci b 3f; \ 348c2ecf20Sopenharmony_ci2: REST_32VSRS(n,c,base); \ 358c2ecf20Sopenharmony_ci3: 368c2ecf20Sopenharmony_ci#else 378c2ecf20Sopenharmony_ci#define __SAVE_32FPRS_VSRS(n,c,base) SAVE_32FPRS(n, base) 388c2ecf20Sopenharmony_ci#define __REST_32FPRS_VSRS(n,c,base) REST_32FPRS(n, base) 398c2ecf20Sopenharmony_ci#endif 408c2ecf20Sopenharmony_ci#define SAVE_32FPRS_VSRS(n,c,base) \ 418c2ecf20Sopenharmony_ci __SAVE_32FPRS_VSRS(n,__REG_##c,__REG_##base) 428c2ecf20Sopenharmony_ci#define REST_32FPRS_VSRS(n,c,base) \ 438c2ecf20Sopenharmony_ci __REST_32FPRS_VSRS(n,__REG_##c,__REG_##base) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* Stack frame offsets for local variables. */ 468c2ecf20Sopenharmony_ci#define TM_FRAME_L0 TM_FRAME_SIZE-16 478c2ecf20Sopenharmony_ci#define TM_FRAME_L1 TM_FRAME_SIZE-8 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* In order to access the TM SPRs, TM must be enabled. So, do so: */ 518c2ecf20Sopenharmony_ci_GLOBAL(tm_enable) 528c2ecf20Sopenharmony_ci mfmsr r4 538c2ecf20Sopenharmony_ci li r3, MSR_TM >> 32 548c2ecf20Sopenharmony_ci sldi r3, r3, 32 558c2ecf20Sopenharmony_ci and. r0, r4, r3 568c2ecf20Sopenharmony_ci bne 1f 578c2ecf20Sopenharmony_ci or r4, r4, r3 588c2ecf20Sopenharmony_ci mtmsrd r4 598c2ecf20Sopenharmony_ci1: blr 608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tm_enable); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci_GLOBAL(tm_disable) 638c2ecf20Sopenharmony_ci mfmsr r4 648c2ecf20Sopenharmony_ci li r3, MSR_TM >> 32 658c2ecf20Sopenharmony_ci sldi r3, r3, 32 668c2ecf20Sopenharmony_ci andc r4, r4, r3 678c2ecf20Sopenharmony_ci mtmsrd r4 688c2ecf20Sopenharmony_ci blr 698c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tm_disable); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci_GLOBAL(tm_save_sprs) 728c2ecf20Sopenharmony_ci mfspr r0, SPRN_TFHAR 738c2ecf20Sopenharmony_ci std r0, THREAD_TM_TFHAR(r3) 748c2ecf20Sopenharmony_ci mfspr r0, SPRN_TEXASR 758c2ecf20Sopenharmony_ci std r0, THREAD_TM_TEXASR(r3) 768c2ecf20Sopenharmony_ci mfspr r0, SPRN_TFIAR 778c2ecf20Sopenharmony_ci std r0, THREAD_TM_TFIAR(r3) 788c2ecf20Sopenharmony_ci blr 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci_GLOBAL(tm_restore_sprs) 818c2ecf20Sopenharmony_ci ld r0, THREAD_TM_TFHAR(r3) 828c2ecf20Sopenharmony_ci mtspr SPRN_TFHAR, r0 838c2ecf20Sopenharmony_ci ld r0, THREAD_TM_TEXASR(r3) 848c2ecf20Sopenharmony_ci mtspr SPRN_TEXASR, r0 858c2ecf20Sopenharmony_ci ld r0, THREAD_TM_TFIAR(r3) 868c2ecf20Sopenharmony_ci mtspr SPRN_TFIAR, r0 878c2ecf20Sopenharmony_ci blr 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* Passed an 8-bit failure cause as first argument. */ 908c2ecf20Sopenharmony_ci_GLOBAL(tm_abort) 918c2ecf20Sopenharmony_ci TABORT(R3) 928c2ecf20Sopenharmony_ci blr 938c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(tm_abort); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* 968c2ecf20Sopenharmony_ci * void tm_reclaim(struct thread_struct *thread, 978c2ecf20Sopenharmony_ci * uint8_t cause) 988c2ecf20Sopenharmony_ci * 998c2ecf20Sopenharmony_ci * - Performs a full reclaim. This destroys outstanding 1008c2ecf20Sopenharmony_ci * transactions and updates thread.ckpt_regs, thread.ckfp_state and 1018c2ecf20Sopenharmony_ci * thread.ckvr_state with the original checkpointed state. Note that 1028c2ecf20Sopenharmony_ci * thread->regs is unchanged. 1038c2ecf20Sopenharmony_ci * 1048c2ecf20Sopenharmony_ci * Purpose is to both abort transactions of, and preserve the state of, 1058c2ecf20Sopenharmony_ci * a transactions at a context switch. We preserve/restore both sets of process 1068c2ecf20Sopenharmony_ci * state to restore them when the thread's scheduled again. We continue in 1078c2ecf20Sopenharmony_ci * userland as though nothing happened, but when the transaction is resumed 1088c2ecf20Sopenharmony_ci * they will abort back to the checkpointed state we save out here. 1098c2ecf20Sopenharmony_ci * 1108c2ecf20Sopenharmony_ci * Call with IRQs off, stacks get all out of sync for some periods in here! 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_ci_GLOBAL(tm_reclaim) 1138c2ecf20Sopenharmony_ci mfcr r5 1148c2ecf20Sopenharmony_ci mflr r0 1158c2ecf20Sopenharmony_ci stw r5, 8(r1) 1168c2ecf20Sopenharmony_ci std r0, 16(r1) 1178c2ecf20Sopenharmony_ci std r2, STK_GOT(r1) 1188c2ecf20Sopenharmony_ci stdu r1, -TM_FRAME_SIZE(r1) 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. */ 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci std r3, STK_PARAM(R3)(r1) 1238c2ecf20Sopenharmony_ci SAVE_NVGPRS(r1) 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* 1268c2ecf20Sopenharmony_ci * Save kernel live AMR since it will be clobbered by treclaim 1278c2ecf20Sopenharmony_ci * but can be used elsewhere later in kernel space. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci mfspr r3, SPRN_AMR 1308c2ecf20Sopenharmony_ci std r3, TM_FRAME_L1(r1) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* We need to setup MSR for VSX register save instructions. */ 1338c2ecf20Sopenharmony_ci mfmsr r14 1348c2ecf20Sopenharmony_ci mr r15, r14 1358c2ecf20Sopenharmony_ci ori r15, r15, MSR_FP 1368c2ecf20Sopenharmony_ci li r16, 0 1378c2ecf20Sopenharmony_ci ori r16, r16, MSR_EE /* IRQs hard off */ 1388c2ecf20Sopenharmony_ci andc r15, r15, r16 1398c2ecf20Sopenharmony_ci oris r15, r15, MSR_VEC@h 1408c2ecf20Sopenharmony_ci#ifdef CONFIG_VSX 1418c2ecf20Sopenharmony_ci BEGIN_FTR_SECTION 1428c2ecf20Sopenharmony_ci oris r15,r15, MSR_VSX@h 1438c2ecf20Sopenharmony_ci END_FTR_SECTION_IFSET(CPU_FTR_VSX) 1448c2ecf20Sopenharmony_ci#endif 1458c2ecf20Sopenharmony_ci mtmsrd r15 1468c2ecf20Sopenharmony_ci std r14, TM_FRAME_L0(r1) 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* Do sanity check on MSR to make sure we are suspended */ 1498c2ecf20Sopenharmony_ci li r7, (MSR_TS_S)@higher 1508c2ecf20Sopenharmony_ci srdi r6, r14, 32 1518c2ecf20Sopenharmony_ci and r6, r6, r7 1528c2ecf20Sopenharmony_ci1: tdeqi r6, 0 1538c2ecf20Sopenharmony_ci EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* Stash the stack pointer away for use after reclaim */ 1568c2ecf20Sopenharmony_ci std r1, PACAR1(r13) 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Clear MSR RI since we are about to use SCRATCH0, EE is already off */ 1598c2ecf20Sopenharmony_ci li r5, 0 1608c2ecf20Sopenharmony_ci mtmsrd r5, 1 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci /* 1638c2ecf20Sopenharmony_ci * BE CAREFUL HERE: 1648c2ecf20Sopenharmony_ci * At this point we can't take an SLB miss since we have MSR_RI 1658c2ecf20Sopenharmony_ci * off. Load only to/from the stack/paca which are in SLB bolted regions 1668c2ecf20Sopenharmony_ci * until we turn MSR RI back on. 1678c2ecf20Sopenharmony_ci * 1688c2ecf20Sopenharmony_ci * The moment we treclaim, ALL of our GPRs will switch 1698c2ecf20Sopenharmony_ci * to user register state. (FPRs, CCR etc. also!) 1708c2ecf20Sopenharmony_ci * Use an sprg and a tm_scratch in the PACA to shuffle. 1718c2ecf20Sopenharmony_ci */ 1728c2ecf20Sopenharmony_ci TRECLAIM(R4) /* Cause in r4 */ 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci /* 1758c2ecf20Sopenharmony_ci * ******************** GPRs ******************** 1768c2ecf20Sopenharmony_ci * Stash the checkpointed r13 in the scratch SPR and get the real paca. 1778c2ecf20Sopenharmony_ci */ 1788c2ecf20Sopenharmony_ci SET_SCRATCH0(r13) 1798c2ecf20Sopenharmony_ci GET_PACA(r13) 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci /* 1828c2ecf20Sopenharmony_ci * Stash the checkpointed r1 away in paca->tm_scratch and get the real 1838c2ecf20Sopenharmony_ci * stack pointer back into r1. 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci std r1, PACATMSCRATCH(r13) 1868c2ecf20Sopenharmony_ci ld r1, PACAR1(r13) 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci std r11, GPR11(r1) /* Temporary stash */ 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /* 1918c2ecf20Sopenharmony_ci * Move the saved user r1 to the kernel stack in case PACATMSCRATCH is 1928c2ecf20Sopenharmony_ci * clobbered by an exception once we turn on MSR_RI below. 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_ci ld r11, PACATMSCRATCH(r13) 1958c2ecf20Sopenharmony_ci std r11, GPR1(r1) 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* 1988c2ecf20Sopenharmony_ci * Store r13 away so we can free up the scratch SPR for the SLB fault 1998c2ecf20Sopenharmony_ci * handler (needed once we start accessing the thread_struct). 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci GET_SCRATCH0(r11) 2028c2ecf20Sopenharmony_ci std r11, GPR13(r1) 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* Reset MSR RI so we can take SLB faults again */ 2058c2ecf20Sopenharmony_ci li r11, MSR_RI 2068c2ecf20Sopenharmony_ci mtmsrd r11, 1 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci /* Store the PPR in r11 and reset to decent value */ 2098c2ecf20Sopenharmony_ci mfspr r11, SPRN_PPR 2108c2ecf20Sopenharmony_ci HMT_MEDIUM 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci /* Now get some more GPRS free */ 2138c2ecf20Sopenharmony_ci std r7, GPR7(r1) /* Temporary stash */ 2148c2ecf20Sopenharmony_ci std r12, GPR12(r1) /* '' '' '' */ 2158c2ecf20Sopenharmony_ci ld r12, STK_PARAM(R3)(r1) /* Param 0, thread_struct * */ 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci std r11, THREAD_TM_PPR(r12) /* Store PPR and free r11 */ 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci /* 2228c2ecf20Sopenharmony_ci * Make r7 look like an exception frame so that we can use the neat 2238c2ecf20Sopenharmony_ci * GPRx(n) macros. r7 is NOT a pt_regs ptr! 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_ci subi r7, r7, STACK_FRAME_OVERHEAD 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* Sync the userland GPRs 2-12, 14-31 to thread->regs: */ 2288c2ecf20Sopenharmony_ci SAVE_GPR(0, r7) /* user r0 */ 2298c2ecf20Sopenharmony_ci SAVE_GPR(2, r7) /* user r2 */ 2308c2ecf20Sopenharmony_ci SAVE_4GPRS(3, r7) /* user r3-r6 */ 2318c2ecf20Sopenharmony_ci SAVE_GPR(8, r7) /* user r8 */ 2328c2ecf20Sopenharmony_ci SAVE_GPR(9, r7) /* user r9 */ 2338c2ecf20Sopenharmony_ci SAVE_GPR(10, r7) /* user r10 */ 2348c2ecf20Sopenharmony_ci ld r3, GPR1(r1) /* user r1 */ 2358c2ecf20Sopenharmony_ci ld r4, GPR7(r1) /* user r7 */ 2368c2ecf20Sopenharmony_ci ld r5, GPR11(r1) /* user r11 */ 2378c2ecf20Sopenharmony_ci ld r6, GPR12(r1) /* user r12 */ 2388c2ecf20Sopenharmony_ci ld r8, GPR13(r1) /* user r13 */ 2398c2ecf20Sopenharmony_ci std r3, GPR1(r7) 2408c2ecf20Sopenharmony_ci std r4, GPR7(r7) 2418c2ecf20Sopenharmony_ci std r5, GPR11(r7) 2428c2ecf20Sopenharmony_ci std r6, GPR12(r7) 2438c2ecf20Sopenharmony_ci std r8, GPR13(r7) 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci SAVE_NVGPRS(r7) /* user r14-r31 */ 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* ******************** NIP ******************** */ 2488c2ecf20Sopenharmony_ci mfspr r3, SPRN_TFHAR 2498c2ecf20Sopenharmony_ci std r3, _NIP(r7) /* Returns to failhandler */ 2508c2ecf20Sopenharmony_ci /* 2518c2ecf20Sopenharmony_ci * The checkpointed NIP is ignored when rescheduling/rechkpting, 2528c2ecf20Sopenharmony_ci * but is used in signal return to 'wind back' to the abort handler. 2538c2ecf20Sopenharmony_ci */ 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* ***************** CTR, LR, CR, XER ********** */ 2568c2ecf20Sopenharmony_ci mfctr r3 2578c2ecf20Sopenharmony_ci mflr r4 2588c2ecf20Sopenharmony_ci mfcr r5 2598c2ecf20Sopenharmony_ci mfxer r6 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci std r3, _CTR(r7) 2628c2ecf20Sopenharmony_ci std r4, _LINK(r7) 2638c2ecf20Sopenharmony_ci std r5, _CCR(r7) 2648c2ecf20Sopenharmony_ci std r6, _XER(r7) 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* ******************** TAR, DSCR ********** */ 2678c2ecf20Sopenharmony_ci mfspr r3, SPRN_TAR 2688c2ecf20Sopenharmony_ci mfspr r4, SPRN_DSCR 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci std r3, THREAD_TM_TAR(r12) 2718c2ecf20Sopenharmony_ci std r4, THREAD_TM_DSCR(r12) 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* ******************** AMR **************** */ 2748c2ecf20Sopenharmony_ci mfspr r3, SPRN_AMR 2758c2ecf20Sopenharmony_ci std r3, THREAD_TM_AMR(r12) 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* 2788c2ecf20Sopenharmony_ci * MSR and flags: We don't change CRs, and we don't need to alter MSR. 2798c2ecf20Sopenharmony_ci */ 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* 2838c2ecf20Sopenharmony_ci * ******************** FPR/VR/VSRs ************ 2848c2ecf20Sopenharmony_ci * After reclaiming, capture the checkpointed FPRs/VRs. 2858c2ecf20Sopenharmony_ci * 2868c2ecf20Sopenharmony_ci * We enabled VEC/FP/VSX in the msr above, so we can execute these 2878c2ecf20Sopenharmony_ci * instructions! 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_ci mr r3, r12 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* Altivec (VEC/VMX/VR)*/ 2928c2ecf20Sopenharmony_ci addi r7, r3, THREAD_CKVRSTATE 2938c2ecf20Sopenharmony_ci SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 ckvr_state */ 2948c2ecf20Sopenharmony_ci mfvscr v0 2958c2ecf20Sopenharmony_ci li r6, VRSTATE_VSCR 2968c2ecf20Sopenharmony_ci stvx v0, r7, r6 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* VRSAVE */ 2998c2ecf20Sopenharmony_ci mfspr r0, SPRN_VRSAVE 3008c2ecf20Sopenharmony_ci std r0, THREAD_CKVRSAVE(r3) 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci /* Floating Point (FP) */ 3038c2ecf20Sopenharmony_ci addi r7, r3, THREAD_CKFPSTATE 3048c2ecf20Sopenharmony_ci SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 ckfp_state */ 3058c2ecf20Sopenharmony_ci mffs fr0 3068c2ecf20Sopenharmony_ci stfd fr0,FPSTATE_FPSCR(r7) 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci /* 3108c2ecf20Sopenharmony_ci * TM regs, incl TEXASR -- these live in thread_struct. Note they've 3118c2ecf20Sopenharmony_ci * been updated by the treclaim, to explain to userland the failure 3128c2ecf20Sopenharmony_ci * cause (aborted). 3138c2ecf20Sopenharmony_ci */ 3148c2ecf20Sopenharmony_ci mfspr r0, SPRN_TEXASR 3158c2ecf20Sopenharmony_ci mfspr r3, SPRN_TFHAR 3168c2ecf20Sopenharmony_ci mfspr r4, SPRN_TFIAR 3178c2ecf20Sopenharmony_ci std r0, THREAD_TM_TEXASR(r12) 3188c2ecf20Sopenharmony_ci std r3, THREAD_TM_TFHAR(r12) 3198c2ecf20Sopenharmony_ci std r4, THREAD_TM_TFIAR(r12) 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* Restore kernel live AMR */ 3228c2ecf20Sopenharmony_ci ld r8, TM_FRAME_L1(r1) 3238c2ecf20Sopenharmony_ci mtspr SPRN_AMR, r8 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* Restore original MSR/IRQ state & clear TM mode */ 3268c2ecf20Sopenharmony_ci ld r14, TM_FRAME_L0(r1) /* Orig MSR */ 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci li r15, 0 3298c2ecf20Sopenharmony_ci rldimi r14, r15, MSR_TS_LG, (63-MSR_TS_LG)-1 3308c2ecf20Sopenharmony_ci mtmsrd r14 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci REST_NVGPRS(r1) 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci addi r1, r1, TM_FRAME_SIZE 3358c2ecf20Sopenharmony_ci lwz r4, 8(r1) 3368c2ecf20Sopenharmony_ci ld r0, 16(r1) 3378c2ecf20Sopenharmony_ci mtcr r4 3388c2ecf20Sopenharmony_ci mtlr r0 3398c2ecf20Sopenharmony_ci ld r2, STK_GOT(r1) 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* Load CPU's default DSCR */ 3428c2ecf20Sopenharmony_ci ld r0, PACA_DSCR_DEFAULT(r13) 3438c2ecf20Sopenharmony_ci mtspr SPRN_DSCR, r0 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci blr 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* 3498c2ecf20Sopenharmony_ci * void __tm_recheckpoint(struct thread_struct *thread) 3508c2ecf20Sopenharmony_ci * - Restore the checkpointed register state saved by tm_reclaim 3518c2ecf20Sopenharmony_ci * when we switch_to a process. 3528c2ecf20Sopenharmony_ci * 3538c2ecf20Sopenharmony_ci * Call with IRQs off, stacks get all out of sync for 3548c2ecf20Sopenharmony_ci * some periods in here! 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_ci_GLOBAL(__tm_recheckpoint) 3578c2ecf20Sopenharmony_ci mfcr r5 3588c2ecf20Sopenharmony_ci mflr r0 3598c2ecf20Sopenharmony_ci stw r5, 8(r1) 3608c2ecf20Sopenharmony_ci std r0, 16(r1) 3618c2ecf20Sopenharmony_ci std r2, STK_GOT(r1) 3628c2ecf20Sopenharmony_ci stdu r1, -TM_FRAME_SIZE(r1) 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci /* 3658c2ecf20Sopenharmony_ci * We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. 3668c2ecf20Sopenharmony_ci * This is used for backing up the NVGPRs: 3678c2ecf20Sopenharmony_ci */ 3688c2ecf20Sopenharmony_ci SAVE_NVGPRS(r1) 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci /* 3718c2ecf20Sopenharmony_ci * Save kernel live AMR since it will be clobbered for trechkpt 3728c2ecf20Sopenharmony_ci * but can be used elsewhere later in kernel space. 3738c2ecf20Sopenharmony_ci */ 3748c2ecf20Sopenharmony_ci mfspr r8, SPRN_AMR 3758c2ecf20Sopenharmony_ci std r8, TM_FRAME_L0(r1) 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci /* Load complete register state from ts_ckpt* registers */ 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci addi r7, r3, PT_CKPT_REGS /* Thread's ckpt_regs */ 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci /* 3828c2ecf20Sopenharmony_ci * Make r7 look like an exception frame so that we can use the neat 3838c2ecf20Sopenharmony_ci * GPRx(n) macros. r7 is now NOT a pt_regs ptr! 3848c2ecf20Sopenharmony_ci */ 3858c2ecf20Sopenharmony_ci subi r7, r7, STACK_FRAME_OVERHEAD 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci /* We need to setup MSR for FP/VMX/VSX register save instructions. */ 3888c2ecf20Sopenharmony_ci mfmsr r6 3898c2ecf20Sopenharmony_ci mr r5, r6 3908c2ecf20Sopenharmony_ci ori r5, r5, MSR_FP 3918c2ecf20Sopenharmony_ci#ifdef CONFIG_ALTIVEC 3928c2ecf20Sopenharmony_ci oris r5, r5, MSR_VEC@h 3938c2ecf20Sopenharmony_ci#endif 3948c2ecf20Sopenharmony_ci#ifdef CONFIG_VSX 3958c2ecf20Sopenharmony_ci BEGIN_FTR_SECTION 3968c2ecf20Sopenharmony_ci oris r5,r5, MSR_VSX@h 3978c2ecf20Sopenharmony_ci END_FTR_SECTION_IFSET(CPU_FTR_VSX) 3988c2ecf20Sopenharmony_ci#endif 3998c2ecf20Sopenharmony_ci mtmsrd r5 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci#ifdef CONFIG_ALTIVEC 4028c2ecf20Sopenharmony_ci /* 4038c2ecf20Sopenharmony_ci * FP and VEC registers: These are recheckpointed from 4048c2ecf20Sopenharmony_ci * thread.ckfp_state and thread.ckvr_state respectively. The 4058c2ecf20Sopenharmony_ci * thread.fp_state[] version holds the 'live' (transactional) 4068c2ecf20Sopenharmony_ci * and will be loaded subsequently by any FPUnavailable trap. 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_ci addi r8, r3, THREAD_CKVRSTATE 4098c2ecf20Sopenharmony_ci li r5, VRSTATE_VSCR 4108c2ecf20Sopenharmony_ci lvx v0, r8, r5 4118c2ecf20Sopenharmony_ci mtvscr v0 4128c2ecf20Sopenharmony_ci REST_32VRS(0, r5, r8) /* r5 scratch, r8 ptr */ 4138c2ecf20Sopenharmony_ci ld r5, THREAD_CKVRSAVE(r3) 4148c2ecf20Sopenharmony_ci mtspr SPRN_VRSAVE, r5 4158c2ecf20Sopenharmony_ci#endif 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci addi r8, r3, THREAD_CKFPSTATE 4188c2ecf20Sopenharmony_ci lfd fr0, FPSTATE_FPSCR(r8) 4198c2ecf20Sopenharmony_ci MTFSF_L(fr0) 4208c2ecf20Sopenharmony_ci REST_32FPRS_VSRS(0, R4, R8) 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci mtmsr r6 /* FP/Vec off again! */ 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cirestore_gprs: 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci /* ****************** CTR, LR, XER ************* */ 4278c2ecf20Sopenharmony_ci ld r4, _CTR(r7) 4288c2ecf20Sopenharmony_ci ld r5, _LINK(r7) 4298c2ecf20Sopenharmony_ci ld r8, _XER(r7) 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci mtctr r4 4328c2ecf20Sopenharmony_ci mtlr r5 4338c2ecf20Sopenharmony_ci mtxer r8 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci /* ******************** TAR ******************** */ 4368c2ecf20Sopenharmony_ci ld r4, THREAD_TM_TAR(r3) 4378c2ecf20Sopenharmony_ci mtspr SPRN_TAR, r4 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* ******************** AMR ******************** */ 4408c2ecf20Sopenharmony_ci ld r4, THREAD_TM_AMR(r3) 4418c2ecf20Sopenharmony_ci mtspr SPRN_AMR, r4 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci /* Load up the PPR and DSCR in GPRs only at this stage */ 4448c2ecf20Sopenharmony_ci ld r5, THREAD_TM_DSCR(r3) 4458c2ecf20Sopenharmony_ci ld r6, THREAD_TM_PPR(r3) 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci REST_GPR(0, r7) /* GPR0 */ 4488c2ecf20Sopenharmony_ci REST_2GPRS(2, r7) /* GPR2-3 */ 4498c2ecf20Sopenharmony_ci REST_GPR(4, r7) /* GPR4 */ 4508c2ecf20Sopenharmony_ci REST_4GPRS(8, r7) /* GPR8-11 */ 4518c2ecf20Sopenharmony_ci REST_2GPRS(12, r7) /* GPR12-13 */ 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci REST_NVGPRS(r7) /* GPR14-31 */ 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci /* Load up PPR and DSCR here so we don't run with user values for long */ 4568c2ecf20Sopenharmony_ci mtspr SPRN_DSCR, r5 4578c2ecf20Sopenharmony_ci mtspr SPRN_PPR, r6 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci /* 4608c2ecf20Sopenharmony_ci * Do final sanity check on TEXASR to make sure FS is set. Do this 4618c2ecf20Sopenharmony_ci * here before we load up the userspace r1 so any bugs we hit will get 4628c2ecf20Sopenharmony_ci * a call chain. 4638c2ecf20Sopenharmony_ci */ 4648c2ecf20Sopenharmony_ci mfspr r5, SPRN_TEXASR 4658c2ecf20Sopenharmony_ci srdi r5, r5, 16 4668c2ecf20Sopenharmony_ci li r6, (TEXASR_FS)@h 4678c2ecf20Sopenharmony_ci and r6, r6, r5 4688c2ecf20Sopenharmony_ci1: tdeqi r6, 0 4698c2ecf20Sopenharmony_ci EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* 4728c2ecf20Sopenharmony_ci * Do final sanity check on MSR to make sure we are not transactional 4738c2ecf20Sopenharmony_ci * or suspended. 4748c2ecf20Sopenharmony_ci */ 4758c2ecf20Sopenharmony_ci mfmsr r6 4768c2ecf20Sopenharmony_ci li r5, (MSR_TS_MASK)@higher 4778c2ecf20Sopenharmony_ci srdi r6, r6, 32 4788c2ecf20Sopenharmony_ci and r6, r6, r5 4798c2ecf20Sopenharmony_ci1: tdnei r6, 0 4808c2ecf20Sopenharmony_ci EMIT_BUG_ENTRY 1b,__FILE__,__LINE__,0 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /* Restore CR */ 4838c2ecf20Sopenharmony_ci ld r6, _CCR(r7) 4848c2ecf20Sopenharmony_ci mtcr r6 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci REST_GPR(6, r7) 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci /* 4898c2ecf20Sopenharmony_ci * Store r1 and r5 on the stack so that we can access them after we 4908c2ecf20Sopenharmony_ci * clear MSR RI. 4918c2ecf20Sopenharmony_ci */ 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci REST_GPR(5, r7) 4948c2ecf20Sopenharmony_ci std r5, -8(r1) 4958c2ecf20Sopenharmony_ci ld r5, GPR1(r7) 4968c2ecf20Sopenharmony_ci std r5, -16(r1) 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci REST_GPR(7, r7) 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci /* Clear MSR RI since we are about to use SCRATCH0. EE is already off */ 5018c2ecf20Sopenharmony_ci li r5, 0 5028c2ecf20Sopenharmony_ci mtmsrd r5, 1 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci /* 5058c2ecf20Sopenharmony_ci * BE CAREFUL HERE: 5068c2ecf20Sopenharmony_ci * At this point we can't take an SLB miss since we have MSR_RI 5078c2ecf20Sopenharmony_ci * off. Load only to/from the stack/paca which are in SLB bolted regions 5088c2ecf20Sopenharmony_ci * until we turn MSR RI back on. 5098c2ecf20Sopenharmony_ci */ 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci SET_SCRATCH0(r1) 5128c2ecf20Sopenharmony_ci ld r5, -8(r1) 5138c2ecf20Sopenharmony_ci ld r1, -16(r1) 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci /* Commit register state as checkpointed state: */ 5168c2ecf20Sopenharmony_ci TRECHKPT 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci HMT_MEDIUM 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci /* 5218c2ecf20Sopenharmony_ci * Our transactional state has now changed. 5228c2ecf20Sopenharmony_ci * 5238c2ecf20Sopenharmony_ci * Now just get out of here. Transactional (current) state will be 5248c2ecf20Sopenharmony_ci * updated once restore is called on the return path in the _switch-ed 5258c2ecf20Sopenharmony_ci * -to process. 5268c2ecf20Sopenharmony_ci */ 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci GET_PACA(r13) 5298c2ecf20Sopenharmony_ci GET_SCRATCH0(r1) 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci /* R1 is restored, so we are recoverable again. EE is still off */ 5328c2ecf20Sopenharmony_ci li r4, MSR_RI 5338c2ecf20Sopenharmony_ci mtmsrd r4, 1 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci /* Restore kernel live AMR */ 5368c2ecf20Sopenharmony_ci ld r8, TM_FRAME_L0(r1) 5378c2ecf20Sopenharmony_ci mtspr SPRN_AMR, r8 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci REST_NVGPRS(r1) 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci addi r1, r1, TM_FRAME_SIZE 5428c2ecf20Sopenharmony_ci lwz r4, 8(r1) 5438c2ecf20Sopenharmony_ci ld r0, 16(r1) 5448c2ecf20Sopenharmony_ci mtcr r4 5458c2ecf20Sopenharmony_ci mtlr r0 5468c2ecf20Sopenharmony_ci ld r2, STK_GOT(r1) 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci /* Load CPU's default DSCR */ 5498c2ecf20Sopenharmony_ci ld r0, PACA_DSCR_DEFAULT(r13) 5508c2ecf20Sopenharmony_ci mtspr SPRN_DSCR, r0 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci blr 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* ****************************************************************** */ 555