[PATCH] powerpc: Create a trampoline for the fwnmi vectors
The fwnmi vectors can be anywhere < 32 MB, so we need to use a trampoline for them. The kdump kernel will register the trampoline addresses, which will then jump up to the real code above 32 MB. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
committed by
Paul Mackerras
parent
398ab1fcb9
commit
8c4f1f2958
@@ -553,6 +553,7 @@ slb_miss_user_pseries:
|
|||||||
* Vectors for the FWNMI option. Share common code.
|
* Vectors for the FWNMI option. Share common code.
|
||||||
*/
|
*/
|
||||||
.globl system_reset_fwnmi
|
.globl system_reset_fwnmi
|
||||||
|
.align 7
|
||||||
system_reset_fwnmi:
|
system_reset_fwnmi:
|
||||||
HMT_MEDIUM
|
HMT_MEDIUM
|
||||||
mtspr SPRN_SPRG1,r13 /* save r13 */
|
mtspr SPRN_SPRG1,r13 /* save r13 */
|
||||||
@@ -560,6 +561,7 @@ system_reset_fwnmi:
|
|||||||
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
|
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
|
||||||
|
|
||||||
.globl machine_check_fwnmi
|
.globl machine_check_fwnmi
|
||||||
|
.align 7
|
||||||
machine_check_fwnmi:
|
machine_check_fwnmi:
|
||||||
HMT_MEDIUM
|
HMT_MEDIUM
|
||||||
mtspr SPRN_SPRG1,r13 /* save r13 */
|
mtspr SPRN_SPRG1,r13 /* save r13 */
|
||||||
|
@@ -49,14 +49,12 @@
|
|||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
#include <asm/rtas.h>
|
#include <asm/rtas.h>
|
||||||
#include <asm/udbg.h>
|
#include <asm/udbg.h>
|
||||||
|
#include <asm/firmware.h>
|
||||||
|
|
||||||
static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
|
static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
|
||||||
static DEFINE_SPINLOCK(ras_log_buf_lock);
|
static DEFINE_SPINLOCK(ras_log_buf_lock);
|
||||||
|
|
||||||
char mce_data_buf[RTAS_ERROR_LOG_MAX]
|
char mce_data_buf[RTAS_ERROR_LOG_MAX];
|
||||||
;
|
|
||||||
/* This is true if we are using the firmware NMI handler (typically LPAR) */
|
|
||||||
extern int fwnmi_active;
|
|
||||||
|
|
||||||
static int ras_get_sensor_state_token;
|
static int ras_get_sensor_state_token;
|
||||||
static int ras_check_exception_token;
|
static int ras_check_exception_token;
|
||||||
|
@@ -77,8 +77,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void find_udbg_vterm(void);
|
extern void find_udbg_vterm(void);
|
||||||
extern void system_reset_fwnmi(void); /* from head.S */
|
|
||||||
extern void machine_check_fwnmi(void); /* from head.S */
|
|
||||||
|
|
||||||
int fwnmi_active; /* TRUE if an FWNMI handler is present */
|
int fwnmi_active; /* TRUE if an FWNMI handler is present */
|
||||||
|
|
||||||
@@ -104,18 +102,22 @@ void pSeries_show_cpuinfo(struct seq_file *m)
|
|||||||
|
|
||||||
/* Initialize firmware assisted non-maskable interrupts if
|
/* Initialize firmware assisted non-maskable interrupts if
|
||||||
* the firmware supports this feature.
|
* the firmware supports this feature.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static void __init fwnmi_init(void)
|
static void __init fwnmi_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
unsigned long system_reset_addr, machine_check_addr;
|
||||||
|
|
||||||
int ibm_nmi_register = rtas_token("ibm,nmi-register");
|
int ibm_nmi_register = rtas_token("ibm,nmi-register");
|
||||||
if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
|
if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
|
||||||
return;
|
return;
|
||||||
ret = rtas_call(ibm_nmi_register, 2, 1, NULL,
|
|
||||||
__pa((unsigned long)system_reset_fwnmi),
|
/* If the kernel's not linked at zero we point the firmware at low
|
||||||
__pa((unsigned long)machine_check_fwnmi));
|
* addresses anyway, and use a trampoline to get to the real code. */
|
||||||
if (ret == 0)
|
system_reset_addr = __pa(system_reset_fwnmi) - PHYSICAL_START;
|
||||||
|
machine_check_addr = __pa(machine_check_fwnmi) - PHYSICAL_START;
|
||||||
|
|
||||||
|
if (0 == rtas_call(ibm_nmi_register, 2, 1, NULL, system_reset_addr,
|
||||||
|
machine_check_addr))
|
||||||
fwnmi_active = 1;
|
fwnmi_active = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -98,6 +98,12 @@ typedef struct {
|
|||||||
extern firmware_feature_t firmware_features_table[];
|
extern firmware_feature_t firmware_features_table[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern void system_reset_fwnmi(void);
|
||||||
|
extern void machine_check_fwnmi(void);
|
||||||
|
|
||||||
|
/* This is true if we are using the firmware NMI handler (typically LPAR) */
|
||||||
|
extern int fwnmi_active;
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
#endif /* __ASM_POWERPC_FIRMWARE_H */
|
#endif /* __ASM_POWERPC_FIRMWARE_H */
|
||||||
|
Reference in New Issue
Block a user