linux/arch/powerpc/kvm/book3s_rmhandlers.S
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 *
   4 * Copyright SUSE Linux Products GmbH 2009
   5 *
   6 * Authors: Alexander Graf <agraf@suse.de>
   7 */
   8
   9#include <asm/ppc_asm.h>
  10#include <asm/kvm_asm.h>
  11#include <asm/reg.h>
  12#include <asm/mmu.h>
  13#include <asm/page.h>
  14#include <asm/asm-offsets.h>
  15#include <asm/asm-compat.h>
  16
  17#ifdef CONFIG_PPC_BOOK3S_64
  18#include <asm/exception-64s.h>
  19#endif
  20
  21/*****************************************************************************
  22 *                                                                           *
  23 *        Real Mode handlers that need to be in low physical memory          *
  24 *                                                                           *
  25 ****************************************************************************/
  26
  27#if defined(CONFIG_PPC_BOOK3S_64)
  28
  29#ifdef PPC64_ELF_ABI_v2
  30#define FUNC(name)              name
  31#else
  32#define FUNC(name)              GLUE(.,name)
  33#endif
  34
  35#elif defined(CONFIG_PPC_BOOK3S_32)
  36
  37#define FUNC(name)              name
  38
  39#define RFI_TO_KERNEL   rfi
  40#define RFI_TO_GUEST    rfi
  41
  42.macro INTERRUPT_TRAMPOLINE intno
  43
  44.global kvmppc_trampoline_\intno
  45kvmppc_trampoline_\intno:
  46
  47        mtspr   SPRN_SPRG_SCRATCH0, r13         /* Save r13 */
  48
  49        /*
  50         * First thing to do is to find out if we're coming
  51         * from a KVM guest or a Linux process.
  52         *
  53         * To distinguish, we check a magic byte in the PACA/current
  54         */
  55        mfspr   r13, SPRN_SPRG_THREAD
  56        lwz     r13, THREAD_KVM_SVCPU(r13)
  57        /* PPC32 can have a NULL pointer - let's check for that */
  58        mtspr   SPRN_SPRG_SCRATCH1, r12         /* Save r12 */
  59        mfcr    r12
  60        cmpwi   r13, 0
  61        bne     1f
  622:      mtcr    r12
  63        mfspr   r12, SPRN_SPRG_SCRATCH1
  64        mfspr   r13, SPRN_SPRG_SCRATCH0         /* r13 = original r13 */
  65        b       kvmppc_resume_\intno            /* Get back original handler */
  66
  671:      tophys(r13, r13)
  68        stw     r12, HSTATE_SCRATCH1(r13)
  69        mfspr   r12, SPRN_SPRG_SCRATCH1
  70        stw     r12, HSTATE_SCRATCH0(r13)
  71        lbz     r12, HSTATE_IN_GUEST(r13)
  72        cmpwi   r12, KVM_GUEST_MODE_NONE
  73        bne     ..kvmppc_handler_hasmagic_\intno
  74        /* No KVM guest? Then jump back to the Linux handler! */
  75        lwz     r12, HSTATE_SCRATCH1(r13)
  76        b       2b
  77
  78        /* Now we know we're handling a KVM guest */
  79..kvmppc_handler_hasmagic_\intno:
  80
  81        /* Should we just skip the faulting instruction? */
  82        cmpwi   r12, KVM_GUEST_MODE_SKIP
  83        beq     kvmppc_handler_skip_ins
  84
  85        /* Let's store which interrupt we're handling */
  86        li      r12, \intno
  87
  88        /* Jump into the SLB exit code that goes to the highmem handler */
  89        b       kvmppc_handler_trampoline_exit
  90
  91.endm
  92
  93INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_SYSTEM_RESET
  94INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_MACHINE_CHECK
  95INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_DATA_STORAGE
  96INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_INST_STORAGE
  97INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_EXTERNAL
  98INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_ALIGNMENT
  99INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_PROGRAM
 100INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_FP_UNAVAIL
 101INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_DECREMENTER
 102INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_SYSCALL
 103INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_TRACE
 104INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_PERFMON
 105INTERRUPT_TRAMPOLINE    BOOK3S_INTERRUPT_ALTIVEC
 106
 107/*
 108 * Bring us back to the faulting code, but skip the
 109 * faulting instruction.
 110 *
 111 * This is a generic exit path from the interrupt
 112 * trampolines above.
 113 *
 114 * Input Registers:
 115 *
 116 * R12            = free
 117 * R13            = Shadow VCPU (PACA)
 118 * HSTATE.SCRATCH0 = guest R12
 119 * HSTATE.SCRATCH1 = guest CR
 120 * SPRG_SCRATCH0  = guest R13
 121 *
 122 */
 123kvmppc_handler_skip_ins:
 124
 125        /* Patch the IP to the next instruction */
 126        mfsrr0  r12
 127        addi    r12, r12, 4
 128        mtsrr0  r12
 129
 130        /* Clean up all state */
 131        lwz     r12, HSTATE_SCRATCH1(r13)
 132        mtcr    r12
 133        PPC_LL  r12, HSTATE_SCRATCH0(r13)
 134        GET_SCRATCH0(r13)
 135
 136        /* And get back into the code */
 137        RFI_TO_KERNEL
 138#endif
 139
 140/*
 141 * Call kvmppc_handler_trampoline_enter in real mode
 142 *
 143 * On entry, r4 contains the guest shadow MSR
 144 * MSR.EE has to be 0 when calling this function
 145 */
 146_GLOBAL_TOC(kvmppc_entry_trampoline)
 147        mfmsr   r5
 148        LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter)
 149        toreal(r7)
 150
 151        li      r6, MSR_IR | MSR_DR
 152        andc    r6, r5, r6      /* Clear DR and IR in MSR value */
 153        /*
 154         * Set EE in HOST_MSR so that it's enabled when we get into our
 155         * C exit handler function.
 156         */
 157        ori     r5, r5, MSR_EE
 158        mtsrr0  r7
 159        mtsrr1  r6
 160        RFI_TO_KERNEL
 161
 162#include "book3s_segment.S"
 163