Hi,

Iain Kyte wrote:
> What has made the KVM-13 stop working with Linux 2.6.20 kvm and kvm-intel?  
> 

API has been modified.

As said Avi in kvm-13 release note : "if you use the modules from Linux 2.6.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
-- 
------------- [EMAIL PROTECTED]  --------------
       "Any sufficiently advanced technology is
  indistinguishable from magic." - Arthur C. Clarke
Index: linux-2.6.20/drivers/kvm/kvm.h
===================================================================
--- linux-2.6.20.orig/drivers/kvm/kvm.h 2007-02-08 13:43:04.000000000 +0100
+++ linux-2.6.20/drivers/kvm/kvm.h      2007-02-08 13:43:07.000000000 +0100
@@ -14,6 +14,7 @@
 
 #include "vmx.h"
 #include <linux/kvm.h>
+#include <linux/kvm_para.h>
 
 #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;
 };
 
 struct kvm_stat {
@@ -340,6 +345,7 @@
 
        struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu);
        void (*vcpu_put)(struct kvm_vcpu *vcpu);
+       void (*vcpu_decache)(struct kvm_vcpu *vcpu);
 
        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);
 };
 
 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);
 
+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 = pfn_to_page(shadow_page >> PAGE_SHIFT);
 
-       return (struct kvm_mmu_page *)page->private;
+       return (struct kvm_mmu_page *)page_private(page);
 }
 
 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
 
Index: linux-2.6.20/drivers/kvm/kvm_main.c
===================================================================
--- linux-2.6.20.orig/drivers/kvm/kvm_main.c    2007-02-08 13:43:04.000000000 
+0100
+++ linux-2.6.20/drivers/kvm/kvm_main.c 2007-02-08 13:43:07.000000000 +0100
@@ -34,6 +34,8 @@
 #include <linux/highmem.h>
 #include <linux/file.h>
 #include <asm/desc.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
 
 #include "x86_emulate.h"
 #include "segment_descriptor.h"
@@ -41,6 +43,9 @@
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
+static spinlock_t kvm_lock = SPIN_LOCK_UNLOCKED;
+static struct list_head vm_list = 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 >= 0 && n < KVM_MAX_VCPUS);
 }
 
-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 = dest;
        unsigned long req_size = size;
@@ -156,10 +159,8 @@
 }
 EXPORT_SYMBOL_GPL(kvm_read_guest);
 
-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 size,
+                   void *data)
 {
        unsigned char *host_buf = data;
        unsigned long req_size = size;
@@ -230,9 +231,13 @@
                struct kvm_vcpu *vcpu = &kvm->vcpus[i];
 
                mutex_init(&vcpu->mutex);
+               vcpu->cpu = -1;
                vcpu->kvm = kvm;
                vcpu->mmu.root_hpa = 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 = kvm;
        return 0;
@@ -272,7 +277,9 @@
 
 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 = filp->private_data;
 
+       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 = vcpu->host_fx_image + FX_IMAGE_SIZE;
 
-       vcpu->cpu = -1;  /* First load will set up TR */
        r = 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 = 0;
+                       set_page_private(new.phys_mem[i],0);
                }
        }
 
@@ -761,7 +770,6 @@
        if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n))
                goto out;
 
-
        if (any) {
                cleared = 0;
                for (i = 0; i < KVM_MAX_VCPUS; ++i) {
@@ -890,8 +898,9 @@
                return X86EMUL_CONTINUE;
        else {
                gpa_t gpa = vcpu->mmu.gva_to_gpa(vcpu, addr);
+
                if (gpa == UNMAPPED_GVA)
-                       return vcpu_printf(vcpu, "not present\n"), 
X86EMUL_PROPAGATE_FAULT;
+                       return X86EMUL_PROPAGATE_FAULT;
                vcpu->mmio_needed = 1;
                vcpu->mmio_phys_addr = gpa;
                vcpu->mmio_size = bytes;
@@ -1129,6 +1138,42 @@
 }
 EXPORT_SYMBOL_GPL(emulate_instruction);
 
+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 = -KVM_EINVAL;
+#ifdef CONFIG_X86_64
+       if (is_long_mode(vcpu)) {
+               nr = vcpu->regs[VCPU_REGS_RAX];
+               a0 = vcpu->regs[VCPU_REGS_RDI];
+               a1 = vcpu->regs[VCPU_REGS_RSI];
+               a2 = vcpu->regs[VCPU_REGS_RDX];
+               a3 = vcpu->regs[VCPU_REGS_RCX];
+               a4 = vcpu->regs[VCPU_REGS_R8];
+               a5 = vcpu->regs[VCPU_REGS_R9];
+       } else
+#endif
+       {
+               nr = vcpu->regs[VCPU_REGS_RBX] & -1u;
+               a0 = vcpu->regs[VCPU_REGS_RAX] & -1u;
+               a1 = vcpu->regs[VCPU_REGS_RCX] & -1u;
+               a2 = vcpu->regs[VCPU_REGS_RDX] & -1u;
+               a3 = vcpu->regs[VCPU_REGS_RSI] & -1u;
+               a4 = vcpu->regs[VCPU_REGS_RDI] & -1u;
+               a5 = vcpu->regs[VCPU_REGS_RBP] & -1u;
+       }
+       switch (nr) {
+       default:
+               ;
+       }
+       vcpu->regs[VCPU_REGS_RAX] = 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 @@
        }
 }
 
