linux/arch/powerpc/kernel
Michael Ellerman 56376c5864 powerpc/kvm: Fix lockups when running KVM guests on Power8
When running KVM guests on Power8 we can see a lockup where one CPU
stops responding. This often leads to a message such as:

  watchdog: CPU 136 detected hard LOCKUP on other CPUs 72
  Task dump for CPU 72:
  qemu-system-ppc R  running task    10560 20917  20908 0x00040004

And then backtraces on other CPUs, such as:

  Task dump for CPU 48:
  ksmd            R  running task    10032  1519      2 0x00000804
  Call Trace:
    ...
    --- interrupt: 901 at smp_call_function_many+0x3c8/0x460
        LR = smp_call_function_many+0x37c/0x460
    pmdp_invalidate+0x100/0x1b0
    __split_huge_pmd+0x52c/0xdb0
    try_to_unmap_one+0x764/0x8b0
    rmap_walk_anon+0x15c/0x370
    try_to_unmap+0xb4/0x170
    split_huge_page_to_list+0x148/0xa30
    try_to_merge_one_page+0xc8/0x990
    try_to_merge_with_ksm_page+0x74/0xf0
    ksm_scan_thread+0x10ec/0x1ac0
    kthread+0x160/0x1a0
    ret_from_kernel_thread+0x5c/0x78

This is caused by commit 8c1c7fb0b5 ("powerpc/64s/idle: avoid sync
for KVM state when waking from idle"), which added a check in
pnv_powersave_wakeup() to see if the kvm_hstate.hwthread_state is
already set to KVM_HWTHREAD_IN_KERNEL, and if so to skip the store and
test of kvm_hstate.hwthread_req.

The problem is that the primary does not set KVM_HWTHREAD_IN_KVM when
entering the guest, so it can then come out to cede with
KVM_HWTHREAD_IN_KERNEL set. It can then go idle in kvm_do_nap after
setting hwthread_req to 1, but because hwthread_state is still
KVM_HWTHREAD_IN_KERNEL we will skip the test of hwthread_req when we
wake up from idle and won't go to kvm_start_guest. From there the
thread will return somewhere garbage and crash.

Fix it by skipping the store of hwthread_state, but not the test of
hwthread_req, when coming out of idle. It's OK to skip the sync in
that case because hwthread_req will have been set on the same thread,
so there is no synchronisation required.

Fixes: 8c1c7fb0b5 ("powerpc/64s/idle: avoid sync for KVM state when waking from idle")
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2018-04-19 16:22:20 +10:00
..
trace
vdso32
vdso64
.gitignore
align.c
asm-offsets.c
audit.c
btext.c
cacheinfo.c
cacheinfo.h
compat_audit.c
cpu_setup_6xx.S
cpu_setup_44x.S
cpu_setup_fsl_booke.S
cpu_setup_pa6t.S
cpu_setup_power.S
cpu_setup_ppc970.S
cputable.c
crash_dump.c
crash.c
dbell.c
dma-iommu.c
dma-swiotlb.c
dma.c
dt_cpu_ftrs.c
eeh_cache.c
eeh_dev.c
eeh_driver.c
eeh_event.c
eeh_pe.c powerpc/eeh: Fix enabling bridge MMIO windows 2018-04-19 13:02:38 +10:00
eeh_sysfs.c
eeh.c
entry_32.S
entry_64.S
epapr_hcalls.S
epapr_paravirt.c
exceptions-64e.S
exceptions-64s.S
fadump.c
firmware.c
fpu.S
fsl_booke_entry_mapping.S
head_8xx.S
head_32.S
head_40x.S
head_44x.S
head_64.S
head_booke.h
head_fsl_booke.S
hw_breakpoint.c
idle_6xx.S
idle_book3e.S
idle_book3s.S powerpc/kvm: Fix lockups when running KVM guests on Power8 2018-04-19 16:22:20 +10:00
idle_e500.S
idle_power4.S
idle.c
ima_kexec.c
io-workarounds.c
io.c
iomap.c
iommu.c
irq.c
isa-bridge.c
jump_label.c
kexec_elf_64.c
kgdb.c
kprobes-ftrace.c
kprobes.c
kvm_emul.S
kvm.c
l2cr_6xx.S
legacy_serial.c
machine_kexec_32.c
machine_kexec_64.c
machine_kexec_file_64.c
machine_kexec.c
Makefile
mce_power.c
mce.c
misc_32.S
misc_64.S
misc.S
module_32.c
module_64.c
module.c
module.lds
msi.c
nvram_64.c
of_platform.c
optprobes_head.S
optprobes.c
paca.c
pci_32.c
pci_64.c
pci_dn.c
pci_of_scan.c
pci-common.c
pci-hotplug.c
pmc.c
ppc32.h
ppc_save_regs.S
proc_powerpc.c
process.c
prom_init_check.sh
prom_init.c
prom_parse.c
prom.c
ptrace32.c
ptrace.c
reloc_32.S
reloc_64.S
rtas_flash.c
rtas_pci.c
rtas-proc.c
rtas-rtc.c
rtas.c
rtasd.c
security.c
setup_32.c
setup_64.c
setup-common.c
setup.h
signal_32.c
signal_64.c
signal.c
signal.h
smp-tbsync.c
smp.c
stacktrace.c
suspend.c
swsusp_32.S
swsusp_64.c
swsusp_asm64.S
swsusp_booke.S
swsusp.c
sys_ppc32.c
syscalls.c
sysfs.c
systbl_chk.c
systbl_chk.sh
systbl.S
tau_6xx.c
time.c
tm.S
traps.c
udbg_16550.c
udbg.c
uprobes.c
vdso.c
vecemu.c
vector.S
vmlinux.lds.S
watchdog.c