Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2008-2011 Freescale Semiconductor, Inc. All rights reserved.
0004  *
0005  * Author: Yu Liu, <yu.liu@freescale.com>
0006  *
0007  * Description:
0008  * This file is derived from arch/powerpc/kvm/44x_emulate.c,
0009  * by Hollis Blanchard <hollisb@us.ibm.com>.
0010  */
0011 
0012 #include <asm/kvm_ppc.h>
0013 #include <asm/disassemble.h>
0014 #include <asm/dbell.h>
0015 #include <asm/reg_booke.h>
0016 
0017 #include "booke.h"
0018 #include "e500.h"
0019 
0020 #define XOP_DCBTLS  166
0021 #define XOP_MSGSND  206
0022 #define XOP_MSGCLR  238
0023 #define XOP_MFTMR   366
0024 #define XOP_TLBIVAX 786
0025 #define XOP_TLBSX   914
0026 #define XOP_TLBRE   946
0027 #define XOP_TLBWE   978
0028 #define XOP_TLBILX  18
0029 #define XOP_EHPRIV  270
0030 
0031 #ifdef CONFIG_KVM_E500MC
0032 static int dbell2prio(ulong param)
0033 {
0034     int msg = param & PPC_DBELL_TYPE_MASK;
0035     int prio = -1;
0036 
0037     switch (msg) {
0038     case PPC_DBELL_TYPE(PPC_DBELL):
0039         prio = BOOKE_IRQPRIO_DBELL;
0040         break;
0041     case PPC_DBELL_TYPE(PPC_DBELL_CRIT):
0042         prio = BOOKE_IRQPRIO_DBELL_CRIT;
0043         break;
0044     default:
0045         break;
0046     }
0047 
0048     return prio;
0049 }
0050 
0051 static int kvmppc_e500_emul_msgclr(struct kvm_vcpu *vcpu, int rb)
0052 {
0053     ulong param = vcpu->arch.regs.gpr[rb];
0054     int prio = dbell2prio(param);
0055 
0056     if (prio < 0)
0057         return EMULATE_FAIL;
0058 
0059     clear_bit(prio, &vcpu->arch.pending_exceptions);
0060     return EMULATE_DONE;
0061 }
0062 
0063 static int kvmppc_e500_emul_msgsnd(struct kvm_vcpu *vcpu, int rb)
0064 {
0065     ulong param = vcpu->arch.regs.gpr[rb];
0066     int prio = dbell2prio(rb);
0067     int pir = param & PPC_DBELL_PIR_MASK;
0068     unsigned long i;
0069     struct kvm_vcpu *cvcpu;
0070 
0071     if (prio < 0)
0072         return EMULATE_FAIL;
0073 
0074     kvm_for_each_vcpu(i, cvcpu, vcpu->kvm) {
0075         int cpir = cvcpu->arch.shared->pir;
0076         if ((param & PPC_DBELL_MSG_BRDCAST) || (cpir == pir)) {
0077             set_bit(prio, &cvcpu->arch.pending_exceptions);
0078             kvm_vcpu_kick(cvcpu);
0079         }
0080     }
0081 
0082     return EMULATE_DONE;
0083 }
0084 #endif
0085 
0086 static int kvmppc_e500_emul_ehpriv(struct kvm_vcpu *vcpu,
0087                    unsigned int inst, int *advance)
0088 {
0089     int emulated = EMULATE_DONE;
0090 
0091     switch (get_oc(inst)) {
0092     case EHPRIV_OC_DEBUG:
0093         vcpu->run->exit_reason = KVM_EXIT_DEBUG;
0094         vcpu->run->debug.arch.address = vcpu->arch.regs.nip;
0095         vcpu->run->debug.arch.status = 0;
0096         kvmppc_account_exit(vcpu, DEBUG_EXITS);
0097         emulated = EMULATE_EXIT_USER;
0098         *advance = 0;
0099         break;
0100     default:
0101         emulated = EMULATE_FAIL;
0102     }
0103     return emulated;
0104 }
0105 
0106 static int kvmppc_e500_emul_dcbtls(struct kvm_vcpu *vcpu)
0107 {
0108     struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
0109 
0110     /* Always fail to lock the cache */
0111     vcpu_e500->l1csr0 |= L1CSR0_CUL;
0112     return EMULATE_DONE;
0113 }
0114 
0115 static int kvmppc_e500_emul_mftmr(struct kvm_vcpu *vcpu, unsigned int inst,
0116                   int rt)
0117 {
0118     /* Expose one thread per vcpu */
0119     if (get_tmrn(inst) == TMRN_TMCFG0) {
0120         kvmppc_set_gpr(vcpu, rt,
0121                    1 | (1 << TMRN_TMCFG0_NATHRD_SHIFT));
0122         return EMULATE_DONE;
0123     }
0124 
0125     return EMULATE_FAIL;
0126 }
0127 
0128 int kvmppc_core_emulate_op_e500(struct kvm_vcpu *vcpu,
0129                 unsigned int inst, int *advance)
0130 {
0131     int emulated = EMULATE_DONE;
0132     int ra = get_ra(inst);
0133     int rb = get_rb(inst);
0134     int rt = get_rt(inst);
0135     gva_t ea;
0136 
0137     switch (get_op(inst)) {
0138     case 31:
0139         switch (get_xop(inst)) {
0140 
0141         case XOP_DCBTLS:
0142             emulated = kvmppc_e500_emul_dcbtls(vcpu);
0143             break;
0144 
0145 #ifdef CONFIG_KVM_E500MC
0146         case XOP_MSGSND:
0147             emulated = kvmppc_e500_emul_msgsnd(vcpu, rb);
0148             break;
0149 
0150         case XOP_MSGCLR:
0151             emulated = kvmppc_e500_emul_msgclr(vcpu, rb);
0152             break;
0153 #endif
0154 
0155         case XOP_TLBRE:
0156             emulated = kvmppc_e500_emul_tlbre(vcpu);
0157             break;
0158 
0159         case XOP_TLBWE:
0160             emulated = kvmppc_e500_emul_tlbwe(vcpu);
0161             break;
0162 
0163         case XOP_TLBSX:
0164             ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
0165             emulated = kvmppc_e500_emul_tlbsx(vcpu, ea);
0166             break;
0167 
0168         case XOP_TLBILX: {
0169             int type = rt & 0x3;
0170             ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
0171             emulated = kvmppc_e500_emul_tlbilx(vcpu, type, ea);
0172             break;
0173         }
0174 
0175         case XOP_TLBIVAX:
0176             ea = kvmppc_get_ea_indexed(vcpu, ra, rb);
0177             emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
0178             break;
0179 
0180         case XOP_MFTMR:
0181             emulated = kvmppc_e500_emul_mftmr(vcpu, inst, rt);
0182             break;
0183 
0184         case XOP_EHPRIV:
0185             emulated = kvmppc_e500_emul_ehpriv(vcpu, inst, advance);
0186             break;
0187 
0188         default:
0189             emulated = EMULATE_FAIL;
0190         }
0191 
0192         break;
0193 
0194     default:
0195         emulated = EMULATE_FAIL;
0196     }
0197 
0198     if (emulated == EMULATE_FAIL)
0199         emulated = kvmppc_booke_emulate_op(vcpu, inst, advance);
0200 
0201     return emulated;
0202 }
0203 
0204 int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
0205 {
0206     struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
0207     int emulated = EMULATE_DONE;
0208 
0209     switch (sprn) {
0210 #ifndef CONFIG_KVM_BOOKE_HV
0211     case SPRN_PID:
0212         kvmppc_set_pid(vcpu, spr_val);
0213         break;
0214     case SPRN_PID1:
0215         if (spr_val != 0)
0216             return EMULATE_FAIL;
0217         vcpu_e500->pid[1] = spr_val;
0218         break;
0219     case SPRN_PID2:
0220         if (spr_val != 0)
0221             return EMULATE_FAIL;
0222         vcpu_e500->pid[2] = spr_val;
0223         break;
0224     case SPRN_MAS0:
0225         vcpu->arch.shared->mas0 = spr_val;
0226         break;
0227     case SPRN_MAS1:
0228         vcpu->arch.shared->mas1 = spr_val;
0229         break;
0230     case SPRN_MAS2:
0231         vcpu->arch.shared->mas2 = spr_val;
0232         break;
0233     case SPRN_MAS3:
0234         vcpu->arch.shared->mas7_3 &= ~(u64)0xffffffff;
0235         vcpu->arch.shared->mas7_3 |= spr_val;
0236         break;
0237     case SPRN_MAS4:
0238         vcpu->arch.shared->mas4 = spr_val;
0239         break;
0240     case SPRN_MAS6:
0241         vcpu->arch.shared->mas6 = spr_val;
0242         break;
0243     case SPRN_MAS7:
0244         vcpu->arch.shared->mas7_3 &= (u64)0xffffffff;
0245         vcpu->arch.shared->mas7_3 |= (u64)spr_val << 32;
0246         break;
0247 #endif
0248     case SPRN_L1CSR0:
0249         vcpu_e500->l1csr0 = spr_val;
0250         vcpu_e500->l1csr0 &= ~(L1CSR0_DCFI | L1CSR0_CLFC);
0251         break;
0252     case SPRN_L1CSR1:
0253         vcpu_e500->l1csr1 = spr_val;
0254         vcpu_e500->l1csr1 &= ~(L1CSR1_ICFI | L1CSR1_ICLFR);
0255         break;
0256     case SPRN_HID0:
0257         vcpu_e500->hid0 = spr_val;
0258         break;
0259     case SPRN_HID1:
0260         vcpu_e500->hid1 = spr_val;
0261         break;
0262 
0263     case SPRN_MMUCSR0:
0264         emulated = kvmppc_e500_emul_mt_mmucsr0(vcpu_e500,
0265                 spr_val);
0266         break;
0267 
0268     case SPRN_PWRMGTCR0:
0269         /*
0270          * Guest relies on host power management configurations
0271          * Treat the request as a general store
0272          */
0273         vcpu->arch.pwrmgtcr0 = spr_val;
0274         break;
0275 
0276     case SPRN_BUCSR:
0277         /*
0278          * If we are here, it means that we have already flushed the
0279          * branch predictor, so just return to guest.
0280          */
0281         break;
0282 
0283     /* extra exceptions */
0284 #ifdef CONFIG_SPE_POSSIBLE
0285     case SPRN_IVOR32:
0286         vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val;
0287         break;
0288     case SPRN_IVOR33:
0289         vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA] = spr_val;
0290         break;
0291     case SPRN_IVOR34:
0292         vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND] = spr_val;
0293         break;
0294 #endif
0295 #ifdef CONFIG_ALTIVEC
0296     case SPRN_IVOR32:
0297         vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL] = spr_val;
0298         break;
0299     case SPRN_IVOR33:
0300         vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST] = spr_val;
0301         break;
0302 #endif
0303     case SPRN_IVOR35:
0304         vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR] = spr_val;
0305         break;
0306 #ifdef CONFIG_KVM_BOOKE_HV
0307     case SPRN_IVOR36:
0308         vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL] = spr_val;
0309         break;
0310     case SPRN_IVOR37:
0311         vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT] = spr_val;
0312         break;
0313 #endif
0314     default:
0315         emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, spr_val);
0316     }
0317 
0318     return emulated;
0319 }
0320 
0321 int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
0322 {
0323     struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
0324     int emulated = EMULATE_DONE;
0325 
0326     switch (sprn) {
0327 #ifndef CONFIG_KVM_BOOKE_HV
0328     case SPRN_PID:
0329         *spr_val = vcpu_e500->pid[0];
0330         break;
0331     case SPRN_PID1:
0332         *spr_val = vcpu_e500->pid[1];
0333         break;
0334     case SPRN_PID2:
0335         *spr_val = vcpu_e500->pid[2];
0336         break;
0337     case SPRN_MAS0:
0338         *spr_val = vcpu->arch.shared->mas0;
0339         break;
0340     case SPRN_MAS1:
0341         *spr_val = vcpu->arch.shared->mas1;
0342         break;
0343     case SPRN_MAS2:
0344         *spr_val = vcpu->arch.shared->mas2;
0345         break;
0346     case SPRN_MAS3:
0347         *spr_val = (u32)vcpu->arch.shared->mas7_3;
0348         break;
0349     case SPRN_MAS4:
0350         *spr_val = vcpu->arch.shared->mas4;
0351         break;
0352     case SPRN_MAS6:
0353         *spr_val = vcpu->arch.shared->mas6;
0354         break;
0355     case SPRN_MAS7:
0356         *spr_val = vcpu->arch.shared->mas7_3 >> 32;
0357         break;
0358 #endif
0359     case SPRN_DECAR:
0360         *spr_val = vcpu->arch.decar;
0361         break;
0362     case SPRN_TLB0CFG:
0363         *spr_val = vcpu->arch.tlbcfg[0];
0364         break;
0365     case SPRN_TLB1CFG:
0366         *spr_val = vcpu->arch.tlbcfg[1];
0367         break;
0368     case SPRN_TLB0PS:
0369         if (!has_feature(vcpu, VCPU_FTR_MMU_V2))
0370             return EMULATE_FAIL;
0371         *spr_val = vcpu->arch.tlbps[0];
0372         break;
0373     case SPRN_TLB1PS:
0374         if (!has_feature(vcpu, VCPU_FTR_MMU_V2))
0375             return EMULATE_FAIL;
0376         *spr_val = vcpu->arch.tlbps[1];
0377         break;
0378     case SPRN_L1CSR0:
0379         *spr_val = vcpu_e500->l1csr0;
0380         break;
0381     case SPRN_L1CSR1:
0382         *spr_val = vcpu_e500->l1csr1;
0383         break;
0384     case SPRN_HID0:
0385         *spr_val = vcpu_e500->hid0;
0386         break;
0387     case SPRN_HID1:
0388         *spr_val = vcpu_e500->hid1;
0389         break;
0390     case SPRN_SVR:
0391         *spr_val = vcpu_e500->svr;
0392         break;
0393 
0394     case SPRN_MMUCSR0:
0395         *spr_val = 0;
0396         break;
0397 
0398     case SPRN_MMUCFG:
0399         *spr_val = vcpu->arch.mmucfg;
0400         break;
0401     case SPRN_EPTCFG:
0402         if (!has_feature(vcpu, VCPU_FTR_MMU_V2))
0403             return EMULATE_FAIL;
0404         /*
0405          * Legacy Linux guests access EPTCFG register even if the E.PT
0406          * category is disabled in the VM. Give them a chance to live.
0407          */
0408         *spr_val = vcpu->arch.eptcfg;
0409         break;
0410 
0411     case SPRN_PWRMGTCR0:
0412         *spr_val = vcpu->arch.pwrmgtcr0;
0413         break;
0414 
0415     /* extra exceptions */
0416 #ifdef CONFIG_SPE_POSSIBLE
0417     case SPRN_IVOR32:
0418         *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL];
0419         break;
0420     case SPRN_IVOR33:
0421         *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_DATA];
0422         break;
0423     case SPRN_IVOR34:
0424         *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_FP_ROUND];
0425         break;
0426 #endif
0427 #ifdef CONFIG_ALTIVEC
0428     case SPRN_IVOR32:
0429         *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_UNAVAIL];
0430         break;
0431     case SPRN_IVOR33:
0432         *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_ALTIVEC_ASSIST];
0433         break;
0434 #endif
0435     case SPRN_IVOR35:
0436         *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_PERFORMANCE_MONITOR];
0437         break;
0438 #ifdef CONFIG_KVM_BOOKE_HV
0439     case SPRN_IVOR36:
0440         *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL];
0441         break;
0442     case SPRN_IVOR37:
0443         *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT];
0444         break;
0445 #endif
0446     default:
0447         emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, spr_val);
0448     }
0449 
0450     return emulated;
0451 }
0452