aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-07-29 08:47:59 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:50:52 -0400
commitd1293c927568f5b5b8dd3fa263a98683cf8556dc (patch)
tree81e278085861e233ca8f313dfe2e2d11e14f098d /arch/powerpc/kernel
parent73a18109829e7696226a9fd4062d339e7c6ee130 (diff)
KVM: PPC: PV instructions to loads and stores
Some instructions can simply be replaced by load and store instructions to or from the magic page. This patch replaces often called instructions that fall into the above category. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/kvm.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index e93366fbbd21..9ec572c4d2a5 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -33,7 +33,34 @@
33#define KVM_MAGIC_PAGE (-4096L) 33#define KVM_MAGIC_PAGE (-4096L)
34#define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) 34#define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x)
35 35
36#define KVM_INST_LWZ 0x80000000
37#define KVM_INST_STW 0x90000000
38#define KVM_INST_LD 0xe8000000
39#define KVM_INST_STD 0xf8000000
40#define KVM_INST_NOP 0x60000000
41#define KVM_INST_B 0x48000000
42#define KVM_INST_B_MASK 0x03ffffff
43#define KVM_INST_B_MAX 0x01ffffff
44
36#define KVM_MASK_RT 0x03e00000 45#define KVM_MASK_RT 0x03e00000
46#define KVM_INST_MFMSR 0x7c0000a6
47#define KVM_INST_MFSPR_SPRG0 0x7c1042a6
48#define KVM_INST_MFSPR_SPRG1 0x7c1142a6
49#define KVM_INST_MFSPR_SPRG2 0x7c1242a6
50#define KVM_INST_MFSPR_SPRG3 0x7c1342a6
51#define KVM_INST_MFSPR_SRR0 0x7c1a02a6
52#define KVM_INST_MFSPR_SRR1 0x7c1b02a6
53#define KVM_INST_MFSPR_DAR 0x7c1302a6
54#define KVM_INST_MFSPR_DSISR 0x7c1202a6
55
56#define KVM_INST_MTSPR_SPRG0 0x7c1043a6
57#define KVM_INST_MTSPR_SPRG1 0x7c1143a6
58#define KVM_INST_MTSPR_SPRG2 0x7c1243a6
59#define KVM_INST_MTSPR_SPRG3 0x7c1343a6
60#define KVM_INST_MTSPR_SRR0 0x7c1a03a6
61#define KVM_INST_MTSPR_SRR1 0x7c1b03a6
62#define KVM_INST_MTSPR_DAR 0x7c1303a6
63#define KVM_INST_MTSPR_DSISR 0x7c1203a6
37 64
38static bool kvm_patching_worked = true; 65static bool kvm_patching_worked = true;
39 66
@@ -43,6 +70,34 @@ static inline void kvm_patch_ins(u32 *inst, u32 new_inst)
43 flush_icache_range((ulong)inst, (ulong)inst + 4); 70 flush_icache_range((ulong)inst, (ulong)inst + 4);
44} 71}
45 72
73static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt)
74{
75#ifdef CONFIG_64BIT
76 kvm_patch_ins(inst, KVM_INST_LD | rt | (addr & 0x0000fffc));
77#else
78 kvm_patch_ins(inst, KVM_INST_LWZ | rt | ((addr + 4) & 0x0000fffc));
79#endif
80}
81
82static void kvm_patch_ins_lwz(u32 *inst, long addr, u32 rt)
83{
84 kvm_patch_ins(inst, KVM_INST_LWZ | rt | (addr & 0x0000ffff));
85}
86
87static void kvm_patch_ins_std(u32 *inst, long addr, u32 rt)
88{
89#ifdef CONFIG_64BIT
90 kvm_patch_ins(inst, KVM_INST_STD | rt | (addr & 0x0000fffc));
91#else
92 kvm_patch_ins(inst, KVM_INST_STW | rt | ((addr + 4) & 0x0000fffc));
93#endif
94}
95
96static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt)
97{
98 kvm_patch_ins(inst, KVM_INST_STW | rt | (addr & 0x0000fffc));
99}
100
46static void kvm_map_magic_page(void *data) 101static void kvm_map_magic_page(void *data)
47{ 102{
48 kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE, 103 kvm_hypercall2(KVM_HC_PPC_MAP_MAGIC_PAGE,
@@ -57,6 +112,60 @@ static void kvm_check_ins(u32 *inst)
57 u32 inst_rt = _inst & KVM_MASK_RT; 112 u32 inst_rt = _inst & KVM_MASK_RT;
58 113
59 switch (inst_no_rt) { 114 switch (inst_no_rt) {
115 /* Loads */
116 case KVM_INST_MFMSR:
117 kvm_patch_ins_ld(inst, magic_var(msr), inst_rt);
118 break;
119 case KVM_INST_MFSPR_SPRG0:
120 kvm_patch_ins_ld(inst, magic_var(sprg0), inst_rt);
121 break;
122 case KVM_INST_MFSPR_SPRG1:
123 kvm_patch_ins_ld(inst, magic_var(sprg1), inst_rt);
124 break;
125 case KVM_INST_MFSPR_SPRG2:
126 kvm_patch_ins_ld(inst, magic_var(sprg2), inst_rt);
127 break;
128 case KVM_INST_MFSPR_SPRG3:
129 kvm_patch_ins_ld(inst, magic_var(sprg3), inst_rt);
130 break;
131 case KVM_INST_MFSPR_SRR0:
132 kvm_patch_ins_ld(inst, magic_var(srr0), inst_rt);
133 break;
134 case KVM_INST_MFSPR_SRR1:
135 kvm_patch_ins_ld(inst, magic_var(srr1), inst_rt);
136 break;
137 case KVM_INST_MFSPR_DAR:
138 kvm_patch_ins_ld(inst, magic_var(dar), inst_rt);
139 break;
140 case KVM_INST_MFSPR_DSISR:
141 kvm_patch_ins_lwz(inst, magic_var(dsisr), inst_rt);
142 break;
143
144 /* Stores */
145 case KVM_INST_MTSPR_SPRG0:
146 kvm_patch_ins_std(inst, magic_var(sprg0), inst_rt);
147 break;
148 case KVM_INST_MTSPR_SPRG1:
149 kvm_patch_ins_std(inst, magic_var(sprg1), inst_rt);
150 break;
151 case KVM_INST_MTSPR_SPRG2:
152 kvm_patch_ins_std(inst, magic_var(sprg2), inst_rt);
153 break;
154 case KVM_INST_MTSPR_SPRG3:
155 kvm_patch_ins_std(inst, magic_var(sprg3), inst_rt);
156 break;
157 case KVM_INST_MTSPR_SRR0:
158 kvm_patch_ins_std(inst, magic_var(srr0), inst_rt);
159 break;
160 case KVM_INST_MTSPR_SRR1:
161 kvm_patch_ins_std(inst, magic_var(srr1), inst_rt);
162 break;
163 case KVM_INST_MTSPR_DAR:
164 kvm_patch_ins_std(inst, magic_var(dar), inst_rt);
165 break;
166 case KVM_INST_MTSPR_DSISR:
167 kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt);
168 break;
60 } 169 }
61 170
62 switch (_inst) { 171 switch (_inst) {