Commit 409232a4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull KVM fixes from Paolo Bonzini:
 "ARM fixes:
   - A bug in handling of SPE state for non-vhe systems
   - A fix for a crash on system shutdown
   - Three timer fixes, introduced by the timer optimizations for v4.15

  x86 fixes:
   - fix for a WARN that was introduced in 4.15
   - fix for SMM when guest uses PCID
   - fixes for several bugs found by syzkaller

  ... and a dozen papercut fixes for the kvm_stat tool"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (22 commits)
  tools/kvm_stat: sort '-f help' output
  kvm: x86: fix RSM when PCID is non-zero
  KVM: Fix stack-out-of-bounds read in write_mmio
  KVM: arm/arm64: Fix timer enable flow
  KVM: arm/arm64: Properly handle arch-timer IRQs after vtimer_save_state
  KVM: arm/arm64: timer: Don't set irq as forwarded if no usable GIC
  KVM: arm/arm64: Fix HYP unmapping going off limits
  arm64: kvm: Prevent restoring stale PMSCR_EL1 for vcpu
  KVM/x86: Check input paging mode when cs.l is set
  tools/kvm_stat: add line for totals
  tools/kvm_stat: stop ignoring unhandled arguments
  tools/kvm_stat: suppress usage information on command line errors
  tools/kvm_stat: handle invalid regular expressions
  tools/kvm_stat: add hint on '-f help' to man page
  tools/kvm_stat: fix child trace events accounting
  tools/kvm_stat: fix extra handling of 'help' with fields filter
  tools/kvm_stat: fix missing field update after filter change
  tools/kvm_stat: fix drilldown in events-by-guests mode
  tools/kvm_stat: fix command line option '-g'
  kvm: x86: fix WARN due to uninitialized guest FPU state
  ...
