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>
* Vectors for the FWNMI option. Share common code.
*/
.globl system_reset_fwnmi
* Vectors for the FWNMI option. Share common code.
*/
.globl system_reset_fwnmi
system_reset_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
system_reset_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
.globl machine_check_fwnmi
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
.globl machine_check_fwnmi
machine_check_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
machine_check_fwnmi:
HMT_MEDIUM
mtspr SPRN_SPRG1,r13 /* save r13 */
#include <asm/machdep.h>
#include <asm/rtas.h>
#include <asm/udbg.h>
#include <asm/machdep.h>
#include <asm/rtas.h>
#include <asm/udbg.h>
+#include <asm/firmware.h>
static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
static DEFINE_SPINLOCK(ras_log_buf_lock);
static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX];
static DEFINE_SPINLOCK(ras_log_buf_lock);
-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;
+char mce_data_buf[RTAS_ERROR_LOG_MAX];
static int ras_get_sensor_state_token;
static int ras_check_exception_token;
static int ras_get_sensor_state_token;
static int ras_check_exception_token;
#endif
extern void find_udbg_vterm(void);
#endif
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 */
/* Initialize firmware assisted non-maskable interrupts if
* the firmware supports this feature.
/* Initialize firmware assisted non-maskable interrupts if
* the firmware supports this feature.
*/
static void __init fwnmi_init(void)
{
*/
static void __init fwnmi_init(void)
{
+ unsigned long system_reset_addr, machine_check_addr;
+
int ibm_nmi_register = rtas_token("ibm,nmi-register");
if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
return;
int ibm_nmi_register = rtas_token("ibm,nmi-register");
if (ibm_nmi_register == RTAS_UNKNOWN_SERVICE)
return;
- ret = rtas_call(ibm_nmi_register, 2, 1, NULL,
- __pa((unsigned long)system_reset_fwnmi),
- __pa((unsigned long)machine_check_fwnmi));
- if (ret == 0)
+
+ /* If the kernel's not linked at zero we point the firmware at low
+ * addresses anyway, and use a trampoline to get to the real code. */
+ 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))
extern firmware_feature_t firmware_features_table[];
#endif
extern firmware_feature_t firmware_features_table[];
#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 /* __KERNEL__ */
#endif /* __ASM_POWERPC_FIRMWARE_H */
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_FIRMWARE_H */