diff options
author | Ingo Molnar <mingo@elte.hu> | 2007-02-19 07:37:47 -0500 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-03-04 04:12:40 -0500 |
commit | 102d8325a1d2f266d3d0a03fdde948544e72c12d (patch) | |
tree | 21024c8b9b2b702c79200343e26f14f075da0479 /drivers/kvm/kvm_main.c | |
parent | 5972e9535e94bf875eb8eab8a667ba04c7583874 (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.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; |