linux/arch/powerpc/kvm/booke_emulate.c
<<
>>
Prefs
   1/*
   2 * This program is free software; you can redistribute it and/or modify
   3 * it under the terms of the GNU General Public License, version 2, as
   4 * published by the Free Software Foundation.
   5 *
   6 * This program is distributed in the hope that it will be useful,
   7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   9 * GNU General Public License for more details.
  10 *
  11 * You should have received a copy of the GNU General Public License
  12 * along with this program; if not, write to the Free Software
  13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  14 *
  15 * Copyright IBM Corp. 2008
  16 *
  17 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  18 */
  19
  20#include <linux/kvm_host.h>
  21#include <asm/disassemble.h>
  22
  23#include "booke.h"
  24
  25#define OP_19_XOP_RFI     50
  26
  27#define OP_31_XOP_MFMSR   83
  28#define OP_31_XOP_WRTEE   131
  29#define OP_31_XOP_MTMSR   146
  30#define OP_31_XOP_WRTEEI  163
  31
  32static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
  33{
  34        vcpu->arch.pc = vcpu->arch.srr0;
  35        kvmppc_set_msr(vcpu, vcpu->arch.srr1);
  36}
  37
  38int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
  39                            unsigned int inst, int *advance)
  40{
  41        int emulated = EMULATE_DONE;
  42        int rs;
  43        int rt;
  44
  45        switch (get_op(inst)) {
  46        case 19:
  47                switch (get_xop(inst)) {
  48                case OP_19_XOP_RFI:
  49                        kvmppc_emul_rfi(vcpu);
  50                        kvmppc_set_exit_type(vcpu, EMULATED_RFI_EXITS);
  51                        *advance = 0;
  52                        break;
  53
  54                default:
  55                        emulated = EMULATE_FAIL;
  56                        break;
  57                }
  58                break;
  59
  60        case 31:
  61                switch (get_xop(inst)) {
  62
  63                case OP_31_XOP_MFMSR:
  64                        rt = get_rt(inst);
  65                        vcpu->arch.gpr[rt] = vcpu->arch.msr;
  66                        kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS);
  67                        break;
  68
  69                case OP_31_XOP_MTMSR:
  70                        rs = get_rs(inst);
  71                        kvmppc_set_exit_type(vcpu, EMULATED_MTMSR_EXITS);
  72                        kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]);
  73                        break;
  74
  75                case OP_31_XOP_WRTEE:
  76                        rs = get_rs(inst);
  77                        vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
  78                                                         | (vcpu->arch.gpr[rs] & MSR_EE);
  79                        kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
  80                        break;
  81
  82                case OP_31_XOP_WRTEEI:
  83                        vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE)
  84                                                         | (inst & MSR_EE);
  85                        kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS);
  86                        break;
  87
  88                default:
  89                        emulated = EMULATE_FAIL;
  90                }
  91
  92                break;
  93
  94        default:
  95                emulated = EMULATE_FAIL;
  96        }
  97
  98        return emulated;
  99}
 100
 101int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
 102{
 103        int emulated = EMULATE_DONE;
 104
 105        switch (sprn) {
 106        case SPRN_DEAR:
 107                vcpu->arch.dear = vcpu->arch.gpr[rs]; break;
 108        case SPRN_ESR:
 109                vcpu->arch.esr = vcpu->arch.gpr[rs]; break;
 110        case SPRN_DBCR0:
 111                vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break;
 112        case SPRN_DBCR1:
 113                vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break;
 114        case SPRN_DBSR:
 115                vcpu->arch.dbsr &= ~vcpu->arch.gpr[rs]; break;
 116        case SPRN_TSR:
 117                vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break;
 118        case SPRN_TCR:
 119                vcpu->arch.tcr = vcpu->arch.gpr[rs];
 120                kvmppc_emulate_dec(vcpu);
 121                break;
 122
 123        /* Note: SPRG4-7 are user-readable. These values are
 124         * loaded into the real SPRGs when resuming the
 125         * guest. */
 126        case SPRN_SPRG4:
 127                vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break;
 128        case SPRN_SPRG5:
 129                vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break;
 130        case SPRN_SPRG6:
 131                vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break;
 132        case SPRN_SPRG7:
 133                vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break;
 134
 135        case SPRN_IVPR:
 136                vcpu->arch.ivpr = vcpu->arch.gpr[rs];
 137                break;
 138        case SPRN_IVOR0:
 139                vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL] = vcpu->arch.gpr[rs];
 140                break;
 141        case SPRN_IVOR1:
 142                vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK] = vcpu->arch.gpr[rs];
 143                break;
 144        case SPRN_IVOR2:
 145                vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE] = vcpu->arch.gpr[rs];
 146                break;
 147        case SPRN_IVOR3:
 148                vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE] = vcpu->arch.gpr[rs];
 149                break;
 150        case SPRN_IVOR4:
 151                vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL] = vcpu->arch.gpr[rs];
 152                break;
 153        case SPRN_IVOR5:
 154                vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT] = vcpu->arch.gpr[rs];
 155                break;
 156        case SPRN_IVOR6:
 157                vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM] = vcpu->arch.gpr[rs];
 158                break;
 159        case SPRN_IVOR7:
 160                vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL] = vcpu->arch.gpr[rs];
 161                break;
 162        case SPRN_IVOR8:
 163                vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL] = vcpu->arch.gpr[rs];
 164                break;
 165        case SPRN_IVOR9:
 166                vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL] = vcpu->arch.gpr[rs];
 167                break;
 168        case SPRN_IVOR10:
 169                vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER] = vcpu->arch.gpr[rs];
 170                break;
 171        case SPRN_IVOR11:
 172                vcpu->arch.ivor[BOOKE_IRQPRIO_FIT] = vcpu->arch.gpr[rs];
 173                break;
 174        case SPRN_IVOR12:
 175                vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG] = vcpu->arch.gpr[rs];
 176                break;
 177        case SPRN_IVOR13:
 178                vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS] = vcpu->arch.gpr[rs];
 179                break;
 180        case SPRN_IVOR14:
 181                vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS] = vcpu->arch.gpr[rs];
 182                break;
 183        case SPRN_IVOR15:
 184                vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = vcpu->arch.gpr[rs];
 185                break;
 186
 187        default:
 188                emulated = EMULATE_FAIL;
 189        }
 190
 191        return emulated;
 192}
 193
 194int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
 195{
 196        int emulated = EMULATE_DONE;
 197
 198        switch (sprn) {
 199        case SPRN_IVPR:
 200                vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break;
 201        case SPRN_DEAR:
 202                vcpu->arch.gpr[rt] = vcpu->arch.dear; break;
 203        case SPRN_ESR:
 204                vcpu->arch.gpr[rt] = vcpu->arch.esr; break;
 205        case SPRN_DBCR0:
 206                vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break;
 207        case SPRN_DBCR1:
 208                vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break;
 209        case SPRN_DBSR:
 210                vcpu->arch.gpr[rt] = vcpu->arch.dbsr; break;
 211
 212        case SPRN_IVOR0:
 213                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_CRITICAL];
 214                break;
 215        case SPRN_IVOR1:
 216                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_MACHINE_CHECK];
 217                break;
 218        case SPRN_IVOR2:
 219                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DATA_STORAGE];
 220                break;
 221        case SPRN_IVOR3:
 222                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_INST_STORAGE];
 223                break;
 224        case SPRN_IVOR4:
 225                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_EXTERNAL];
 226                break;
 227        case SPRN_IVOR5:
 228                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ALIGNMENT];
 229                break;
 230        case SPRN_IVOR6:
 231                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PROGRAM];
 232                break;
 233        case SPRN_IVOR7:
 234                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FP_UNAVAIL];
 235                break;
 236        case SPRN_IVOR8:
 237                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SYSCALL];
 238                break;
 239        case SPRN_IVOR9:
 240                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_AP_UNAVAIL];
 241                break;
 242        case SPRN_IVOR10:
 243                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DECREMENTER];
 244                break;
 245        case SPRN_IVOR11:
 246                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_FIT];
 247                break;
 248        case SPRN_IVOR12:
 249                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_WATCHDOG];
 250                break;
 251        case SPRN_IVOR13:
 252                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS];
 253                break;
 254        case SPRN_IVOR14:
 255                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS];
 256                break;
 257        case SPRN_IVOR15:
 258                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
 259                break;
 260
 261        default:
 262                emulated = EMULATE_FAIL;
 263        }
 264
 265        return emulated;
 266}
 267