1d94d71cbSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 2d17051cbSAlexander Graf/* 3d17051cbSAlexander Graf * 4d17051cbSAlexander Graf * Copyright SUSE Linux Products GmbH 2010 5940b45ecSScott Wood * Copyright 2010-2011 Freescale Semiconductor, Inc. 6d17051cbSAlexander Graf * 7d17051cbSAlexander Graf * Authors: Alexander Graf <agraf@suse.de> 8d17051cbSAlexander Graf */ 9d17051cbSAlexander Graf 10d17051cbSAlexander Graf#include <asm/ppc_asm.h> 11d17051cbSAlexander Graf#include <asm/kvm_asm.h> 12d17051cbSAlexander Graf#include <asm/reg.h> 13d17051cbSAlexander Graf#include <asm/page.h> 14d17051cbSAlexander Graf#include <asm/asm-offsets.h> 15ec0c464cSChristophe Leroy#include <asm/asm-compat.h> 16d17051cbSAlexander Graf 17d17051cbSAlexander Graf#define KVM_MAGIC_PAGE (-4096) 1892234722SAlexander Graf 1992234722SAlexander Graf#ifdef CONFIG_64BIT 2092234722SAlexander Graf#define LL64(reg, offs, reg2) ld reg, (offs)(reg2) 2192234722SAlexander Graf#define STL64(reg, offs, reg2) std reg, (offs)(reg2) 2292234722SAlexander Graf#else 2392234722SAlexander Graf#define LL64(reg, offs, reg2) lwz reg, (offs + 4)(reg2) 2492234722SAlexander Graf#define STL64(reg, offs, reg2) stw reg, (offs + 4)(reg2) 2592234722SAlexander Graf#endif 2692234722SAlexander Graf 2792234722SAlexander Graf#define SCRATCH_SAVE \ 2892234722SAlexander Graf /* Enable critical section. We are critical if \ 2992234722SAlexander Graf shared->critical == r1 */ \ 3092234722SAlexander Graf STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0); \ 3192234722SAlexander Graf \ 3292234722SAlexander Graf /* Save state */ \ 3392234722SAlexander Graf PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \ 3492234722SAlexander Graf PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \ 3592234722SAlexander Graf mfcr r31; \ 3692234722SAlexander Graf stw r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); 3792234722SAlexander Graf 3892234722SAlexander Graf#define SCRATCH_RESTORE \ 3992234722SAlexander Graf /* Restore state */ \ 4092234722SAlexander Graf PPC_LL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \ 4192234722SAlexander Graf lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); \ 4292234722SAlexander Graf mtcr r30; \ 4392234722SAlexander Graf PPC_LL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \ 4492234722SAlexander Graf \ 4592234722SAlexander Graf /* Disable critical section. We are critical if \ 4692234722SAlexander Graf shared->critical == r1 and r2 is always != r1 */ \ 4792234722SAlexander Graf STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0); 48819a63dcSAlexander Graf 49befdc0a6SLiu Yu-B13201.global kvm_template_start 50befdc0a6SLiu Yu-B13201kvm_template_start: 51befdc0a6SLiu Yu-B13201 52819a63dcSAlexander Graf.global kvm_emulate_mtmsrd 53819a63dcSAlexander Grafkvm_emulate_mtmsrd: 54819a63dcSAlexander Graf 55819a63dcSAlexander Graf SCRATCH_SAVE 56819a63dcSAlexander Graf 57819a63dcSAlexander Graf /* Put MSR & ~(MSR_EE|MSR_RI) in r31 */ 58819a63dcSAlexander Graf LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) 59819a63dcSAlexander Graf lis r30, (~(MSR_EE | MSR_RI))@h 60819a63dcSAlexander Graf ori r30, r30, (~(MSR_EE | MSR_RI))@l 61819a63dcSAlexander Graf and r31, r31, r30 62819a63dcSAlexander Graf 63819a63dcSAlexander Graf /* OR the register's (MSR_EE|MSR_RI) on MSR */ 64819a63dcSAlexander Grafkvm_emulate_mtmsrd_reg: 65df08bd10SAlexander Graf ori r30, r0, 0 66df08bd10SAlexander Graf andi. r30, r30, (MSR_EE|MSR_RI) 67819a63dcSAlexander Graf or r31, r31, r30 68819a63dcSAlexander Graf 69819a63dcSAlexander Graf /* Put MSR back into magic page */ 70819a63dcSAlexander Graf STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) 71819a63dcSAlexander Graf 72819a63dcSAlexander Graf /* Check if we have to fetch an interrupt */ 73819a63dcSAlexander Graf lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0) 74819a63dcSAlexander Graf cmpwi r31, 0 75819a63dcSAlexander Graf beq+ no_check 76819a63dcSAlexander Graf 77819a63dcSAlexander Graf /* Check if we may trigger an interrupt */ 78819a63dcSAlexander Graf andi. r30, r30, MSR_EE 79819a63dcSAlexander Graf beq no_check 80819a63dcSAlexander Graf 81819a63dcSAlexander Graf SCRATCH_RESTORE 82819a63dcSAlexander Graf 83819a63dcSAlexander Graf /* Nag hypervisor */ 84df08bd10SAlexander Grafkvm_emulate_mtmsrd_orig_ins: 85819a63dcSAlexander Graf tlbsync 86819a63dcSAlexander Graf 87819a63dcSAlexander Graf b kvm_emulate_mtmsrd_branch 88819a63dcSAlexander Graf 89819a63dcSAlexander Grafno_check: 90819a63dcSAlexander Graf 91819a63dcSAlexander Graf SCRATCH_RESTORE 92819a63dcSAlexander Graf 93819a63dcSAlexander Graf /* Go back to caller */ 94819a63dcSAlexander Grafkvm_emulate_mtmsrd_branch: 95819a63dcSAlexander Graf b . 96819a63dcSAlexander Grafkvm_emulate_mtmsrd_end: 97819a63dcSAlexander Graf 98819a63dcSAlexander Graf.global kvm_emulate_mtmsrd_branch_offs 99819a63dcSAlexander Grafkvm_emulate_mtmsrd_branch_offs: 100819a63dcSAlexander Graf .long (kvm_emulate_mtmsrd_branch - kvm_emulate_mtmsrd) / 4 101819a63dcSAlexander Graf 102819a63dcSAlexander Graf.global kvm_emulate_mtmsrd_reg_offs 103819a63dcSAlexander Grafkvm_emulate_mtmsrd_reg_offs: 104819a63dcSAlexander Graf .long (kvm_emulate_mtmsrd_reg - kvm_emulate_mtmsrd) / 4 105819a63dcSAlexander Graf 106df08bd10SAlexander Graf.global kvm_emulate_mtmsrd_orig_ins_offs 107df08bd10SAlexander Grafkvm_emulate_mtmsrd_orig_ins_offs: 108df08bd10SAlexander Graf .long (kvm_emulate_mtmsrd_orig_ins - kvm_emulate_mtmsrd) / 4 109df08bd10SAlexander Graf 110819a63dcSAlexander Graf.global kvm_emulate_mtmsrd_len 111819a63dcSAlexander Grafkvm_emulate_mtmsrd_len: 112819a63dcSAlexander Graf .long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4 11378109277SAlexander Graf 11478109277SAlexander Graf 115d35b1075SBharat Bhushan#define MSR_SAFE_BITS (MSR_EE | MSR_RI) 11678109277SAlexander Graf#define MSR_CRITICAL_BITS ~MSR_SAFE_BITS 11778109277SAlexander Graf 11878109277SAlexander Graf.global kvm_emulate_mtmsr 11978109277SAlexander Grafkvm_emulate_mtmsr: 12078109277SAlexander Graf 12178109277SAlexander Graf SCRATCH_SAVE 12278109277SAlexander Graf 12378109277SAlexander Graf /* Fetch old MSR in r31 */ 12478109277SAlexander Graf LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) 12578109277SAlexander Graf 12678109277SAlexander Graf /* Find the changed bits between old and new MSR */ 12778109277SAlexander Grafkvm_emulate_mtmsr_reg1: 128512ba59eSAlexander Graf ori r30, r0, 0 129512ba59eSAlexander Graf xor r31, r30, r31 13078109277SAlexander Graf 13178109277SAlexander Graf /* Check if we need to really do mtmsr */ 13278109277SAlexander Graf LOAD_REG_IMMEDIATE(r30, MSR_CRITICAL_BITS) 13378109277SAlexander Graf and. r31, r31, r30 13478109277SAlexander Graf 13578109277SAlexander Graf /* No critical bits changed? Maybe we can stay in the guest. */ 13678109277SAlexander Graf beq maybe_stay_in_guest 13778109277SAlexander Graf 13878109277SAlexander Grafdo_mtmsr: 13978109277SAlexander Graf 14078109277SAlexander Graf SCRATCH_RESTORE 14178109277SAlexander Graf 14278109277SAlexander Graf /* Just fire off the mtmsr if it's critical */ 14378109277SAlexander Grafkvm_emulate_mtmsr_orig_ins: 14478109277SAlexander Graf mtmsr r0 14578109277SAlexander Graf 14678109277SAlexander Graf b kvm_emulate_mtmsr_branch 14778109277SAlexander Graf 14878109277SAlexander Grafmaybe_stay_in_guest: 14978109277SAlexander Graf 150512ba59eSAlexander Graf /* Get the target register in r30 */ 151512ba59eSAlexander Grafkvm_emulate_mtmsr_reg2: 152512ba59eSAlexander Graf ori r30, r0, 0 153512ba59eSAlexander Graf 154f9208427SBharat Bhushan /* Put MSR into magic page because we don't call mtmsr */ 155f9208427SBharat Bhushan STL64(r30, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) 156f9208427SBharat Bhushan 15778109277SAlexander Graf /* Check if we have to fetch an interrupt */ 15878109277SAlexander Graf lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0) 15978109277SAlexander Graf cmpwi r31, 0 16078109277SAlexander Graf beq+ no_mtmsr 16178109277SAlexander Graf 16278109277SAlexander Graf /* Check if we may trigger an interrupt */ 163512ba59eSAlexander Graf andi. r31, r30, MSR_EE 164f9208427SBharat Bhushan bne do_mtmsr 16578109277SAlexander Graf 16678109277SAlexander Grafno_mtmsr: 16778109277SAlexander Graf 16878109277SAlexander Graf SCRATCH_RESTORE 16978109277SAlexander Graf 17078109277SAlexander Graf /* Go back to caller */ 17178109277SAlexander Grafkvm_emulate_mtmsr_branch: 17278109277SAlexander Graf b . 17378109277SAlexander Grafkvm_emulate_mtmsr_end: 17478109277SAlexander Graf 17578109277SAlexander Graf.global kvm_emulate_mtmsr_branch_offs 17678109277SAlexander Grafkvm_emulate_mtmsr_branch_offs: 17778109277SAlexander Graf .long (kvm_emulate_mtmsr_branch - kvm_emulate_mtmsr) / 4 17878109277SAlexander Graf 17978109277SAlexander Graf.global kvm_emulate_mtmsr_reg1_offs 18078109277SAlexander Grafkvm_emulate_mtmsr_reg1_offs: 18178109277SAlexander Graf .long (kvm_emulate_mtmsr_reg1 - kvm_emulate_mtmsr) / 4 18278109277SAlexander Graf 18378109277SAlexander Graf.global kvm_emulate_mtmsr_reg2_offs 18478109277SAlexander Grafkvm_emulate_mtmsr_reg2_offs: 18578109277SAlexander Graf .long (kvm_emulate_mtmsr_reg2 - kvm_emulate_mtmsr) / 4 18678109277SAlexander Graf 18778109277SAlexander Graf.global kvm_emulate_mtmsr_orig_ins_offs 18878109277SAlexander Grafkvm_emulate_mtmsr_orig_ins_offs: 18978109277SAlexander Graf .long (kvm_emulate_mtmsr_orig_ins - kvm_emulate_mtmsr) / 4 19078109277SAlexander Graf 19178109277SAlexander Graf.global kvm_emulate_mtmsr_len 19278109277SAlexander Grafkvm_emulate_mtmsr_len: 19378109277SAlexander Graf .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4 194644bfa01SAlexander Graf 195*caff52dcSMichael Ellerman#ifdef CONFIG_BOOKE 196*caff52dcSMichael Ellerman 197940b45ecSScott Wood/* also used for wrteei 1 */ 198940b45ecSScott Wood.global kvm_emulate_wrtee 199940b45ecSScott Woodkvm_emulate_wrtee: 200644bfa01SAlexander Graf 201644bfa01SAlexander Graf SCRATCH_SAVE 202644bfa01SAlexander Graf 203644bfa01SAlexander Graf /* Fetch old MSR in r31 */ 204644bfa01SAlexander Graf LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) 205644bfa01SAlexander Graf 206940b45ecSScott Wood /* Insert new MSR[EE] */ 207940b45ecSScott Woodkvm_emulate_wrtee_reg: 208940b45ecSScott Wood ori r30, r0, 0 209940b45ecSScott Wood rlwimi r31, r30, 0, MSR_EE 210644bfa01SAlexander Graf 211940b45ecSScott Wood /* 212940b45ecSScott Wood * If MSR[EE] is now set, check for a pending interrupt. 213940b45ecSScott Wood * We could skip this if MSR[EE] was already on, but that 214940b45ecSScott Wood * should be rare, so don't bother. 215940b45ecSScott Wood */ 216940b45ecSScott Wood andi. r30, r30, MSR_EE 217940b45ecSScott Wood 218940b45ecSScott Wood /* Put MSR into magic page because we don't call wrtee */ 219940b45ecSScott Wood STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) 220940b45ecSScott Wood 221940b45ecSScott Wood beq no_wrtee 222940b45ecSScott Wood 223940b45ecSScott Wood /* Check if we have to fetch an interrupt */ 224940b45ecSScott Wood lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0) 225940b45ecSScott Wood cmpwi r30, 0 226940b45ecSScott Wood bne do_wrtee 227940b45ecSScott Wood 228940b45ecSScott Woodno_wrtee: 229940b45ecSScott Wood SCRATCH_RESTORE 230940b45ecSScott Wood 231940b45ecSScott Wood /* Go back to caller */ 232940b45ecSScott Woodkvm_emulate_wrtee_branch: 233940b45ecSScott Wood b . 234940b45ecSScott Wood 235940b45ecSScott Wooddo_wrtee: 236940b45ecSScott Wood SCRATCH_RESTORE 237940b45ecSScott Wood 238940b45ecSScott Wood /* Just fire off the wrtee if it's critical */ 239940b45ecSScott Woodkvm_emulate_wrtee_orig_ins: 240940b45ecSScott Wood wrtee r0 241940b45ecSScott Wood 242940b45ecSScott Wood b kvm_emulate_wrtee_branch 243940b45ecSScott Wood 244940b45ecSScott Woodkvm_emulate_wrtee_end: 245940b45ecSScott Wood 246940b45ecSScott Wood.global kvm_emulate_wrtee_branch_offs 247940b45ecSScott Woodkvm_emulate_wrtee_branch_offs: 248940b45ecSScott Wood .long (kvm_emulate_wrtee_branch - kvm_emulate_wrtee) / 4 249940b45ecSScott Wood 250940b45ecSScott Wood.global kvm_emulate_wrtee_reg_offs 251940b45ecSScott Woodkvm_emulate_wrtee_reg_offs: 252940b45ecSScott Wood .long (kvm_emulate_wrtee_reg - kvm_emulate_wrtee) / 4 253940b45ecSScott Wood 254940b45ecSScott Wood.global kvm_emulate_wrtee_orig_ins_offs 255940b45ecSScott Woodkvm_emulate_wrtee_orig_ins_offs: 256940b45ecSScott Wood .long (kvm_emulate_wrtee_orig_ins - kvm_emulate_wrtee) / 4 257940b45ecSScott Wood 258940b45ecSScott Wood.global kvm_emulate_wrtee_len 259940b45ecSScott Woodkvm_emulate_wrtee_len: 260940b45ecSScott Wood .long (kvm_emulate_wrtee_end - kvm_emulate_wrtee) / 4 261940b45ecSScott Wood 262940b45ecSScott Wood.global kvm_emulate_wrteei_0 263940b45ecSScott Woodkvm_emulate_wrteei_0: 264940b45ecSScott Wood SCRATCH_SAVE 265940b45ecSScott Wood 266940b45ecSScott Wood /* Fetch old MSR in r31 */ 267940b45ecSScott Wood LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) 268940b45ecSScott Wood 269940b45ecSScott Wood /* Remove MSR_EE from old MSR */ 270940b45ecSScott Wood rlwinm r31, r31, 0, ~MSR_EE 271644bfa01SAlexander Graf 272644bfa01SAlexander Graf /* Write new MSR value back */ 273644bfa01SAlexander Graf STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) 274644bfa01SAlexander Graf 275644bfa01SAlexander Graf SCRATCH_RESTORE 276644bfa01SAlexander Graf 277644bfa01SAlexander Graf /* Go back to caller */ 278940b45ecSScott Woodkvm_emulate_wrteei_0_branch: 279644bfa01SAlexander Graf b . 280940b45ecSScott Woodkvm_emulate_wrteei_0_end: 281644bfa01SAlexander Graf 282940b45ecSScott Wood.global kvm_emulate_wrteei_0_branch_offs 283940b45ecSScott Woodkvm_emulate_wrteei_0_branch_offs: 284940b45ecSScott Wood .long (kvm_emulate_wrteei_0_branch - kvm_emulate_wrteei_0) / 4 285644bfa01SAlexander Graf 286940b45ecSScott Wood.global kvm_emulate_wrteei_0_len 287940b45ecSScott Woodkvm_emulate_wrteei_0_len: 288940b45ecSScott Wood .long (kvm_emulate_wrteei_0_end - kvm_emulate_wrteei_0) / 4 289cbe487faSAlexander Graf 290*caff52dcSMichael Ellerman#endif /* CONFIG_BOOKE */ 291*caff52dcSMichael Ellerman 292*caff52dcSMichael Ellerman#ifdef CONFIG_PPC_BOOK3S_32 293*caff52dcSMichael Ellerman 294cbe487faSAlexander Graf.global kvm_emulate_mtsrin 295cbe487faSAlexander Grafkvm_emulate_mtsrin: 296cbe487faSAlexander Graf 297cbe487faSAlexander Graf SCRATCH_SAVE 298cbe487faSAlexander Graf 299cbe487faSAlexander Graf LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) 300cbe487faSAlexander Graf andi. r31, r31, MSR_DR | MSR_IR 301cbe487faSAlexander Graf beq kvm_emulate_mtsrin_reg1 302cbe487faSAlexander Graf 303cbe487faSAlexander Graf SCRATCH_RESTORE 304cbe487faSAlexander Graf 305cbe487faSAlexander Grafkvm_emulate_mtsrin_orig_ins: 306cbe487faSAlexander Graf nop 307cbe487faSAlexander Graf b kvm_emulate_mtsrin_branch 308cbe487faSAlexander Graf 309cbe487faSAlexander Grafkvm_emulate_mtsrin_reg1: 310cbe487faSAlexander Graf /* rX >> 26 */ 311cbe487faSAlexander Graf rlwinm r30,r0,6,26,29 312cbe487faSAlexander Graf 313cbe487faSAlexander Grafkvm_emulate_mtsrin_reg2: 314cbe487faSAlexander Graf stw r0, (KVM_MAGIC_PAGE + KVM_MAGIC_SR)(r30) 315cbe487faSAlexander Graf 316cbe487faSAlexander Graf SCRATCH_RESTORE 317cbe487faSAlexander Graf 318cbe487faSAlexander Graf /* Go back to caller */ 319cbe487faSAlexander Grafkvm_emulate_mtsrin_branch: 320cbe487faSAlexander Graf b . 321cbe487faSAlexander Grafkvm_emulate_mtsrin_end: 322cbe487faSAlexander Graf 323cbe487faSAlexander Graf.global kvm_emulate_mtsrin_branch_offs 324cbe487faSAlexander Grafkvm_emulate_mtsrin_branch_offs: 325cbe487faSAlexander Graf .long (kvm_emulate_mtsrin_branch - kvm_emulate_mtsrin) / 4 326cbe487faSAlexander Graf 327cbe487faSAlexander Graf.global kvm_emulate_mtsrin_reg1_offs 328cbe487faSAlexander Grafkvm_emulate_mtsrin_reg1_offs: 329cbe487faSAlexander Graf .long (kvm_emulate_mtsrin_reg1 - kvm_emulate_mtsrin) / 4 330cbe487faSAlexander Graf 331cbe487faSAlexander Graf.global kvm_emulate_mtsrin_reg2_offs 332cbe487faSAlexander Grafkvm_emulate_mtsrin_reg2_offs: 333cbe487faSAlexander Graf .long (kvm_emulate_mtsrin_reg2 - kvm_emulate_mtsrin) / 4 334cbe487faSAlexander Graf 335cbe487faSAlexander Graf.global kvm_emulate_mtsrin_orig_ins_offs 336cbe487faSAlexander Grafkvm_emulate_mtsrin_orig_ins_offs: 337cbe487faSAlexander Graf .long (kvm_emulate_mtsrin_orig_ins - kvm_emulate_mtsrin) / 4 338cbe487faSAlexander Graf 339cbe487faSAlexander Graf.global kvm_emulate_mtsrin_len 340cbe487faSAlexander Grafkvm_emulate_mtsrin_len: 341cbe487faSAlexander Graf .long (kvm_emulate_mtsrin_end - kvm_emulate_mtsrin) / 4 342befdc0a6SLiu Yu-B13201 343*caff52dcSMichael Ellerman#endif /* CONFIG_PPC_BOOK3S_32 */ 344*caff52dcSMichael Ellerman 3450cb0837fSMichael Ellerman .balign 4 3460cb0837fSMichael Ellerman .global kvm_tmp 3470cb0837fSMichael Ellermankvm_tmp: 3480cb0837fSMichael Ellerman .space (64 * 1024) 3490cb0837fSMichael Ellerman 3500cb0837fSMichael Ellerman.global kvm_tmp_end 3510cb0837fSMichael Ellermankvm_tmp_end: 3520cb0837fSMichael Ellerman 353befdc0a6SLiu Yu-B13201.global kvm_template_end 354befdc0a6SLiu Yu-B13201kvm_template_end: 355