Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: PPC: Book3S HV: Synthesize segment fault if SLB lookup fails

When handling a hypervisor data or instruction storage interrupt (HDSI
or HISI), we look up the SLB entry for the address being accessed in
order to translate the effective address to a virtual address which can
be looked up in the guest HPT. This lookup can occasionally fail due
to the guest replacing an SLB entry without invalidating the evicted
SLB entry. In this situation an ERAT (effective to real address
translation cache) entry can persist and be used by the hardware even
though there is no longer a corresponding SLB entry.

Previously we would just deliver a data or instruction storage interrupt
(DSI or ISI) to the guest in this case. However, this is not correct
and has been observed to cause guests to crash, typically with a
data storage protection interrupt on a store to the vmemmap area.

Instead, what we do now is to synthesize a data or instruction segment
interrupt. That should cause the guest to reload an appropriate entry
into the SLB and retry the faulting instruction. If it still faults,
we should find an appropriate SLB entry next time and be able to handle
the fault.

Tested-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>

+12 -8
+12 -8
arch/powerpc/kvm/book3s_hv_rmhandlers.S
··· 1749 1749 beq 3f 1750 1750 clrrdi r0, r4, 28 1751 1751 PPC_SLBFEE_DOT(R5, R0) /* if so, look up SLB */ 1752 - bne 1f /* if no SLB entry found */ 1752 + li r0, BOOK3S_INTERRUPT_DATA_SEGMENT 1753 + bne 7f /* if no SLB entry found */ 1753 1754 4: std r4, VCPU_FAULT_DAR(r9) 1754 1755 stw r6, VCPU_FAULT_DSISR(r9) 1755 1756 ··· 1769 1768 cmpdi r3, -2 /* MMIO emulation; need instr word */ 1770 1769 beq 2f 1771 1770 1772 - /* Synthesize a DSI for the guest */ 1771 + /* Synthesize a DSI (or DSegI) for the guest */ 1773 1772 ld r4, VCPU_FAULT_DAR(r9) 1774 1773 mr r6, r3 1775 - 1: mtspr SPRN_DAR, r4 1774 + 1: li r0, BOOK3S_INTERRUPT_DATA_STORAGE 1776 1775 mtspr SPRN_DSISR, r6 1776 + 7: mtspr SPRN_DAR, r4 1777 1777 mtspr SPRN_SRR0, r10 1778 1778 mtspr SPRN_SRR1, r11 1779 - li r10, BOOK3S_INTERRUPT_DATA_STORAGE 1779 + mr r10, r0 1780 1780 bl kvmppc_msr_interrupt 1781 1781 fast_interrupt_c_return: 1782 1782 6: ld r7, VCPU_CTR(r9) ··· 1825 1823 beq 3f 1826 1824 clrrdi r0, r10, 28 1827 1825 PPC_SLBFEE_DOT(R5, R0) /* if so, look up SLB */ 1828 - bne 1f /* if no SLB entry found */ 1826 + li r0, BOOK3S_INTERRUPT_INST_SEGMENT 1827 + bne 7f /* if no SLB entry found */ 1829 1828 4: 1830 1829 /* Search the hash table. */ 1831 1830 mr r3, r9 /* vcpu pointer */ ··· 1843 1840 cmpdi r3, -1 /* handle in kernel mode */ 1844 1841 beq guest_exit_cont 1845 1842 1846 - /* Synthesize an ISI for the guest */ 1843 + /* Synthesize an ISI (or ISegI) for the guest */ 1847 1844 mr r11, r3 1848 - 1: mtspr SPRN_SRR0, r10 1845 + 1: li r0, BOOK3S_INTERRUPT_INST_STORAGE 1846 + 7: mtspr SPRN_SRR0, r10 1849 1847 mtspr SPRN_SRR1, r11 1850 - li r10, BOOK3S_INTERRUPT_INST_STORAGE 1848 + mr r10, r0 1851 1849 bl kvmppc_msr_interrupt 1852 1850 b fast_interrupt_c_return 1853 1851