+/*
+ * Register the para guest with the host:
+ */
+static int vcpu_register_para(struct kvm_vcpu *vcpu, gpa_t para_state_gpa)
+{
+       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 != PAGE_ALIGN(para_state_gpa))
+               goto err_gp;
+
+       para_state_hpa = 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 = pfn_to_page(para_state_hpa >> PAGE_SHIFT);
+       para_state = kmap_atomic(para_state_page, KM_USER0);
+
+       printk(KERN_DEBUG "....  guest version: %d\n", 
para_state->guest_version);
+       printk(KERN_DEBUG "....           size: %d\n", para_state->size);
+
+       para_state->host_version = 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 = -KVM_EINVAL;
+               goto err_kunmap_skip;
+       }
+
+       hypercall_gpa = para_state->hypercall_gpa;
+       hypercall_hpa = gpa_to_hpa(vcpu, hypercall_gpa);
+       printk(KERN_DEBUG ".... hypercall_hpa: %08Lx\n", hypercall_hpa);
+       if (is_error_hpa(hypercall_hpa)) {
+               para_state->ret = -KVM_EINVAL;
+               goto err_kunmap_skip;
+       }
+
+       printk(KERN_DEBUG "kvm: para guest successfully registered.\n");
+       vcpu->para_state_page = para_state_page;
+       vcpu->para_state_gpa = para_state_gpa;
+       vcpu->hypercall_gpa = hypercall_gpa;
+
+       hypercall = 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 = 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 = 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;
 
+       /* re-sync apic's tpr */
+       vcpu->cr8 = kvm_run->cr8;
+
        if (kvm_run->emulated) {
                kvm_arch_ops->skip_emulated_instruction(vcpu);
                kvm_run->emulated = 0;
@@ -1784,12 +1905,11 @@
        case KVM_GET_API_VERSION:
                r = KVM_API_VERSION;
                break;
-       case KVM_CREATE_VCPU: {
+       case KVM_CREATE_VCPU:
                r = kvm_dev_ioctl_create_vcpu(kvm, arg);
                if (r)
                        goto out;
                break;
-       }
        case KVM_RUN: {
                struct kvm_run kvm_run;
 
@@ -2024,6 +2144,68 @@
        .priority = 0,
 };
 
+/*
+ * Make sure that a cpu that is being hot-unplugged does not have any vcpus
+ * 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 = 0; i < KVM_MAX_VCPUS; ++i) {
+                       vcpu = &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 == cpu) {
+                                       kvm_arch_ops->vcpu_decache(vcpu);
+                                       vcpu->cpu = -1;
+                               }
+                               mutex_unlock(&vcpu->mutex);
+                       }
+               }
+       spin_unlock(&kvm_lock);
+}
+
+static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
+                          void *v)
+{
+       int cpu = (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 = {
+       .notifier_call = kvm_cpu_hotplug,
+       .priority = 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);
 }
 
+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 = {
+       set_kset_name("kvm"),
+       .suspend = kvm_suspend,
+       .resume = kvm_resume,
+};
+
+static struct sys_device kvm_sysdev = {
+       .id = 0,
+       .cls = &kvm_sysdev_class,
+};
+
 hpa_t bad_page_address;
 
 int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
@@ -2070,8 +2276,19 @@
            return r;
 
        on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1);
+       r = register_cpu_notifier(&kvm_cpu_notifier);
+       if (r)
+               goto out_free_1;
        register_reboot_notifier(&kvm_reboot_notifier);
 
+       r = sysdev_class_register(&kvm_sysdev_class);
+       if (r)
+               goto out_free_2;
+
+       r = sysdev_register(&kvm_sysdev);
+       if (r)
+               goto out_free_3;
+
        kvm_chardev_ops.owner = module;
 
        r = misc_register(&kvm_dev);
@@ -2083,7 +2300,13 @@
        return r;
 
 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 = NULL;
Index: linux-2.6.20/drivers/kvm/kvm_svm.h
===================================================================
--- 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 +0100
@@ -1,6 +1,7 @@
 #ifndef __KVM_SVM_H
 #define __KVM_SVM_H
 
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/list.h>
 #include <asm/msr.h>
@@ -18,7 +19,7 @@
        MSR_IA32_LASTBRANCHTOIP, MSR_IA32_LASTINTFROMIP,MSR_IA32_LASTINTTOIP,*/
 };
 
