KVM: PPC: Add Gekko SPRs
authorAlexander Graf <agraf@suse.de>
Fri, 19 Feb 2010 10:00:33 +0000 (11:00 +0100)
committerAvi Kivity <avi@redhat.com>
Sun, 25 Apr 2010 09:34:53 +0000 (12:34 +0300)
The Gekko has some SPR values that differ from other PPC core values and
also some additional ones.

Let's add support for them in our mfspr/mtspr emulator.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kvm/book3s_64_emulate.c

index db7db0a96967ad8dc4c2eb2a5c2438d878187e73..d28ee839ed84338a6e75a56b5fdc9bd050e2aa09 100644 (file)
@@ -82,6 +82,7 @@ struct kvmppc_vcpu_book3s {
        struct kvmppc_bat ibat[8];
        struct kvmppc_bat dbat[8];
        u64 hid[6];
+       u64 gqr[8];
        int slb_nr;
        u64 sdr1;
        u64 dsisr;
index 5572e86223f4f5afcf0634063d3279391fb1fa10..8a69a39a10b19c2f30c9fa70cb06e7f8e504dcbe 100644 (file)
 #define HID1_ABE       (1<<10)         /* 7450 Address Broadcast Enable */
 #define HID1_PS                (1<<16)         /* 750FX PLL selection */
 #define SPRN_HID2      0x3F8           /* Hardware Implementation Register 2 */
+#define SPRN_HID2_GEKKO        0x398           /* Gekko HID2 Register */
 #define SPRN_IABR      0x3F2   /* Instruction Address Breakpoint Register */
 #define SPRN_IABR2     0x3FA           /* 83xx */
 #define SPRN_IBCR      0x135           /* 83xx Insn Breakpoint Control Reg */
 #define SPRN_HID4      0x3F4           /* 970 HID4 */
+#define SPRN_HID4_GEKKO        0x3F3           /* Gekko HID4 */
 #define SPRN_HID5      0x3F6           /* 970 HID5 */
 #define SPRN_HID6      0x3F9   /* BE HID 6 */
 #define   HID6_LB      (0x0F<<12) /* Concurrent Large Page Modes */
 #define SPRN_VRSAVE    0x100   /* Vector Register Save Register */
 #define SPRN_XER       0x001   /* Fixed Point Exception Register */
 
+#define SPRN_MMCR0_GEKKO 0x3B8 /* Gekko Monitor Mode Control Register 0 */
+#define SPRN_MMCR1_GEKKO 0x3BC /* Gekko Monitor Mode Control Register 1 */
+#define SPRN_PMC1_GEKKO  0x3B9 /* Gekko Performance Monitor Control 1 */
+#define SPRN_PMC2_GEKKO  0x3BA /* Gekko Performance Monitor Control 2 */
+#define SPRN_PMC3_GEKKO  0x3BD /* Gekko Performance Monitor Control 3 */
+#define SPRN_PMC4_GEKKO  0x3BE /* Gekko Performance Monitor Control 4 */
+#define SPRN_WPAR_GEKKO  0x399 /* Gekko Write Pipe Address Register */
+
 #define SPRN_SCOMC     0x114   /* SCOM Access Control */
 #define SPRN_SCOMD     0x115   /* SCOM Access DATA */
 
index 2b0ee7e040c90d7870851ae46d564b1e17451ad7..bb4a7c1f8f05492f2269f72af760ce99eb6a1bd1 100644 (file)
 /* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */
 #define OP_31_XOP_DCBZ         1010
 
+#define SPRN_GQR0              912
+#define SPRN_GQR1              913
+#define SPRN_GQR2              914
+#define SPRN_GQR3              915
+#define SPRN_GQR4              916
+#define SPRN_GQR5              917
+#define SPRN_GQR6              918
+#define SPRN_GQR7              919
+
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
 {
@@ -268,7 +277,29 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
        case SPRN_HID2:
                to_book3s(vcpu)->hid[2] = spr_val;
                break;
+       case SPRN_HID2_GEKKO:
+               to_book3s(vcpu)->hid[2] = spr_val;
+               /* HID2.PSE controls paired single on gekko */
+               switch (vcpu->arch.pvr) {
+               case 0x00080200:        /* lonestar 2.0 */
+               case 0x00088202:        /* lonestar 2.2 */
+               case 0x70000100:        /* gekko 1.0 */
+               case 0x00080100:        /* gekko 2.0 */
+               case 0x00083203:        /* gekko 2.3a */
+               case 0x00083213:        /* gekko 2.3b */
+               case 0x00083204:        /* gekko 2.4 */
+               case 0x00083214:        /* gekko 2.4e (8SE) - retail HW2 */
+                       if (spr_val & (1 << 29)) { /* HID2.PSE */
+                               vcpu->arch.hflags |= BOOK3S_HFLAG_PAIRED_SINGLE;
+                               kvmppc_giveup_ext(vcpu, MSR_FP);
+                       } else {
+                               vcpu->arch.hflags &= ~BOOK3S_HFLAG_PAIRED_SINGLE;
+                       }
+                       break;
+               }
+               break;
        case SPRN_HID4:
+       case SPRN_HID4_GEKKO:
                to_book3s(vcpu)->hid[4] = spr_val;
                break;
        case SPRN_HID5:
@@ -278,12 +309,30 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
                    (mfmsr() & MSR_HV))
                        vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32;
                break;
+       case SPRN_GQR0:
+       case SPRN_GQR1:
+       case SPRN_GQR2:
+       case SPRN_GQR3:
+       case SPRN_GQR4:
+       case SPRN_GQR5:
+       case SPRN_GQR6:
+       case SPRN_GQR7:
+               to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val;
+               break;
        case SPRN_ICTC:
        case SPRN_THRM1:
        case SPRN_THRM2:
        case SPRN_THRM3:
        case SPRN_CTRLF:
        case SPRN_CTRLT:
+       case SPRN_L2CR:
+       case SPRN_MMCR0_GEKKO:
+       case SPRN_MMCR1_GEKKO:
+       case SPRN_PMC1_GEKKO:
+       case SPRN_PMC2_GEKKO:
+       case SPRN_PMC3_GEKKO:
+       case SPRN_PMC4_GEKKO:
+       case SPRN_WPAR_GEKKO:
                break;
        default:
                printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn);
