diff options
Diffstat (limited to 'drivers/kvm/kvm_main.c')
| -rw-r--r-- | drivers/kvm/kvm_main.c | 73 | 
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 122c05f283e1..757a41f1db84 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c  | |||
| @@ -1204,6 +1204,73 @@ void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val, | |||
| 1204 | } | 1204 | } | 
| 1205 | } | 1205 | } | 
| 1206 | 1206 | ||
| 1207 | /* | ||
| 1208 | * Register the para guest with the host: | ||
| 1209 | */ | ||
| 1210 | static int vcpu_register_para(struct kvm_vcpu *vcpu, gpa_t para_state_gpa) | ||
| 1211 | { | ||
| 1212 | struct kvm_vcpu_para_state *para_state; | ||
| 1213 | hpa_t para_state_hpa, hypercall_hpa; | ||
| 1214 | struct page *para_state_page; | ||
| 1215 | unsigned char *hypercall; | ||
| 1216 | gpa_t hypercall_gpa; | ||
| 1217 | |||
| 1218 | printk(KERN_DEBUG "kvm: guest trying to enter paravirtual mode\n"); | ||
| 1219 | printk(KERN_DEBUG ".... para_state_gpa: %08Lx\n", para_state_gpa); | ||
| 1220 | |||
| 1221 | /* | ||
| 1222 | * Needs to be page aligned: | ||
| 1223 | */ | ||
| 1224 | if (para_state_gpa != PAGE_ALIGN(para_state_gpa)) | ||
| 1225 | goto err_gp; | ||
| 1226 | |||
| 1227 | para_state_hpa = gpa_to_hpa(vcpu, para_state_gpa); | ||
| 1228 | printk(KERN_DEBUG ".... para_state_hpa: %08Lx\n", para_state_hpa); | ||
| 1229 | if (is_error_hpa(para_state_hpa)) | ||
| 1230 | goto err_gp; | ||
| 1231 | |||
| 1232 | para_state_page = pfn_to_page(para_state_hpa >> PAGE_SHIFT); | ||
| 1233 | para_state = kmap_atomic(para_state_page, KM_USER0); | ||
| 1234 | |||
| 1235 | printk(KERN_DEBUG ".... guest version: %d\n", para_state->guest_version); | ||
| 1236 | printk(KERN_DEBUG ".... size: %d\n", para_state->size); | ||
| 1237 | |||
| 1238 | para_state->host_version = KVM_PARA_API_VERSION; | ||
| 1239 | /* | ||
| 1240 | * We cannot support guests that try to register themselves | ||
| 1241 | * with a newer API version than the host supports: | ||
| 1242 | */ | ||
| 1243 | if (para_state->guest_version > KVM_PARA_API_VERSION) { | ||
| 1244 | para_state->ret = -KVM_EINVAL; | ||
| 1245 | goto err_kunmap_skip; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | hypercall_gpa = para_state->hypercall_gpa; | ||
| 1249 | hypercall_hpa = gpa_to_hpa(vcpu, hypercall_gpa); | ||
| 1250 | printk(KERN_DEBUG ".... hypercall_hpa: %08Lx\n", hypercall_hpa); | ||
| 1251 | if (is_error_hpa(hypercall_hpa)) { | ||
| 1252 | para_state->ret = -KVM_EINVAL; | ||
| 1253 | goto err_kunmap_skip; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | printk(KERN_DEBUG "kvm: para guest successfully registered.\n"); | ||
| 1257 | vcpu->para_state_page = para_state_page; | ||
| 1258 | vcpu->para_state_gpa = para_state_gpa; | ||
| 1259 | vcpu->hypercall_gpa = hypercall_gpa; | ||
| 1260 | |||
| 1261 | hypercall = kmap_atomic(pfn_to_page(hypercall_hpa >> PAGE_SHIFT), | ||
| 1262 | KM_USER1) + (hypercall_hpa & ~PAGE_MASK); | ||
| 1263 | kvm_arch_ops->patch_hypercall(vcpu, hypercall); | ||
| 1264 | kunmap_atomic(hypercall, KM_USER1); | ||
| 1265 | |||
| 1266 | para_state->ret = 0; | ||
| 1267 | err_kunmap_skip: | ||
| 1268 | kunmap_atomic(para_state, KM_USER0); | ||
| 1269 | return 0; | ||
| 1270 | err_gp: | ||
| 1271 | return 1; | ||
| 1272 | } | ||
| 1273 | |||
| 1207 | int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | 1274 | int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | 
| 1208 | { | 1275 | { | 
| 1209 | u64 data; | 1276 | u64 data; | 
| @@ -1312,6 +1379,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |||
| 1312 | case MSR_IA32_MISC_ENABLE: | 1379 | case MSR_IA32_MISC_ENABLE: | 
| 1313 | vcpu->ia32_misc_enable_msr = data; | 1380 | vcpu->ia32_misc_enable_msr = data; | 
| 1314 | break; | 1381 | break; | 
| 1382 | /* | ||
| 1383 | * This is the 'probe whether the host is KVM' logic: | ||
| 1384 | */ | ||
| 1385 | case MSR_KVM_API_MAGIC: | ||
| 1386 | return vcpu_register_para(vcpu, data); | ||
| 1387 | |||
| 1315 | default: | 1388 | default: | 
| 1316 | printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr); | 1389 | printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr); | 
| 1317 | return 1; | 1390 | return 1; | 
