Skip to content

Commit

Permalink
Merge branch 'kvm-updates/2.6.28' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/avi/kvm

* 'kvm-updates/2.6.28' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm:
  KVM: ia64: Makefile fix for forcing to re-generate asm-offsets.h
  KVM: Future-proof device assignment ABI
  KVM: ia64: Fix halt emulation logic
  KVM: Fix guest shared interrupt with in-kernel irqchip
  KVM: MMU: sync root on paravirt TLB flush
  • Loading branch information
Linus Torvalds committed Oct 28, 2008
2 parents 0d8762c + e45948b commit a186576
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 56 deletions.
6 changes: 5 additions & 1 deletion arch/ia64/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,8 @@ struct kvm_vcpu_arch {
long itc_offset;
unsigned long itc_check;
unsigned long timer_check;
unsigned long timer_pending;
unsigned int timer_pending;
unsigned int timer_fired;

unsigned long vrr[8];
unsigned long ibr[8];
Expand Down Expand Up @@ -417,6 +418,9 @@ struct kvm_arch {
struct list_head assigned_dev_head;
struct dmar_domain *intel_iommu_domain;
struct hlist_head irq_ack_notifier_list;

unsigned long irq_sources_bitmap;
unsigned long irq_states[KVM_IOAPIC_NUM_PINS];
};

union cpuid3_t {
Expand Down
8 changes: 6 additions & 2 deletions arch/ia64/kvm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,18 @@ define cmd_offsets
echo ""; \
echo "#endif" ) > $@
endef

# We use internal rules to avoid the "is up to date" message from make
arch/ia64/kvm/asm-offsets.s: arch/ia64/kvm/asm-offsets.c
arch/ia64/kvm/asm-offsets.s: arch/ia64/kvm/asm-offsets.c \
$(wildcard $(srctree)/arch/ia64/include/asm/*.h)\
$(wildcard $(srctree)/include/linux/*.h)
$(call if_changed_dep,cc_s_c)

$(obj)/$(offsets-file): arch/ia64/kvm/asm-offsets.s
$(call cmd,offsets)

FORCE : $(obj)/$(offsets-file)

#
# Makefile for Kernel-based Virtual Machine module
#
Expand All @@ -53,7 +58,6 @@ endif
kvm-objs := $(common-objs) kvm-ia64.o kvm_fw.o
obj-$(CONFIG_KVM) += kvm.o

FORCE : $(obj)/$(offsets-file)
EXTRA_CFLAGS_vcpu.o += -mfixed-range=f2-f5,f12-f127
kvm-intel-objs = vmm.o vmm_ivt.o trampoline.o vcpu.o optvfault.o mmio.o \
vtlb.o process.o
Expand Down
80 changes: 41 additions & 39 deletions arch/ia64/kvm/kvm-ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ static int handle_global_purge(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
struct kvm *kvm = vcpu->kvm;
struct call_data call_data;
int i;

call_data.ptc_g_data = p->u.ptc_g_data;

for (i = 0; i < KVM_MAX_VCPUS; i++) {
Expand Down Expand Up @@ -418,33 +419,41 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu)
ktime_t kt;
long itc_diff;
unsigned long vcpu_now_itc;

unsigned long expires;
struct hrtimer *p_ht = &vcpu->arch.hlt_timer;
unsigned long cyc_per_usec = local_cpu_data->cyc_per_usec;
struct vpd *vpd = to_host(vcpu->kvm, vcpu->arch.vpd);

vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset;
if (irqchip_in_kernel(vcpu->kvm)) {

if (time_after(vcpu_now_itc, vpd->itm)) {
vcpu->arch.timer_check = 1;
return 1;
}
itc_diff = vpd->itm - vcpu_now_itc;
if (itc_diff < 0)
itc_diff = -itc_diff;
vcpu_now_itc = ia64_getreg(_IA64_REG_AR_ITC) + vcpu->arch.itc_offset;

expires = div64_u64(itc_diff, cyc_per_usec);
kt = ktime_set(0, 1000 * expires);
vcpu->arch.ht_active = 1;
hrtimer_start(p_ht, kt, HRTIMER_MODE_ABS);
if (time_after(vcpu_now_itc, vpd->itm)) {
vcpu->arch.timer_check = 1;
return 1;
}
itc_diff = vpd->itm - vcpu_now_itc;
if (itc_diff < 0)
itc_diff = -itc_diff;

expires = div64_u64(itc_diff, cyc_per_usec);
kt = ktime_set(0, 1000 * expires);

down_read(&vcpu->kvm->slots_lock);
vcpu->arch.ht_active = 1;
hrtimer_start(p_ht, kt, HRTIMER_MODE_ABS);

if (irqchip_in_kernel(vcpu->kvm)) {
vcpu->arch.mp_state = KVM_MP_STATE_HALTED;
kvm_vcpu_block(vcpu);
hrtimer_cancel(p_ht);
vcpu->arch.ht_active = 0;

if (test_and_clear_bit(KVM_REQ_UNHALT, &vcpu->requests))
if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
vcpu->arch.mp_state =
KVM_MP_STATE_RUNNABLE;
up_read(&vcpu->kvm->slots_lock);

if (vcpu->arch.mp_state != KVM_MP_STATE_RUNNABLE)
return -EINTR;
return 1;
Expand Down Expand Up @@ -484,10 +493,6 @@ static int (*kvm_vti_exit_handlers[])(struct kvm_vcpu *vcpu,
static const int kvm_vti_max_exit_handlers =
sizeof(kvm_vti_exit_handlers)/sizeof(*kvm_vti_exit_handlers);

static void kvm_prepare_guest_switch(struct kvm_vcpu *vcpu)
{
}

static uint32_t kvm_get_exit_reason(struct kvm_vcpu *vcpu)
{
struct exit_ctl_data *p_exit_data;
Expand Down Expand Up @@ -600,8 +605,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)

again:
preempt_disable();

kvm_prepare_guest_switch(vcpu);
local_irq_disable();

if (signal_pending(current)) {
Expand All @@ -614,7 +617,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)

vcpu->guest_mode = 1;
kvm_guest_enter();

down_read(&vcpu->kvm->slots_lock);
r = vti_vcpu_run(vcpu, kvm_run);
if (r < 0) {
local_irq_enable();
Expand All @@ -634,9 +637,8 @@ static int __vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
* But we need to prevent reordering, hence this barrier():
*/
barrier();

kvm_guest_exit();

up_read(&vcpu->kvm->slots_lock);
preempt_enable();

r = kvm_handle_exit(kvm_run, vcpu);
Expand Down Expand Up @@ -673,6 +675,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)

if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
kvm_vcpu_block(vcpu);
clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
vcpu_put(vcpu);
return -EAGAIN;
}
Expand Down Expand Up @@ -778,6 +781,9 @@ static void kvm_init_vm(struct kvm *kvm)
kvm_build_io_pmt(kvm);

INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);

/* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap);
}

struct kvm *kvm_arch_create_vm(void)
Expand Down Expand Up @@ -941,9 +947,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
goto out;
if (irqchip_in_kernel(kvm)) {
mutex_lock(&kvm->lock);
kvm_ioapic_set_irq(kvm->arch.vioapic,
irq_event.irq,
irq_event.level);
kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
irq_event.irq, irq_event.level);
mutex_unlock(&kvm->lock);
r = 0;
}
Expand Down Expand Up @@ -1123,15 +1128,16 @@ static enum hrtimer_restart hlt_timer_fn(struct hrtimer *data)
wait_queue_head_t *q;

vcpu = container_of(data, struct kvm_vcpu, arch.hlt_timer);
q = &vcpu->wq;

if (vcpu->arch.mp_state != KVM_MP_STATE_HALTED)
goto out;

q = &vcpu->wq;
if (waitqueue_active(q)) {
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
if (waitqueue_active(q))
wake_up_interruptible(q);
}

out:
vcpu->arch.timer_fired = 1;
vcpu->arch.timer_check = 1;
return HRTIMER_NORESTART;
}
Expand Down Expand Up @@ -1700,12 +1706,14 @@ static void vcpu_kick_intr(void *info)
void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
{
int ipi_pcpu = vcpu->cpu;
int cpu = get_cpu();

if (waitqueue_active(&vcpu->wq))
wake_up_interruptible(&vcpu->wq);

if (vcpu->guest_mode)
if (vcpu->guest_mode && cpu != ipi_pcpu)
smp_call_function_single(ipi_pcpu, vcpu_kick_intr, vcpu, 0);
put_cpu();
}

int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)
Expand All @@ -1715,13 +1723,7 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, u8 vec, u8 trig)

if (!test_and_set_bit(vec, &vpd->irr[0])) {
vcpu->arch.irq_new_pending = 1;
if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
kvm_vcpu_kick(vcpu);
else if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED) {
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
if (waitqueue_active(&vcpu->wq))
wake_up_interruptible(&vcpu->wq);
}
kvm_vcpu_kick(vcpu);
return 1;
}
return 0;
Expand Down Expand Up @@ -1791,7 +1793,7 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu)

int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
{
return 0;
return vcpu->arch.timer_fired;
}

gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
Expand Down
9 changes: 7 additions & 2 deletions arch/ia64/kvm/kvm_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,12 @@ static u64 kvm_get_pal_call_index(struct kvm_vcpu *vcpu)
return index;
}

static void prepare_for_halt(struct kvm_vcpu *vcpu)
{
vcpu->arch.timer_pending = 1;
vcpu->arch.timer_fired = 0;
}

int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
{

Expand All @@ -304,11 +310,10 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run)
break;
case PAL_HALT_LIGHT:
{
vcpu->arch.timer_pending = 1;
INIT_PAL_STATUS_SUCCESS(result);
prepare_for_halt(vcpu);
if (kvm_highest_pending_irq(vcpu) == -1)
ret = kvm_emulate_halt(vcpu);

}
break;

Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/kvm/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ void leave_hypervisor_tail(void)
if (!(VCPU(v, itv) & (1 << 16))) {
vcpu_pend_interrupt(v, VCPU(v, itv)
& 0xff);
VMX(v, itc_check) = 0;
VMX(v, itc_check) = 0;
} else {
v->arch.timer_pending = 1;
}
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,9 @@ struct kvm_arch{

struct page *ept_identity_pagetable;
bool ept_identity_pagetable_done;

unsigned long irq_sources_bitmap;
unsigned long irq_states[KVM_IOAPIC_NUM_PINS];
};

struct kvm_vm_stat {
Expand Down
11 changes: 9 additions & 2 deletions arch/x86/kvm/i8254.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,12 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm)
if (!pit)
return NULL;

mutex_lock(&kvm->lock);
pit->irq_source_id = kvm_request_irq_source_id(kvm);
mutex_unlock(&kvm->lock);
if (pit->irq_source_id < 0)
return NULL;

mutex_init(&pit->pit_state.lock);
mutex_lock(&pit->pit_state.lock);
spin_lock_init(&pit->pit_state.inject_lock);
Expand Down Expand Up @@ -587,6 +593,7 @@ void kvm_free_pit(struct kvm *kvm)
mutex_lock(&kvm->arch.vpit->pit_state.lock);
timer = &kvm->arch.vpit->pit_state.pit_timer.timer;
hrtimer_cancel(timer);
kvm_free_irq_source_id(kvm, kvm->arch.vpit->irq_source_id);
mutex_unlock(&kvm->arch.vpit->pit_state.lock);
kfree(kvm->arch.vpit);
}
Expand All @@ -595,8 +602,8 @@ void kvm_free_pit(struct kvm *kvm)
static void __inject_pit_timer_intr(struct kvm *kvm)
{
mutex_lock(&kvm->lock);
kvm_set_irq(kvm, 0, 1);
kvm_set_irq(kvm, 0, 0);
kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 1);
kvm_set_irq(kvm, kvm->arch.vpit->irq_source_id, 0, 0);
mutex_unlock(&kvm->lock);
}

Expand Down
1 change: 1 addition & 0 deletions arch/x86/kvm/i8254.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct kvm_pit {
struct kvm_io_device speaker_dev;
struct kvm *kvm;
struct kvm_kpit_state pit_state;
int irq_source_id;
};

#define KVM_PIT_BASE_ADDRESS 0x40
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -2634,6 +2634,7 @@ static int kvm_pv_mmu_write(struct kvm_vcpu *vcpu,
static int kvm_pv_mmu_flush_tlb(struct kvm_vcpu *vcpu)
{
kvm_x86_ops->tlb_flush(vcpu);
set_bit(KVM_REQ_MMU_SYNC, &vcpu->requests);
return 1;
}

Expand Down
6 changes: 5 additions & 1 deletion arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -1742,7 +1742,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
goto out;
if (irqchip_in_kernel(kvm)) {
mutex_lock(&kvm->lock);
kvm_set_irq(kvm, irq_event.irq, irq_event.level);
kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
irq_event.irq, irq_event.level);
mutex_unlock(&kvm->lock);
r = 0;
}
Expand Down Expand Up @@ -4013,6 +4014,9 @@ struct kvm *kvm_arch_create_vm(void)
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);

/* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap);

return kvm;
}

Expand Down
6 changes: 6 additions & 0 deletions include/linux/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,13 +489,19 @@ struct kvm_assigned_pci_dev {
__u32 busnr;
__u32 devfn;
__u32 flags;
union {
__u32 reserved[12];
};
};

struct kvm_assigned_irq {
__u32 assigned_dev_id;
__u32 host_irq;
__u32 guest_irq;
__u32 flags;
union {
__u32 reserved[12];
};
};

#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
Expand Down
Loading

0 comments on commit a186576

Please sign in to comment.