forked from Minki/linux
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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJaO6N9AAoJEL/70l94x66DC1wH/Rf+u0Cj6ZQil6LK6Nf8bfPd 3TqrwrxUDeXwi8GzsvK14izBr1mDzidSHIO0Q4XINFRSRdaf43h3R2im/SJqvNhP xktCmJI2CxN96oaC7kIExgwf3YKhFdLIADfbT8oR9p3xZG/+c97dkr3b4XtmVCDb ZXdUEOcKnoW4zwpfJN30FLlq4OwYvuYVz02AEfPivZRDfhhus/TYSnuSdxH8CLNf 75ymuKyXoo/RELbimwbMk8Cm9+ey7PjlUGOgbnbXIFtmgznXhLzAOeES2B+46J5b sMBPlmiJrn6N//lM18CC5yOBzBLGsYOoXggtw4aU/5nM4GVcFebWedpcoD4D8Jw= =Bt8w -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
409232a450
@ -74,6 +74,9 @@ static void __hyp_text __debug_save_spe_nvhe(u64 *pmscr_el1)
|
||||
{
|
||||
u64 reg;
|
||||
|
||||
/* Clear pmscr in case of early return */
|
||||
*pmscr_el1 = 0;
|
||||
|
||||
/* SPE present on this CPU? */
|
||||
if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
|
||||
ID_AA64DFR0_PMSVER_SHIFT))
|
||||
|
@ -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,
|
||||
u64 cr0, u64 cr4)
|
||||
u64 cr0, u64 cr3, u64 cr4)
|
||||
{
|
||||
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.
|
||||
@ -2411,6 +2423,12 @@ static int rsm_enter_protected_mode(struct x86_emulate_ctxt *ctxt,
|
||||
bad = ctxt->ops->set_cr(ctxt, 4, cr4);
|
||||
if (bad)
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
if (pcid) {
|
||||
bad = ctxt->ops->set_cr(ctxt, 3, cr3 | pcid);
|
||||
if (bad)
|
||||
return X86EMUL_UNHANDLEABLE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return X86EMUL_CONTINUE;
|
||||
@ -2421,11 +2439,11 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase)
|
||||
struct desc_struct desc;
|
||||
struct desc_ptr dt;
|
||||
u16 selector;
|
||||
u32 val, cr0, cr4;
|
||||
u32 val, cr0, cr3, cr4;
|
||||
int i;
|
||||
|
||||
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->_eip = GET_SMSTATE(u32, smbase, 0x7ff0);
|
||||
|
||||
@ -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));
|
||||
|
||||
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)
|
||||
{
|
||||
struct desc_struct desc;
|
||||
struct desc_ptr dt;
|
||||
u64 val, cr0, cr4;
|
||||
u64 val, cr0, cr3, cr4;
|
||||
u32 base3;
|
||||
u16 selector;
|
||||
int i, r;
|
||||
@ -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);
|
||||
|
||||
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);
|
||||
ctxt->ops->set_smbase(ctxt, GET_SMSTATE(u32, smbase, 0x7f00));
|
||||
val = GET_SMSTATE(u64, smbase, 0x7ed0);
|
||||
@ -2519,7 +2537,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase)
|
||||
dt.address = GET_SMSTATE(u64, smbase, 0x7e68);
|
||||
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)
|
||||
return r;
|
||||
|
||||
|
@ -3395,7 +3395,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
|
||||
spin_lock(&vcpu->kvm->mmu_lock);
|
||||
if(make_mmu_pages_available(vcpu) < 0) {
|
||||
spin_unlock(&vcpu->kvm->mmu_lock);
|
||||
return 1;
|
||||
return -ENOSPC;
|
||||
}
|
||||
sp = kvm_mmu_get_page(vcpu, 0, 0,
|
||||
vcpu->arch.mmu.shadow_root_level, 1, ACC_ALL);
|
||||
@ -3410,7 +3410,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
|
||||
spin_lock(&vcpu->kvm->mmu_lock);
|
||||
if (make_mmu_pages_available(vcpu) < 0) {
|
||||
spin_unlock(&vcpu->kvm->mmu_lock);
|
||||
return 1;
|
||||
return -ENOSPC;
|
||||
}
|
||||
sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT),
|
||||
i << 30, PT32_ROOT_LEVEL, 1, ACC_ALL);
|
||||
@ -3450,7 +3450,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
|
||||
spin_lock(&vcpu->kvm->mmu_lock);
|
||||
if (make_mmu_pages_available(vcpu) < 0) {
|
||||
spin_unlock(&vcpu->kvm->mmu_lock);
|
||||
return 1;
|
||||
return -ENOSPC;
|
||||
}
|
||||
sp = kvm_mmu_get_page(vcpu, root_gfn, 0,
|
||||
vcpu->arch.mmu.shadow_root_level, 0, ACC_ALL);
|
||||
@ -3487,7 +3487,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
|
||||
spin_lock(&vcpu->kvm->mmu_lock);
|
||||
if (make_mmu_pages_available(vcpu) < 0) {
|
||||
spin_unlock(&vcpu->kvm->mmu_lock);
|
||||
return 1;
|
||||
return -ENOSPC;
|
||||
}
|
||||
sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, PT32_ROOT_LEVEL,
|
||||
0, ACC_ALL);
|
||||
|
@ -4384,7 +4384,7 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
|
||||
addr, n, v))
|
||||
&& kvm_io_bus_read(vcpu, KVM_MMIO_BUS, addr, n, v))
|
||||
break;
|
||||
trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
|
||||
trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, v);
|
||||
handled += n;
|
||||
addr += n;
|
||||
len -= n;
|
||||
@ -4643,7 +4643,7 @@ static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes)
|
||||
{
|
||||
if (vcpu->mmio_read_completed) {
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
struct fpu *fpu = ¤t->thread.fpu;
|
||||
int r;
|
||||
|
||||
fpu__initialize(fpu);
|
||||
|
||||
kvm_sigset_activate(vcpu);
|
||||
|
||||
kvm_load_guest_fpu(vcpu);
|
||||
|
||||
if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
|
||||
if (kvm_run->immediate_exit) {
|
||||
r = -EINTR;
|
||||
@ -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)) {
|
||||
int (*cui)(struct kvm_vcpu *) = vcpu->arch.complete_userspace_io;
|
||||
vcpu->arch.complete_userspace_io = NULL;
|
||||
r = cui(vcpu);
|
||||
if (r <= 0)
|
||||
goto out_fpu;
|
||||
goto out;
|
||||
} else
|
||||
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)
|
||||
else
|
||||
r = vcpu_run(vcpu);
|
||||
|
||||
out_fpu:
|
||||
kvm_put_guest_fpu(vcpu);
|
||||
out:
|
||||
kvm_put_guest_fpu(vcpu);
|
||||
post_kvm_run_save(vcpu);
|
||||
kvm_sigset_deactivate(vcpu);
|
||||
|
||||
@ -7384,7 +7380,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
@ -7498,6 +7494,29 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
|
||||
}
|
||||
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,
|
||||
struct kvm_sregs *sregs)
|
||||
{
|
||||
@ -7510,6 +7529,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
||||
(sregs->cr4 & X86_CR4_OSXSAVE))
|
||||
return -EINVAL;
|
||||
|
||||
if (kvm_valid_sregs(vcpu, sregs))
|
||||
return -EINVAL;
|
||||
|
||||
apic_base_msr.data = sregs->apic_base;
|
||||
apic_base_msr.host_initiated = true;
|
||||
if (kvm_set_apic_base(vcpu, &apic_base_msr))
|
||||
|
@ -62,7 +62,7 @@ struct arch_timer_cpu {
|
||||
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_vcpu_reset(struct kvm_vcpu *vcpu);
|
||||
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
|
||||
|
@ -211,7 +211,7 @@ TRACE_EVENT(kvm_ack_irq,
|
||||
{ KVM_TRACE_MMIO_WRITE, "write" }
|
||||
|
||||
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_STRUCT__entry(
|
||||
@ -225,7 +225,10 @@ TRACE_EVENT(kvm_mmio,
|
||||
__entry->type = type;
|
||||
__entry->len = len;
|
||||
__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",
|
||||
|
@ -478,7 +478,7 @@ class Provider(object):
|
||||
@staticmethod
|
||||
def is_field_wanted(fields_filter, field):
|
||||
"""Indicate whether field is valid according to fields_filter."""
|
||||
if not fields_filter or fields_filter == "help":
|
||||
if not fields_filter:
|
||||
return True
|
||||
return re.match(fields_filter, field) is not None
|
||||
|
||||
@ -549,8 +549,8 @@ class TracepointProvider(Provider):
|
||||
|
||||
def update_fields(self, fields_filter):
|
||||
"""Refresh fields, applying fields_filter"""
|
||||
self._fields = [field for field in self.get_available_fields()
|
||||
if self.is_field_wanted(fields_filter, field)]
|
||||
self.fields = [field for field in self.get_available_fields()
|
||||
if self.is_field_wanted(fields_filter, field)]
|
||||
|
||||
@staticmethod
|
||||
def get_online_cpus():
|
||||
@ -950,7 +950,8 @@ class Tui(object):
|
||||
curses.nocbreak()
|
||||
curses.endwin()
|
||||
|
||||
def get_all_gnames(self):
|
||||
@staticmethod
|
||||
def get_all_gnames():
|
||||
"""Returns a list of (pid, gname) tuples of all running guests"""
|
||||
res = []
|
||||
try:
|
||||
@ -963,7 +964,7 @@ class Tui(object):
|
||||
# perform a sanity check before calling the more expensive
|
||||
# function to possibly extract the guest name
|
||||
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()
|
||||
|
||||
return res
|
||||
@ -984,7 +985,8 @@ class Tui(object):
|
||||
except Exception:
|
||||
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.
|
||||
|
||||
Returns a list of potential pids, can be empty if no match found.
|
||||
@ -992,7 +994,7 @@ class Tui(object):
|
||||
|
||||
"""
|
||||
pids = []
|
||||
for line in self.get_all_gnames():
|
||||
for line in Tui.get_all_gnames():
|
||||
if gname == line[1]:
|
||||
pids.append(int(line[0]))
|
||||
|
||||
@ -1090,15 +1092,16 @@ class Tui(object):
|
||||
# sort by totals
|
||||
return (0, -stats[x][0])
|
||||
total = 0.
|
||||
for val in stats.values():
|
||||
total += val[0]
|
||||
for key in stats.keys():
|
||||
if key.find('(') is -1:
|
||||
total += stats[key][0]
|
||||
if self._sorting == SORT_DEFAULT:
|
||||
sortkey = sortCurAvg
|
||||
else:
|
||||
sortkey = sortTotal
|
||||
tavg = 0
|
||||
for key in sorted(stats.keys(), key=sortkey):
|
||||
|
||||
if row >= self.screen.getmaxyx()[0]:
|
||||
if row >= self.screen.getmaxyx()[0] - 1:
|
||||
break
|
||||
values = stats[key]
|
||||
if not values[0] and not values[1]:
|
||||
@ -1110,9 +1113,15 @@ class Tui(object):
|
||||
self.screen.addstr(row, 1, '%-40s %10d%7.1f %8s' %
|
||||
(key, values[0], values[0] * 100 / total,
|
||||
cur))
|
||||
if cur is not '' and key.find('(') is -1:
|
||||
tavg += cur
|
||||
row += 1
|
||||
if row == 3:
|
||||
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()
|
||||
|
||||
def show_msg(self, text):
|
||||
@ -1358,7 +1367,7 @@ class Tui(object):
|
||||
if char == 'x':
|
||||
self.update_drilldown()
|
||||
# prevents display of current values on next refresh
|
||||
self.stats.get()
|
||||
self.stats.get(self._display_guests)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
except curses.error:
|
||||
@ -1451,16 +1460,13 @@ Press any other key to refresh statistics immediately.
|
||||
try:
|
||||
pids = Tui.get_pid_from_gname(val)
|
||||
except:
|
||||
raise optparse.OptionValueError('Error while searching for guest '
|
||||
'"{}", use "-p" to specify a pid '
|
||||
'instead'.format(val))
|
||||
sys.exit('Error while searching for guest "{}". Use "-p" to '
|
||||
'specify a pid instead?'.format(val))
|
||||
if len(pids) == 0:
|
||||
raise optparse.OptionValueError('No guest by the name "{}" '
|
||||
'found'.format(val))
|
||||
sys.exit('Error: No guest by the name "{}" found'.format(val))
|
||||
if len(pids) > 1:
|
||||
raise optparse.OptionValueError('Multiple processes found (pids: '
|
||||
'{}) - use "-p" to specify a pid '
|
||||
'instead'.format(" ".join(pids)))
|
||||
sys.exit('Error: Multiple processes found (pids: {}). Use "-p" '
|
||||
'to specify the desired pid'.format(" ".join(pids)))
|
||||
parser.values.pid = pids[0]
|
||||
|
||||
optparser = optparse.OptionParser(description=description_text,
|
||||
@ -1518,7 +1524,16 @@ Press any other key to refresh statistics immediately.
|
||||
help='restrict statistics to guest by name',
|
||||
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
|
||||
|
||||
|
||||
@ -1564,16 +1579,13 @@ def main():
|
||||
|
||||
stats = Stats(options)
|
||||
|
||||
if options.fields == "help":
|
||||
event_list = "\n"
|
||||
s = stats.get()
|
||||
for key in s.keys():
|
||||
if key.find('(') != -1:
|
||||
key = key[0:key.find('(')]
|
||||
if event_list.find('\n' + key + '\n') == -1:
|
||||
event_list += key + '\n'
|
||||
sys.stdout.write(event_list)
|
||||
return ""
|
||||
if options.fields == 'help':
|
||||
stats.fields_filter = None
|
||||
event_list = []
|
||||
for key in stats.get().keys():
|
||||
event_list.append(key.split('(', 1)[0])
|
||||
sys.stdout.write(' ' + '\n '.join(sorted(set(event_list))) + '\n')
|
||||
sys.exit(0)
|
||||
|
||||
if options.log:
|
||||
log(stats)
|
||||
|
@ -50,6 +50,8 @@ INTERACTIVE COMMANDS
|
||||
*s*:: set update interval
|
||||
|
||||
*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.
|
||||
|
||||
@ -86,7 +88,7 @@ OPTIONS
|
||||
|
||||
-f<fields>::
|
||||
--fields=<fields>::
|
||||
fields to display (regex)
|
||||
fields to display (regex), "-f help" for a list of available events
|
||||
|
||||
-h::
|
||||
--help::
|
||||
|
@ -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 arch_timer_context *vtimer;
|
||||
u32 cnt_ctl;
|
||||
|
||||
/*
|
||||
* We may see a timer interrupt after vcpu_put() has been called which
|
||||
* sets the CPU's vcpu pointer to NULL, because even though the timer
|
||||
* has been disabled in vtimer_save_state(), the hardware interrupt
|
||||
* signal may not have been retired from the interrupt controller yet.
|
||||
*/
|
||||
if (!vcpu)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (!vcpu) {
|
||||
pr_warn_once("Spurious arch timer IRQ on non-VCPU thread\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
vtimer = vcpu_vtimer(vcpu);
|
||||
|
||||
if (!vtimer->irq.level) {
|
||||
vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
|
||||
if (kvm_timer_irq_can_fire(vtimer))
|
||||
cnt_ctl = read_sysreg_el0(cntv_ctl);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -355,6 +362,7 @@ static void vtimer_save_state(struct kvm_vcpu *vcpu)
|
||||
|
||||
/* Disable the virtual timer */
|
||||
write_sysreg_el0(0, cntv_ctl);
|
||||
isb();
|
||||
|
||||
vtimer->loaded = false;
|
||||
out:
|
||||
@ -720,7 +728,7 @@ static int kvm_timer_dying_cpu(unsigned int cpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_timer_hyp_init(void)
|
||||
int kvm_timer_hyp_init(bool has_gic)
|
||||
{
|
||||
struct arch_timer_kvm_info *info;
|
||||
int err;
|
||||
@ -756,10 +764,13 @@ int kvm_timer_hyp_init(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = irq_set_vcpu_affinity(host_vtimer_irq, kvm_get_running_vcpus());
|
||||
if (err) {
|
||||
kvm_err("kvm_arch_timer: error setting vcpu affinity\n");
|
||||
goto out_free_irq;
|
||||
if (has_gic) {
|
||||
err = irq_set_vcpu_affinity(host_vtimer_irq,
|
||||
kvm_get_running_vcpus());
|
||||
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);
|
||||
@ -835,10 +846,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
|
||||
no_vgic:
|
||||
preempt_disable();
|
||||
timer->enabled = 1;
|
||||
if (!irqchip_in_kernel(vcpu->kvm))
|
||||
kvm_timer_vcpu_load_user(vcpu);
|
||||
else
|
||||
kvm_timer_vcpu_load_vgic(vcpu);
|
||||
kvm_timer_vcpu_load(vcpu);
|
||||
preempt_enable();
|
||||
|
||||
return 0;
|
||||
|
@ -1326,7 +1326,7 @@ static int init_subsystems(void)
|
||||
/*
|
||||
* Init HYP architected timer support
|
||||
*/
|
||||
err = kvm_timer_hyp_init();
|
||||
err = kvm_timer_hyp_init(vgic_present);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -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,
|
||||
data);
|
||||
&data);
|
||||
data = vcpu_data_host_to_guest(vcpu, data, len);
|
||||
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,
|
||||
data = vcpu_data_guest_to_host(vcpu, vcpu_get_reg(vcpu, rt),
|
||||
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);
|
||||
|
||||
ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, fault_ipa, len,
|
||||
data_buf);
|
||||
} else {
|
||||
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,
|
||||
data_buf);
|
||||
|
@ -509,8 +509,6 @@ static void unmap_hyp_range(pgd_t *pgdp, phys_addr_t start, u64 size)
|
||||
*/
|
||||
void free_hyp_pgds(void)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
mutex_lock(&kvm_hyp_pgd_mutex);
|
||||
|
||||
if (boot_hyp_pgd) {
|
||||
@ -521,10 +519,10 @@ void free_hyp_pgds(void)
|
||||
|
||||
if (hyp_pgd) {
|
||||
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(addr), PGDIR_SIZE);
|
||||
for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
|
||||
unmap_hyp_range(hyp_pgd, kern_hyp_va(addr), PGDIR_SIZE);
|
||||
unmap_hyp_range(hyp_pgd, kern_hyp_va(PAGE_OFFSET),
|
||||
(uintptr_t)high_memory - PAGE_OFFSET);
|
||||
unmap_hyp_range(hyp_pgd, kern_hyp_va(VMALLOC_START),
|
||||
VMALLOC_END - VMALLOC_START);
|
||||
|
||||
free_pages((unsigned long)hyp_pgd, hyp_pgd_order);
|
||||
hyp_pgd = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user