parents d1ce8ceb aa12f594
...@@ -74,6 +74,9 @@ static void __hyp_text __debug_save_spe_nvhe(u64 *pmscr_el1) ...@@ -74,6 +74,9 @@ static void __hyp_text __debug_save_spe_nvhe(u64 *pmscr_el1)
{ {
u64 reg; u64 reg;
/* Clear pmscr in case of early return */
*pmscr_el1 = 0;
/* SPE present on this CPU? */ /* SPE present on this CPU? */
if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1), if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
ID_AA64DFR0_PMSVER_SHIFT)) ID_AA64DFR0_PMSVER_SHIFT))
......
...@@ -2390,9 +2390,21 @@ static int rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, u64 smbase, int n) ...@@ -2390,9 +2390,21 @@ static int rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, u64 smbase, int n)
} }
static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt, static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt,
u64 cr0, u64 cr4) u64 cr0, u64 cr3, u64 cr4)
{ {
int bad; int bad;
u64 pcid;
/* In order to later set CR4.PCIDE, CR3[11:0] must be zero. */
pcid = 0;
if (cr4 & X86_CR4_PCIDE) {
pcid = cr3 & 0xfff;
cr3 &= ~0xfff;
}
bad = ctxt->ops->set_cr(ctxt, 3, cr3);
if (bad)
return X86EMUL_UNHANDLEABLE;
/* /*
* First enable PAE, long mode needs it before CR0.PG = 1 is set. * First enable PAE, long mode needs it before CR0.PG = 1 is set.
...@@ -2411,6 +2423,12 @@ static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt, ...@@ -2411,6 +2423,12 @@ static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt,
bad = ctxt->ops->set_cr(ctxt, 4, cr4); bad = ctxt->ops->set_cr(ctxt, 4, cr4);
if (bad) if (bad)
return X86EMUL_UNHANDLEABLE; return X86EMUL_UNHANDLEABLE;
if (pcid) {
bad = ctxt->ops->set_cr(ctxt, 3, cr3 | pcid);
if (bad)
return X86EMUL_UNHANDLEABLE;
}
} }
return X86EMUL_CONTINUE; return X86EMUL_CONTINUE;
...@@ -2421,11 +2439,11 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase) ...@@ -2421,11 +2439,11 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase)
struct desc_struct desc; struct desc_struct desc;
struct desc_ptr dt; struct desc_ptr dt;
u16 selector; u16 selector;
u32 val, cr0, cr4; u32 val, cr0, cr3, cr4;
int i; int i;
cr0 = GET_SMSTATE(u32, smbase, 0x7ffc); cr0 = GET_SMSTATE(u32, smbase, 0x7ffc);
ctxt->ops->set_cr(ctxt, 3, GET_SMSTATE(u32, smbase, 0x7ff8)); cr3 = GET_SMSTATE(u32, smbase, 0x7ff8);
ctxt->eflags = GET_SMSTATE(u32, smbase, 0x7ff4) | X86_EFLAGS_FIXED; ctxt->eflags = GET_SMSTATE(u32, smbase, 0x7ff4) | X86_EFLAGS_FIXED;
ctxt->_eip = GET_SMSTATE(u32, smbase, 0x7ff0); ctxt->_eip = GET_SMSTATE(u32, smbase, 0x7ff0);
...@@ -2467,14 +2485,14 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase) ...@@ -2467,14 +2485,14 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase)
ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7ef8)); ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7ef8));
return rsm_enter_protected_mode(ctxt, cr0, cr4); return rsm_enter_protected_mode(ctxt, cr0, cr3, cr4);
} }
static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase) static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
{ {
struct desc_struct desc; struct desc_struct desc;
struct desc_ptr dt; struct desc_ptr dt;
u64 val, cr0, cr4; u64 val, cr0, cr3, cr4;
u32 base3; u32 base3;
u16 selector; u16 selector;
int i, r; int i, r;
...@@ -2491,7 +2509,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase) ...@@ -2491,7 +2509,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1); ctxt->ops->set_dr(ctxt, 7, (val & DR7_VOLATILE) | DR7_FIXED_1);
cr0 = GET_SMSTATE(u64, smbase, 0x7f58); cr0 = GET_SMSTATE(u64, smbase, 0x7f58);
ctxt->ops->set_cr(ctxt, 3, GET_SMSTATE(u64, smbase, 0x7f50)); cr3 = GET_SMSTATE(u64, smbase, 0x7f50);
cr4 = GET_SMSTATE(u64, smbase, 0x7f48); cr4 = GET_SMSTATE(u64, smbase, 0x7f48);
ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7f00)); ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7f00));
val = GET_SMSTATE(u64, smbase, 0x7ed0); val = GET_SMSTATE(u64, smbase, 0x7ed0);
...@@ -2519,7 +2537,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase) ...@@ -2519,7 +2537,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
dt.address = GET_SMSTATE(u64, smbase, 0x7e68); dt.address = GET_SMSTATE(u64, smbase, 0x7e68);
ctxt->ops->set_gdt(ctxt, &dt); ctxt->ops->set_gdt(ctxt, &dt);
r = rsm_enter_protected_mode(ctxt, cr0, cr4); r = rsm_enter_protected_mode(ctxt, cr0, cr3, cr4);
if (r != X86EMUL_CONTINUE) if (r != X86EMUL_CONTINUE)
return r; return r;
......
...@@ -3395,7 +3395,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) ...@@ -3395,7 +3395,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
spin_lock(&vcpu->kvm->mmu_lock); spin_lock(&vcpu->kvm->mmu_lock);
if(make_mmu_pages_available(vcpu) < 0) { if(make_mmu_pages_available(vcpu) < 0) {
spin_unlock(&vcpu->kvm->mmu_lock); spin_unlock(&vcpu->kvm->mmu_lock);
return 1; return -ENOSPC;
} }
sp = kvm_mmu_get_page(vcpu, 0, 0, sp = kvm_mmu_get_page(vcpu, 0, 0,
vcpu->arch.mmu.shadow_root_level, 1, ACC_ALL); vcpu->arch.mmu.shadow_root_level, 1, ACC_ALL);
...@@ -3410,7 +3410,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) ...@@ -3410,7 +3410,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
spin_lock(&vcpu->kvm->mmu_lock); spin_lock(&vcpu->kvm->mmu_lock);
if (make_mmu_pages_available(vcpu) < 0) { if (make_mmu_pages_available(vcpu) < 0) {
spin_unlock(&vcpu->kvm->mmu_lock); spin_unlock(&vcpu->kvm->mmu_lock);
return 1; return -ENOSPC;
} }
sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT), sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT),
i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL); i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL);
...@@ -3450,7 +3450,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) ...@@ -3450,7 +3450,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
spin_lock(&vcpu->kvm->mmu_lock); spin_lock(&vcpu->kvm->mmu_lock);
if (make_mmu_pages_available(vcpu) < 0) { if (make_mmu_pages_available(vcpu) < 0) {
spin_unlock(&vcpu->kvm->mmu_lock); spin_unlock(&vcpu->kvm->mmu_lock);
return 1; return -ENOSPC;
} }
sp = kvm_mmu_get_page(vcpu, root_gfn, 0, sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
vcpu->arch.mmu.shadow_root_level, 0, ACC_ALL); vcpu->arch.mmu.shadow_root_level, 0, ACC_ALL);
...@@ -3487,7 +3487,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) ...@@ -3487,7 +3487,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
spin_lock(&vcpu->kvm->mmu_lock); spin_lock(&vcpu->kvm->mmu_lock);
if (make_mmu_pages_available(vcpu) < 0) { if (make_mmu_pages_available(vcpu) < 0) {
spin_unlock(&vcpu->kvm->mmu_lock); spin_unlock(&vcpu->kvm->mmu_lock);
return 1; return -ENOSPC;
} }
sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, PT32_ROOT_LEVEL, sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, PT32_ROOT_LEVEL,
0, ACC_ALL); 0, ACC_ALL);
......
...@@ -4384,7 +4384,7 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v) ...@@ -4384,7 +4384,7 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
addr, n, v)) addr, n, v))
&& kvm_io_bus_read(vcpu, KVM_MMIO_BUS, addr, n, v)) && kvm_io_bus_read(vcpu, KVM_MMIO_BUS, addr, n, v))
break; break;
trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v); trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, v);
handled += n; handled += n;
addr += n; addr += n;
len -= n; len -= n;
...@@ -4643,7 +4643,7 @@ static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes) ...@@ -4643,7 +4643,7 @@ static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes)
{ {
if (vcpu->mmio_read_completed) { if (vcpu->mmio_read_completed) {
trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes,
vcpu->mmio_fragments[0].gpa, *(u64 *)val); vcpu->mmio_fragments[0].gpa, val);
vcpu->mmio_read_completed = 0; vcpu->mmio_read_completed = 0;
return 1; return 1;
} }
...@@ -4665,14 +4665,14 @@ static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa, ...@@ -4665,14 +4665,14 @@ static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val) static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val)
{ {
trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val); trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, val);
return vcpu_mmio_write(vcpu, gpa, bytes, val); return vcpu_mmio_write(vcpu, gpa, bytes, val);
} }
static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
void *val, int bytes) void *val, int bytes)
{ {
trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0); trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, NULL);
return X86EMUL_IO_NEEDED; return X86EMUL_IO_NEEDED;
} }
...@@ -7264,13 +7264,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu) ...@@ -7264,13 +7264,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{ {
struct fpu *fpu = &current->thread.fpu;
int r; int r;
fpu__initialize(fpu);
kvm_sigset_activate(vcpu); kvm_sigset_activate(vcpu);
kvm_load_guest_fpu(vcpu);
if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) { if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
if (kvm_run->immediate_exit) { if (kvm_run->immediate_exit) {
r = -EINTR; r = -EINTR;
...@@ -7296,14 +7295,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) ...@@ -7296,14 +7295,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
} }
} }
kvm_load_guest_fpu(vcpu);
if (unlikely(vcpu->arch.complete_userspace_io)) { if (unlikely(vcpu->arch.complete_userspace_io)) {
int (*cui)(struct kvm_vcpu *) = vcpu->arch.complete_userspace_io; int (*cui)(struct kvm_vcpu *) = vcpu->arch.complete_userspace_io;
vcpu->arch.complete_userspace_io = NULL; vcpu->arch.complete_userspace_io = NULL;
r = cui(vcpu); r = cui(vcpu);
if (r <= 0) if (r <= 0)
goto out_fpu; goto out;
} else } else
WARN_ON(vcpu->arch.pio.count || vcpu->mmio_needed); WARN_ON(vcpu->arch.pio.count || vcpu->mmio_needed);
...@@ -7312,9 +7309,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) ...@@ -7312,9 +7309,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
else else
r = vcpu_run(vcpu); r = vcpu_run(vcpu);
out_fpu:
kvm_put_guest_fpu(vcpu);
out: out:
kvm_put_guest_fpu(vcpu);
post_kvm_run_save(vcpu); post_kvm_run_save(vcpu);
kvm_sigset_deactivate(vcpu); kvm_sigset_deactivate(vcpu);
...@@ -7384,7 +7380,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) ...@@ -7384,7 +7380,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
#endif #endif
kvm_rip_write(vcpu, regs->rip); kvm_rip_write(vcpu, regs->rip);
kvm_set_rflags(vcpu, regs->rflags); kvm_set_rflags(vcpu, regs->rflags | X86_EFLAGS_FIXED);
vcpu->arch.exception.pending = false; vcpu->arch.exception.pending = false;
...@@ -7498,6 +7494,29 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index, ...@@ -7498,6 +7494,29 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
} }
EXPORT_SYMBOL_GPL(kvm_task_switch); EXPORT_SYMBOL_GPL(kvm_task_switch);
int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
{
if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG_BIT)) {
/*
* When EFER.LME and CR0.PG are set, the processor is in
* 64-bit mode (though maybe in a 32-bit code segment).
* CR4.PAE and EFER.LMA must be set.
*/
if (!(sregs->cr4 & X86_CR4_PAE_BIT)
|| !(sregs->efer & EFER_LMA))
return -EINVAL;
} else {
/*
* Not in 64-bit mode: EFER.LMA is clear and the code
* segment cannot be 64-bit.
*/
if (sregs->efer & EFER_LMA || sregs->cs.l)
return -EINVAL;
}
return 0;
}
int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
struct kvm_sregs *sregs) struct kvm_sregs *sregs)
{ {
...@@ -7510,6 +7529,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, ...@@ -7510,6 +7529,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
(sregs->cr4 & X86_CR4_OSXSAVE)) (sregs->cr4 & X86_CR4_OSXSAVE))
return -EINVAL; return -EINVAL;
if (kvm_valid_sregs(vcpu, sregs))
return -EINVAL;
apic_base_msr.data = sregs->apic_base; apic_base_msr.data = sregs->apic_base;
apic_base_msr.host_initiated = true; apic_base_msr.host_initiated = true;
if (kvm_set_apic_base(vcpu, &apic_base_msr)) if (kvm_set_apic_base(vcpu, &apic_base_msr))
......
...@@ -62,7 +62,7 @@ struct arch_timer_cpu { ...@@ -62,7 +62,7 @@ struct arch_timer_cpu {
bool enabled; bool enabled;
}; };
int kvm_timer_hyp_init(void); int kvm_timer_hyp_init(bool);
int kvm_timer_enable(struct kvm_vcpu *vcpu); int kvm_timer_enable(struct kvm_vcpu *vcpu);
int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu); int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu);
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
......
...@@ -211,7 +211,7 @@ TRACE_EVENT(kvm_ack_irq, ...@@ -211,7 +211,7 @@ TRACE_EVENT(kvm_ack_irq,
{ KVM_TRACE_MMIO_WRITE, "write" } { KVM_TRACE_MMIO_WRITE, "write" }
TRACE_EVENT(kvm_mmio, TRACE_EVENT(kvm_mmio,
TP_PROTO(int type, int len, u64 gpa, u64 val), TP_PROTO(int type, int len, u64 gpa, void *val),
TP_ARGS(type, len, gpa, val), TP_ARGS(type, len, gpa, val),
TP_STRUCT__entry( TP_STRUCT__entry(
...@@ -225,7 +225,10 @@ TRACE_EVENT(kvm_mmio, ...@@ -225,7 +225,10 @@ TRACE_EVENT(kvm_mmio,
__entry->type = type; __entry->type = type;
__entry->len = len; __entry->len = len;
__entry->gpa = gpa; __entry->gpa = gpa;
__entry->val = val; __entry->val = 0;
if (val)
memcpy(&__entry->val, val,
min_t(u32, sizeof(__entry->val), len));
), ),
TP_printk("mmio %s len %u gpa 0x%llx val 0x%llx", TP_printk("mmio %s len %u gpa 0x%llx val 0x%llx",
......
...@@ -478,7 +478,7 @@ class Provider(object): ...@@ -478,7 +478,7 @@ class Provider(object):
@staticmethod @staticmethod
def is_field_wanted(fields_filter, field): def is_field_wanted(fields_filter, field):
"""Indicate whether field is valid according to fields_filter.""" """Indicate whether field is valid according to fields_filter."""
if not fields_filter or fields_filter == "help": if not fields_filter:
return True return True
return re.match(fields_filter, field) is not None return re.match(fields_filter, field) is not None
...@@ -549,8 +549,8 @@ class TracepointProvider(Provider): ...@@ -549,8 +549,8 @@ class TracepointProvider(Provider):
def update_fields(self, fields_filter): def update_fields(self, fields_filter):
"""Refresh fields, applying fields_filter""" """Refresh fields, applying fields_filter"""
self._fields = [field for field in self.get_available_fields() self.fields = [field for field in self.get_available_fields()
if self.is_field_wanted(fields_filter, field)] if self.is_field_wanted(fields_filter, field)]
@staticmethod @staticmethod
def get_online_cpus(): def get_online_cpus():
...@@ -950,7 +950,8 @@ class Tui(object): ...@@ -950,7 +950,8 @@ class Tui(object):
curses.nocbreak() curses.nocbreak()
curses.endwin() curses.endwin()
def get_all_gnames(self): @staticmethod
def get_all_gnames():
"""Returns a list of (pid, gname) tuples of all running guests""" """Returns a list of (pid, gname) tuples of all running guests"""
res = [] res = []
try: try:
...@@ -963,7 +964,7 @@ class Tui(object): ...@@ -963,7 +964,7 @@ class Tui(object):
# perform a sanity check before calling the more expensive # perform a sanity check before calling the more expensive
# function to possibly extract the guest name # function to possibly extract the guest name
if ' -name ' in line[1]: if ' -name ' in line[1]:
res.append((line[0], self.get_gname_from_pid(line[0]))) res.append((line[0], Tui.get_gname_from_pid(line[0])))
child.stdout.close() child.stdout.close()
return res return res
...@@ -984,7 +985,8 @@ class Tui(object): ...@@ -984,7 +985,8 @@ class Tui(object):
except Exception: except Exception:
self.screen.addstr(row + 1, 2, 'Not available') self.screen.addstr(row + 1, 2, 'Not available')
def get_pid_from_gname(self, gname): @staticmethod
def get_pid_from_gname(gname):
"""Fuzzy function to convert guest name to QEMU process pid. """Fuzzy function to convert guest name to QEMU process pid.
Returns a list of potential pids, can be empty if no match found. Returns a list of potential pids, can be empty if no match found.
...@@ -992,7 +994,7 @@ class Tui(object): ...@@ -992,7 +994,7 @@ class Tui(object):
""" """
pids = [] pids = []
for line in self.get_all_gnames(): for line in Tui.get_all_gnames():
if gname == line[1]: if gname == line[1]:
pids.append(int(line[0])) pids.append(int(line[0]))
...@@ -1090,15 +1092,16 @@ class Tui(object): ...@@ -1090,15 +1092,16 @@ class Tui(object):
# sort by totals # sort by totals
return (0, -stats[x][0]) return (0, -stats[x][0])
total = 0. total = 0.
for val in stats.values(): for key in stats.keys():
total += val[0] if key.find('(') is -1:
total += stats[key][0]
if self._sorting == SORT_DEFAULT: if self._sorting == SORT_DEFAULT:
sortkey = sortCurAvg sortkey = sortCurAvg
else: else:
sortkey = sortTotal sortkey = sortTotal
tavg = 0
for key in sorted(stats.keys(), key=sortkey): for key in sorted(stats.keys(), key=sortkey):
if row >= self.screen.getmaxyx()[0] - 1:
if row >= self.screen.getmaxyx()[0]:
break break
values = stats[key] values = stats[key]
if not values[0] and not values[1]: if not values[0] and not values[1]:
...@@ -1110,9 +1113,15 @@ class Tui(object): ...@@ -1110,9 +1113,15 @@ class Tui(object):
self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' % self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' %
(key, values[0], values[0] * 100 / total, (key, values[0], values[0] * 100 / total,
cur)) cur))
if cur is not '' and key.find('(') is -1:
tavg += cur
row += 1 row += 1
if row == 3: if row == 3:
self.screen.addstr(4, 1, 'No matching events reported yet') self.screen.addstr(4, 1, 'No matching events reported yet')
else:
self.screen.addstr(row, 1, '%-40s %10d %8s' %
('Total', total, tavg if tavg else ''),
curses.A_BOLD)
self.screen.refresh() self.screen.refresh()
def show_msg(self, text): def show_msg(self, text):
...@@ -1358,7 +1367,7 @@ class Tui(object): ...@@ -1358,7 +1367,7 @@ class Tui(object):
if char == 'x': if char == 'x':
self.update_drilldown() self.update_drilldown()
# prevents display of current values on next refresh # prevents display of current values on next refresh
self.stats.get() self.stats.get(self._display_guests)
except KeyboardInterrupt: except KeyboardInterrupt:
break break
except curses.error: except curses.error:
...@@ -1451,16 +1460,13 @@ Press any other key to refresh statistics immediately. ...@@ -1451,16 +1460,13 @@ Press any other key to refresh statistics immediately.
try: try:
pids = Tui.get_pid_from_gname(val) pids = Tui.get_pid_from_gname(val)
except: except:
raise optparse.OptionValueError('Error while searching for guest ' sys.exit('Error while searching for guest "{}". Use "-p" to '
'"{}", use "-p" to specify a pid ' 'specify a pid instead?'.format(val))
'instead'.format(val))
if len(pids) == 0: if len(pids) == 0:
raise optparse.OptionValueError('No guest by the name "{}" ' sys.exit('Error: No guest by the name "{}" found'.format(val))
'found'.format(val))
if len(pids) > 1: if len(pids) > 1:
raise optparse.OptionValueError('Multiple processes found (pids: ' sys.exit('Error: Multiple processes found (pids: {}). Use "-p" '
'{}) - use "-p" to specify a pid ' 'to specify the desired pid'.format(" ".join(pids)))
'instead'.format(" ".join(pids)))
parser.values.pid = pids[0] parser.values.pid = pids[0]
optparser = optparse.OptionParser(description=description_text, optparser = optparse.OptionParser(description=description_text,
...@@ -1518,7 +1524,16 @@ Press any other key to refresh statistics immediately. ...@@ -1518,7 +1524,16 @@ Press any other key to refresh statistics immediately.
help='restrict statistics to guest by name', help='restrict statistics to guest by name',
callback=cb_guest_to_pid, callback=cb_guest_to_pid,
) )
(options, _) = optparser.parse_args(sys.argv) options, unkn = optparser.parse_args(sys.argv)
if len(unkn) != 1:
sys.exit('Error: Extra argument(s): ' + ' '.join(unkn[1:]))
try:
# verify that we were passed a valid regex up front
re.compile(options.fields)
except re.error:
sys.exit('Error: "' + options.fields + '" is not a valid regular '
'expression')
return options return options
...@@ -1564,16 +1579,13 @@ def main(): ...@@ -1564,16 +1579,13 @@ def main():
stats = Stats(options) stats = Stats(options)
if options.fields == "help": if options.fields == 'help':
event_list = "\n" stats.fields_filter = None
s = stats.get() event_list = []
for key in s.keys(): for key in stats.get().keys():
if key.find('(') != -1: event_list.append(key.split('(', 1)[0])
key = key[0:key.find('(')] sys.stdout.write(' ' + '\n '.join(sorted(set(event_list))) + '\n')
if event_list.find('\n' + key + '\n') == -1: sys.exit(0)
event_list += key + '\n'
sys.stdout.write(event_list)
return ""
if options.log: if options.log:
log(stats) log(stats)
......
...@@ -50,6 +50,8 @@ INTERACTIVE COMMANDS ...@@ -50,6 +50,8 @@ INTERACTIVE COMMANDS
*s*:: set update interval *s*:: set update interval
*x*:: toggle reporting of stats for child trace events *x*:: toggle reporting of stats for child trace events
:: *Note*: The stats for the parents summarize the respective child trace
events
Press any other key to refresh statistics immediately. Press any other key to refresh statistics immediately.
...@@ -86,7 +88,7 @@ OPTIONS ...@@ -86,7 +88,7 @@ OPTIONS
-f<fields>:: -f<fields>::
--fields=<fields>:: --fields=<fields>::
fields to display (regex) fields to display (regex), "-f help" for a list of available events
-h:: -h::
--help:: --help::
......
...@@ -92,16 +92,23 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id) ...@@ -92,16 +92,23 @@ static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
{ {
struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id; struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id;
struct arch_timer_context *vtimer; struct arch_timer_context *vtimer;
u32 cnt_ctl;
if (!vcpu) { /*
pr_warn_once("Spurious arch timer IRQ on non-VCPU thread\n"); * We may see a timer interrupt after vcpu_put() has been called which
return IRQ_NONE; * sets the CPU's vcpu pointer to NULL, because even though the timer
} * has been disabled in vtimer_save_state(), the hardware interrupt
vtimer = vcpu_vtimer(vcpu); * signal may not have been retired from the interrupt controller yet.
*/
if (!vcpu)
return IRQ_HANDLED;
vtimer = vcpu_vtimer(vcpu);
if (!vtimer->irq.level) { if (!vtimer->irq.level) {
vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl); cnt_ctl = read_sysreg_el0(cntv_ctl);
if (kvm_timer_irq_can_fire(vtimer)) cnt_ctl &= ARCH_TIMER_CTRL_ENABLE | ARCH_TIMER_CTRL_IT_STAT |
ARCH_TIMER_CTRL_IT_MASK;
if (cnt_ctl == (ARCH_TIMER_CTRL_ENABLE | ARCH_TIMER_CTRL_IT_STAT))
kvm_timer_update_irq(vcpu, true, vtimer); kvm_timer_update_irq(vcpu, true, vtimer);
} }
...@@ -355,6 +362,7 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu) ...@@ -355,6 +362,7 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu)
/* Disable the virtual timer */ /* Disable the virtual timer */
write_sysreg_el0(0, cntv_ctl); write_sysreg_el0(0, cntv_ctl);
isb();
vtimer->loaded = false; vtimer->loaded = false;
out: out:
...@@ -720,7 +728,7 @@ static int kvm_timer_dying_cpu(unsigned int cpu) ...@@ -720,7 +728,7 @@ static int kvm_timer_dying_cpu(unsigned int cpu)
return 0; return 0;
} }
int kvm_timer_hyp_init(void) int kvm_timer_hyp_init(bool has_gic)
{ {
struct arch_timer_kvm_info *info; struct arch_timer_kvm_info *info;
int err; int err;
...@@ -756,10 +764,13 @@ int kvm_timer_hyp_init(void) ...@@ -756,10 +764,13 @@ int kvm_timer_hyp_init(void)
return err; return err;
} }
err = irq_set_vcpu_affinity(host_vtimer_irq, kvm_get_running_vcpus()); if (has_gic) {
if (err) { err = irq_set_vcpu_affinity(host_vtimer_irq,
kvm_err("kvm_arch_timer: error setting vcpu affinity\n"); kvm_get_running_vcpus());
goto out_free_irq; if (err) {
kvm_err("kvm_arch_timer: error setting vcpu affinity\n");
goto out_free_irq;
}
} }
kvm_info("virtual timer IRQ%d\n", host_vtimer_irq); kvm_info("virtual timer IRQ%d\n", host_vtimer_irq);
...@@ -835,10 +846,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) ...@@ -835,10 +846,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
no_vgic: no_vgic:
preempt_disable(); preempt_disable();
timer->enabled = 1; timer->enabled = 1;
if (!irqchip_in_kernel(vcpu->kvm)) kvm_timer_vcpu_load(vcpu);
kvm_timer_vcpu_load_user(vcpu);
else
kvm_timer_vcpu_load_vgic(vcpu);
preempt_enable(); preempt_enable();
return 0; return 0;
......
...@@ -1326,7 +1326,7 @@ static int init_subsystems(void) ...@@ -1326,7 +1326,7 @@ static int init_subsystems(void)
/* /*
* Init HYP architected timer support * Init HYP architected timer support
*/ */
err = kvm_timer_hyp_init(); err = kvm_timer_hyp_init(vgic_present);
if (err) if (err)
goto out; goto out;
......
...@@ -112,7 +112,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) ...@@ -112,7 +112,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
} }
trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr, trace_kvm_mmio(KVM_TRACE_MMIO_READ, len, run->mmio.phys_addr,
data); &data);
data = vcpu_data_host_to_guest(vcpu, data, len); data = vcpu_data_host_to_guest(vcpu, data, len);
vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data); vcpu_set_reg(vcpu, vcpu->arch.mmio_decode.rt, data);
} }
...@@ -182,14 +182,14 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, ...@@ -182,14 +182,14 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt), data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt),
len); len);
trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, data); trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, len, fault_ipa, &data);
kvm_mmio_write_buf(data_buf, len, data); kvm_mmio_write_buf(data_buf, len, data);
ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len, ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
data_buf); data_buf);
} else { } else {
trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, len, trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, len,
fault_ipa, 0); fault_ipa, NULL);
ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len, ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, fault_ipa, len,
data_buf); data_buf);
......
...@@ -509,8 +509,6 @@ static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t start, u64 size) ...@@ -509,8 +509,6 @@ static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t start, u64 size)
*/ */
void free_hyp_pgds(void) void free_hyp_pgds(void)
{ {
unsigned long addr;
mutex_lock(&kvm_hyp_pgd_mutex); mutex_lock(&kvm_hyp_pgd_mutex);
if (boot_hyp_pgd) { if (boot_hyp_pgd) {
...@@ -521,10 +519,10 @@ void free_hyp_pgds(void) ...@@ -521,10 +519,10 @@ void free_hyp_pgds(void)
if (hyp_pgd) { if (hyp_pgd) {
unmap_hyp_range(hyp_pgd, hyp_idmap_start, PAGE_SIZE); unmap_hyp_range(hyp_pgd, hyp_idmap_start, PAGE_SIZE);
for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE) unmap_hyp_range(hyp_pgd, kern_hyp_va(PAGE_OFFSET),
unmap_hyp_range(hyp_pgd, kern_hyp_va(addr), PGDIR_SIZE); (uintptr_t)high_memory - PAGE_OFFSET);
for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE) unmap_hyp_range(hyp_pgd, kern_hyp_va(VMALLOC_START),
unmap_hyp_range(hyp_pgd, kern_hyp_va(addr), PGDIR_SIZE); VMALLOC_END - VMALLOC_START);
free_pages((unsigned long)hyp_pgd, hyp_pgd_order); free_pages((unsigned long)hyp_pgd, hyp_pgd_order);
hyp_pgd = NULL; hyp_pgd = NULL;
......
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