Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'kvm-updates/2.6.39' of git://git.kernel.org/pub/scm/virt/kvm/kvm

* 'kvm-updates/2.6.39' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
KVM: move and fix substitue search for missing CPUID entries
KVM: fix XSAVE bit scanning
KVM: Enable async page fault processing
KVM: fix crash on irqfd deassign

+50 -12
+28 -9
arch/x86/kvm/x86.c
··· 2395 2395 int i; 2396 2396 2397 2397 entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX; 2398 - for (i = 1; *nent < maxnent; ++i) { 2399 - if (entry[i - 1].eax == 0 && i != 2) 2400 - break; 2398 + for (i = 1; *nent < maxnent && i < 64; ++i) { 2399 + if (entry[i].eax == 0) 2400 + continue; 2401 2401 do_cpuid_1_ent(&entry[i], function, i); 2402 2402 entry[i].flags |= 2403 2403 KVM_CPUID_FLAG_SIGNIFCANT_INDEX; ··· 4958 4958 best = e; 4959 4959 break; 4960 4960 } 4961 - /* 4962 - * Both basic or both extended? 4963 - */ 4964 - if (((e->function ^ function) & 0x80000000) == 0) 4965 - if (!best || e->function > best->function) 4966 - best = e; 4967 4961 } 4968 4962 return best; 4969 4963 } ··· 4977 4983 return 36; 4978 4984 } 4979 4985 4986 + /* 4987 + * If no match is found, check whether we exceed the vCPU's limit 4988 + * and return the content of the highest valid _standard_ leaf instead. 4989 + * This is to satisfy the CPUID specification. 4990 + */ 4991 + static struct kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu, 4992 + u32 function, u32 index) 4993 + { 4994 + struct kvm_cpuid_entry2 *maxlevel; 4995 + 4996 + maxlevel = kvm_find_cpuid_entry(vcpu, function & 0x80000000, 0); 4997 + if (!maxlevel || maxlevel->eax >= function) 4998 + return NULL; 4999 + if (function & 0x80000000) { 5000 + maxlevel = kvm_find_cpuid_entry(vcpu, 0, 0); 5001 + if (!maxlevel) 5002 + return NULL; 5003 + } 5004 + return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index); 5005 + } 5006 + 4980 5007 void kvm_emulate_cpuid(struct kvm_vcpu *vcpu) 4981 5008 { 4982 5009 u32 function, index; ··· 5010 4995 kvm_register_write(vcpu, VCPU_REGS_RCX, 0); 5011 4996 kvm_register_write(vcpu, VCPU_REGS_RDX, 0); 5012 4997 best = kvm_find_cpuid_entry(vcpu, function, index); 4998 + 4999 + if (!best) 5000 + best = check_cpuid_limit(vcpu, function, index); 5001 + 5013 5002 if (best) { 5014 5003 kvm_register_write(vcpu, VCPU_REGS_RAX, best->eax); 5015 5004 kvm_register_write(vcpu, VCPU_REGS_RBX, best->ebx);
+1 -1
virt/kvm/eventfd.c
··· 90 90 * We know no new events will be scheduled at this point, so block 91 91 * until all previously outstanding events have completed 92 92 */ 93 - flush_work(&irqfd->inject); 93 + flush_work_sync(&irqfd->inject); 94 94 95 95 /* 96 96 * It is now safe to release the object's resources
+21 -2
virt/kvm/kvm_main.c
··· 1037 1037 return fault_pfn; 1038 1038 } 1039 1039 1040 + int get_user_page_nowait(struct task_struct *tsk, struct mm_struct *mm, 1041 + unsigned long start, int write, struct page **page) 1042 + { 1043 + int flags = FOLL_TOUCH | FOLL_NOWAIT | FOLL_HWPOISON | FOLL_GET; 1044 + 1045 + if (write) 1046 + flags |= FOLL_WRITE; 1047 + 1048 + return __get_user_pages(tsk, mm, start, 1, flags, page, NULL, NULL); 1049 + } 1050 + 1040 1051 static inline int check_user_page_hwpoison(unsigned long addr) 1041 1052 { 1042 1053 int rc, flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_WRITE; ··· 1081 1070 if (writable) 1082 1071 *writable = write_fault; 1083 1072 1084 - npages = get_user_pages_fast(addr, 1, write_fault, page); 1073 + if (async) { 1074 + down_read(&current->mm->mmap_sem); 1075 + npages = get_user_page_nowait(current, current->mm, 1076 + addr, write_fault, page); 1077 + up_read(&current->mm->mmap_sem); 1078 + } else 1079 + npages = get_user_pages_fast(addr, 1, write_fault, 1080 + page); 1085 1081 1086 1082 /* map read fault as writable if possible */ 1087 1083 if (unlikely(!write_fault) && npages == 1) { ··· 1111 1093 return get_fault_pfn(); 1112 1094 1113 1095 down_read(&current->mm->mmap_sem); 1114 - if (check_user_page_hwpoison(addr)) { 1096 + if (npages == -EHWPOISON || 1097 + (!async && check_user_page_hwpoison(addr))) { 1115 1098 up_read(&current->mm->mmap_sem); 1116 1099 get_page(hwpoison_page); 1117 1100 return page_to_pfn(hwpoison_page);