root/arch/powerpc/kvm/emulate.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. kvmppc_emulate_dec
  2. kvmppc_get_dec
  3. kvmppc_emulate_mtspr
  4. kvmppc_emulate_mfspr
  5. kvmppc_emulate_instruction

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *
   4  * Copyright IBM Corp. 2007
   5  * Copyright 2011 Freescale Semiconductor, Inc.
   6  *
   7  * Authors: Hollis Blanchard <hollisb@us.ibm.com>
   8  */
   9 
  10 #include <linux/jiffies.h>
  11 #include <linux/hrtimer.h>
  12 #include <linux/types.h>
  13 #include <linux/string.h>
  14 #include <linux/kvm_host.h>
  15 #include <linux/clockchips.h>
  16 
  17 #include <asm/reg.h>
  18 #include <asm/time.h>
  19 #include <asm/byteorder.h>
  20 #include <asm/kvm_ppc.h>
  21 #include <asm/disassemble.h>
  22 #include <asm/ppc-opcode.h>
  23 #include "timing.h"
  24 #include "trace.h"
  25 
  26 void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
  27 {
  28         unsigned long dec_nsec;
  29         unsigned long long dec_time;
  30 
  31         pr_debug("mtDEC: %lx\n", vcpu->arch.dec);
  32         hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
  33 
  34 #ifdef CONFIG_PPC_BOOK3S
  35         /* mtdec lowers the interrupt line when positive. */
  36         kvmppc_core_dequeue_dec(vcpu);
  37 #endif
  38 
  39 #ifdef CONFIG_BOOKE
  40         /* On BOOKE, DEC = 0 is as good as decrementer not enabled */
  41         if (vcpu->arch.dec == 0)
  42                 return;
  43 #endif
  44 
  45         /*
  46          * The decrementer ticks at the same rate as the timebase, so
  47          * that's how we convert the guest DEC value to the number of
  48          * host ticks.
  49          */
  50 
  51         dec_time = vcpu->arch.dec;
  52         /*
  53          * Guest timebase ticks at the same frequency as host timebase.
  54          * So use the host timebase calculations for decrementer emulation.
  55          */
  56         dec_time = tb_to_ns(dec_time);
  57         dec_nsec = do_div(dec_time, NSEC_PER_SEC);
  58         hrtimer_start(&vcpu->arch.dec_timer,
  59                 ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL);
  60         vcpu->arch.dec_jiffies = get_tb();
  61 }
  62 
  63 u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
  64 {
  65         u64 jd = tb - vcpu->arch.dec_jiffies;
  66 
  67 #ifdef CONFIG_BOOKE
  68         if (vcpu->arch.dec < jd)
  69                 return 0;
  70 #endif
  71 
  72         return vcpu->arch.dec - jd;
  73 }
  74 
  75 static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
  76 {
  77         enum emulation_result emulated = EMULATE_DONE;
  78         ulong spr_val = kvmppc_get_gpr(vcpu, rs);
  79 
  80         switch (sprn) {
  81         case SPRN_SRR0:
  82                 kvmppc_set_srr0(vcpu, spr_val);
  83                 break;
  84         case SPRN_SRR1:
  85                 kvmppc_set_srr1(vcpu, spr_val);
  86                 break;
  87 
  88         /* XXX We need to context-switch the timebase for
  89          * watchdog and FIT. */
  90         case SPRN_TBWL: break;
  91         case SPRN_TBWU: break;
  92 
  93         case SPRN_DEC:
  94                 vcpu->arch.dec = (u32) spr_val;
  95                 kvmppc_emulate_dec(vcpu);
  96                 break;
  97 
  98         case SPRN_SPRG0:
  99                 kvmppc_set_sprg0(vcpu, spr_val);
 100                 break;
 101         case SPRN_SPRG1:
 102                 kvmppc_set_sprg1(vcpu, spr_val);
 103                 break;
 104         case SPRN_SPRG2:
 105                 kvmppc_set_sprg2(vcpu, spr_val);
 106                 break;
 107         case SPRN_SPRG3:
 108                 kvmppc_set_sprg3(vcpu, spr_val);
 109                 break;
 110 
 111         /* PIR can legally be written, but we ignore it */
 112         case SPRN_PIR: break;
 113 
 114         default:
 115                 emulated = vcpu->kvm->arch.kvm_ops->emulate_mtspr(vcpu, sprn,
 116                                                                   spr_val);
 117                 if (emulated == EMULATE_FAIL)
 118                         printk(KERN_INFO "mtspr: unknown spr "
 119                                 "0x%x\n", sprn);
 120                 break;
 121         }
 122 
 123         kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
 124 
 125         return emulated;
 126 }
 127 
 128 static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
 129 {
 130         enum emulation_result emulated = EMULATE_DONE;
 131         ulong spr_val = 0;
 132 
 133         switch (sprn) {
 134         case SPRN_SRR0:
 135                 spr_val = kvmppc_get_srr0(vcpu);
 136                 break;
 137         case SPRN_SRR1:
 138                 spr_val = kvmppc_get_srr1(vcpu);
 139                 break;
 140         case SPRN_PVR:
 141                 spr_val = vcpu->arch.pvr;
 142                 break;
 143         case SPRN_PIR:
 144                 spr_val = vcpu->vcpu_id;
 145                 break;
 146 
 147         /* Note: mftb and TBRL/TBWL are user-accessible, so
 148          * the guest can always access the real TB anyways.
 149          * In fact, we probably will never see these traps. */
 150         case SPRN_TBWL:
 151                 spr_val = get_tb() >> 32;
 152                 break;
 153         case SPRN_TBWU:
 154                 spr_val = get_tb();
 155                 break;
 156 
 157         case SPRN_SPRG0:
 158                 spr_val = kvmppc_get_sprg0(vcpu);
 159                 break;
 160         case SPRN_SPRG1:
 161                 spr_val = kvmppc_get_sprg1(vcpu);
 162                 break;
 163         case SPRN_SPRG2:
 164                 spr_val = kvmppc_get_sprg2(vcpu);
 165                 break;
 166         case SPRN_SPRG3:
 167                 spr_val = kvmppc_get_sprg3(vcpu);
 168                 break;
 169         /* Note: SPRG4-7 are user-readable, so we don't get
 170          * a trap. */
 171 
 172         case SPRN_DEC:
 173                 spr_val = kvmppc_get_dec(vcpu, get_tb());
 174                 break;
 175         default:
 176                 emulated = vcpu->kvm->arch.kvm_ops->emulate_mfspr(vcpu, sprn,
 177                                                                   &spr_val);
 178                 if (unlikely(emulated == EMULATE_FAIL)) {
 179                         printk(KERN_INFO "mfspr: unknown spr "
 180                                 "0x%x\n", sprn);
 181                 }
 182                 break;
 183         }
 184 
 185         if (emulated == EMULATE_DONE)
 186                 kvmppc_set_gpr(vcpu, rt, spr_val);
 187         kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
 188 
 189         return emulated;
 190 }
 191 
 192 /* XXX Should probably auto-generate instruction decoding for a particular core
 193  * from opcode tables in the future. */
 194 int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
 195 {
 196         u32 inst;
 197         int rs, rt, sprn;
 198         enum emulation_result emulated;
 199         int advance = 1;
 200 
 201         /* this default type might be overwritten by subcategories */
 202         kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
 203 
 204         emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst);
 205         if (emulated != EMULATE_DONE)
 206                 return emulated;
 207 
 208         pr_debug("Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
 209 
 210         rs = get_rs(inst);
 211         rt = get_rt(inst);
 212         sprn = get_sprn(inst);
 213 
 214         switch (get_op(inst)) {
 215         case OP_TRAP:
 216 #ifdef CONFIG_PPC_BOOK3S
 217         case OP_TRAP_64:
 218                 kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP);
 219 #else
 220                 kvmppc_core_queue_program(vcpu,
 221                                           vcpu->arch.shared->esr | ESR_PTR);
 222 #endif
 223                 advance = 0;
 224                 break;
 225 
 226         case 31:
 227                 switch (get_xop(inst)) {
 228 
 229                 case OP_31_XOP_TRAP:
 230 #ifdef CONFIG_64BIT
 231                 case OP_31_XOP_TRAP_64:
 232 #endif
 233 #ifdef CONFIG_PPC_BOOK3S
 234                         kvmppc_core_queue_program(vcpu, SRR1_PROGTRAP);
 235 #else
 236                         kvmppc_core_queue_program(vcpu,
 237                                         vcpu->arch.shared->esr | ESR_PTR);
 238 #endif
 239                         advance = 0;
 240                         break;
 241 
 242                 case OP_31_XOP_MFSPR:
 243                         emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
 244                         if (emulated == EMULATE_AGAIN) {
 245                                 emulated = EMULATE_DONE;
 246                                 advance = 0;
 247                         }
 248                         break;
 249 
 250                 case OP_31_XOP_MTSPR:
 251                         emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
 252                         if (emulated == EMULATE_AGAIN) {
 253                                 emulated = EMULATE_DONE;
 254                                 advance = 0;
 255                         }
 256                         break;
 257 
 258                 case OP_31_XOP_TLBSYNC:
 259                         break;
 260 
 261                 default:
 262                         /* Attempt core-specific emulation below. */
 263                         emulated = EMULATE_FAIL;
 264                 }
 265                 break;
 266 
 267         case 0:
 268                 /*
 269                  * Instruction with primary opcode 0. Based on PowerISA
 270                  * these are illegal instructions.
 271                  */
 272                 if (inst == KVMPPC_INST_SW_BREAKPOINT) {
 273                         run->exit_reason = KVM_EXIT_DEBUG;
 274                         run->debug.arch.status = 0;
 275                         run->debug.arch.address = kvmppc_get_pc(vcpu);
 276                         emulated = EMULATE_EXIT_USER;
 277                         advance = 0;
 278                 } else
 279                         emulated = EMULATE_FAIL;
 280 
 281                 break;
 282 
 283         default:
 284                 emulated = EMULATE_FAIL;
 285         }
 286 
 287         if (emulated == EMULATE_FAIL) {
 288                 emulated = vcpu->kvm->arch.kvm_ops->emulate_op(run, vcpu, inst,
 289                                                                &advance);
 290                 if (emulated == EMULATE_AGAIN) {
 291                         advance = 0;
 292                 } else if (emulated == EMULATE_FAIL) {
 293                         advance = 0;
 294                         printk(KERN_ERR "Couldn't emulate instruction 0x%08x "
 295                                "(op %d xop %d)\n", inst, get_op(inst), get_xop(inst));
 296                 }
 297         }
 298 
 299         trace_kvm_ppc_instr(inst, kvmppc_get_pc(vcpu), emulated);
 300 
 301         /* Advance past emulated instruction. */
 302         if (advance)
 303                 kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4);
 304 
 305         return emulated;
 306 }
 307 EXPORT_SYMBOL_GPL(kvmppc_emulate_instruction);

/* [<][>][^][v][top][bottom][index][help] */