mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-26 13:55:09 +07:00
d075745d89
Hypervisor maintenance interrupts (HMIs) are generated by various causes, signalled by bits in the hypervisor maintenance exception register (HMER). In most cases calling OPAL to handle the interrupt is the correct thing to do, but the "debug trigger" HMIs signalled by PPC bit 17 (bit 46) of HMER are used to invoke software workarounds for hardware bugs, and OPAL does not have any code to handle this cause. The debug trigger HMI is used in POWER9 DD2.0 and DD2.1 chips to work around a hardware bug in executing vector load instructions to cache inhibited memory. In POWER9 DD2.2 chips, it is generated when conditions are detected relating to threads being in TM (transactional memory) suspended mode when the core SMT configuration needs to be reconfigured. The kernel currently has code to detect the vector CI load condition, but only when the HMI occurs in the host, not when it occurs in a guest. If a HMI occurs in the guest, it is always passed to OPAL, and then we always re-sync the timebase, because the HMI cause might have been a timebase error, for which OPAL would re-sync the timebase, thus removing the timebase offset which KVM applied for the guest. Since we don't know what OPAL did, we don't know whether to subtract the timebase offset from the timebase, so instead we re-sync the timebase. This adds code to determine explicitly what the cause of a debug trigger HMI will be. This is based on a new device-tree property under the CPU nodes called ibm,hmi-special-triggers, if it is present, or otherwise based on the PVR (processor version register). The handling of debug trigger HMIs is pulled out into a separate function which can be called from the KVM guest exit code. If this function handles and clears the HMI, and no other HMI causes remain, then we skip calling OPAL and we proceed to subtract the guest timebase offset from the timebase. The overall handling for HMIs that occur in the host (i.e. not in a KVM guest) is largely unchanged, except that we now don't set the flag for the vector CI load workaround on DD2.2 processors. This also removes a BUG_ON in the KVM code. BUG_ON is generally not useful in KVM guest entry/exit code since it is difficult to handle the resulting trap gracefully. Signed-off-by: Paul Mackerras <paulus@ozlabs.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
50 lines
1.5 KiB
C
50 lines
1.5 KiB
C
/*
|
|
* Hypervisor Maintenance Interrupt header file.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program.
|
|
*
|
|
* Copyright 2015 IBM Corporation
|
|
* Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
|
|
*/
|
|
|
|
#ifndef __ASM_PPC64_HMI_H__
|
|
#define __ASM_PPC64_HMI_H__
|
|
|
|
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
|
|
|
|
#define CORE_TB_RESYNC_REQ_BIT 63
|
|
#define MAX_SUBCORE_PER_CORE 4
|
|
|
|
/*
|
|
* sibling_subcore_state structure is used to co-ordinate all threads
|
|
* during HMI to avoid TB corruption. This structure is allocated once
|
|
* per each core and shared by all threads on that core.
|
|
*/
|
|
struct sibling_subcore_state {
|
|
unsigned long flags;
|
|
u8 in_guest[MAX_SUBCORE_PER_CORE];
|
|
};
|
|
|
|
extern void wait_for_subcore_guest_exit(void);
|
|
extern void wait_for_tb_resync(void);
|
|
#else
|
|
static inline void wait_for_subcore_guest_exit(void) { }
|
|
static inline void wait_for_tb_resync(void) { }
|
|
#endif
|
|
|
|
struct pt_regs;
|
|
extern long hmi_handle_debugtrig(struct pt_regs *regs);
|
|
|
|
#endif /* __ASM_PPC64_HMI_H__ */
|