-#define NR_HOST_SAVE_MSRS (sizeof(host_save_msrs) / sizeof(*host_save_msrs))
+#define NR_HOST_SAVE_MSRS ARRAY_SIZE(host_save_msrs)
 #define NUM_DB_REGS 4
 
 struct vcpu_svm {
Index: linux-2.6.20/drivers/kvm/mmu.c
===================================================================
--- linux-2.6.20.orig/drivers/kvm/mmu.c 2007-02-08 13:43:05.000000000 +0100
+++ 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 = 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 = (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 = mmu_alloc_rmap_desc(vcpu);
-               desc->shadow_ptes[0] = (u64 *)page->private;
+               desc->shadow_ptes[0] = (u64 *)page_private(page);
                desc->shadow_ptes[1] = spte;
-               page->private = (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 = (struct kvm_rmap_desc *)(page->private & ~1ul);
+               desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul);
                while (desc->shadow_ptes[RMAP_EXT-1] && desc->more)
                        desc = desc->more;
                if (desc->shadow_ptes[RMAP_EXT-1]) {
@@ -337,12 +337,12 @@
        if (j != 0)
                return;
        if (!prev_desc && !desc->more)
-               page->private = (unsigned long)desc->shadow_ptes[0];
+               set_page_private(page,(unsigned long)desc->shadow_ptes[0]);
        else
                if (prev_desc)
                        prev_desc->more = desc->more;
                else
-                       page->private = (unsigned long)desc->more | 1;
+                       set_page_private(page,(unsigned long)desc->more | 1);
        mmu_free_rmap_desc(vcpu, desc);
 }
 
@@ -356,20 +356,20 @@
        if (!is_rmap_pte(*spte))
                return;
        page = 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 != spte) {
+               if ((u64 *)page_private(page) != spte) {
                        printk(KERN_ERR "rmap_remove:  %p %llx 1->BUG\n",
                               spte, *spte);
                        BUG();
                }
-               page->private = 0;
+               set_page_private(page,0);
        } else {
                rmap_printk("rmap_remove:  %p %llx many->many\n", spte, *spte);
-               desc = (struct kvm_rmap_desc *)(page->private & ~1ul);
+               desc = (struct kvm_rmap_desc *)(page_private(page) & ~1ul);
                prev_desc = NULL;
                while (desc) {
                        for (i = 0; i < RMAP_EXT && desc->shadow_ptes[i]; ++i)
@@ -398,11 +398,11 @@
        BUG_ON(!slot);
        page = gfn_to_page(slot, gfn);
 
-       while (page->private) {
-               if (!(page->private & 1))
-                       spte = (u64 *)page->private;
+       while (page_private(page)) {
+               if (!(page_private(page) & 1))
+                       spte = (u64 *)page_private(page);
                else {
-                       desc = (struct kvm_rmap_desc *)(page->private & ~1ul);
+                       desc = (struct kvm_rmap_desc *)(page_private(page) & 
~1ul);
                        spte = desc->shadow_ptes[0];
                }
                BUG_ON(!spte);
@@ -1218,7 +1218,7 @@
                INIT_LIST_HEAD(&page_header->link);
                if ((page = alloc_page(GFP_KERNEL)) == NULL)
                        goto error_1;
-               page->private = (unsigned long)page_header;
+               set_page_private(page, (unsigned long)page_header);
                page_header->page_hpa = (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
===================================================================
--- linux-2.6.20.orig/drivers/kvm/paging_tmpl.h 2007-02-08 13:43:05.000000000 
+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
 
-               if (!(*ptep & PT_ACCESSED_MASK))
-                       *ptep |= PT_ACCESSED_MASK;      /* avoid rmw */
+               if (!(*ptep & PT_ACCESSED_MASK)) {
+                       mark_page_dirty(vcpu->kvm, table_gfn);
+                       *ptep |= PT_ACCESSED_MASK;
+               }
 
                if (walker->level == PT_PAGE_TABLE_LEVEL) {
                        walker->gfn = (*ptep & PT_BASE_ADDR_MASK)
@@ -185,6 +187,12 @@
                kunmap_atomic(walker->table, KM_USER0);
 }
 
+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 |= PT_DIRTY_MASK;
                *write_pt = 1;
                return 0;
        }
        mark_page_dirty(vcpu->kvm, gfn);
        *shadow_ent |= PT_WRITABLE_MASK;
+       FNAME(mark_pagetable_dirty)(vcpu->kvm, walker);
        *guest_ent |= PT_DIRTY_MASK;
        rmap_add(vcpu, shadow_ent);
 
@@ -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;
-       }
 
        ++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 = *walker.ptep;
-       FNAME(release_walker)(&walker);
+       gpa_t gpa = UNMAPPED_GVA;
+       int r;
 
-       if (!is_present_pte(guest_pte))
-               return UNMAPPED_GVA;
+       r = FNAME(walk_addr)(&walker, vcpu, vaddr, 0, 0, 0);
 
-       if (walker.level == PT_DIRECTORY_LEVEL) {
-               ASSERT((guest_pte & PT_PAGE_SIZE_MASK));
-               ASSERT(PTTYPE == 64 || is_pse(vcpu));
-
-               gpa = (guest_pte & PT_DIR_BASE_ADDR_MASK) | (vaddr &
-                       (PT_LEVEL_MASK(PT_PAGE_TABLE_LEVEL) | ~PAGE_MASK));
-
-               if (PTTYPE == 32 && is_cpuid_PSE36())
-                       gpa |= (guest_pte & PT32_DIR_PSE36_MASK) <<
-                                       (32 - PT32_DIR_PSE36_SHIFT);
-       } else {
-               gpa = (guest_pte & PT_BASE_ADDR_MASK);
-               gpa |= (vaddr & ~PAGE_MASK);
+       if (r) {
+               gpa = (gpa_t)walker.gfn << PAGE_SHIFT;
+               gpa |= vaddr & ~PAGE_MASK;
        }
 
+       FNAME(release_walker)(&walker);
        return gpa;
 }
 
Index: linux-2.6.20/drivers/kvm/svm.c
===================================================================
--- linux-2.6.20.orig/drivers/kvm/svm.c 2007-02-08 13:43:05.000000000 +0100
+++ linux-2.6.20/drivers/kvm/svm.c      2007-02-08 13:43:07.000000000 +0100
@@ -15,6 +15,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
 #include <linux/profile.h>
@@ -75,7 +76,7 @@
 
 static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
 
-#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)
 
@@ -528,7 +529,13 @@
        save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK |
                SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK;
        save->cs.limit = 0xffff;
-       save->cs.base = 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 = 0xf0000;
 
        save->gdtr.limit = 0xffff;
        save->idtr.limit = 0xffff;
@@ -603,6 +610,10 @@
        put_cpu();
 }
 
+static void svm_vcpu_decache(struct kvm_vcpu *vcpu)
+{
+}
+
 static void svm_cache_regs(struct kvm_vcpu *vcpu)
 {
        vcpu->regs[VCPU_REGS_RAX] = vcpu->svm->vmcb->save.rax;
@@ -723,7 +734,7 @@
        }
 #endif
        vcpu->svm->cr0 = cr0;
-       vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK;
+       vcpu->svm->vmcb->save.cr0 = cr0 | CR0_PG_MASK | CR0_WP_MASK;
        vcpu->cr0 = cr0;
 }
 
@@ -1032,22 +1043,22 @@
 
                addr_mask = 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;
                }
 
                if (kvm_run->io.rep) {
-                       kvm_run->io.count = vcpu->regs[VCPU_REGS_RCX] & 
addr_mask;
+                       kvm_run->io.count
+                               = vcpu->regs[VCPU_REGS_RCX] & addr_mask;
                        kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags
                                                   & X86_EFLAGS_DF) != 0;
                }
