Path: blob/master/arch/powerpc/kvm/book3s_segment.S
10818 views
/*1* This program is free software; you can redistribute it and/or modify2* it under the terms of the GNU General Public License, version 2, as3* published by the Free Software Foundation.4*5* This program is distributed in the hope that it will be useful,6* but WITHOUT ANY WARRANTY; without even the implied warranty of7* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the8* GNU General Public License for more details.9*10* You should have received a copy of the GNU General Public License11* along with this program; if not, write to the Free Software12* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.13*14* Copyright SUSE Linux Products GmbH 201015*16* Authors: Alexander Graf <[email protected]>17*/1819/* Real mode helpers */2021#if defined(CONFIG_PPC_BOOK3S_64)2223#define GET_SHADOW_VCPU(reg) \24addi reg, r13, PACA_KVM_SVCPU2526#elif defined(CONFIG_PPC_BOOK3S_32)2728#define GET_SHADOW_VCPU(reg) \29tophys(reg, r2); \30lwz reg, (THREAD + THREAD_KVM_SVCPU)(reg); \31tophys(reg, reg)3233#endif3435/* Disable for nested KVM */36#define USE_QUICK_LAST_INST373839/* Get helper functions for subarch specific functionality */4041#if defined(CONFIG_PPC_BOOK3S_64)42#include "book3s_64_slb.S"43#elif defined(CONFIG_PPC_BOOK3S_32)44#include "book3s_32_sr.S"45#endif4647/******************************************************************************48* *49* Entry code *50* *51*****************************************************************************/5253.global kvmppc_handler_trampoline_enter54kvmppc_handler_trampoline_enter:5556/* Required state:57*58* MSR = ~IR|DR59* R13 = PACA60* R1 = host R161* R2 = host R262* R10 = guest MSR63* all other volatile GPRS = free64* SVCPU[CR] = guest CR65* SVCPU[XER] = guest XER66* SVCPU[CTR] = guest CTR67* SVCPU[LR] = guest LR68*/6970/* r3 = shadow vcpu */71GET_SHADOW_VCPU(r3)7273/* Move SRR0 and SRR1 into the respective regs */74PPC_LL r9, SVCPU_PC(r3)75mtsrr0 r976mtsrr1 r107778/* Activate guest mode, so faults get handled by KVM */79li r11, KVM_GUEST_MODE_GUEST80stb r11, SVCPU_IN_GUEST(r3)8182/* Switch to guest segment. This is subarch specific. */83LOAD_GUEST_SEGMENTS8485/* Enter guest */8687PPC_LL r4, (SVCPU_CTR)(r3)88PPC_LL r5, (SVCPU_LR)(r3)89lwz r6, (SVCPU_CR)(r3)90lwz r7, (SVCPU_XER)(r3)9192mtctr r493mtlr r594mtcr r695mtxer r79697PPC_LL r0, (SVCPU_R0)(r3)98PPC_LL r1, (SVCPU_R1)(r3)99PPC_LL r2, (SVCPU_R2)(r3)100PPC_LL r4, (SVCPU_R4)(r3)101PPC_LL r5, (SVCPU_R5)(r3)102PPC_LL r6, (SVCPU_R6)(r3)103PPC_LL r7, (SVCPU_R7)(r3)104PPC_LL r8, (SVCPU_R8)(r3)105PPC_LL r9, (SVCPU_R9)(r3)106PPC_LL r10, (SVCPU_R10)(r3)107PPC_LL r11, (SVCPU_R11)(r3)108PPC_LL r12, (SVCPU_R12)(r3)109PPC_LL r13, (SVCPU_R13)(r3)110111PPC_LL r3, (SVCPU_R3)(r3)112113RFI114kvmppc_handler_trampoline_enter_end:115116117118/******************************************************************************119* *120* Exit code *121* *122*****************************************************************************/123124.global kvmppc_handler_trampoline_exit125kvmppc_handler_trampoline_exit:126127/* Register usage at this point:128*129* SPRG_SCRATCH0 = guest R13130* R12 = exit handler id131* R13 = shadow vcpu - SHADOW_VCPU_OFF [=PACA on PPC64]132* SVCPU.SCRATCH0 = guest R12133* SVCPU.SCRATCH1 = guest CR134*135*/136137/* Save registers */138139PPC_STL r0, (SHADOW_VCPU_OFF + SVCPU_R0)(r13)140PPC_STL r1, (SHADOW_VCPU_OFF + SVCPU_R1)(r13)141PPC_STL r2, (SHADOW_VCPU_OFF + SVCPU_R2)(r13)142PPC_STL r3, (SHADOW_VCPU_OFF + SVCPU_R3)(r13)143PPC_STL r4, (SHADOW_VCPU_OFF + SVCPU_R4)(r13)144PPC_STL r5, (SHADOW_VCPU_OFF + SVCPU_R5)(r13)145PPC_STL r6, (SHADOW_VCPU_OFF + SVCPU_R6)(r13)146PPC_STL r7, (SHADOW_VCPU_OFF + SVCPU_R7)(r13)147PPC_STL r8, (SHADOW_VCPU_OFF + SVCPU_R8)(r13)148PPC_STL r9, (SHADOW_VCPU_OFF + SVCPU_R9)(r13)149PPC_STL r10, (SHADOW_VCPU_OFF + SVCPU_R10)(r13)150PPC_STL r11, (SHADOW_VCPU_OFF + SVCPU_R11)(r13)151152/* Restore R1/R2 so we can handle faults */153PPC_LL r1, (SHADOW_VCPU_OFF + SVCPU_HOST_R1)(r13)154PPC_LL r2, (SHADOW_VCPU_OFF + SVCPU_HOST_R2)(r13)155156/* Save guest PC and MSR */157andi. r0,r12,0x2158beq 1f159mfspr r3,SPRN_HSRR0160mfspr r4,SPRN_HSRR1161andi. r12,r12,0x3ffd162b 2f1631: mfsrr0 r3164mfsrr1 r41652:166PPC_STL r3, (SHADOW_VCPU_OFF + SVCPU_PC)(r13)167PPC_STL r4, (SHADOW_VCPU_OFF + SVCPU_SHADOW_SRR1)(r13)168169/* Get scratch'ed off registers */170GET_SCRATCH0(r9)171PPC_LL r8, (SHADOW_VCPU_OFF + SVCPU_SCRATCH0)(r13)172lwz r7, (SHADOW_VCPU_OFF + SVCPU_SCRATCH1)(r13)173174PPC_STL r9, (SHADOW_VCPU_OFF + SVCPU_R13)(r13)175PPC_STL r8, (SHADOW_VCPU_OFF + SVCPU_R12)(r13)176stw r7, (SHADOW_VCPU_OFF + SVCPU_CR)(r13)177178/* Save more register state */179180mfxer r5181mfdar r6182mfdsisr r7183mfctr r8184mflr r9185186stw r5, (SHADOW_VCPU_OFF + SVCPU_XER)(r13)187PPC_STL r6, (SHADOW_VCPU_OFF + SVCPU_FAULT_DAR)(r13)188stw r7, (SHADOW_VCPU_OFF + SVCPU_FAULT_DSISR)(r13)189PPC_STL r8, (SHADOW_VCPU_OFF + SVCPU_CTR)(r13)190PPC_STL r9, (SHADOW_VCPU_OFF + SVCPU_LR)(r13)191192/*193* In order for us to easily get the last instruction,194* we got the #vmexit at, we exploit the fact that the195* virtual layout is still the same here, so we can just196* ld from the guest's PC address197*/198199/* We only load the last instruction when it's safe */200cmpwi r12, BOOK3S_INTERRUPT_DATA_STORAGE201beq ld_last_inst202cmpwi r12, BOOK3S_INTERRUPT_PROGRAM203beq ld_last_inst204cmpwi r12, BOOK3S_INTERRUPT_ALIGNMENT205beq- ld_last_inst206207b no_ld_last_inst208209ld_last_inst:210/* Save off the guest instruction we're at */211212/* In case lwz faults */213li r0, KVM_INST_FETCH_FAILED214215#ifdef USE_QUICK_LAST_INST216217/* Set guest mode to 'jump over instruction' so if lwz faults218* we'll just continue at the next IP. */219li r9, KVM_GUEST_MODE_SKIP220stb r9, (SHADOW_VCPU_OFF + SVCPU_IN_GUEST)(r13)221222/* 1) enable paging for data */223mfmsr r9224ori r11, r9, MSR_DR /* Enable paging for data */225mtmsr r11226sync227/* 2) fetch the instruction */228lwz r0, 0(r3)229/* 3) disable paging again */230mtmsr r9231sync232233#endif234stw r0, (SHADOW_VCPU_OFF + SVCPU_LAST_INST)(r13)235236no_ld_last_inst:237238/* Unset guest mode */239li r9, KVM_GUEST_MODE_NONE240stb r9, (SHADOW_VCPU_OFF + SVCPU_IN_GUEST)(r13)241242/* Switch back to host MMU */243LOAD_HOST_SEGMENTS244245/* Register usage at this point:246*247* R1 = host R1248* R2 = host R2249* R12 = exit handler id250* R13 = shadow vcpu - SHADOW_VCPU_OFF [=PACA on PPC64]251* SVCPU.* = guest *252*253*/254255/* RFI into the highmem handler */256mfmsr r7257ori r7, r7, MSR_IR|MSR_DR|MSR_RI|MSR_ME /* Enable paging */258mtsrr1 r7259/* Load highmem handler address */260PPC_LL r8, (SHADOW_VCPU_OFF + SVCPU_VMHANDLER)(r13)261mtsrr0 r8262263RFI264kvmppc_handler_trampoline_exit_end:265266267