Commit 67171a3f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm:
  x86: disable KVM for Voyager and friends
  KVM: VMX: Avoid rearranging switched guest msrs while they are loaded
  KVM: MMU: Fix race when instantiating a shadow pte
  KVM: Route irq 0 to vcpu 0 exclusively
  KVM: Avoid infinite-frequency local apic timer
  KVM: make MMU_DEBUG compile again
  KVM: move alloc_apic_access_page() outside of non-preemptable region
  KVM: SVM: fix Windows XP 64 bit installation crash
  KVM: remove the usage of the mmap_sem for the protection of the memory slots.
  KVM: emulate access to MSR_IA32_MCG_CTL
  KVM: Make the supported cpuid list a host property rather than a vm property
  KVM: Fix kvm_arch_vcpu_ioctl_set_sregs so that set_cr0 works properly
  KVM: SVM: set NM intercept when enabling CR0.TS in the guest
  KVM: SVM: Fix lazy FPU switching
parents ce932967 1a4e3f89
...@@ -21,7 +21,7 @@ config X86 ...@@ -21,7 +21,7 @@ config X86
select HAVE_IDE select HAVE_IDE
select HAVE_OPROFILE select HAVE_OPROFILE
select HAVE_KPROBES select HAVE_KPROBES
select HAVE_KVM select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
config GENERIC_LOCKBREAK config GENERIC_LOCKBREAK
......
...@@ -647,6 +647,10 @@ static void start_apic_timer(struct kvm_lapic *apic) ...@@ -647,6 +647,10 @@ static void start_apic_timer(struct kvm_lapic *apic)
apic->timer.period = apic_get_reg(apic, APIC_TMICT) * apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
APIC_BUS_CYCLE_NS * apic->timer.divide_count; APIC_BUS_CYCLE_NS * apic->timer.divide_count;
atomic_set(&apic->timer.pending, 0); atomic_set(&apic->timer.pending, 0);
if (!apic->timer.period)
return;
hrtimer_start(&apic->timer.dev, hrtimer_start(&apic->timer.dev,
ktime_add_ns(now, apic->timer.period), ktime_add_ns(now, apic->timer.period),
HRTIMER_MODE_ABS); HRTIMER_MODE_ABS);
......
...@@ -681,8 +681,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, ...@@ -681,8 +681,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
unsigned level, unsigned level,
int metaphysical, int metaphysical,
unsigned access, unsigned access,
u64 *parent_pte, u64 *parent_pte)
bool *new_page)
{ {
union kvm_mmu_page_role role; union kvm_mmu_page_role role;
unsigned index; unsigned index;
...@@ -722,8 +721,6 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu, ...@@ -722,8 +721,6 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
vcpu->arch.mmu.prefetch_page(vcpu, sp); vcpu->arch.mmu.prefetch_page(vcpu, sp);
if (!metaphysical) if (!metaphysical)
rmap_write_protect(vcpu->kvm, gfn); rmap_write_protect(vcpu->kvm, gfn);
if (new_page)
*new_page = 1;
return sp; return sp;
} }
...@@ -876,11 +873,18 @@ static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn) ...@@ -876,11 +873,18 @@ static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn)
struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva) struct page *gva_to_page(struct kvm_vcpu *vcpu, gva_t gva)
{ {
struct page *page;
gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva); gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
if (gpa == UNMAPPED_GVA) if (gpa == UNMAPPED_GVA)
return NULL; return NULL;
return gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
down_read(&current->mm->mmap_sem);
page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
up_read(&current->mm->mmap_sem);
return page;
} }
static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte, static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
...@@ -999,8 +1003,7 @@ static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, ...@@ -999,8 +1003,7 @@ static int __nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write,
>> PAGE_SHIFT; >> PAGE_SHIFT;
new_table = kvm_mmu_get_page(vcpu, pseudo_gfn, new_table = kvm_mmu_get_page(vcpu, pseudo_gfn,
v, level - 1, v, level - 1,
1, ACC_ALL, &table[index], 1, ACC_ALL, &table[index]);
NULL);
if (!new_table) { if (!new_table) {
pgprintk("nonpaging_map: ENOMEM\n"); pgprintk("nonpaging_map: ENOMEM\n");
kvm_release_page_clean(page); kvm_release_page_clean(page);
...@@ -1020,15 +1023,18 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn) ...@@ -1020,15 +1023,18 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
struct page *page; struct page *page;
down_read(&vcpu->kvm->slots_lock);
down_read(&current->mm->mmap_sem); down_read(&current->mm->mmap_sem);
page = gfn_to_page(vcpu->kvm, gfn); page = gfn_to_page(vcpu->kvm, gfn);
up_read(&current->mm->mmap_sem);
spin_lock(&vcpu->kvm->mmu_lock); spin_lock(&vcpu->kvm->mmu_lock);
kvm_mmu_free_some_pages(vcpu); kvm_mmu_free_some_pages(vcpu);
r = __nonpaging_map(vcpu, v, write, gfn, page); r = __nonpaging_map(vcpu, v, write, gfn, page);
spin_unlock(&vcpu->kvm->mmu_lock); spin_unlock(&vcpu->kvm->mmu_lock);
up_read(&current->mm->mmap_sem); up_read(&vcpu->kvm->slots_lock);
return r; return r;
} }
...@@ -1090,7 +1096,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) ...@@ -1090,7 +1096,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
ASSERT(!VALID_PAGE(root)); ASSERT(!VALID_PAGE(root));
sp = kvm_mmu_get_page(vcpu, root_gfn, 0, sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
PT64_ROOT_LEVEL, 0, ACC_ALL, NULL, NULL); PT64_ROOT_LEVEL, 0, ACC_ALL, NULL);
root = __pa(sp->spt); root = __pa(sp->spt);
++sp->root_count; ++sp->root_count;
vcpu->arch.mmu.root_hpa = root; vcpu->arch.mmu.root_hpa = root;
...@@ -1111,7 +1117,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu) ...@@ -1111,7 +1117,7 @@ static void mmu_alloc_roots(struct kvm_vcpu *vcpu)
root_gfn = 0; root_gfn = 0;
sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30,
PT32_ROOT_LEVEL, !is_paging(vcpu), PT32_ROOT_LEVEL, !is_paging(vcpu),
ACC_ALL, NULL, NULL); ACC_ALL, NULL);
root = __pa(sp->spt); root = __pa(sp->spt);
++sp->root_count; ++sp->root_count;
vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK; vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK;
...@@ -1172,7 +1178,7 @@ void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu) ...@@ -1172,7 +1178,7 @@ void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu)
static void paging_new_cr3(struct kvm_vcpu *vcpu) static void paging_new_cr3(struct kvm_vcpu *vcpu)
{ {
pgprintk("%s: cr3 %lx\n", __FUNCTION__, vcpu->cr3); pgprintk("%s: cr3 %lx\n", __FUNCTION__, vcpu->arch.cr3);
mmu_free_roots(vcpu); mmu_free_roots(vcpu);
} }
...@@ -1362,6 +1368,7 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, ...@@ -1362,6 +1368,7 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
gfn_t gfn; gfn_t gfn;
int r; int r;
u64 gpte = 0; u64 gpte = 0;
struct page *page;
if (bytes != 4 && bytes != 8) if (bytes != 4 && bytes != 8)
return; return;
...@@ -1389,6 +1396,11 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, ...@@ -1389,6 +1396,11 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
if (!is_present_pte(gpte)) if (!is_present_pte(gpte))
return; return;
gfn = (gpte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT; gfn = (gpte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
down_read(&current->mm->mmap_sem);
page = gfn_to_page(vcpu->kvm, gfn);
up_read(&current->mm->mmap_sem);
vcpu->arch.update_pte.gfn = gfn; vcpu->arch.update_pte.gfn = gfn;
vcpu->arch.update_pte.page = gfn_to_page(vcpu->kvm, gfn); vcpu->arch.update_pte.page = gfn_to_page(vcpu->kvm, gfn);
} }
...@@ -1496,9 +1508,9 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva) ...@@ -1496,9 +1508,9 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
gpa_t gpa; gpa_t gpa;
int r; int r;
down_read(&current->mm->mmap_sem); down_read(&vcpu->kvm->slots_lock);
gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva); gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, gva);
up_read(&current->mm->mmap_sem); up_read(&vcpu->kvm->slots_lock);
spin_lock(&vcpu->kvm->mmu_lock); spin_lock(&vcpu->kvm->mmu_lock);
r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT); r = kvm_mmu_unprotect_page(vcpu->kvm, gpa >> PAGE_SHIFT);
......
...@@ -91,7 +91,10 @@ static bool FNAME(cmpxchg_gpte)(struct kvm *kvm, ...@@ -91,7 +91,10 @@ static bool FNAME(cmpxchg_gpte)(struct kvm *kvm,
pt_element_t *table; pt_element_t *table;
struct page *page; struct page *page;
down_read(&current->mm->mmap_sem);
page = gfn_to_page(kvm, table_gfn); page = gfn_to_page(kvm, table_gfn);
up_read(&current->mm->mmap_sem);
table = kmap_atomic(page, KM_USER0); table = kmap_atomic(page, KM_USER0);
ret = CMPXCHG(&table[index], orig_pte, new_pte); ret = CMPXCHG(&table[index], orig_pte, new_pte);
...@@ -140,7 +143,7 @@ walk: ...@@ -140,7 +143,7 @@ walk:
} }
#endif #endif
ASSERT((!is_long_mode(vcpu) && is_pae(vcpu)) || ASSERT((!is_long_mode(vcpu) && is_pae(vcpu)) ||
(vcpu->cr3 & CR3_NONPAE_RESERVED_BITS) == 0); (vcpu->arch.cr3 & CR3_NONPAE_RESERVED_BITS) == 0);
pt_access = ACC_ALL; pt_access = ACC_ALL;
...@@ -297,7 +300,6 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, ...@@ -297,7 +300,6 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
u64 shadow_pte; u64 shadow_pte;
int metaphysical; int metaphysical;
gfn_t table_gfn; gfn_t table_gfn;
bool new_page = 0;
shadow_ent = ((u64 *)__va(shadow_addr)) + index; shadow_ent = ((u64 *)__va(shadow_addr)) + index;
if (level == PT_PAGE_TABLE_LEVEL) if (level == PT_PAGE_TABLE_LEVEL)
...@@ -319,8 +321,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, ...@@ -319,8 +321,8 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
} }
shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1, shadow_page = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
metaphysical, access, metaphysical, access,
shadow_ent, &new_page); shadow_ent);
if (new_page && !metaphysical) { if (!metaphysical) {
int r; int r;
pt_element_t curr_pte; pt_element_t curr_pte;
r = kvm_read_guest_atomic(vcpu->kvm, r = kvm_read_guest_atomic(vcpu->kvm,
...@@ -378,7 +380,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, ...@@ -378,7 +380,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
if (r) if (r)
return r; return r;
down_read(&current->mm->mmap_sem); down_read(&vcpu->kvm->slots_lock);
/* /*
* Look up the shadow pte for the faulting address. * Look up the shadow pte for the faulting address.
*/ */
...@@ -392,11 +394,13 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, ...@@ -392,11 +394,13 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
pgprintk("%s: guest page fault\n", __FUNCTION__); pgprintk("%s: guest page fault\n", __FUNCTION__);
inject_page_fault(vcpu, addr, walker.error_code); inject_page_fault(vcpu, addr, walker.error_code);
vcpu->arch.last_pt_write_count = 0; /* reset fork detector */ vcpu->arch.last_pt_write_count = 0; /* reset fork detector */
up_read(&current->mm->mmap_sem); up_read(&vcpu->kvm->slots_lock);
return 0; return 0;
} }
down_read(&current->mm->mmap_sem);
page = gfn_to_page(vcpu->kvm, walker.gfn); page = gfn_to_page(vcpu->kvm, walker.gfn);
up_read(&current->mm->mmap_sem);
spin_lock(&vcpu->kvm->mmu_lock); spin_lock(&vcpu->kvm->mmu_lock);
kvm_mmu_free_some_pages(vcpu); kvm_mmu_free_some_pages(vcpu);
...@@ -413,14 +417,14 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, ...@@ -413,14 +417,14 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
*/ */
if (shadow_pte && is_io_pte(*shadow_pte)) { if (shadow_pte && is_io_pte(*shadow_pte)) {
spin_unlock(&vcpu->kvm->mmu_lock); spin_unlock(&vcpu->kvm->mmu_lock);
up_read(&current->mm->mmap_sem); up_read(&vcpu->kvm->slots_lock);
return 1; return 1;
} }
++vcpu->stat.pf_fixed; ++vcpu->stat.pf_fixed;
kvm_mmu_audit(vcpu, "post page fault (fixed)"); kvm_mmu_audit(vcpu, "post page fault (fixed)");
spin_unlock(&vcpu->kvm->mmu_lock); spin_unlock(&vcpu->kvm->mmu_lock);
up_read(&current->mm->mmap_sem); up_read(&vcpu->kvm->slots_lock);
return write_pt; return write_pt;
} }
......
...@@ -792,6 +792,10 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) ...@@ -792,6 +792,10 @@ static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
vcpu->arch.cr0 = cr0; vcpu->arch.cr0 = cr0;
cr0 |= X86_CR0_PG | X86_CR0_WP; cr0 |= X86_CR0_PG | X86_CR0_WP;
cr0 &= ~(X86_CR0_CD | X86_CR0_NW); cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
if (!vcpu->fpu_active) {
svm->vmcb->control.intercept_exceptions |= (1 << NM_VECTOR);
cr0 |= X86_CR0_TS;
}
svm->vmcb->save.cr0 = cr0; svm->vmcb->save.cr0 = cr0;
} }
...@@ -1096,6 +1100,24 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) ...@@ -1096,6 +1100,24 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data)
case MSR_IA32_SYSENTER_ESP: case MSR_IA32_SYSENTER_ESP:
*data = svm->vmcb->save.sysenter_esp; *data = svm->vmcb->save.sysenter_esp;
break; break;
/* Nobody will change the following 5 values in the VMCB so
we can safely return them on rdmsr. They will always be 0
until LBRV is implemented. */
case MSR_IA32_DEBUGCTLMSR:
*data = svm->vmcb->save.dbgctl;
break;
case MSR_IA32_LASTBRANCHFROMIP:
*data = svm->vmcb->save.br_from;
break;
case MSR_IA32_LASTBRANCHTOIP:
*data = svm->vmcb->save.br_to;
break;
case MSR_IA32_LASTINTFROMIP:
*data = svm->vmcb->save.last_excp_from;
break;
case MSR_IA32_LASTINTTOIP:
*data = svm->vmcb->save.last_excp_to;
break;
default: default:
return kvm_get_msr_common(vcpu, ecx, data); return kvm_get_msr_common(vcpu, ecx, data);
} }
...@@ -1156,6 +1178,10 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) ...@@ -1156,6 +1178,10 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data)
case MSR_IA32_SYSENTER_ESP: case MSR_IA32_SYSENTER_ESP:
svm->vmcb->save.sysenter_esp = data; svm->vmcb->save.sysenter_esp = data;
break; break;
case MSR_IA32_DEBUGCTLMSR:
pr_unimpl(vcpu, "%s: MSR_IA32_DEBUGCTLMSR 0x%llx, nop\n",
__FUNCTION__, data);
break;
case MSR_K7_EVNTSEL0: case MSR_K7_EVNTSEL0:
case MSR_K7_EVNTSEL1: case MSR_K7_EVNTSEL1:
case MSR_K7_EVNTSEL2: case MSR_K7_EVNTSEL2:
......
...@@ -638,6 +638,7 @@ static void setup_msrs(struct vcpu_vmx *vmx) ...@@ -638,6 +638,7 @@ static void setup_msrs(struct vcpu_vmx *vmx)
{ {
int save_nmsrs; int save_nmsrs;
vmx_load_host_state(vmx);
save_nmsrs = 0; save_nmsrs = 0;
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
if (is_long_mode(&vmx->vcpu)) { if (is_long_mode(&vmx->vcpu)) {
...@@ -1477,7 +1478,7 @@ static int alloc_apic_access_page(struct kvm *kvm) ...@@ -1477,7 +1478,7 @@ static int alloc_apic_access_page(struct kvm *kvm)
struct kvm_userspace_memory_region kvm_userspace_mem; struct kvm_userspace_memory_region kvm_userspace_mem;
int r = 0; int r = 0;
down_write(&current->mm->mmap_sem); down_write(&kvm->slots_lock);
if (kvm->arch.apic_access_page) if (kvm->arch.apic_access_page)
goto out; goto out;
kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT; kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
...@@ -1487,9 +1488,12 @@ static int alloc_apic_access_page(struct kvm *kvm) ...@@ -1487,9 +1488,12 @@ static int alloc_apic_access_page(struct kvm *kvm)
r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0); r = __kvm_set_memory_region(kvm, &kvm_userspace_mem, 0);
if (r) if (r)
goto out; goto out;
down_read(&current->mm->mmap_sem);
kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00); kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00);
up_read(&current->mm->mmap_sem);
out: out:
up_write(&current->mm->mmap_sem); up_write(&kvm->slots_lock);
return r; return r;
} }
...@@ -1602,9 +1606,6 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) ...@@ -1602,9 +1606,6 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL); vmcs_writel(CR0_GUEST_HOST_MASK, ~0UL);
vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK); vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
if (vm_need_virtualize_apic_accesses(vmx->vcpu.kvm))
if (alloc_apic_access_page(vmx->vcpu.kvm) != 0)
return -ENOMEM;
return 0; return 0;
} }
...@@ -2534,6 +2535,9 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) ...@@ -2534,6 +2535,9 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
put_cpu(); put_cpu();
if (err) if (err)
goto free_vmcs; goto free_vmcs;
if (vm_need_virtualize_apic_accesses(kvm))
if (alloc_apic_access_page(kvm) != 0)
goto free_vmcs;
return &vmx->vcpu; return &vmx->vcpu;
......
This diff is collapsed.
...@@ -221,6 +221,7 @@ struct kvm_vapic_addr { ...@@ -221,6 +221,7 @@ struct kvm_vapic_addr {
* Get size for mmap(vcpu_fd) * Get size for mmap(vcpu_fd)
*/ */
#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */ #define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */
#define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2)
/* /*
* Extension capability list. * Extension capability list.
...@@ -230,8 +231,8 @@ struct kvm_vapic_addr { ...@@ -230,8 +231,8 @@ struct kvm_vapic_addr {
#define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2 #define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2
#define KVM_CAP_USER_MEMORY 3 #define KVM_CAP_USER_MEMORY 3
#define KVM_CAP_SET_TSS_ADDR 4 #define KVM_CAP_SET_TSS_ADDR 4
#define KVM_CAP_EXT_CPUID 5
#define KVM_CAP_VAPIC 6 #define KVM_CAP_VAPIC 6
#define KVM_CAP_EXT_CPUID 7
/* /*
* ioctls for VM fds * ioctls for VM fds
...@@ -249,7 +250,6 @@ struct kvm_vapic_addr { ...@@ -249,7 +250,6 @@ struct kvm_vapic_addr {
#define KVM_CREATE_VCPU _IO(KVMIO, 0x41) #define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log) #define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias) #define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)
#define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x48, struct kvm_cpuid2)
/* Device model IOC */ /* Device model IOC */
#define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) #define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60)
#define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level) #define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level)
......
...@@ -107,6 +107,7 @@ struct kvm_memory_slot { ...@@ -107,6 +107,7 @@ struct kvm_memory_slot {
struct kvm { struct kvm {
struct mutex lock; /* protects the vcpus array and APIC accesses */ struct mutex lock; /* protects the vcpus array and APIC accesses */
spinlock_t mmu_lock; spinlock_t mmu_lock;
struct rw_semaphore slots_lock;
struct mm_struct *mm; /* userspace tied to this vm */ struct mm_struct *mm; /* userspace tied to this vm */
int nmemslots; int nmemslots;
struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS + struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS +
......
...@@ -211,6 +211,10 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq) ...@@ -211,6 +211,10 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
case IOAPIC_LOWEST_PRIORITY: case IOAPIC_LOWEST_PRIORITY:
vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector, vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector,
deliver_bitmask); deliver_bitmask);
#ifdef CONFIG_X86
if (irq == 0)
vcpu = ioapic->kvm->vcpus[0];
#endif
if (vcpu != NULL) if (vcpu != NULL)
ioapic_inj_irq(ioapic, vcpu, vector, ioapic_inj_irq(ioapic, vcpu, vector,
trig_mode, delivery_mode); trig_mode, delivery_mode);
...@@ -220,6 +224,10 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq) ...@@ -220,6 +224,10 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
deliver_bitmask, vector, IOAPIC_LOWEST_PRIORITY); deliver_bitmask, vector, IOAPIC_LOWEST_PRIORITY);
break; break;
case IOAPIC_FIXED: case IOAPIC_FIXED:
#ifdef CONFIG_X86
if (irq == 0)
deliver_bitmask = 1;
#endif
for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) { for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) {
if (!(deliver_bitmask & (1 << vcpu_id))) if (!(deliver_bitmask & (1 << vcpu_id)))
continue; continue;
......
...@@ -169,6 +169,7 @@ static struct kvm *kvm_create_vm(void) ...@@ -169,6 +169,7 @@ static struct kvm *kvm_create_vm(void)
kvm_io_bus_init(&kvm->pio_bus); kvm_io_bus_init(&kvm->pio_bus);
mutex_init(&kvm->lock); mutex_init(&kvm->lock);
kvm_io_bus_init(&kvm->mmio_bus); kvm_io_bus_init(&kvm->mmio_bus);
init_rwsem(&kvm->slots_lock);
spin_lock(&kvm_lock); spin_lock(&kvm_lock);
list_add(&kvm->vm_list, &vm_list); list_add(&kvm->vm_list, &vm_list);
spin_unlock(&kvm_lock); spin_unlock(&kvm_lock);
...@@ -339,9 +340,9 @@ int kvm_set_memory_region(struct kvm *kvm, ...@@ -339,9 +340,9 @@ int kvm_set_memory_region(struct kvm *kvm,
{ {
int r; int r;
down_write(&current->mm->mmap_sem); down_write(&kvm->slots_lock);
r = __kvm_set_memory_region(kvm, mem, user_alloc); r = __kvm_set_memory_region(kvm, mem, user_alloc);
up_write(&current->mm->mmap_sem); up_write(&kvm->slots_lock);
return r; return r;
} }
EXPORT_SYMBOL_GPL(kvm_set_memory_region); EXPORT_SYMBOL_GPL(kvm_set_memory_region);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment