Skip to content

Commit

Permalink
Merge branch 'kvm-updates/2.6.39' of git://git.kernel.org/pub/scm/vir…
Browse files Browse the repository at this point in the history
…t/kvm/kvm

* 'kvm-updates/2.6.39' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (55 commits)
  KVM: unbreak userspace that does not sets tss address
  KVM: MMU: cleanup pte write path
  KVM: MMU: introduce a common function to get no-dirty-logged slot
  KVM: fix rcu usage in init_rmode_* functions
  KVM: fix kvmclock regression due to missing clock update
  KVM: emulator: Fix permission checking in io permission bitmap
  KVM: emulator: Fix io permission checking for 64bit guest
  KVM: SVM: Load %gs earlier if CONFIG_X86_32_LAZY_GS=n
  KVM: x86: Remove useless regs_page pointer from kvm_lapic
  KVM: improve comment on rcu use in irqfd_deassign
  KVM: MMU: remove unused macros
  KVM: MMU: cleanup page alloc and free
  KVM: MMU: do not record gfn in kvm_mmu_pte_write
  KVM: MMU: move mmu pages calculated out of mmu lock
  KVM: MMU: set spte accessed bit properly
  KVM: MMU: fix kvm_mmu_slot_remove_write_access dropping intermediate W bits
  KVM: Start lock documentation
  KVM: better readability of efer_reserved_bits
  KVM: Clear async page fault hash after switching to real mode
  KVM: VMX: Initialize vm86 TSS only once.
  ...
  • Loading branch information
Linus Torvalds committed Mar 18, 2011
2 parents 804f185 + 776e58e commit ec0afc9
Show file tree
Hide file tree
Showing 33 changed files with 554 additions and 400 deletions.
25 changes: 25 additions & 0 deletions Documentation/kvm/locking.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
KVM Lock Overview
=================

1. Acquisition Orders
---------------------

(to be written)

2. Reference
------------

Name: kvm_lock
Type: raw_spinlock
Arch: any
Protects: - vm_list
- hardware virtualization enable/disable
Comment: 'raw' because hardware enabling/disabling must be atomic /wrt
migration.

Name: kvm_arch::tsc_write_lock
Type: raw_spinlock
Arch: x86
Protects: - kvm_arch::{last_tsc_write,last_tsc_nsec,last_tsc_offset}
- tsc offset in vmcb
Comment: 'raw' because updating the tsc offsets must not be preempted.
2 changes: 2 additions & 0 deletions arch/alpha/include/asm/errno.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,6 @@

#define ERFKILL 138 /* Operation not possible due to RF-kill */

#define EHWPOISON 139 /* Memory page has hardware error */

#endif
2 changes: 2 additions & 0 deletions arch/ia64/kvm/kvm-ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
goto vcpu_run_fail;

srcu_read_unlock(&vcpu->kvm->srcu, idx);
vcpu->mode = IN_GUEST_MODE;
kvm_guest_enter();

/*
Expand All @@ -683,6 +684,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
*/
barrier();
kvm_guest_exit();
vcpu->mode = OUTSIDE_GUEST_MODE;
preempt_enable();

idx = srcu_read_lock(&vcpu->kvm->srcu);
Expand Down
2 changes: 2 additions & 0 deletions arch/mips/include/asm/errno.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@

#define ERFKILL 167 /* Operation not possible due to RF-kill */

#define EHWPOISON 168 /* Memory page has hardware error */

#define EDQUOT 1133 /* Quota exceeded */

#ifdef __KERNEL__
Expand Down
2 changes: 2 additions & 0 deletions arch/parisc/include/asm/errno.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,6 @@

#define ERFKILL 256 /* Operation not possible due to RF-kill */

#define EHWPOISON 257 /* Memory page has hardware error */

#endif
14 changes: 8 additions & 6 deletions arch/powerpc/kvm/book3s.c
Original file line number Diff line number Diff line change
Expand Up @@ -1141,9 +1141,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->sprg1 = vcpu->arch.shared->sprg1;
regs->sprg2 = vcpu->arch.shared->sprg2;
regs->sprg3 = vcpu->arch.shared->sprg3;
regs->sprg5 = vcpu->arch.sprg4;
regs->sprg6 = vcpu->arch.sprg5;
regs->sprg7 = vcpu->arch.sprg6;
regs->sprg4 = vcpu->arch.sprg4;
regs->sprg5 = vcpu->arch.sprg5;
regs->sprg6 = vcpu->arch.sprg6;
regs->sprg7 = vcpu->arch.sprg7;