@@ -320,19 +369,40 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
                kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[1]);
                break;
        case SPRN_HID2:
+       case SPRN_HID2_GEKKO:
                kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[2]);
                break;
        case SPRN_HID4:
+       case SPRN_HID4_GEKKO:
                kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[4]);
                break;
        case SPRN_HID5:
                kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hid[5]);
                break;
+       case SPRN_GQR0:
+       case SPRN_GQR1:
+       case SPRN_GQR2:
+       case SPRN_GQR3:
+       case SPRN_GQR4:
+       case SPRN_GQR5:
+       case SPRN_GQR6:
+       case SPRN_GQR7:
+               kvmppc_set_gpr(vcpu, rt,
+                              to_book3s(vcpu)->gqr[sprn - SPRN_GQR0]);
+               break;
        case SPRN_THRM1:
        case SPRN_THRM2:
        case SPRN_THRM3:
        case SPRN_CTRLF:
        case SPRN_CTRLT:
+       case SPRN_L2CR:
+       case SPRN_MMCR0_GEKKO:
+       case SPRN_MMCR1_GEKKO:
+       case SPRN_PMC1_GEKKO:
+       case SPRN_PMC2_GEKKO:
+       case SPRN_PMC3_GEKKO:
+       case SPRN_PMC4_GEKKO:
+       case SPRN_WPAR_GEKKO:
                kvmppc_set_gpr(vcpu, rt, 0);
                break;
        default: