Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fd56c70 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm:
  KVM: Use new smp_call_function_mask() in kvm_flush_remote_tlbs()
  sched: don't clear PF_VCPU in scheduler
  KVM: Improve local apic timer wraparound handling
  KVM: Fix local apic timer divide by zero
  KVM: Move kvm_guest_exit() after local_irq_enable()
  KVM: x86 emulator: fix access registers for instructions with ModR/M byte and Mod = 3
  KVM: VMX: Force vm86 mode if setting flags during real mode
  KVM: x86 emulator: implement 'movnti mem, reg'
  KVM: VMX: Reset mmu context when entering real mode
  KVM: VMX: Handle NMIs before enabling interrupts and preemption
  KVM: MMU: Set shadow pte atomically in mmu_pte_write_zap_pte()
  KVM: x86 emulator: fix repne/repnz decoding
  KVM: x86 emulator: fix merge screwup due to emulator split
parents 56d61a0e 49d3bd7e
Loading
Loading
Loading
Loading
+13 −24
Original line number Original line Diff line number Diff line
@@ -198,21 +198,15 @@ static void vcpu_put(struct kvm_vcpu *vcpu)


static void ack_flush(void *_completed)
static void ack_flush(void *_completed)
{
{
	atomic_t *completed = _completed;

	atomic_inc(completed);
}
}


void kvm_flush_remote_tlbs(struct kvm *kvm)
void kvm_flush_remote_tlbs(struct kvm *kvm)
{
{
	int i, cpu, needed;
	int i, cpu;
	cpumask_t cpus;
	cpumask_t cpus;
	struct kvm_vcpu *vcpu;
	struct kvm_vcpu *vcpu;
	atomic_t completed;


	atomic_set(&completed, 0);
	cpus_clear(cpus);
	cpus_clear(cpus);
	needed = 0;
	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
		vcpu = kvm->vcpus[i];
		vcpu = kvm->vcpus[i];
		if (!vcpu)
		if (!vcpu)
@@ -221,23 +215,9 @@ void kvm_flush_remote_tlbs(struct kvm *kvm)
			continue;
			continue;
		cpu = vcpu->cpu;
		cpu = vcpu->cpu;
		if (cpu != -1 && cpu != raw_smp_processor_id())
		if (cpu != -1 && cpu != raw_smp_processor_id())
			if (!cpu_isset(cpu, cpus)) {
			cpu_set(cpu, cpus);
			cpu_set(cpu, cpus);
				++needed;
			}
	}

	/*
	 * We really want smp_call_function_mask() here.  But that's not
	 * available, so ipi all cpus in parallel and wait for them
	 * to complete.
	 */
	for (cpu = first_cpu(cpus); cpu != NR_CPUS; cpu = next_cpu(cpu, cpus))
		smp_call_function_single(cpu, ack_flush, &completed, 1, 0);
	while (atomic_read(&completed) != needed) {
		cpu_relax();
		barrier();
	}
	}
	smp_call_function_mask(cpus, ack_flush, NULL, 1);
}
}


int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
@@ -2054,12 +2034,21 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)


	kvm_x86_ops->run(vcpu, kvm_run);
	kvm_x86_ops->run(vcpu, kvm_run);


	kvm_guest_exit();
	vcpu->guest_mode = 0;
	vcpu->guest_mode = 0;
	local_irq_enable();
	local_irq_enable();


	++vcpu->stat.exits;
	++vcpu->stat.exits;


	/*
	 * We must have an instruction between local_irq_enable() and
	 * kvm_guest_exit(), so the timer interrupt isn't delayed by
	 * the interrupt shadow.  The stat.exits increment will do nicely.
	 * But we need to prevent reordering, hence this barrier():
	 */
	barrier();

	kvm_guest_exit();

	preempt_enable();
	preempt_enable();


	/*
	/*
+27 −11
Original line number Original line Diff line number Diff line
@@ -494,12 +494,19 @@ static void apic_send_ipi(struct kvm_lapic *apic)


static u32 apic_get_tmcct(struct kvm_lapic *apic)
static u32 apic_get_tmcct(struct kvm_lapic *apic)
{
{
	u32 counter_passed;
	u64 counter_passed;
	ktime_t passed, now = apic->timer.dev.base->get_time();
	ktime_t passed, now;
	u32 tmcct = apic_get_reg(apic, APIC_TMICT);
	u32 tmcct;


	ASSERT(apic != NULL);
	ASSERT(apic != NULL);


	now = apic->timer.dev.base->get_time();
	tmcct = apic_get_reg(apic, APIC_TMICT);

	/* if initial count is 0, current count should also be 0 */
	if (tmcct == 0)
		return 0;

	if (unlikely(ktime_to_ns(now) <=
	if (unlikely(ktime_to_ns(now) <=
		ktime_to_ns(apic->timer.last_update))) {
		ktime_to_ns(apic->timer.last_update))) {
		/* Wrap around */
		/* Wrap around */
@@ -514,15 +521,24 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)


	counter_passed = div64_64(ktime_to_ns(passed),
	counter_passed = div64_64(ktime_to_ns(passed),
				  (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
				  (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
	tmcct -= counter_passed;


	if (tmcct <= 0) {
	if (counter_passed > tmcct) {
		if (unlikely(!apic_lvtt_period(apic)))
		if (unlikely(!apic_lvtt_period(apic))) {
			/* one-shot timers stick at 0 until reset */
			tmcct = 0;
			tmcct = 0;
		else
		} else {
			do {
			/*
				tmcct += apic_get_reg(apic, APIC_TMICT);
			 * periodic timers reset to APIC_TMICT when they
			} while (tmcct <= 0);
			 * hit 0. The while loop simulates this happening N
			 * times. (counter_passed %= tmcct) would also work,
			 * but might be slower or not work on 32-bit??
			 */
			while (counter_passed > tmcct)
				counter_passed -= tmcct;
			tmcct -= counter_passed;
		}
	} else {
		tmcct -= counter_passed;
	}
	}


	return tmcct;
	return tmcct;
@@ -853,7 +869,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
		apic_set_reg(apic, APIC_ISR + 0x10 * i, 0);
		apic_set_reg(apic, APIC_ISR + 0x10 * i, 0);
		apic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
		apic_set_reg(apic, APIC_TMR + 0x10 * i, 0);
	}
	}
	apic->timer.divide_count = 0;
	update_divide_count(apic);
	atomic_set(&apic->timer.pending, 0);
	atomic_set(&apic->timer.pending, 0);
	if (vcpu->vcpu_id == 0)
	if (vcpu->vcpu_id == 0)
		vcpu->apic_base |= MSR_IA32_APICBASE_BSP;
		vcpu->apic_base |= MSR_IA32_APICBASE_BSP;
+2 −1
Original line number Original line Diff line number Diff line
@@ -1049,6 +1049,7 @@ int kvm_mmu_reset_context(struct kvm_vcpu *vcpu)
	destroy_kvm_mmu(vcpu);
	destroy_kvm_mmu(vcpu);
	return init_kvm_mmu(vcpu);
	return init_kvm_mmu(vcpu);
}
}
EXPORT_SYMBOL_GPL(kvm_mmu_reset_context);


int kvm_mmu_load(struct kvm_vcpu *vcpu)
int kvm_mmu_load(struct kvm_vcpu *vcpu)
{
{
@@ -1088,7 +1089,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
			mmu_page_remove_parent_pte(child, spte);
			mmu_page_remove_parent_pte(child, spte);
		}
		}
	}
	}
	*spte = 0;
	set_shadow_pte(spte, 0);
	kvm_flush_remote_tlbs(vcpu->kvm);
	kvm_flush_remote_tlbs(vcpu->kvm);
}
}


+12 −4
Original line number Original line Diff line number Diff line
@@ -523,6 +523,8 @@ static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)


static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
{
{
	if (vcpu->rmode.active)
		rflags |= IOPL_MASK | X86_EFLAGS_VM;
	vmcs_writel(GUEST_RFLAGS, rflags);
	vmcs_writel(GUEST_RFLAGS, rflags);
}
}


@@ -1128,6 +1130,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
	fix_rmode_seg(VCPU_SREG_GS, &vcpu->rmode.gs);
	fix_rmode_seg(VCPU_SREG_GS, &vcpu->rmode.gs);
	fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs);
	fix_rmode_seg(VCPU_SREG_FS, &vcpu->rmode.fs);


	kvm_mmu_reset_context(vcpu);
	init_rmode_tss(vcpu->kvm);
	init_rmode_tss(vcpu->kvm);
}
}


@@ -1760,10 +1763,8 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
		set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary);
		set_bit(irq / BITS_PER_LONG, &vcpu->irq_summary);
	}
	}


	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */
	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */
		asm ("int $2");
		return 1;  /* already handled by vmx_vcpu_run() */
		return 1;
	}


	if (is_no_device(intr_info)) {
	if (is_no_device(intr_info)) {
		vmx_fpu_activate(vcpu);
		vmx_fpu_activate(vcpu);
@@ -2196,6 +2197,7 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
{
	struct vcpu_vmx *vmx = to_vmx(vcpu);
	struct vcpu_vmx *vmx = to_vmx(vcpu);
	u32 intr_info;


	/*
	/*
	 * Loading guest fpu may have cleared host cr0.ts
	 * Loading guest fpu may have cleared host cr0.ts
@@ -2322,6 +2324,12 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)


	asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
	asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
	vmx->launched = 1;
	vmx->launched = 1;

	intr_info = vmcs_read32(VM_EXIT_INTR_INFO);

	/* We need to handle NMIs before interrupts are enabled */
	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) /* nmi */
		asm("int $2");
}
}


static void vmx_inject_page_fault(struct kvm_vcpu *vcpu,
static void vmx_inject_page_fault(struct kvm_vcpu *vcpu,
+49 −28
Original line number Original line Diff line number Diff line
@@ -212,7 +212,8 @@ static u16 twobyte_table[256] = {
	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
	0, 0, ByteOp | DstReg | SrcMem | ModRM | Mov,
	    DstReg | SrcMem16 | ModRM | Mov,
	    DstReg | SrcMem16 | ModRM | Mov,
	/* 0xC0 - 0xCF */
	/* 0xC0 - 0xCF */
	0, 0, 0, 0, 0, 0, 0, ImplicitOps | ModRM, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, DstMem | SrcReg | ModRM | Mov, 0, 0, 0, ImplicitOps | ModRM,
	0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xD0 - 0xDF */
	/* 0xD0 - 0xDF */
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	/* 0xE0 - 0xEF */
	/* 0xE0 - 0xEF */
@@ -596,11 +597,10 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
		case 0xf0:	/* LOCK */
		case 0xf0:	/* LOCK */
			lock_prefix = 1;
			lock_prefix = 1;
			break;
			break;
		case 0xf2:	/* REPNE/REPNZ */
		case 0xf3:	/* REP/REPE/REPZ */
		case 0xf3:	/* REP/REPE/REPZ */
			rep_prefix = 1;
			rep_prefix = 1;
			break;
			break;
		case 0xf2:	/* REPNE/REPNZ */
			break;
		default:
		default:
			goto done_prefixes;
			goto done_prefixes;
		}
		}
@@ -825,6 +825,14 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
		if (twobyte && b == 0x01 && modrm_reg == 7)
		if (twobyte && b == 0x01 && modrm_reg == 7)
			break;
			break;
	      srcmem_common:
	      srcmem_common:
		/*
		 * For instructions with a ModR/M byte, switch to register
		 * access if Mod = 3.
		 */
		if ((d & ModRM) && modrm_mod == 3) {
			src.type = OP_REG;
			break;
		}
		src.type = OP_MEM;
		src.type = OP_MEM;
		src.ptr = (unsigned long *)cr2;
		src.ptr = (unsigned long *)cr2;
		src.val = 0;
		src.val = 0;
@@ -893,6 +901,14 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
		dst.ptr = (unsigned long *)cr2;
		dst.ptr = (unsigned long *)cr2;
		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
		dst.bytes = (d & ByteOp) ? 1 : op_bytes;
		dst.val = 0;
		dst.val = 0;
		/*
		 * For instructions with a ModR/M byte, switch to register
		 * access if Mod = 3.
		 */
		if ((d & ModRM) && modrm_mod == 3) {
			dst.type = OP_REG;
			break;
		}
		if (d & BitOp) {
		if (d & BitOp) {
			unsigned long mask = ~(dst.bytes * 8 - 1);
			unsigned long mask = ~(dst.bytes * 8 - 1);


@@ -1083,31 +1099,6 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
	case 0xd2 ... 0xd3:	/* Grp2 */
	case 0xd2 ... 0xd3:	/* Grp2 */
		src.val = _regs[VCPU_REGS_RCX];
		src.val = _regs[VCPU_REGS_RCX];
		goto grp2;
		goto grp2;
	case 0xe8: /* call (near) */ {
		long int rel;
		switch (op_bytes) {
		case 2:
			rel = insn_fetch(s16, 2, _eip);
			break;
		case 4:
			rel = insn_fetch(s32, 4, _eip);
			break;
		case 8:
			rel = insn_fetch(s64, 8, _eip);
			break;
		default:
			DPRINTF("Call: Invalid op_bytes\n");
			goto cannot_emulate;
		}
		src.val = (unsigned long) _eip;
		JMP_REL(rel);
		goto push;
	}
	case 0xe9: /* jmp rel */
	case 0xeb: /* jmp rel short */
		JMP_REL(src.val);
		no_wb = 1; /* Disable writeback. */
		break;
	case 0xf6 ... 0xf7:	/* Grp3 */
	case 0xf6 ... 0xf7:	/* Grp3 */
		switch (modrm_reg) {
		switch (modrm_reg) {
		case 0 ... 1:	/* test */
		case 0 ... 1:	/* test */
@@ -1350,6 +1341,32 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
	case 0xae ... 0xaf:	/* scas */
	case 0xae ... 0xaf:	/* scas */
		DPRINTF("Urk! I don't handle SCAS.\n");
		DPRINTF("Urk! I don't handle SCAS.\n");
		goto cannot_emulate;
		goto cannot_emulate;
	case 0xe8: /* call (near) */ {
		long int rel;
		switch (op_bytes) {
		case 2:
			rel = insn_fetch(s16, 2, _eip);
			break;
		case 4:
			rel = insn_fetch(s32, 4, _eip);
			break;
		case 8:
			rel = insn_fetch(s64, 8, _eip);
			break;
		default:
			DPRINTF("Call: Invalid op_bytes\n");
			goto cannot_emulate;
		}
		src.val = (unsigned long) _eip;
		JMP_REL(rel);
		goto push;
	}
	case 0xe9: /* jmp rel */
	case 0xeb: /* jmp rel short */
		JMP_REL(src.val);
		no_wb = 1; /* Disable writeback. */
		break;



	}
	}
	goto writeback;
	goto writeback;
@@ -1501,6 +1518,10 @@ x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
		dst.bytes = op_bytes;
		dst.bytes = op_bytes;
		dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val;
		dst.val = (d & ByteOp) ? (s8) src.val : (s16) src.val;
		break;
		break;
	case 0xc3:		/* movnti */
		dst.bytes = op_bytes;
		dst.val = (op_bytes == 4) ? (u32) src.val : (u64) src.val;
		break;
	}
	}
	goto writeback;
	goto writeback;


Loading