for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
Expand All @@ -1167,9 +1168,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
vcpu->arch.shared->sprg1 = regs->sprg1;
vcpu->arch.shared->sprg2 = regs->sprg2;
vcpu->arch.shared->sprg3 = regs->sprg3;
vcpu->arch.sprg5 = regs->sprg4;
vcpu->arch.sprg6 = regs->sprg5;
vcpu->arch.sprg7 = regs->sprg6;
vcpu->arch.sprg4 = regs->sprg4;
vcpu->arch.sprg5 = regs->sprg5;
vcpu->arch.sprg6 = regs->sprg6;
vcpu->arch.sprg7 = regs->sprg7;

for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
Expand Down
14 changes: 8 additions & 6 deletions arch/powerpc/kvm/booke.c
Original file line number Diff line number Diff line change
Expand Up @@ -546,9 +546,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
regs->sprg1 = vcpu->arch.shared->sprg1;
regs->sprg2 = vcpu->arch.shared->sprg2;
regs->sprg3 = vcpu->arch.shared->sprg3;
regs->sprg5 = vcpu->arch.sprg4;
regs->sprg6 = vcpu->arch.sprg5;
regs->sprg7 = vcpu->arch.sprg6;
regs->sprg4 = vcpu->arch.sprg4;
regs->sprg5 = vcpu->arch.sprg5;
regs->sprg6 = vcpu->arch.sprg6;
regs->sprg7 = vcpu->arch.sprg7;

for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
Expand All @@ -572,9 +573,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
vcpu->arch.shared->sprg1 = regs->sprg1;
vcpu->arch.shared->sprg2 = regs->sprg2;
vcpu->arch.shared->sprg3 = regs->sprg3;
vcpu->arch.sprg5 = regs->sprg4;
vcpu->arch.sprg6 = regs->sprg5;
vcpu->arch.sprg7 = regs->sprg6;
vcpu->arch.sprg4 = regs->sprg4;
vcpu->arch.sprg5 = regs->sprg5;
vcpu->arch.sprg6 = regs->sprg6;
vcpu->arch.sprg7 = regs->sprg7;

for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
Expand Down
2 changes: 2 additions & 0 deletions arch/sparc/include/asm/errno.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,6 @@

#define ERFKILL 134 /* Operation not possible due to RF-kill */

#define EHWPOISON 135 /* Memory page has hardware error */

