From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Vivier Subject: Re: KVM-13 and 2.6.20 kvm and kvm-intel Date: Fri, 09 Feb 2007 10:54:53 +0100 Message-ID: <45CC44ED.9080007@bull.net> References: <344847.94266.qm@web52607.mail.yahoo.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============1477004643==" Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org To: Iain Kyte Return-path: In-Reply-To: <344847.94266.qm-by7sfUAcWISA/QwVtaZbd3CJp6faPEW9@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org Errors-To: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org List-Id: kvm.vger.kernel.org This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --===============1477004643== Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enig346ED40B59EC5BE04003836A" This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig346ED40B59EC5BE04003836A Content-Type: multipart/mixed; boundary="------------080401050509090601020402" This is a multi-part message in MIME format. --------------080401050509090601020402 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Hi, Iain Kyte wrote: > What has made the KVM-13 stop working with Linux 2.6.20 kvm and kvm-int= el? =20 >=20 API has been modified. As said Avi in kvm-13 release note : "if you use the modules from Linux 2= =2E6.20, you need to use kvm-12". You can also apply attached patch on linux-2.6.20 source tree (it's just = a copy of kvm-13 in linux-2.6.20/drivers/kernel) Regards, Laurent --=20 ------------- Laurent.Vivier-6ktuUTfB/bM@public.gmane.org -------------- "Any sufficiently advanced technology is indistinguishable from magic." - Arthur C. Clarke --------------080401050509090601020402 Content-Type: text/plain; name="kvm-13" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="kvm-13" Index: linux-2.6.20/drivers/kvm/kvm.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/drivers/kvm/kvm.h 2007-02-08 13:43:04.000000000 +01= 00 +++ linux-2.6.20/drivers/kvm/kvm.h 2007-02-08 13:43:07.000000000 +0100 @@ -14,6 +14,7 @@ =20 #include "vmx.h" #include +#include =20 #define CR0_PE_MASK (1ULL << 0) #define CR0_TS_MASK (1ULL << 3) @@ -237,6 +238,9 @@ unsigned long cr0; unsigned long cr2; unsigned long cr3; + gpa_t para_state_gpa; + struct page *para_state_page; + gpa_t hypercall_gpa; unsigned long cr4; unsigned long cr8; u64 pdptrs[4]; /* pae */ @@ -304,6 +308,7 @@ int memory_config_version; int busy; unsigned long rmap_overflow; + struct list_head vm_list; }; =20 struct kvm_stat { @@ -340,6 +345,7 @@ =20 struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu); void (*vcpu_put)(struct kvm_vcpu *vcpu); + void (*vcpu_decache)(struct kvm_vcpu *vcpu); =20 int (*set_guest_debug)(struct kvm_vcpu *vcpu, struct kvm_debug_guest *dbg); @@ -380,6 +386,8 @@ int (*run)(struct kvm_vcpu *vcpu, struct kvm_run *run); int (*vcpu_setup)(struct kvm_vcpu *vcpu); void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu); + void (*patch_hypercall)(struct kvm_vcpu *vcpu, + unsigned char *hypercall_addr); }; =20 extern struct kvm_stat kvm_stat; @@ -474,6 +482,8 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva); void kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu); =20 +int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run); + static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code) { @@ -521,7 +531,7 @@ { struct page *page =3D pfn_to_page(shadow_page >> PAGE_SHIFT); =20 - return (struct kvm_mmu_page *)page->private; + return (struct kvm_mmu_page *)page_private(page); } =20 static inline u16 read_fs(void) @@ -558,7 +568,7 @@ #ifndef load_ldt static inline void load_ldt(u16 sel) { - asm ("lldt %0" : : "g"(sel)); + asm ("lldt %0" : : "rm"(sel)); } #endif =20 Index: linux-2.6.20/drivers/kvm/kvm_main.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/drivers/kvm/kvm_main.c 2007-02-08 13:43:04.00000000= 0 +0100 +++ linux-2.6.20/drivers/kvm/kvm_main.c 2007-02-08 13:43:07.000000000 +01= 00 @@ -34,6 +34,8 @@ #include #include #include +#include +#include =20 #include "x86_emulate.h" #include "segment_descriptor.h" @@ -41,6 +43,9 @@ MODULE_AUTHOR("Qumranet"); MODULE_LICENSE("GPL"); =20 +static spinlock_t kvm_lock =3D SPIN_LOCK_UNLOCKED; +static struct list_head vm_list =3D LIST_HEAD_INIT(vm_list); + struct kvm_arch_ops *kvm_arch_ops; struct kvm_stat kvm_stat; EXPORT_SYMBOL_GPL(kvm_stat); @@ -121,10 +126,8 @@ return likely(n >=3D 0 && n < KVM_MAX_VCPUS); } =20 -int kvm_read_guest(struct kvm_vcpu *vcpu, - gva_t addr, - unsigned long size, - void *dest) +int kvm_read_guest(struct kvm_vcpu *vcpu, gva_t addr, unsigned long size= , + void *dest) { unsigned char *host_buf =3D dest; unsigned long req_size =3D size; @@ -156,10 +159,8 @@ } EXPORT_SYMBOL_GPL(kvm_read_guest); =20 -int kvm_write_guest(struct kvm_vcpu *vcpu, - gva_t addr, - unsigned long size, - void *data) +int kvm_write_guest(struct kvm_vcpu *vcpu, gva_t addr, unsigned long siz= e, + void *data) { unsigned char *host_buf =3D data; unsigned long req_size =3D size; @@ -230,9 +231,13 @@ struct kvm_vcpu *vcpu =3D &kvm->vcpus[i]; =20 mutex_init(&vcpu->mutex); + vcpu->cpu =3D -1; vcpu->kvm =3D kvm; vcpu->mmu.root_hpa =3D INVALID_PAGE; INIT_LIST_HEAD(&vcpu->free_pages); + spin_lock(&kvm_lock); + list_add(&kvm->vm_list, &vm_list); + spin_unlock(&kvm_lock); } filp->private_data =3D kvm; return 0; @@ -272,7 +277,9 @@ =20 static void kvm_free_vcpu(struct kvm_vcpu *vcpu) { - vcpu_load(vcpu->kvm, vcpu_slot(vcpu)); + if (!vcpu_load(vcpu->kvm, vcpu_slot(vcpu))) + return; + kvm_mmu_destroy(vcpu); vcpu_put(vcpu); kvm_arch_ops->vcpu_free(vcpu); @@ -290,6 +297,9 @@ { struct kvm *kvm =3D filp->private_data; =20 + spin_lock(&kvm_lock); + list_del(&kvm->vm_list); + spin_unlock(&kvm_lock); kvm_free_vcpus(kvm); kvm_free_physmem(kvm); kfree(kvm); @@ -443,7 +453,7 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) { if (is_long_mode(vcpu)) { - if ( cr3 & CR3_L_MODE_RESEVED_BITS) { + if (cr3 & CR3_L_MODE_RESEVED_BITS) { printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); inject_gp(vcpu); return; @@ -544,7 +554,6 @@ FX_IMAGE_ALIGN); vcpu->guest_fx_image =3D vcpu->host_fx_image + FX_IMAGE_SIZE; =20 - vcpu->cpu =3D -1; /* First load will set up TR */ r =3D kvm_arch_ops->vcpu_create(vcpu); if (r < 0) goto out_free_vcpus; @@ -661,7 +670,7 @@ | __GFP_ZERO); if (!new.phys_mem[i]) goto out_free; - new.phys_mem[i]->private =3D 0; + set_page_private(new.phys_mem[i],0); } } =20 @@ -761,7 +770,6 @@ if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n)) goto out; =20 - if (any) { cleared =3D 0; for (i =3D 0; i < KVM_MAX_VCPUS; ++i) { @@ -890,8 +898,9 @@ return X86EMUL_CONTINUE; else { gpa_t gpa =3D vcpu->mmu.gva_to_gpa(vcpu, addr); + if (gpa =3D=3D UNMAPPED_GVA) - return vcpu_printf(vcpu, "not present\n"), X86EMUL_PROPAGATE_FAULT; + return X86EMUL_PROPAGATE_FAULT; vcpu->mmio_needed =3D 1; vcpu->mmio_phys_addr =3D gpa; vcpu->mmio_size =3D bytes; @@ -1129,6 +1138,42 @@ } EXPORT_SYMBOL_GPL(emulate_instruction); =20 +int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + unsigned long nr, a0, a1, a2, a3, a4, a5, ret; + + kvm_arch_ops->decache_regs(vcpu); + ret =3D -KVM_EINVAL; +#ifdef CONFIG_X86_64 + if (is_long_mode(vcpu)) { + nr =3D vcpu->regs[VCPU_REGS_RAX]; + a0 =3D vcpu->regs[VCPU_REGS_RDI]; + a1 =3D vcpu->regs[VCPU_REGS_RSI]; + a2 =3D vcpu->regs[VCPU_REGS_RDX]; + a3 =3D vcpu->regs[VCPU_REGS_RCX]; + a4 =3D vcpu->regs[VCPU_REGS_R8]; + a5 =3D vcpu->regs[VCPU_REGS_R9]; + } else +#endif + { + nr =3D vcpu->regs[VCPU_REGS_RBX] & -1u; + a0 =3D vcpu->regs[VCPU_REGS_RAX] & -1u; + a1 =3D vcpu->regs[VCPU_REGS_RCX] & -1u; + a2 =3D vcpu->regs[VCPU_REGS_RDX] & -1u; + a3 =3D vcpu->regs[VCPU_REGS_RSI] & -1u; + a4 =3D vcpu->regs[VCPU_REGS_RDI] & -1u; + a5 =3D vcpu->regs[VCPU_REGS_RBP] & -1u; + } + switch (nr) { + default: + ; + } + vcpu->regs[VCPU_REGS_RAX] =3D ret; + kvm_arch_ops->cache_regs(vcpu); + return 1; +} +EXPORT_SYMBOL_GPL(kvm_hypercall); + static u64 mk_cr_64(u64 curr_cr, u32 new_val) { return (curr_cr & ~((1ULL << 32) - 1)) | new_val; @@ -1195,6 +1240,73 @@ } } =20 +/* + * Register the para guest with the host: + */ +static int vcpu_register_para(struct kvm_vcpu *vcpu, gpa_t para_state_gp= a) +{ + struct kvm_vcpu_para_state *para_state; + hpa_t para_state_hpa, hypercall_hpa; + struct page *para_state_page; + unsigned char *hypercall; + gpa_t hypercall_gpa; + + printk(KERN_DEBUG "kvm: guest trying to enter paravirtual mode\n"); + printk(KERN_DEBUG ".... para_state_gpa: %08Lx\n", para_state_gpa); + + /* + * Needs to be page aligned: + */ + if (para_state_gpa !=3D PAGE_ALIGN(para_state_gpa)) + goto err_gp; + + para_state_hpa =3D gpa_to_hpa(vcpu, para_state_gpa); + printk(KERN_DEBUG ".... para_state_hpa: %08Lx\n", para_state_hpa); + if (is_error_hpa(para_state_hpa)) + goto err_gp; + + para_state_page =3D pfn_to_page(para_state_hpa >> PAGE_SHIFT); + para_state =3D kmap_atomic(para_state_page, KM_USER0); + + printk(KERN_DEBUG ".... guest version: %d\n", para_state->guest_versio= n); + printk(KERN_DEBUG ".... size: %d\n", para_state->size); + + para_state->host_version =3D KVM_PARA_API_VERSION; + /* + * We cannot support guests that try to register themselves + * with a newer API version than the host supports: + */ + if (para_state->guest_version > KVM_PARA_API_VERSION) { + para_state->ret =3D -KVM_EINVAL; + goto err_kunmap_skip; + } + + hypercall_gpa =3D para_state->hypercall_gpa; + hypercall_hpa =3D gpa_to_hpa(vcpu, hypercall_gpa); + printk(KERN_DEBUG ".... hypercall_hpa: %08Lx\n", hypercall_hpa); + if (is_error_hpa(hypercall_hpa)) { + para_state->ret =3D -KVM_EINVAL; + goto err_kunmap_skip; + } + + printk(KERN_DEBUG "kvm: para guest successfully registered.\n"); + vcpu->para_state_page =3D para_state_page; + vcpu->para_state_gpa =3D para_state_gpa; + vcpu->hypercall_gpa =3D hypercall_gpa; + + hypercall =3D kmap_atomic(pfn_to_page(hypercall_hpa >> PAGE_SHIFT), + KM_USER1) + (hypercall_hpa & ~PAGE_MASK); + kvm_arch_ops->patch_hypercall(vcpu, hypercall); + kunmap_atomic(hypercall, KM_USER1); + + para_state->ret =3D 0; +err_kunmap_skip: + kunmap_atomic(para_state, KM_USER0); + return 0; +err_gp: + return 1; +} + int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) { u64 data; @@ -1303,6 +1415,12 @@ case MSR_IA32_MISC_ENABLE: vcpu->ia32_misc_enable_msr =3D data; break; + /* + * This is the 'probe whether the host is KVM' logic: + */ + case MSR_KVM_API_MAGIC: + return vcpu_register_para(vcpu, data); + default: printk(KERN_ERR "kvm: unhandled wrmsr: 0x%x\n", msr); return 1; @@ -1360,6 +1478,9 @@ if (!vcpu) return -ENOENT; =20 + /* re-sync apic's tpr */ + vcpu->cr8 =3D kvm_run->cr8; + if (kvm_run->emulated) { kvm_arch_ops->skip_emulated_instruction(vcpu); kvm_run->emulated =3D 0; @@ -1784,12 +1905,11 @@ case KVM_GET_API_VERSION: r =3D KVM_API_VERSION; break; - case KVM_CREATE_VCPU: { + case KVM_CREATE_VCPU: r =3D kvm_dev_ioctl_create_vcpu(kvm, arg); if (r) goto out; break; - } case KVM_RUN: { struct kvm_run kvm_run; =20 @@ -2024,6 +2144,68 @@ .priority =3D 0, }; =20 +/* + * Make sure that a cpu that is being hot-unplugged does not have any vc= pus + * cached on it. + */ +static void decache_vcpus_on_cpu(int cpu) +{ + struct kvm *vm; + struct kvm_vcpu *vcpu; + int i; + + spin_lock(&kvm_lock); + list_for_each_entry(vm, &vm_list, vm_list) + for (i =3D 0; i < KVM_MAX_VCPUS; ++i) { + vcpu =3D &vm->vcpus[i]; + /* + * If the vcpu is locked, then it is running on some + * other cpu and therefore it is not cached on the + * cpu in question. + * + * If it's not locked, check the last cpu it executed + * on. + */ + if (mutex_trylock(&vcpu->mutex)) { + if (vcpu->cpu =3D=3D cpu) { + kvm_arch_ops->vcpu_decache(vcpu); + vcpu->cpu =3D -1; + } + mutex_unlock(&vcpu->mutex); + } + } + spin_unlock(&kvm_lock); +} + +static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned lon= g val, + void *v) +{ + int cpu =3D (long)v; + + switch (val) { + case CPU_DOWN_PREPARE: + case CPU_UP_CANCELED: + printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n", + cpu); + decache_vcpus_on_cpu(cpu); + smp_call_function_single(cpu, kvm_arch_ops->hardware_disable, + NULL, 0, 1); + break; + case CPU_ONLINE: + printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n", + cpu); + smp_call_function_single(cpu, kvm_arch_ops->hardware_enable, + NULL, 0, 1); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block kvm_cpu_notifier =3D { + .notifier_call =3D kvm_cpu_hotplug, + .priority =3D 20, /* must be > scheduler priority */ +}; + static __init void kvm_init_debug(void) { struct kvm_stats_debugfs_item *p; @@ -2043,6 +2225,30 @@ debugfs_remove(debugfs_dir); } =20 +static int kvm_suspend(struct sys_device *dev, pm_message_t state) +{ + decache_vcpus_on_cpu(raw_smp_processor_id()); + on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); + return 0; +} + +static int kvm_resume(struct sys_device *dev) +{ + on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1); + return 0; +} + +static struct sysdev_class kvm_sysdev_class =3D { + set_kset_name("kvm"), + .suspend =3D kvm_suspend, + .resume =3D kvm_resume, +}; + +static struct sys_device kvm_sysdev =3D { + .id =3D 0, + .cls =3D &kvm_sysdev_class, +}; + hpa_t bad_page_address; =20 int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) @@ -2070,8 +2276,19 @@ return r; =20 on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1); + r =3D register_cpu_notifier(&kvm_cpu_notifier); + if (r) + goto out_free_1; register_reboot_notifier(&kvm_reboot_notifier); =20 + r =3D sysdev_class_register(&kvm_sysdev_class); + if (r) + goto out_free_2; + + r =3D sysdev_register(&kvm_sysdev); + if (r) + goto out_free_3; + kvm_chardev_ops.owner =3D module; =20 r =3D misc_register(&kvm_dev); @@ -2083,7 +2300,13 @@ return r; =20 out_free: + sysdev_unregister(&kvm_sysdev); +out_free_3: + sysdev_class_unregister(&kvm_sysdev_class); +out_free_2: unregister_reboot_notifier(&kvm_reboot_notifier); + unregister_cpu_notifier(&kvm_cpu_notifier); +out_free_1: on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); kvm_arch_ops->hardware_unsetup(); return r; @@ -2092,8 +2315,10 @@ void kvm_exit_arch(void) { misc_deregister(&kvm_dev); - + sysdev_unregister(&kvm_sysdev); + sysdev_class_unregister(&kvm_sysdev_class); unregister_reboot_notifier(&kvm_reboot_notifier); + unregister_cpu_notifier(&kvm_cpu_notifier); on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); kvm_arch_ops->hardware_unsetup(); kvm_arch_ops =3D NULL; Index: linux-2.6.20/drivers/kvm/kvm_svm.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/drivers/kvm/kvm_svm.h 2007-02-08 13:43:04.000000000= +0100 +++ linux-2.6.20/drivers/kvm/kvm_svm.h 2007-02-08 13:43:07.000000000 +010= 0 @@ -1,6 +1,7 @@ #ifndef __KVM_SVM_H #define __KVM_SVM_H =20 +#include #include #include #include @@ -18,7 +19,7 @@ MSR_IA32_LASTBRANCHTOIP, MSR_IA32_LASTINTFROMIP,MSR_IA32_LASTINTTOIP,*/= }; =20 -#define NR_HOST_SAVE_MSRS (sizeof(host_save_msrs) / sizeof(*host_save_ms= rs)) +#define NR_HOST_SAVE_MSRS ARRAY_SIZE(host_save_msrs) #define NUM_DB_REGS 4 =20 struct vcpu_svm { Index: linux-2.6.20/drivers/kvm/mmu.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/drivers/kvm/mmu.c 2007-02-08 13:43:05.000000000 +01= 00 +++ linux-2.6.20/drivers/kvm/mmu.c 2007-02-08 13:43:07.000000000 +0100 @@ -298,18 +298,18 @@ if (!is_rmap_pte(*spte)) return; page =3D pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT); - if (!page->private) { + if (!page_private(page)) { rmap_printk("rmap_add: %p %llx 0->1\n", spte, *spte); - page->private =3D (unsigned long)spte; - } else if (!(page->private & 1)) { + set_page_private(page,(unsigned long)spte); + } else if (!(page_private(page) & 1)) { rmap_printk("rmap_add: %p %llx 1->many\n", spte, *spte); desc =3D mmu_alloc_rmap_desc(vcpu); - desc->shadow_ptes[0] =3D (u64 *)page->private; + desc->shadow_ptes[0] =3D (u64 *)page_private(page); desc->shadow_ptes[1] =3D spte; - page->private =3D (unsigned long)desc | 1; + set_page_private(page,(unsigned long)desc | 1); } else { rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte); - desc =3D (struct kvm_rmap_desc *)(page->private & ~1ul); + desc =3D (struct kvm_rmap_desc *)(page_private(page) & ~1ul); while (desc->shadow_ptes[RMAP_EXT-1] && desc->more) desc =3D desc->more; if (desc->shadow_ptes[RMAP_EXT-1]) { @@ -337,12 +337,12 @@ if (j !=3D 0) return; if (!prev_desc && !desc->more) - page->private =3D (unsigned long)desc->shadow_ptes[0]; + set_page_private(page,(unsigned long)desc->shadow_ptes[0]); else if (prev_desc) prev_desc->more =3D desc->more; else - page->private =3D (unsigned long)desc->more | 1; + set_page_private(page,(unsigned long)desc->more | 1); mmu_free_rmap_desc(vcpu, desc); } =20 @@ -356,20 +356,20 @@ if (!is_rmap_pte(*spte)) return; page =3D pfn_to_page((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT); - if (!page->private) { + if (!page_private(page)) { printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte); BUG(); - } else if (!(page->private & 1)) { + } else if (!(page_private(page) & 1)) { rmap_printk("rmap_remove: %p %llx 1->0\n", spte, *spte); - if ((u64 *)page->private !=3D spte) { + if ((u64 *)page_private(page) !=3D spte) { printk(KERN_ERR "rmap_remove: %p %llx 1->BUG\n", spte, *spte); BUG(); } - page->private =3D 0; + set_page_private(page,0); } else { rmap_printk("rmap_remove: %p %llx many->many\n", spte, *spte); - desc =3D (struct kvm_rmap_desc *)(page->private & ~1ul); + desc =3D (struct kvm_rmap_desc *)(page_private(page) & ~1ul); prev_desc =3D NULL; while (desc) { for (i =3D 0; i < RMAP_EXT && desc->shadow_ptes[i]; ++i) @@ -398,11 +398,11 @@ BUG_ON(!slot); page =3D gfn_to_page(slot, gfn); =20 - while (page->private) { - if (!(page->private & 1)) - spte =3D (u64 *)page->private; + while (page_private(page)) { + if (!(page_private(page) & 1)) + spte =3D (u64 *)page_private(page); else { - desc =3D (struct kvm_rmap_desc *)(page->private & ~1ul); + desc =3D (struct kvm_rmap_desc *)(page_private(page) & ~1ul); spte =3D desc->shadow_ptes[0]; } BUG_ON(!spte); @@ -1218,7 +1218,7 @@ INIT_LIST_HEAD(&page_header->link); if ((page =3D alloc_page(GFP_KERNEL)) =3D=3D NULL) goto error_1; - page->private =3D (unsigned long)page_header; + set_page_private(page, (unsigned long)page_header); page_header->page_hpa =3D (hpa_t)page_to_pfn(page) << PAGE_SHIFT; memset(__va(page_header->page_hpa), 0, PAGE_SIZE); list_add(&page_header->link, &vcpu->free_pages); Index: linux-2.6.20/drivers/kvm/paging_tmpl.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/drivers/kvm/paging_tmpl.h 2007-02-08 13:43:05.00000= 0000 +0100 +++ linux-2.6.20/drivers/kvm/paging_tmpl.h 2007-02-08 13:43:07.000000000 = +0100 @@ -128,8 +128,10 @@ goto access_error; #endif =20 - if (!(*ptep & PT_ACCESSED_MASK)) - *ptep |=3D PT_ACCESSED_MASK; /* avoid rmw */ + if (!(*ptep & PT_ACCESSED_MASK)) { + mark_page_dirty(vcpu->kvm, table_gfn); + *ptep |=3D PT_ACCESSED_MASK; + } =20 if (walker->level =3D=3D PT_PAGE_TABLE_LEVEL) { walker->gfn =3D (*ptep & PT_BASE_ADDR_MASK) @@ -185,6 +187,12 @@ kunmap_atomic(walker->table, KM_USER0); } =20 +static void FNAME(mark_pagetable_dirty)(struct kvm *kvm, + struct guest_walker *walker) +{ + mark_page_dirty(kvm, walker->table_gfn[walker->level - 1]); +} + static void FNAME(set_pte)(struct kvm_vcpu *vcpu, u64 guest_pte, u64 *shadow_pte, u64 access_bits, gfn_t gfn) { @@ -348,12 +356,15 @@ } else if (kvm_mmu_lookup_page(vcpu, gfn)) { pgprintk("%s: found shadow page for %lx, marking ro\n", __FUNCTION__, gfn); + mark_page_dirty(vcpu->kvm, gfn); + FNAME(mark_pagetable_dirty)(vcpu->kvm, walker); *guest_ent |=3D PT_DIRTY_MASK; *write_pt =3D 1; return 0; } mark_page_dirty(vcpu->kvm, gfn); *shadow_ent |=3D PT_WRITABLE_MASK; + FNAME(mark_pagetable_dirty)(vcpu->kvm, walker); *guest_ent |=3D PT_DIRTY_MASK; rmap_add(vcpu, shadow_ent); =20 @@ -430,9 +441,8 @@ /* * mmio: emulate if accessible, otherwise its a guest fault. */ - if (is_io_pte(*shadow_pte)) { + if (is_io_pte(*shadow_pte)) return 1; - } =20 ++kvm_stat.pf_fixed; kvm_mmu_audit(vcpu, "post page fault (fixed)"); @@ -443,31 +453,17 @@ static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr) { struct guest_walker walker; - pt_element_t guest_pte; - gpa_t gpa; - - FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0); - guest_pte =3D *walker.ptep; - FNAME(release_walker)(&walker); + gpa_t gpa =3D UNMAPPED_GVA; + int r; =20 - if (!is_present_pte(guest_pte)) - return UNMAPPED_GVA; + r =3D FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0); =20 - if (walker.level =3D=3D PT_DIRECTORY_LEVEL) { - ASSERT((guest_pte & PT_PAGE_SIZE_MASK)); - ASSERT(PTTYPE =3D=3D 64 || is_pse(vcpu)); - - gpa =3D (guest_pte & PT_DIR_BASE_ADDR_MASK) | (vaddr & - (PT_LEVEL_MASK(PT_PAGE_TABLE_LEVEL) | ~PAGE_MASK)); - - if (PTTYPE =3D=3D 32 && is_cpuid_PSE36()) - gpa |=3D (guest_pte & PT32_DIR_PSE36_MASK) << - (32 - PT32_DIR_PSE36_SHIFT); - } else { - gpa =3D (guest_pte & PT_BASE_ADDR_MASK); - gpa |=3D (vaddr & ~PAGE_MASK); + if (r) { + gpa =3D (gpa_t)walker.gfn << PAGE_SHIFT; + gpa |=3D vaddr & ~PAGE_MASK; } =20 + FNAME(release_walker)(&walker); return gpa; } =20 Index: linux-2.6.20/drivers/kvm/svm.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/drivers/kvm/svm.c 2007-02-08 13:43:05.000000000 +01= 00 +++ linux-2.6.20/drivers/kvm/svm.c 2007-02-08 13:43:07.000000000 +0100 @@ -15,6 +15,7 @@ */ =20 #include +#include #include #include #include @@ -75,7 +76,7 @@ =20 static u32 msrpm_ranges[] =3D {0, 0xc0000000, 0xc0010000}; =20 -#define NUM_MSR_MAPS (sizeof(msrpm_ranges) / sizeof(*msrpm_ranges)) +#define NUM_MSR_MAPS ARRAY_SIZE(msrpm_ranges) #define MSRS_RANGE_SIZE 2048 #define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2) =20 @@ -528,7 +529,13 @@ save->cs.attrib =3D SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK; save->cs.limit =3D 0xffff; - save->cs.base =3D 0xffff0000; + /* + * cs.base should really be 0xffff0000, but vmx can't handle that, so + * be consistent with it. + * + * Replace when we have real mode working for vmx. + */ + save->cs.base =3D 0xf0000; =20 save->gdtr.limit =3D 0xffff; save->idtr.limit =3D 0xffff; @@ -603,6 +610,10 @@ put_cpu(); } =20 +static void svm_vcpu_decache(struct kvm_vcpu *vcpu) +{ +} + static void svm_cache_regs(struct kvm_vcpu *vcpu) { vcpu->regs[VCPU_REGS_RAX] =3D vcpu->svm->vmcb->save.rax; @@ -723,7 +734,7 @@ } #endif vcpu->svm->cr0 =3D cr0; - vcpu->svm->vmcb->save.cr0 =3D cr0 | CR0_PG_MASK; + vcpu->svm->vmcb->save.cr0 =3D cr0 | CR0_PG_MASK | CR0_WP_MASK; vcpu->cr0 =3D cr0; } =20 @@ -1032,22 +1043,22 @@ =20 addr_mask =3D io_adress(vcpu, _in, &kvm_run->io.address); if (!addr_mask) { - printk(KERN_DEBUG "%s: get io address failed\n", __FUNCTION__); + printk(KERN_DEBUG "%s: get io address failed\n", + __FUNCTION__); return 1; } =20 if (kvm_run->io.rep) { - kvm_run->io.count =3D vcpu->regs[VCPU_REGS_RCX] & addr_mask; + kvm_run->io.count + =3D vcpu->regs[VCPU_REGS_RCX] & addr_mask; kvm_run->io.string_down =3D (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_DF) !=3D 0; } - } else { + } else kvm_run->io.value =3D vcpu->svm->vmcb->save.rax; - } return 0; } =20 - static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kv= m_run) { return 1; @@ -1065,6 +1076,12 @@ return 0; } =20 +static int vmmcall_interception(struct kvm_vcpu *vcpu, struct kvm_run *k= vm_run) +{ + vcpu->svm->vmcb->save.rip +=3D 3; + return kvm_hypercall(vcpu, kvm_run); +} + static int invalid_op_interception(struct kvm_vcpu *vcpu, struct kvm_run= *kvm_run) { inject_ud(vcpu); @@ -1265,7 +1282,7 @@ [SVM_EXIT_TASK_SWITCH] =3D task_switch_interception, [SVM_EXIT_SHUTDOWN] =3D shutdown_interception, [SVM_EXIT_VMRUN] =3D invalid_op_interception, - [SVM_EXIT_VMMCALL] =3D invalid_op_interception, + [SVM_EXIT_VMMCALL] =3D vmmcall_interception, [SVM_EXIT_VMLOAD] =3D invalid_op_interception, [SVM_EXIT_VMSAVE] =3D invalid_op_interception, [SVM_EXIT_STGI] =3D invalid_op_interception, @@ -1287,7 +1304,7 @@ __FUNCTION__, vcpu->svm->vmcb->control.exit_int_info, exit_code); =20 - if (exit_code >=3D sizeof(svm_exit_handlers) / sizeof(*svm_exit_handler= s) + if (exit_code >=3D ARRAY_SIZE(svm_exit_handlers) || svm_exit_handlers[exit_code] =3D=3D 0) { kvm_run->exit_reason =3D KVM_EXIT_UNKNOWN; printk(KERN_ERR "%s: 0x%x @ 0x%llx cr0 0x%lx rflags 0x%llx\n", @@ -1658,6 +1675,18 @@ return 0; } =20 +static void +svm_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall) +{ + /* + * Patch in the VMMCALL instruction: + */ + hypercall[0] =3D 0x0f; + hypercall[1] =3D 0x01; + hypercall[2] =3D 0xd9; + hypercall[3] =3D 0xc3; +} + static struct kvm_arch_ops svm_arch_ops =3D { .cpu_has_kvm_support =3D has_svm, .disabled_by_bios =3D is_disabled, @@ -1671,6 +1700,7 @@ =20 .vcpu_load =3D svm_vcpu_load, .vcpu_put =3D svm_vcpu_put, + .vcpu_decache =3D svm_vcpu_decache, =20 .set_guest_debug =3D svm_guest_debug, .get_msr =3D svm_get_msr, @@ -1705,6 +1735,7 @@ .run =3D svm_vcpu_run, .skip_emulated_instruction =3D skip_emulated_instruction, .vcpu_setup =3D svm_vcpu_setup, + .patch_hypercall =3D svm_patch_hypercall, }; =20 static int __init svm_init(void) Index: linux-2.6.20/drivers/kvm/vmx.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/drivers/kvm/vmx.c 2007-02-08 13:43:05.000000000 +01= 00 +++ linux-2.6.20/drivers/kvm/vmx.c 2007-02-08 13:43:07.000000000 +0100 @@ -19,6 +19,7 @@ #include "vmx.h" #include "kvm_vmx.h" #include +#include #include #include #include @@ -27,7 +28,6 @@ =20 #include "segment_descriptor.h" =20 - MODULE_AUTHOR("Qumranet"); MODULE_LICENSE("GPL"); =20 @@ -76,7 +76,7 @@ #endif MSR_EFER, MSR_K6_STAR, }; -#define NR_VMX_MSR (sizeof(vmx_msr_index) / sizeof(*vmx_msr_index)) +#define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index) =20 static inline int is_page_fault(u32 intr_info) { @@ -125,6 +125,15 @@ per_cpu(current_vmcs, cpu) =3D NULL; } =20 +static void vcpu_clear(struct kvm_vcpu *vcpu) +{ + if (vcpu->cpu !=3D raw_smp_processor_id() && vcpu->cpu !=3D -1) + smp_call_function_single(vcpu->cpu, __vcpu_clear, vcpu, 0, 1); + else + __vcpu_clear(vcpu); + vcpu->launched =3D 0; +} + static unsigned long vmcs_readl(unsigned long field) { unsigned long value; @@ -202,10 +211,8 @@ =20 cpu =3D get_cpu(); =20 - if (vcpu->cpu !=3D cpu) { - smp_call_function(__vcpu_clear, vcpu, 0, 1); - vcpu->launched =3D 0; - } + if (vcpu->cpu !=3D cpu) + vcpu_clear(vcpu); =20 if (per_cpu(current_vmcs, cpu) !=3D vcpu->vmcs) { u8 error; @@ -243,6 +250,11 @@ put_cpu(); } =20 +static void vmx_vcpu_decache(struct kvm_vcpu *vcpu) +{ + vcpu_clear(vcpu); +} + static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu) { return vmcs_readl(GUEST_RFLAGS); @@ -406,10 +418,9 @@ case MSR_IA32_SYSENTER_ESP: vmcs_write32(GUEST_SYSENTER_ESP, data); break; - case MSR_IA32_TIME_STAMP_COUNTER: { + case MSR_IA32_TIME_STAMP_COUNTER: guest_write_tsc(data); break; - } default: msr =3D find_msr_entry(vcpu, msr_index); if (msr) { @@ -502,7 +513,7 @@ return (msr & 5) =3D=3D 1; /* locked but not enabled */ } =20 -static __init void hardware_enable(void *garbage) +static void hardware_enable(void *garbage) { int cpu =3D raw_smp_processor_id(); u64 phys_addr =3D __pa(per_cpu(vmxarea, cpu)); @@ -781,6 +792,9 @@ */ static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned lo= ng cr0) { + if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK)) + enter_rmode(vcpu); + vcpu->rmode.active =3D ((cr0 & CR0_PE_MASK) =3D=3D 0); update_exception_bitmap(vcpu); vmcs_writel(CR0_READ_SHADOW, cr0); @@ -1375,6 +1389,11 @@ return 1; } =20 +static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kv= m_run) +{ + kvm_run->exit_reason =3D KVM_EXIT_SHUTDOWN; + return 0; +} =20 static int get_io_count(struct kvm_vcpu *vcpu, u64 *count) { @@ -1450,6 +1469,18 @@ return 0; } =20 +static void +vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall) +{ + /* + * Patch in the VMCALL instruction: + */ + hypercall[0] =3D 0x0f; + hypercall[1] =3D 0x01; + hypercall[2] =3D 0xc1; + hypercall[3] =3D 0xc3; +} + static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) { u64 exit_qualification; @@ -1626,6 +1657,12 @@ return 0; } =20 +static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)= +{ + vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP)+3); + return kvm_hypercall(vcpu, kvm_run); +} + /* * The exit handlers return 1 if the exit was handled fully and guest ex= ecution * may resume. Otherwise they set the kvm_run parameter to indicate wha= t needs @@ -1635,6 +1672,7 @@ struct kvm_run *kvm_run) =3D { [EXIT_REASON_EXCEPTION_NMI] =3D handle_exception, [EXIT_REASON_EXTERNAL_INTERRUPT] =3D handle_external_interrupt, + [EXIT_REASON_TRIPLE_FAULT] =3D handle_triple_fault, [EXIT_REASON_IO_INSTRUCTION] =3D handle_io, [EXIT_REASON_CR_ACCESS] =3D handle_cr, [EXIT_REASON_DR_ACCESS] =3D handle_dr, @@ -1643,6 +1681,7 @@ [EXIT_REASON_MSR_WRITE] =3D handle_wrmsr, [EXIT_REASON_PENDING_INTERRUPT] =3D handle_interrupt_window, [EXIT_REASON_HLT] =3D handle_halt, + [EXIT_REASON_VMCALL] =3D handle_vmcall, }; =20 static const int kvm_vmx_max_exit_handlers =3D @@ -1786,10 +1825,10 @@ "kvm_vmx_return: " /* Save guest registers, load host registers, keep flags */ #ifdef CONFIG_X86_64 - "xchg %3, 0(%%rsp) \n\t" + "xchg %3, (%%rsp) \n\t" "mov %%rax, %c[rax](%3) \n\t" "mov %%rbx, %c[rbx](%3) \n\t" - "pushq 0(%%rsp); popq %c[rcx](%3) \n\t" + "pushq (%%rsp); popq %c[rcx](%3) \n\t" "mov %%rdx, %c[rdx](%3) \n\t" "mov %%rsi, %c[rsi](%3) \n\t" "mov %%rdi, %c[rdi](%3) \n\t" @@ -1804,24 +1843,24 @@ "mov %%r15, %c[r15](%3) \n\t" "mov %%cr2, %%rax \n\t" "mov %%rax, %c[cr2](%3) \n\t" - "mov 0(%%rsp), %3 \n\t" + "mov (%%rsp), %3 \n\t" =20 "pop %%rcx; pop %%r15; pop %%r14; pop %%r13; pop %%r12;" "pop %%r11; pop %%r10; pop %%r9; pop %%r8;" "pop %%rbp; pop %%rdi; pop %%rsi;" "pop %%rdx; pop %%rbx; pop %%rax \n\t" #else - "xchg %3, 0(%%esp) \n\t" + "xchg %3, (%%esp) \n\t" "mov %%eax, %c[rax](%3) \n\t" "mov %%ebx, %c[rbx](%3) \n\t" - "pushl 0(%%esp); popl %c[rcx](%3) \n\t" + "pushl (%%esp); popl %c[rcx](%3) \n\t" "mov %%edx, %c[rdx](%3) \n\t" "mov %%esi, %c[rsi](%3) \n\t" "mov %%edi, %c[rdi](%3) \n\t" "mov %%ebp, %c[rbp](%3) \n\t" "mov %%cr2, %%eax \n\t" "mov %%eax, %c[cr2](%3) \n\t" - "mov 0(%%esp), %3 \n\t" + "mov (%%esp), %3 \n\t" =20 "pop %%ecx; popa \n\t" #endif @@ -1859,9 +1898,7 @@ fx_restore(vcpu->host_fx_image); vcpu->interrupt_window_open =3D (vmcs_read32(GUEST_INTERRUPTIBILITY_INF= O) & 3) =3D=3D 0; =20 -#ifndef CONFIG_X86_64 asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS)); -#endif =20 /* * Profile KVM exit RIPs: @@ -2012,6 +2049,7 @@ =20 .vcpu_load =3D vmx_vcpu_load, .vcpu_put =3D vmx_vcpu_put, + .vcpu_decache =3D vmx_vcpu_decache, =20 .set_guest_debug =3D set_guest_debug, .get_msr =3D vmx_get_msr, @@ -2045,6 +2083,7 @@ .run =3D vmx_vcpu_run, .skip_emulated_instruction =3D skip_emulated_instruction, .vcpu_setup =3D vmx_vcpu_setup, + .patch_hypercall =3D vmx_patch_hypercall, }; =20 static int __init vmx_init(void) Index: linux-2.6.20/drivers/kvm/vmx.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/drivers/kvm/vmx.h 2007-02-08 13:43:05.000000000 +01= 00 +++ linux-2.6.20/drivers/kvm/vmx.h 2007-02-08 13:43:07.000000000 +0100 @@ -180,6 +180,7 @@ =20 #define EXIT_REASON_EXCEPTION_NMI 0 #define EXIT_REASON_EXTERNAL_INTERRUPT 1 +#define EXIT_REASON_TRIPLE_FAULT 2 =20 #define EXIT_REASON_PENDING_INTERRUPT 7 =20 Index: linux-2.6.20/include/linux/kvm.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-2.6.20.orig/include/linux/kvm.h 2007-02-08 13:43:05.000000000 += 0100 +++ linux-2.6.20/include/linux/kvm.h 2007-02-08 13:43:07.000000000 +0100 @@ -11,7 +11,7 @@ #include #include =20 -#define KVM_API_VERSION 2 +#define KVM_API_VERSION 3 =20 /* * Architectural interrupt line count, and the size of the bitmap needed= @@ -65,6 +65,8 @@ __u8 ready_for_interrupt_injection; __u8 if_flag; __u16 padding2; + + /* in (pre_kvm_run), out (post_kvm_run) */ __u64 cr8; __u64 apic_base; =20 @@ -185,6 +187,7 @@ __u8 valid; __u8 writeable; __u8 usermode; + __u8 pad[5]; }; =20 /* for KVM_INTERRUPT */ Index: linux-2.6.20/include/linux/kvm_para.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.20/include/linux/kvm_para.h 2007-02-08 13:43:07.000000000 += 0100 @@ -0,0 +1,73 @@ +#ifndef __LINUX_KVM_PARA_H +#define __LINUX_KVM_PARA_H + +/* + * Guest OS interface for KVM paravirtualization + * + * Note: this interface is totally experimental, and is certain to chang= e + * as we make progress. + */ + +/* + * Per-VCPU descriptor area shared between guest and host. Writable to + * both guest and host. Registered with the host by the guest when + * a guest acknowledges paravirtual mode. + * + * NOTE: all addresses are guest-physical addresses (gpa), to make it + * easier for the hypervisor to map between the various addresses. + */ +struct kvm_vcpu_para_state { + /* + * API version information for compatibility. If there's any support + * mismatch (too old host trying to execute too new guest) then + * the host will deny entry into paravirtual mode. Any other + * combination (new host + old guest and new host + new guest) + * is supposed to work - new host versions will support all old + * guest API versions. + */ + u32 guest_version; + u32 host_version; + u32 size; + u32 ret; + + /* + * The address of the vm exit instruction (VMCALL or VMMCALL), + * which the host will patch according to the CPU model the + * VM runs on: + */ + u64 hypercall_gpa; + +} __attribute__ ((aligned(PAGE_SIZE))); + +#define KVM_PARA_API_VERSION 1 + +/* + * This is used for an RDMSR's ECX parameter to probe for a KVM host. + * Hopefully no CPU vendor will use up this number. This is placed well + * out of way of the typical space occupied by CPU vendors' MSR indices,= + * and we think (or at least hope) it wont be occupied in the future + * either. + */ +#define MSR_KVM_API_MAGIC 0x87655678 + +#define KVM_EINVAL 1 + +/* + * Hypercall calling convention: + * + * Each hypercall may have 0-6 parameters. + * + * 64-bit hypercall index is in RAX, goes from 0 to __NR_hypercalls-1 + * + * 64-bit parameters 1-6 are in the standard gcc x86_64 calling conventi= on + * order: RDI, RSI, RDX, RCX, R8, R9. + * + * 32-bit index is EBX, parameters are: EAX, ECX, EDX, ESI, EDI, EBP. + * (the first 3 are according to the gcc regparm calling convention) + * + * No registers are clobbered by the hypercall, except that the + * return value is in RAX. + */ +#define __NR_hypercalls 0 + +#endif --------------080401050509090601020402-- --------------enig346ED40B59EC5BE04003836A Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.7 (GNU/Linux) iD8DBQFFzETx9Kffa9pFVzwRAjn5AJ4mBHZztpscRdc4Ri9Wvqb1Qfhk7QCeJxXj 5ApZEHFYnTrGHTb4QjIgUFE= =AcfQ -----END PGP SIGNATURE----- --------------enig346ED40B59EC5BE04003836A-- --===============1477004643== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier. Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 --===============1477004643== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kvm-devel mailing list kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org https://lists.sourceforge.net/lists/listinfo/kvm-devel --===============1477004643==--