linux/arch/powerpc/kvm/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. 2007
  16 *
  17 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
  18 */
  19
  20#include <linux/jiffies.h>
  21#include <linux/timer.h>
  22#include <linux/types.h>
  23#include <linux/string.h>
  24#include <linux/kvm_host.h>
  25
  26#include <asm/reg.h>
  27#include <asm/time.h>
  28#include <asm/byteorder.h>
  29#include <asm/kvm_ppc.h>
  30#include <asm/disassemble.h>
  31#include "timing.h"
  32
  33#define OP_TRAP 3
  34
  35#define OP_31_XOP_LWZX      23
  36#define OP_31_XOP_LBZX      87
  37#define OP_31_XOP_STWX      151
  38#define OP_31_XOP_STBX      215
  39#define OP_31_XOP_STBUX     247
  40#define OP_31_XOP_LHZX      279
  41#define OP_31_XOP_LHZUX     311
  42#define OP_31_XOP_MFSPR     339
  43#define OP_31_XOP_STHX      407
  44#define OP_31_XOP_STHUX     439
  45#define OP_31_XOP_MTSPR     467
  46#define OP_31_XOP_DCBI      470
  47#define OP_31_XOP_LWBRX     534
  48#define OP_31_XOP_TLBSYNC   566
  49#define OP_31_XOP_STWBRX    662
  50#define OP_31_XOP_LHBRX     790
  51#define OP_31_XOP_STHBRX    918
  52
  53#define OP_LWZ  32
  54#define OP_LWZU 33
  55#define OP_LBZ  34
  56#define OP_LBZU 35
  57#define OP_STW  36
  58#define OP_STWU 37
  59#define OP_STB  38
  60#define OP_STBU 39
  61#define OP_LHZ  40
  62#define OP_LHZU 41
  63#define OP_STH  44
  64#define OP_STHU 45
  65
  66void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
  67{
  68        if (vcpu->arch.tcr & TCR_DIE) {
  69                /* The decrementer ticks at the same rate as the timebase, so
  70                 * that's how we convert the guest DEC value to the number of
  71                 * host ticks. */
  72                unsigned long nr_jiffies;
  73
  74                nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy;
  75                mod_timer(&vcpu->arch.dec_timer,
  76                          get_jiffies_64() + nr_jiffies);
  77        } else {
  78                del_timer(&vcpu->arch.dec_timer);
  79        }
  80}
  81
  82/* XXX to do:
  83 * lhax
  84 * lhaux
  85 * lswx
  86 * lswi
  87 * stswx
  88 * stswi
  89 * lha
  90 * lhau
  91 * lmw
  92 * stmw
  93 *
  94 * XXX is_bigendian should depend on MMU mapping or MSR[LE]
  95 */
  96/* XXX Should probably auto-generate instruction decoding for a particular core
  97 * from opcode tables in the future. */
  98int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
  99{
 100        u32 inst = vcpu->arch.last_inst;
 101        u32 ea;
 102        int ra;
 103        int rb;
 104        int rs;
 105        int rt;
 106        int sprn;
 107        enum emulation_result emulated = EMULATE_DONE;
 108        int advance = 1;
 109
 110        /* this default type might be overwritten by subcategories */
 111        kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
 112
 113        switch (get_op(inst)) {
 114        case OP_TRAP:
 115                vcpu->arch.esr |= ESR_PTR;
 116                kvmppc_core_queue_program(vcpu);
 117                advance = 0;
 118                break;
 119
 120        case 31:
 121                switch (get_xop(inst)) {
 122
 123                case OP_31_XOP_LWZX:
 124                        rt = get_rt(inst);
 125                        emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
 126                        break;
 127
 128                case OP_31_XOP_LBZX:
 129                        rt = get_rt(inst);
 130                        emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
 131                        break;
 132
 133                case OP_31_XOP_STWX:
 134                        rs = get_rs(inst);
 135                        emulated = kvmppc_handle_store(run, vcpu,
 136                                                       vcpu->arch.gpr[rs],
 137                                                       4, 1);
 138                        break;
 139
 140                case OP_31_XOP_STBX:
 141                        rs = get_rs(inst);
 142                        emulated = kvmppc_handle_store(run, vcpu,
 143                                                       vcpu->arch.gpr[rs],
 144                                                       1, 1);
 145                        break;
 146
 147                case OP_31_XOP_STBUX:
 148                        rs = get_rs(inst);
 149                        ra = get_ra(inst);
 150                        rb = get_rb(inst);
 151
 152                        ea = vcpu->arch.gpr[rb];
 153                        if (ra)
 154                                ea += vcpu->arch.gpr[ra];
 155
 156                        emulated = kvmppc_handle_store(run, vcpu,
 157                                                       vcpu->arch.gpr[rs],
 158                                                       1, 1);
 159                        vcpu->arch.gpr[rs] = ea;
 160                        break;
 161
 162                case OP_31_XOP_LHZX:
 163                        rt = get_rt(inst);
 164                        emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
 165                        break;
 166
 167                case OP_31_XOP_LHZUX:
 168                        rt = get_rt(inst);
 169                        ra = get_ra(inst);
 170                        rb = get_rb(inst);
 171
 172                        ea = vcpu->arch.gpr[rb];
 173                        if (ra)
 174                                ea += vcpu->arch.gpr[ra];
 175
 176                        emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
 177                        vcpu->arch.gpr[ra] = ea;
 178                        break;
 179
 180                case OP_31_XOP_MFSPR:
 181                        sprn = get_sprn(inst);
 182                        rt = get_rt(inst);
 183
 184                        switch (sprn) {
 185                        case SPRN_SRR0:
 186                                vcpu->arch.gpr[rt] = vcpu->arch.srr0; break;
 187                        case SPRN_SRR1:
 188                                vcpu->arch.gpr[rt] = vcpu->arch.srr1; break;
 189                        case SPRN_PVR:
 190                                vcpu->arch.gpr[rt] = vcpu->arch.pvr; break;
 191
 192                        /* Note: mftb and TBRL/TBWL are user-accessible, so
 193                         * the guest can always access the real TB anyways.
 194                         * In fact, we probably will never see these traps. */
 195                        case SPRN_TBWL:
 196                                vcpu->arch.gpr[rt] = mftbl(); break;
 197                        case SPRN_TBWU:
 198                                vcpu->arch.gpr[rt] = mftbu(); break;
 199
 200                        case SPRN_SPRG0:
 201                                vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break;
 202                        case SPRN_SPRG1:
 203                                vcpu->arch.gpr[rt] = vcpu->arch.sprg1; break;
 204                        case SPRN_SPRG2:
 205                                vcpu->arch.gpr[rt] = vcpu->arch.sprg2; break;
 206                        case SPRN_SPRG3:
 207                                vcpu->arch.gpr[rt] = vcpu->arch.sprg3; break;
 208                        /* Note: SPRG4-7 are user-readable, so we don't get
 209                         * a trap. */
 210
 211                        default:
 212                                emulated = kvmppc_core_emulate_mfspr(vcpu, sprn, rt);
 213                                if (emulated == EMULATE_FAIL) {
 214                                        printk("mfspr: unknown spr %x\n", sprn);
 215                                        vcpu->arch.gpr[rt] = 0;
 216                                }
 217                                break;
 218                        }
 219                        break;
 220
 221                case OP_31_XOP_STHX:
 222                        rs = get_rs(inst);
 223                        ra = get_ra(inst);
 224                        rb = get_rb(inst);
 225
 226                        emulated = kvmppc_handle_store(run, vcpu,
 227                                                       vcpu->arch.gpr[rs],
 228                                                       2, 1);
 229                        break;
 230
 231                case OP_31_XOP_STHUX:
 232                        rs = get_rs(inst);
 233                        ra = get_ra(inst);
 234                        rb = get_rb(inst);
 235
 236                        ea = vcpu->arch.gpr[rb];
 237                        if (ra)
 238                                ea += vcpu->arch.gpr[ra];
 239
 240                        emulated = kvmppc_handle_store(run, vcpu,
 241                                                       vcpu->arch.gpr[rs],
 242                                                       2, 1);
 243                        vcpu->arch.gpr[ra] = ea;
 244                        break;
 245
 246                case OP_31_XOP_MTSPR:
 247                        sprn = get_sprn(inst);
 248                        rs = get_rs(inst);
 249                        switch (sprn) {
 250                        case SPRN_SRR0:
 251                                vcpu->arch.srr0 = vcpu->arch.gpr[rs]; break;
 252                        case SPRN_SRR1:
 253                                vcpu->arch.srr1 = vcpu->arch.gpr[rs]; break;
 254
 255                        /* XXX We need to context-switch the timebase for
 256                         * watchdog and FIT. */
 257                        case SPRN_TBWL: break;
 258                        case SPRN_TBWU: break;
 259
 260                        case SPRN_DEC:
 261                                vcpu->arch.dec = vcpu->arch.gpr[rs];
 262                                kvmppc_emulate_dec(vcpu);
 263                                break;
 264
 265                        case SPRN_SPRG0:
 266                                vcpu->arch.sprg0 = vcpu->arch.gpr[rs]; break;
 267                        case SPRN_SPRG1:
 268                                vcpu->arch.sprg1 = vcpu->arch.gpr[rs]; break;
 269                        case SPRN_SPRG2:
 270                                vcpu->arch.sprg2 = vcpu->arch.gpr[rs]; break;
 271                        case SPRN_SPRG3:
 272                                vcpu->arch.sprg3 = vcpu->arch.gpr[rs]; break;
 273
 274                        default:
 275                                emulated = kvmppc_core_emulate_mtspr(vcpu, sprn, rs);
 276                                if (emulated == EMULATE_FAIL)
 277                                        printk("mtspr: unknown spr %x\n", sprn);
 278                                break;
 279                        }
 280                        break;
 281
 282                case OP_31_XOP_DCBI:
 283                        /* Do nothing. The guest is performing dcbi because
 284                         * hardware DMA is not snooped by the dcache, but
 285                         * emulated DMA either goes through the dcache as
 286                         * normal writes, or the host kernel has handled dcache
 287                         * coherence. */
 288                        break;
 289
 290                case OP_31_XOP_LWBRX:
 291                        rt = get_rt(inst);
 292                        emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0);
 293                        break;
 294
 295                case OP_31_XOP_TLBSYNC:
 296                        break;
 297
 298                case OP_31_XOP_STWBRX:
 299                        rs = get_rs(inst);
 300                        ra = get_ra(inst);
 301                        rb = get_rb(inst);
 302
 303                        emulated = kvmppc_handle_store(run, vcpu,
 304                                                       vcpu->arch.gpr[rs],
 305                                                       4, 0);
 306                        break;
 307
 308                case OP_31_XOP_LHBRX:
 309                        rt = get_rt(inst);
 310                        emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
 311                        break;
 312
 313                case OP_31_XOP_STHBRX:
 314                        rs = get_rs(inst);
 315                        ra = get_ra(inst);
 316                        rb = get_rb(inst);
 317
 318                        emulated = kvmppc_handle_store(run, vcpu,
 319                                                       vcpu->arch.gpr[rs],
 320                                                       2, 0);
 321                        break;
 322
 323                default:
 324                        /* Attempt core-specific emulation below. */
 325                        emulated = EMULATE_FAIL;
 326                }
 327                break;
 328
 329        case OP_LWZ:
 330                rt = get_rt(inst);
 331                emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
 332                break;
 333
 334        case OP_LWZU:
 335                ra = get_ra(inst);
 336                rt = get_rt(inst);
 337                emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
 338                vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
 339                break;
 340
 341        case OP_LBZ:
 342                rt = get_rt(inst);
 343                emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
 344                break;
 345
 346        case OP_LBZU:
 347                ra = get_ra(inst);
 348                rt = get_rt(inst);
 349                emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
 350                vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
 351                break;
 352
 353        case OP_STW:
 354                rs = get_rs(inst);
 355                emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
 356                                               4, 1);
 357                break;
 358
 359        case OP_STWU:
 360                ra = get_ra(inst);
 361                rs = get_rs(inst);
 362                emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
 363                                               4, 1);
 364                vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
 365                break;
 366
 367        case OP_STB:
 368                rs = get_rs(inst);
 369                emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
 370                                               1, 1);
 371                break;
 372
 373        case OP_STBU:
 374                ra = get_ra(inst);
 375                rs = get_rs(inst);
 376                emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
 377                                               1, 1);
 378                vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
 379                break;
 380
 381        case OP_LHZ:
 382                rt = get_rt(inst);
 383                emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
 384                break;
 385
 386        case OP_LHZU:
 387                ra = get_ra(inst);
 388                rt = get_rt(inst);
 389                emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
 390                vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
 391                break;
 392
 393        case OP_STH:
 394                rs = get_rs(inst);
 395                emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
 396                                               2, 1);
 397                break;
 398
 399        case OP_STHU:
 400                ra = get_ra(inst);
 401                rs = get_rs(inst);
 402                emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs],
 403                                               2, 1);
 404                vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed;
 405                break;
 406
 407        default:
 408                emulated = EMULATE_FAIL;
 409        }
 410
 411        if (emulated == EMULATE_FAIL) {
 412                emulated = kvmppc_core_emulate_op(run, vcpu, inst, &advance);
 413                if (emulated == EMULATE_FAIL) {
 414                        advance = 0;
 415                        printk(KERN_ERR "Couldn't emulate instruction 0x%08x "
 416                               "(op %d xop %d)\n", inst, get_op(inst), get_xop(inst));
 417                }
 418        }
 419
 420        KVMTRACE_3D(PPC_INSTR, vcpu, inst, (int)vcpu->arch.pc, emulated, entryexit);
 421
 422        if (advance)
 423                vcpu->arch.pc += 4; /* Advance past emulated instruction. */
 424
 425        return emulated;
 426}
 427