linux/arch/powerpc/kvm/e500_emulate.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2008 Freescale Semiconductor, Inc. All rights reserved.
   3 *
   4 * Author: Yu Liu, <yu.liu@freescale.com>
   5 *
   6 * Description:
   7 * This file is derived from arch/powerpc/kvm/44x_emulate.c,
   8 * by Hollis Blanchard <hollisb@us.ibm.com>.
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License, version 2, as
  12 * published by the Free Software Foundation.
  13 */
  14
  15#include <asm/kvm_ppc.h>
  16#include <asm/disassemble.h>
  17#include <asm/kvm_e500.h>
  18
  19#include "booke.h"
  20#include "e500_tlb.h"
  21
  22#define XOP_TLBIVAX 786
  23#define XOP_TLBSX   914
  24#define XOP_TLBRE   946
  25#define XOP_TLBWE   978
  26
  27int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
  28                           unsigned int inst, int *advance)
  29{
  30        int emulated = EMULATE_DONE;
  31        int ra;
  32        int rb;
  33
  34        switch (get_op(inst)) {
  35        case 31:
  36                switch (get_xop(inst)) {
  37
  38                case XOP_TLBRE:
  39                        emulated = kvmppc_e500_emul_tlbre(vcpu);
  40                        break;
  41
  42                case XOP_TLBWE:
  43                        emulated = kvmppc_e500_emul_tlbwe(vcpu);
  44                        break;
  45
  46                case XOP_TLBSX:
  47                        rb = get_rb(inst);
  48                        emulated = kvmppc_e500_emul_tlbsx(vcpu,rb);
  49                        break;
  50
  51                case XOP_TLBIVAX:
  52                        ra = get_ra(inst);
  53                        rb = get_rb(inst);
  54                        emulated = kvmppc_e500_emul_tlbivax(vcpu, ra, rb);
  55                        break;
  56
  57                default:
  58                        emulated = EMULATE_FAIL;
  59                }
  60
  61                break;
  62
  63        default:
  64                emulated = EMULATE_FAIL;
  65        }
  66
  67        if (emulated == EMULATE_FAIL)
  68                emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance);
  69
  70        return emulated;
  71}
  72
  73int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
  74{
  75        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
  76        int emulated = EMULATE_DONE;
  77
  78        switch (sprn) {
  79        case SPRN_PID:
  80                vcpu_e500->pid[0] = vcpu->arch.shadow_pid =
  81                        vcpu->arch.pid = vcpu->arch.gpr[rs];
  82                break;
  83        case SPRN_PID1:
  84                vcpu_e500->pid[1] = vcpu->arch.gpr[rs]; break;
  85        case SPRN_PID2:
  86                vcpu_e500->pid[2] = vcpu->arch.gpr[rs]; break;
  87        case SPRN_MAS0:
  88                vcpu_e500->mas0 = vcpu->arch.gpr[rs]; break;
  89        case SPRN_MAS1:
  90                vcpu_e500->mas1 = vcpu->arch.gpr[rs]; break;
  91        case SPRN_MAS2:
  92                vcpu_e500->mas2 = vcpu->arch.gpr[rs]; break;
  93        case SPRN_MAS3:
  94                vcpu_e500->mas3 = vcpu->arch.gpr[rs]; break;
  95        case SPRN_MAS4:
  96                vcpu_e500->mas4 = vcpu->arch.gpr[rs]; break;
  97        case SPRN_MAS6:
  98                vcpu_e500->mas6 = vcpu->arch.gpr[rs]; break;
  99        case SPRN_MAS7:
 100                vcpu_e500->mas7 = vcpu->arch.gpr[rs]; break;
 101        case SPRN_L1CSR1:
 102                vcpu_e500->l1csr1 = vcpu->arch.gpr[rs]; break;
 103        case SPRN_HID0:
 104                vcpu_e500->hid0 = vcpu->arch.gpr[rs]; break;
 105        case SPRN_HID1:
 106                vcpu_e500->hid1 = vcpu->arch.gpr[rs]; break;
 107
 108        case SPRN_MMUCSR0:
 109                emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500,
 110                                vcpu->arch.gpr[rs]);
 111                break;
 112
 113        /* extra exceptions */
 114        case SPRN_IVOR32:
 115                vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = vcpu->arch.gpr[rs];
 116                break;
 117        case SPRN_IVOR33:
 118                vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = vcpu->arch.gpr[rs];
 119                break;
 120        case SPRN_IVOR34:
 121                vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = vcpu->arch.gpr[rs];
 122                break;
 123        case SPRN_IVOR35:
 124                vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = vcpu->arch.gpr[rs];
 125                break;
 126
 127        default:
 128                emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, rs);
 129        }
 130
 131        return emulated;
 132}
 133
 134int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
 135{
 136        struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
 137        int emulated = EMULATE_DONE;
 138
 139        switch (sprn) {
 140        case SPRN_PID:
 141                vcpu->arch.gpr[rt] = vcpu_e500->pid[0]; break;
 142        case SPRN_PID1:
 143                vcpu->arch.gpr[rt] = vcpu_e500->pid[1]; break;
 144        case SPRN_PID2:
 145                vcpu->arch.gpr[rt] = vcpu_e500->pid[2]; break;
 146        case SPRN_MAS0:
 147                vcpu->arch.gpr[rt] = vcpu_e500->mas0; break;
 148        case SPRN_MAS1:
 149                vcpu->arch.gpr[rt] = vcpu_e500->mas1; break;
 150        case SPRN_MAS2:
 151                vcpu->arch.gpr[rt] = vcpu_e500->mas2; break;
 152        case SPRN_MAS3:
 153                vcpu->arch.gpr[rt] = vcpu_e500->mas3; break;
 154        case SPRN_MAS4:
 155                vcpu->arch.gpr[rt] = vcpu_e500->mas4; break;
 156        case SPRN_MAS6:
 157                vcpu->arch.gpr[rt] = vcpu_e500->mas6; break;
 158        case SPRN_MAS7:
 159                vcpu->arch.gpr[rt] = vcpu_e500->mas7; break;
 160
 161        case SPRN_TLB0CFG:
 162                vcpu->arch.gpr[rt] = mfspr(SPRN_TLB0CFG);
 163                vcpu->arch.gpr[rt] &= ~0xfffUL;
 164                vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[0];
 165                break;
 166
 167        case SPRN_TLB1CFG:
 168                vcpu->arch.gpr[rt] = mfspr(SPRN_TLB1CFG);
 169                vcpu->arch.gpr[rt] &= ~0xfffUL;
 170                vcpu->arch.gpr[rt] |= vcpu_e500->guest_tlb_size[1];
 171                break;
 172
 173        case SPRN_L1CSR1:
 174                vcpu->arch.gpr[rt] = vcpu_e500->l1csr1; break;
 175        case SPRN_HID0:
 176                vcpu->arch.gpr[rt] = vcpu_e500->hid0; break;
 177        case SPRN_HID1:
 178                vcpu->arch.gpr[rt] = vcpu_e500->hid1; break;
 179
 180        case SPRN_MMUCSR0:
 181                vcpu->arch.gpr[rt] = 0; break;
 182
 183        case SPRN_MMUCFG:
 184                vcpu->arch.gpr[rt] = mfspr(SPRN_MMUCFG); break;
 185
 186        /* extra exceptions */
 187        case SPRN_IVOR32:
 188                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
 189                break;
 190        case SPRN_IVOR33:
 191                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA];
 192                break;
 193        case SPRN_IVOR34:
 194                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND];
 195                break;
 196        case SPRN_IVOR35:
 197                vcpu->arch.gpr[rt] = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR];
 198                break;
 199        default:
 200                emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, rt);
 201        }
 202
 203        return emulated;
 204}
 205
 206