#endif
5 changes: 3 additions & 2 deletions arch/x86/include/asm/kvm_emulate.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ struct x86_emulate_ops {
int (*pio_out_emulated)(int size, unsigned short port, const void *val,
unsigned int count, struct kvm_vcpu *vcpu);

bool (*get_cached_descriptor)(struct desc_struct *desc,
bool (*get_cached_descriptor)(struct desc_struct *desc, u32 *base3,
int seg, struct kvm_vcpu *vcpu);
void (*set_cached_descriptor)(struct desc_struct *desc,
void (*set_cached_descriptor)(struct desc_struct *desc, u32 base3,
int seg, struct kvm_vcpu *vcpu);
u16 (*get_segment_selector)(int seg, struct kvm_vcpu *vcpu);
void (*set_segment_selector)(u16 sel, int seg, struct kvm_vcpu *vcpu);
Expand Down Expand Up @@ -239,6 +239,7 @@ struct x86_emulate_ctxt {
int interruptibility;

bool perm_ok; /* do not check permissions if true */
bool only_vendor_specific_insn;

bool have_exception;
struct x86_exception exception;
Expand Down
12 changes: 4 additions & 8 deletions arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@

#define ASYNC_PF_PER_VCPU 64

extern spinlock_t kvm_lock;
extern raw_spinlock_t kvm_lock;
extern struct list_head vm_list;

struct kvm_vcpu;
Expand Down Expand Up @@ -255,6 +255,8 @@ struct kvm_mmu {
int (*sync_page)(struct kvm_vcpu *vcpu,
struct kvm_mmu_page *sp);
void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva);
void (*update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
u64 *spte, const void *pte, unsigned long mmu_seq);
hpa_t root_hpa;
int root_level;
int shadow_root_level;
Expand Down Expand Up @@ -335,12 +337,6 @@ struct kvm_vcpu_arch {
u64 *last_pte_updated;
gfn_t last_pte_gfn;

struct {
gfn_t gfn; /* presumed gfn during guest pte update */
pfn_t pfn; /* pfn corresponding to that gfn */
unsigned long mmu_seq;
} update_pte;

struct fpu guest_fpu;
u64 xcr0;

Expand Down Expand Up @@ -448,7 +444,7 @@ struct kvm_arch {

unsigned long irq_sources_bitmap;
s64 kvmclock_offset;
spinlock_t tsc_write_lock;
raw_spinlock_t tsc_write_lock;
u64 last_tsc_nsec;
u64 last_tsc_offset;
u64 last_tsc_write;
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/asm/msr-index.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

#define MSR_MTRRcap 0x000000fe
#define MSR_IA32_BBL_CR_CTL 0x00000119
#define MSR_IA32_BBL_CR_CTL3 0x0000011e

#define MSR_IA32_SYSENTER_CS 0x00000174
#define MSR_IA32_SYSENTER_ESP 0x00000175
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ static void __init kvm_smp_prepare_boot_cpu(void)
native_smp_prepare_boot_cpu();
}

static void kvm_guest_cpu_online(void *dummy)
static void __cpuinit kvm_guest_cpu_online(void *dummy)
{
kvm_guest_cpu_init();
}
Expand Down
52 changes: 32 additions & 20 deletions arch/x86/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
#define Group (1<<14) /* Bits 3:5 of modrm byte extend opcode */
#define GroupDual (1<<15) /* Alternate decoding of mod == 3 */
/* Misc flags */
#define VendorSpecific (1<<22) /* Vendor specific instruction */
#define NoAccess (1<<23) /* Don't access memory (lea/invlpg/verr etc) */
#define Op3264 (1<<24) /* Operand is 64b in long mode, 32b otherwise */
#define Undefined (1<<25) /* No Such Instruction */
Expand Down Expand Up @@ -877,7 +878,8 @@ static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
if (selector & 1 << 2) {
struct desc_struct desc;
memset (dt, 0, sizeof *dt);
if (!ops->get_cached_descriptor(&desc, VCPU_SREG_LDTR, ctxt->vcpu))
if (!ops->get_cached_descriptor(&desc, NULL, VCPU_SREG_LDTR,
ctxt->vcpu))
return;

dt->size = desc_limit_scaled(&desc); /* what if limit > 65535? */
Expand Down Expand Up @@ -929,6 +931,7 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
return ret;
}

/* Does not support long mode */
static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops,
u16 selector, int seg)
Expand Down Expand Up @@ -1040,7 +1043,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
}
load:
ops->set_segment_selector(selector, seg, ctxt->vcpu);
ops->set_cached_descriptor(&seg_desc, seg, ctxt->vcpu);
ops->set_cached_descriptor(&seg_desc, 0, seg, ctxt->vcpu);
return X86EMUL_CONTINUE;
exception:
emulate_exception(ctxt, err_vec, err_code, true);
Expand Down Expand Up @@ -1560,7 +1563,7 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
struct desc_struct *ss)
{
memset(cs, 0, sizeof(struct desc_struct));
ops->get_cached_descriptor(cs, VCPU_SREG_CS, ctxt->vcpu);
ops->get_cached_descriptor(cs, NULL, VCPU_SREG_CS, ctxt->vcpu);
memset(ss, 0, sizeof(struct desc_struct));

cs->l = 0; /* will be adjusted later */
Expand Down Expand Up @@ -1607,9 +1610,9 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
cs.d = 0;
cs.l = 1;
}
ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);

c->regs[VCPU_REGS_RCX] = c->eip;
Expand Down Expand Up @@ -1679,9 +1682,9 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
cs.l = 1;
}

ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);

ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_EIP, &msr_data);
Expand Down Expand Up @@ -1736,9 +1739,9 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
cs_sel |= SELECTOR_RPL_MASK;
ss_sel |= SELECTOR_RPL_MASK;

ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);

