aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/kvm_main.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2007-02-19 07:37:47 -0500
committerAvi Kivity <avi@qumranet.com>2007-03-04 04:12:40 -0500
commit102d8325a1d2f266d3d0a03fdde948544e72c12d (patch)
tree21024c8b9b2b702c79200343e26f14f075da0479 /drivers/kvm/kvm_main.c
parent5972e9535e94bf875eb8eab8a667ba04c7583874 (diff)
KVM: add MSR based hypercall API
This adds a special MSR based hypercall API to KVM. This is to be used by paravirtual kernels and virtual drivers. Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r--drivers/kvm/kvm_main.c73
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 */
1210static 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;
1267err_kunmap_skip:
1268 kunmap_atomic(para_state, KM_USER0);
1269 return 0;
1270err_gp:
1271 return 1;
1272}
1273
1207int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) 1274int 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;