1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0-only */ 2*4882a593Smuzhiyun/* 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * Derived from book3s_interrupts.S, which is: 7*4882a593Smuzhiyun * Copyright SUSE Linux Products GmbH 2009 8*4882a593Smuzhiyun * 9*4882a593Smuzhiyun * Authors: Alexander Graf <agraf@suse.de> 10*4882a593Smuzhiyun */ 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun#include <asm/ppc_asm.h> 13*4882a593Smuzhiyun#include <asm/kvm_asm.h> 14*4882a593Smuzhiyun#include <asm/reg.h> 15*4882a593Smuzhiyun#include <asm/page.h> 16*4882a593Smuzhiyun#include <asm/asm-offsets.h> 17*4882a593Smuzhiyun#include <asm/exception-64s.h> 18*4882a593Smuzhiyun#include <asm/ppc-opcode.h> 19*4882a593Smuzhiyun#include <asm/asm-compat.h> 20*4882a593Smuzhiyun#include <asm/feature-fixups.h> 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun/***************************************************************************** 23*4882a593Smuzhiyun * * 24*4882a593Smuzhiyun * Guest entry / exit code that is in kernel module memory (vmalloc) * 25*4882a593Smuzhiyun * * 26*4882a593Smuzhiyun ****************************************************************************/ 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun/* Registers: 29*4882a593Smuzhiyun * none 30*4882a593Smuzhiyun */ 31*4882a593Smuzhiyun_GLOBAL(__kvmppc_vcore_entry) 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun /* Write correct stack frame */ 34*4882a593Smuzhiyun mflr r0 35*4882a593Smuzhiyun std r0,PPC_LR_STKOFF(r1) 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun /* Save host state to the stack */ 38*4882a593Smuzhiyun stdu r1, -SWITCH_FRAME_SIZE(r1) 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun /* Save non-volatile registers (r14 - r31) and CR */ 41*4882a593Smuzhiyun SAVE_NVGPRS(r1) 42*4882a593Smuzhiyun mfcr r3 43*4882a593Smuzhiyun std r3, _CCR(r1) 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun /* Save host DSCR */ 46*4882a593Smuzhiyun mfspr r3, SPRN_DSCR 47*4882a593Smuzhiyun std r3, HSTATE_DSCR(r13) 48*4882a593Smuzhiyun 49*4882a593SmuzhiyunBEGIN_FTR_SECTION 50*4882a593Smuzhiyun /* Save host DABR */ 51*4882a593Smuzhiyun mfspr r3, SPRN_DABR 52*4882a593Smuzhiyun std r3, HSTATE_DABR(r13) 53*4882a593SmuzhiyunEND_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun /* Save host PMU registers */ 56*4882a593Smuzhiyun bl kvmhv_save_host_pmu 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun /* 59*4882a593Smuzhiyun * Put whatever is in the decrementer into the 60*4882a593Smuzhiyun * hypervisor decrementer. 61*4882a593Smuzhiyun * Because of a hardware deviation in P8 and P9, 62*4882a593Smuzhiyun * we need to set LPCR[HDICE] before writing HDEC. 63*4882a593Smuzhiyun */ 64*4882a593Smuzhiyun ld r5, HSTATE_KVM_VCORE(r13) 65*4882a593Smuzhiyun ld r6, VCORE_KVM(r5) 66*4882a593Smuzhiyun ld r9, KVM_HOST_LPCR(r6) 67*4882a593Smuzhiyun ori r8, r9, LPCR_HDICE 68*4882a593Smuzhiyun mtspr SPRN_LPCR, r8 69*4882a593Smuzhiyun isync 70*4882a593Smuzhiyun andis. r0, r9, LPCR_LD@h 71*4882a593Smuzhiyun mfspr r8,SPRN_DEC 72*4882a593Smuzhiyun mftb r7 73*4882a593SmuzhiyunBEGIN_FTR_SECTION 74*4882a593Smuzhiyun /* On POWER9, don't sign-extend if host LPCR[LD] bit is set */ 75*4882a593Smuzhiyun bne 32f 76*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_300) 77*4882a593Smuzhiyun extsw r8,r8 78*4882a593Smuzhiyun32: mtspr SPRN_HDEC,r8 79*4882a593Smuzhiyun add r8,r8,r7 80*4882a593Smuzhiyun std r8,HSTATE_DECEXP(r13) 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun /* Jump to partition switch code */ 83*4882a593Smuzhiyun bl kvmppc_hv_entry_trampoline 84*4882a593Smuzhiyun nop 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun/* 87*4882a593Smuzhiyun * We return here in virtual mode after the guest exits 88*4882a593Smuzhiyun * with something that we can't handle in real mode. 89*4882a593Smuzhiyun * Interrupts are still hard-disabled. 90*4882a593Smuzhiyun */ 91*4882a593Smuzhiyun 92*4882a593Smuzhiyun /* 93*4882a593Smuzhiyun * Register usage at this point: 94*4882a593Smuzhiyun * 95*4882a593Smuzhiyun * R1 = host R1 96*4882a593Smuzhiyun * R2 = host R2 97*4882a593Smuzhiyun * R3 = trap number on this thread 98*4882a593Smuzhiyun * R12 = exit handler id 99*4882a593Smuzhiyun * R13 = PACA 100*4882a593Smuzhiyun */ 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun /* Restore non-volatile host registers (r14 - r31) and CR */ 103*4882a593Smuzhiyun REST_NVGPRS(r1) 104*4882a593Smuzhiyun ld r4, _CCR(r1) 105*4882a593Smuzhiyun mtcr r4 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun addi r1, r1, SWITCH_FRAME_SIZE 108*4882a593Smuzhiyun ld r0, PPC_LR_STKOFF(r1) 109*4882a593Smuzhiyun mtlr r0 110*4882a593Smuzhiyun blr 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun_GLOBAL(kvmhv_save_host_pmu) 113*4882a593SmuzhiyunBEGIN_FTR_SECTION 114*4882a593Smuzhiyun /* Work around P8 PMAE bug */ 115*4882a593Smuzhiyun li r3, -1 116*4882a593Smuzhiyun clrrdi r3, r3, 10 117*4882a593Smuzhiyun mfspr r8, SPRN_MMCR2 118*4882a593Smuzhiyun mtspr SPRN_MMCR2, r3 /* freeze all counters using MMCR2 */ 119*4882a593Smuzhiyun isync 120*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) 121*4882a593Smuzhiyun li r3, 1 122*4882a593Smuzhiyun sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ 123*4882a593Smuzhiyun mfspr r7, SPRN_MMCR0 /* save MMCR0 */ 124*4882a593Smuzhiyun mtspr SPRN_MMCR0, r3 /* freeze all counters, disable interrupts */ 125*4882a593Smuzhiyun mfspr r6, SPRN_MMCRA 126*4882a593Smuzhiyun /* Clear MMCRA in order to disable SDAR updates */ 127*4882a593Smuzhiyun li r5, 0 128*4882a593Smuzhiyun mtspr SPRN_MMCRA, r5 129*4882a593Smuzhiyun isync 130*4882a593Smuzhiyun lbz r5, PACA_PMCINUSE(r13) /* is the host using the PMU? */ 131*4882a593Smuzhiyun cmpwi r5, 0 132*4882a593Smuzhiyun beq 31f /* skip if not */ 133*4882a593Smuzhiyun mfspr r5, SPRN_MMCR1 134*4882a593Smuzhiyun mfspr r9, SPRN_SIAR 135*4882a593Smuzhiyun mfspr r10, SPRN_SDAR 136*4882a593Smuzhiyun std r7, HSTATE_MMCR0(r13) 137*4882a593Smuzhiyun std r5, HSTATE_MMCR1(r13) 138*4882a593Smuzhiyun std r6, HSTATE_MMCRA(r13) 139*4882a593Smuzhiyun std r9, HSTATE_SIAR(r13) 140*4882a593Smuzhiyun std r10, HSTATE_SDAR(r13) 141*4882a593SmuzhiyunBEGIN_FTR_SECTION 142*4882a593Smuzhiyun mfspr r9, SPRN_SIER 143*4882a593Smuzhiyun std r8, HSTATE_MMCR2(r13) 144*4882a593Smuzhiyun std r9, HSTATE_SIER(r13) 145*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) 146*4882a593SmuzhiyunBEGIN_FTR_SECTION 147*4882a593Smuzhiyun mfspr r5, SPRN_MMCR3 148*4882a593Smuzhiyun mfspr r6, SPRN_SIER2 149*4882a593Smuzhiyun mfspr r7, SPRN_SIER3 150*4882a593Smuzhiyun std r5, HSTATE_MMCR3(r13) 151*4882a593Smuzhiyun std r6, HSTATE_SIER2(r13) 152*4882a593Smuzhiyun std r7, HSTATE_SIER3(r13) 153*4882a593SmuzhiyunEND_FTR_SECTION_IFSET(CPU_FTR_ARCH_31) 154*4882a593Smuzhiyun mfspr r3, SPRN_PMC1 155*4882a593Smuzhiyun mfspr r5, SPRN_PMC2 156*4882a593Smuzhiyun mfspr r6, SPRN_PMC3 157*4882a593Smuzhiyun mfspr r7, SPRN_PMC4 158*4882a593Smuzhiyun mfspr r8, SPRN_PMC5 159*4882a593Smuzhiyun mfspr r9, SPRN_PMC6 160*4882a593Smuzhiyun stw r3, HSTATE_PMC1(r13) 161*4882a593Smuzhiyun stw r5, HSTATE_PMC2(r13) 162*4882a593Smuzhiyun stw r6, HSTATE_PMC3(r13) 163*4882a593Smuzhiyun stw r7, HSTATE_PMC4(r13) 164*4882a593Smuzhiyun stw r8, HSTATE_PMC5(r13) 165*4882a593Smuzhiyun stw r9, HSTATE_PMC6(r13) 166*4882a593Smuzhiyun31: blr 167