c->eip = c->regs[VCPU_REGS_RDX];
Expand All @@ -1764,24 +1767,28 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
u16 port, u16 len)
{
struct desc_struct tr_seg;
u32 base3;
int r;
u16 io_bitmap_ptr;
u8 perm, bit_idx = port & 0x7;
u16 io_bitmap_ptr, perm, bit_idx = port & 0x7;
unsigned mask = (1 << len) - 1;
unsigned long base;

ops->get_cached_descriptor(&tr_seg, VCPU_SREG_TR, ctxt->vcpu);
ops->get_cached_descriptor(&tr_seg, &base3, VCPU_SREG_TR, ctxt->vcpu);
if (!tr_seg.p)
return false;
if (desc_limit_scaled(&tr_seg) < 103)
return false;
r = ops->read_std(get_desc_base(&tr_seg) + 102, &io_bitmap_ptr, 2,
ctxt->vcpu, NULL);
base = get_desc_base(&tr_seg);
#ifdef CONFIG_X86_64
base |= ((u64)base3) << 32;
#endif
r = ops->read_std(base + 102, &io_bitmap_ptr, 2, ctxt->vcpu, NULL);
if (r != X86EMUL_CONTINUE)
return false;
if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg))
return false;
r = ops->read_std(get_desc_base(&tr_seg) + io_bitmap_ptr + port/8,
&perm, 1, ctxt->vcpu, NULL);
r = ops->read_std(base + io_bitmap_ptr + port/8, &perm, 2, ctxt->vcpu,
NULL);
if (r != X86EMUL_CONTINUE)
return false;
if ((perm >> bit_idx) & mask)
Expand Down Expand Up @@ -2126,7 +2133,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
}

ops->set_cr(0, ops->get_cr(0, ctxt->vcpu) | X86_CR0_TS, ctxt->vcpu);
ops->set_cached_descriptor(&next_tss_desc, VCPU_SREG_TR, ctxt->vcpu);
ops->set_cached_descriptor(&next_tss_desc, 0, VCPU_SREG_TR, ctxt->vcpu);
ops->set_segment_selector(tss_selector, VCPU_SREG_TR, ctxt->vcpu);

if (has_error_code) {
Expand Down Expand Up @@ -2365,7 +2372,8 @@ static struct group_dual group7 = { {
D(SrcMem16 | ModRM | Mov | Priv),
D(SrcMem | ModRM | ByteOp | Priv | NoAccess),
}, {
D(SrcNone | ModRM | Priv), N, N, D(SrcNone | ModRM | Priv),
D(SrcNone | ModRM | Priv | VendorSpecific), N,
N, D(SrcNone | ModRM | Priv | VendorSpecific),
D(SrcNone | ModRM | DstMem | Mov), N,
D(SrcMem16 | ModRM | Mov | Priv), N,
} };
Expand Down Expand Up @@ -2489,7 +2497,7 @@ static struct opcode opcode_table[256] = {
static struct opcode twobyte_table[256] = {
/* 0x00 - 0x0F */
N, GD(0, &group7), N, N,
N, D(ImplicitOps), D(ImplicitOps | Priv), N,
N, D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv), N,
D(ImplicitOps | Priv), D(ImplicitOps | Priv), N, N,
N, D(ImplicitOps | ModRM), N, N,
/* 0x10 - 0x1F */
Expand All @@ -2502,7 +2510,8 @@ static struct opcode twobyte_table[256] = {
/* 0x30 - 0x3F */
D(ImplicitOps | Priv), I(ImplicitOps, em_rdtsc),
D(ImplicitOps | Priv), N,
D(ImplicitOps), D(ImplicitOps | Priv), N, N,
D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv | VendorSpecific),
N, N,
N, N, N, N, N, N, N, N,
/* 0x40 - 0x4F */
X16(D(DstReg | SrcMem | ModRM | Mov)),
Expand Down Expand Up @@ -2741,6 +2750,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
if (c->d == 0 || (c->d & Undefined))
return -1;

if (!(c->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
return -1;

if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
c->op_bytes = 8;

Expand Down
Loading

0 comments on commit ec0afc9

Please sign in to comment.