-       } else {
+       } else
                kvm_run->io.value = vcpu->svm->vmcb->save.rax;
-       }
        return 0;
 }
 
-
 static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        return 1;
@@ -1065,6 +1076,12 @@
        return 0;
 }
 
+static int vmmcall_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       vcpu->svm->vmcb->save.rip += 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]                  = task_switch_interception,
        [SVM_EXIT_SHUTDOWN]                     = shutdown_interception,
        [SVM_EXIT_VMRUN]                        = invalid_op_interception,
-       [SVM_EXIT_VMMCALL]                      = invalid_op_interception,
+       [SVM_EXIT_VMMCALL]                      = vmmcall_interception,
        [SVM_EXIT_VMLOAD]                       = invalid_op_interception,
        [SVM_EXIT_VMSAVE]                       = invalid_op_interception,
        [SVM_EXIT_STGI]                         = invalid_op_interception,
@@ -1287,7 +1304,7 @@
                       __FUNCTION__, vcpu->svm->vmcb->control.exit_int_info,
                       exit_code);
 
-       if (exit_code >= sizeof(svm_exit_handlers) / sizeof(*svm_exit_handlers)
+       if (exit_code >= ARRAY_SIZE(svm_exit_handlers)
            || svm_exit_handlers[exit_code] == 0) {
                kvm_run->exit_reason = KVM_EXIT_UNKNOWN;
                printk(KERN_ERR "%s: 0x%x @ 0x%llx cr0 0x%lx rflags 0x%llx\n",
@@ -1658,6 +1675,18 @@
        return 0;
 }
 
+static void
+svm_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
+{
+       /*
+        * Patch in the VMMCALL instruction:
+        */
+       hypercall[0] = 0x0f;
+       hypercall[1] = 0x01;
+       hypercall[2] = 0xd9;
+       hypercall[3] = 0xc3;
+}
+
 static struct kvm_arch_ops svm_arch_ops = {
        .cpu_has_kvm_support = has_svm,
        .disabled_by_bios = is_disabled,
@@ -1671,6 +1700,7 @@
 
        .vcpu_load = svm_vcpu_load,
        .vcpu_put = svm_vcpu_put,
+       .vcpu_decache = svm_vcpu_decache,
 
        .set_guest_debug = svm_guest_debug,
        .get_msr = svm_get_msr,
@@ -1705,6 +1735,7 @@
        .run = svm_vcpu_run,
        .skip_emulated_instruction = skip_emulated_instruction,
        .vcpu_setup = svm_vcpu_setup,
+       .patch_hypercall = svm_patch_hypercall,
 };
 
 static int __init svm_init(void)
Index: linux-2.6.20/drivers/kvm/vmx.c
===================================================================
--- linux-2.6.20.orig/drivers/kvm/vmx.c 2007-02-08 13:43:05.000000000 +0100
+++ 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 <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/profile.h>
@@ -27,7 +28,6 @@
 
 #include "segment_descriptor.h"
 
-
 MODULE_AUTHOR("Qumranet");
 MODULE_LICENSE("GPL");
 
@@ -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)
 
 static inline int is_page_fault(u32 intr_info)
 {
@@ -125,6 +125,15 @@
                per_cpu(current_vmcs, cpu) = NULL;
 }
 
+static void vcpu_clear(struct kvm_vcpu *vcpu)
+{
+       if (vcpu->cpu != raw_smp_processor_id() && vcpu->cpu != -1)
+               smp_call_function_single(vcpu->cpu, __vcpu_clear, vcpu, 0, 1);
+       else
+               __vcpu_clear(vcpu);
+       vcpu->launched = 0;
+}
+
 static unsigned long vmcs_readl(unsigned long field)
 {
        unsigned long value;
@@ -202,10 +211,8 @@
 
        cpu = get_cpu();
 
-       if (vcpu->cpu != cpu) {
-               smp_call_function(__vcpu_clear, vcpu, 0, 1);
-               vcpu->launched = 0;
-       }
+       if (vcpu->cpu != cpu)
+               vcpu_clear(vcpu);
 
        if (per_cpu(current_vmcs, cpu) != vcpu->vmcs) {
                u8 error;
@@ -243,6 +250,11 @@
        put_cpu();
 }
 
+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 = find_msr_entry(vcpu, msr_index);
                if (msr) {
@@ -502,7 +513,7 @@
        return (msr & 5) == 1; /* locked but not enabled */
 }
 
-static __init void hardware_enable(void *garbage)
+static void hardware_enable(void *garbage)
 {
        int cpu = raw_smp_processor_id();
        u64 phys_addr = __pa(per_cpu(vmxarea, cpu));
@@ -781,6 +792,9 @@
  */
 static void vmx_set_cr0_no_modeswitch(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
+       if (!vcpu->rmode.active && !(cr0 & CR0_PE_MASK))
+               enter_rmode(vcpu);
+
        vcpu->rmode.active = ((cr0 & CR0_PE_MASK) == 0);
        update_exception_bitmap(vcpu);
        vmcs_writel(CR0_READ_SHADOW, cr0);
@@ -1375,6 +1389,11 @@
        return 1;
 }
 
+static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
+       return 0;
+}
 
 static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
 {
@@ -1450,6 +1469,18 @@
        return 0;
 }
 
+static void
+vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
+{
+       /*
+        * Patch in the VMCALL instruction:
+        */
+       hypercall[0] = 0x0f;
+       hypercall[1] = 0x01;
+       hypercall[2] = 0xc1;
+       hypercall[3] = 0xc3;
+}
+
 static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        u64 exit_qualification;
@@ -1626,6 +1657,12 @@
        return 0;
 }
 
+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 execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
@@ -1635,6 +1672,7 @@
                                      struct kvm_run *kvm_run) = {
        [EXIT_REASON_EXCEPTION_NMI]           = handle_exception,
        [EXIT_REASON_EXTERNAL_INTERRUPT]      = handle_external_interrupt,
+       [EXIT_REASON_TRIPLE_FAULT]            = handle_triple_fault,
        [EXIT_REASON_IO_INSTRUCTION]          = handle_io,
        [EXIT_REASON_CR_ACCESS]               = handle_cr,
        [EXIT_REASON_DR_ACCESS]               = handle_dr,
@@ -1643,6 +1681,7 @@
        [EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
        [EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
        [EXIT_REASON_HLT]                     = handle_halt,
+       [EXIT_REASON_VMCALL]                  = handle_vmcall,
 };
 
 static const int kvm_vmx_max_exit_handlers =
@@ -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"
 
                "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"
 
                "pop %%ecx; popa \n\t"
 #endif
@@ -1859,9 +1898,7 @@
        fx_restore(vcpu->host_fx_image);
        vcpu->interrupt_window_open = (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) 
& 3) == 0;
 
-#ifndef CONFIG_X86_64
        asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
-#endif
 
        /*
         * Profile KVM exit RIPs:
@@ -2012,6 +2049,7 @@
 
        .vcpu_load = vmx_vcpu_load,
        .vcpu_put = vmx_vcpu_put,
+       .vcpu_decache = vmx_vcpu_decache,
 
        .set_guest_debug = set_guest_debug,
        .get_msr = vmx_get_msr,
@@ -2045,6 +2083,7 @@
        .run = vmx_vcpu_run,
        .skip_emulated_instruction = skip_emulated_instruction,
        .vcpu_setup = vmx_vcpu_setup,
+       .patch_hypercall = vmx_patch_hypercall,
 };
 
 static int __init vmx_init(void)
Index: linux-2.6.20/drivers/kvm/vmx.h
===================================================================
--- linux-2.6.20.orig/drivers/kvm/vmx.h 2007-02-08 13:43:05.000000000 +0100
+++ linux-2.6.20/drivers/kvm/vmx.h      2007-02-08 13:43:07.000000000 +0100
@@ -180,6 +180,7 @@
 
 #define EXIT_REASON_EXCEPTION_NMI       0
 #define EXIT_REASON_EXTERNAL_INTERRUPT  1
+#define EXIT_REASON_TRIPLE_FAULT        2
 
 #define EXIT_REASON_PENDING_INTERRUPT   7
 
Index: linux-2.6.20/include/linux/kvm.h
===================================================================
--- 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 <asm/types.h>
 #include <linux/ioctl.h>
 
-#define KVM_API_VERSION 2
+#define KVM_API_VERSION 3
 
 /*
  * 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;
 
@@ -185,6 +187,7 @@
        __u8  valid;
        __u8  writeable;
        __u8  usermode;
+       __u8  pad[5];
 };
 
 /* for KVM_INTERRUPT */
Index: linux-2.6.20/include/linux/kvm_para.h
===================================================================
--- /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 change
+ *       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 convention
+ * 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

Attachment: signature.asc
Description: OpenPGP digital signature

-------------------------------------------------------------------------
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
_______________________________________________
kvm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to