Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 274191
b: refs/heads/master
c: ed79ba9
h: refs/heads/master
i:
  274189: 775aacd
  274187: 26c1167
  274183: 8c1ba5f
  274175: 2216270
v: v3
  • Loading branch information
Benjamin Herrenschmidt committed Sep 20, 2011
1 parent b6c5376 commit bfe43cf
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a125e0928c736bc50cdd9a13151d4f4ee7821266
refs/heads/master: ed79ba9e15f84cef05aba5cbfe6e93f9b43c31f4
2 changes: 2 additions & 0 deletions trunk/arch/powerpc/include/asm/opal.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,8 @@ extern void opal_get_rtc_time(struct rtc_time *tm);
extern unsigned long opal_get_boot_time(void);
extern void opal_nvram_init(void);

extern int opal_machine_check(struct pt_regs *regs);

#endif /* __ASSEMBLY__ */

#endif /* __OPAL_H */
8 changes: 8 additions & 0 deletions trunk/arch/powerpc/include/asm/paca.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ extern unsigned int debug_smp_processor_id(void); /* from linux/smp.h */
#define get_slb_shadow() (get_paca()->slb_shadow_ptr)

struct task_struct;
struct opal_machine_check_event;

/*
* Defines the layout of the paca.
Expand Down Expand Up @@ -135,6 +136,13 @@ struct paca_struct {
u8 io_sync; /* writel() needs spin_unlock sync */
u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */

#ifdef CONFIG_PPC_POWERNV
/* Pointer to OPAL machine check event structure set by the
* early exception handler for use by high level C handler
*/
struct opal_machine_check_event *opal_mc_evt;
#endif

/* Stuff for accurate time accounting */
u64 user_time; /* accumulated usermode TB ticks */
u64 system_time; /* accumulated system TB ticks */
Expand Down
10 changes: 10 additions & 0 deletions trunk/arch/powerpc/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
#ifdef CONFIG_PPC_ISERIES
#include <asm/iseries/alpaca.h>
#endif
#ifdef CONFIG_PPC_POWERNV
#include <asm/opal.h>
#endif
#if defined(CONFIG_KVM) || defined(CONFIG_KVM_GUEST)
#include <linux/kvm_host.h>
#endif
Expand Down Expand Up @@ -609,5 +612,12 @@ int main(void)
arch.timing_last_enter.tv32.tbl));
#endif

#ifdef CONFIG_PPC_POWERNV
DEFINE(OPAL_MC_GPR3, offsetof(struct opal_machine_check_event, gpr3));
DEFINE(OPAL_MC_SRR0, offsetof(struct opal_machine_check_event, srr0));
DEFINE(OPAL_MC_SRR1, offsetof(struct opal_machine_check_event, srr1));
DEFINE(PACA_OPAL_MC_EVT, offsetof(struct paca_struct, opal_mc_evt));
#endif

return 0;
}
27 changes: 23 additions & 4 deletions trunk/arch/powerpc/kernel/exceptions-64s.S
Original file line number Diff line number Diff line change
Expand Up @@ -1143,15 +1143,15 @@ _GLOBAL(do_stab_bolted)
rfid
b . /* prevent speculative execution */

#ifdef CONFIG_PPC_PSERIES
#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
/*
* Data area reserved for FWNMI option.
* This address (0x7000) is fixed by the RPA.
*/
.= 0x7000
.globl fwnmi_data_area
fwnmi_data_area:
#endif /* CONFIG_PPC_PSERIES */
#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */

/* iSeries does not use the FWNMI stuff, so it is safe to put
* this here, even if we later allow kernels that will boot on
Expand All @@ -1176,9 +1176,12 @@ xLparMap:

#endif /* CONFIG_PPC_ISERIES */

#ifdef CONFIG_PPC_PSERIES
#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
/* pseries and powernv need to keep the whole page from
* 0x7000 to 0x8000 free for use by the firmware
*/
. = 0x8000
#endif /* CONFIG_PPC_PSERIES */
#endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */

/*
* Space for CPU0's segment table.
Expand All @@ -1193,3 +1196,19 @@ xLparMap:
.globl initial_stab
initial_stab:
.space 4096
#ifdef CONFIG_PPC_POWERNV
_GLOBAL(opal_mc_secondary_handler)
HMT_MEDIUM
SET_SCRATCH0(r13)
GET_PACA(r13)
clrldi r3,r3,2
tovirt(r3,r3)
std r3,PACA_OPAL_MC_EVT(r13)
ld r13,OPAL_MC_SRR0(r3)
mtspr SPRN_SRR0,r13
ld r13,OPAL_MC_SRR1(r3)
mtspr SPRN_SRR1,r13
ld r3,OPAL_MC_GPR3(r3)
GET_SCRATCH0(r13)
b machine_check_pSeries
#endif /* CONFIG_PPC_POWERNV */
130 changes: 130 additions & 0 deletions trunk/arch/powerpc/platforms/powernv/opal.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ struct opal {

static struct device_node *opal_node;
static DEFINE_SPINLOCK(opal_write_lock);
extern u64 opal_mc_secondary_handler[];

int __init early_init_dt_scan_opal(unsigned long node,
const char *uname, int depth, void *data)
{
const void *basep, *entryp;
unsigned long basesz, entrysz;
u64 glue;

if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
return 0;
Expand All @@ -59,6 +61,19 @@ int __init early_init_dt_scan_opal(unsigned long node,
printk("OPAL V1 detected !\n");
}

/* Hookup some exception handlers. We use the fwnmi area at 0x7000
* to provide the glue space to OPAL
*/
glue = 0x7000;
opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER,
__pa(opal_mc_secondary_handler[0]),
glue);
glue += 128;
opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
0, glue);
glue += 128;
opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);

return 1;
}

Expand Down Expand Up @@ -136,6 +151,121 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
return written;
}

int opal_machine_check(struct pt_regs *regs)
{
struct opal_machine_check_event *opal_evt = get_paca()->opal_mc_evt;
struct opal_machine_check_event evt;
const char *level, *sevstr, *subtype;
static const char *opal_mc_ue_types[] = {
"Indeterminate",
"Instruction fetch",
"Page table walk ifetch",
"Load/Store",
"Page table walk Load/Store",
};
static const char *opal_mc_slb_types[] = {
"Indeterminate",
"Parity",
"Multihit",
};
static const char *opal_mc_erat_types[] = {
"Indeterminate",
"Parity",
"Multihit",
};
static const char *opal_mc_tlb_types[] = {
"Indeterminate",
"Parity",
"Multihit",
};

/* Copy the event structure and release the original */
evt = *opal_evt;
opal_evt->in_use = 0;

/* Print things out */
if (evt.version != OpalMCE_V1) {
pr_err("Machine Check Exception, Unknown event version %d !\n",
evt.version);
return 0;
}
switch(evt.severity) {
case OpalMCE_SEV_NO_ERROR:
level = KERN_INFO;
sevstr = "Harmless";
break;
case OpalMCE_SEV_WARNING:
level = KERN_WARNING;
sevstr = "";
break;
case OpalMCE_SEV_ERROR_SYNC:
level = KERN_ERR;
sevstr = "Severe";
break;
case OpalMCE_SEV_FATAL:
default:
level = KERN_ERR;
sevstr = "Fatal";
break;
}

printk("%s%s Machine check interrupt [%s]\n", level, sevstr,
evt.disposition == OpalMCE_DISPOSITION_RECOVERED ?
"Recovered" : "[Not recovered");
printk("%s Initiator: %s\n", level,
evt.initiator == OpalMCE_INITIATOR_CPU ? "CPU" : "Unknown");
switch(evt.error_type) {
case OpalMCE_ERROR_TYPE_UE:
subtype = evt.u.ue_error.ue_error_type <
ARRAY_SIZE(opal_mc_ue_types) ?
opal_mc_ue_types[evt.u.ue_error.ue_error_type]
: "Unknown";
printk("%s Error type: UE [%s]\n", level, subtype);
if (evt.u.ue_error.effective_address_provided)
printk("%s Effective address: %016llx\n",
level, evt.u.ue_error.effective_address);
if (evt.u.ue_error.physical_address_provided)
printk("%s Physial address: %016llx\n",
level, evt.u.ue_error.physical_address);
break;
case OpalMCE_ERROR_TYPE_SLB:
subtype = evt.u.slb_error.slb_error_type <
ARRAY_SIZE(opal_mc_slb_types) ?
opal_mc_slb_types[evt.u.slb_error.slb_error_type]
: "Unknown";
printk("%s Error type: SLB [%s]\n", level, subtype);
if (evt.u.slb_error.effective_address_provided)
printk("%s Effective address: %016llx\n",
level, evt.u.slb_error.effective_address);
break;
case OpalMCE_ERROR_TYPE_ERAT:
subtype = evt.u.erat_error.erat_error_type <
ARRAY_SIZE(opal_mc_erat_types) ?
opal_mc_erat_types[evt.u.erat_error.erat_error_type]
: "Unknown";
printk("%s Error type: ERAT [%s]\n", level, subtype);
if (evt.u.erat_error.effective_address_provided)
printk("%s Effective address: %016llx\n",
level, evt.u.erat_error.effective_address);
break;
case OpalMCE_ERROR_TYPE_TLB:
subtype = evt.u.tlb_error.tlb_error_type <
ARRAY_SIZE(opal_mc_tlb_types) ?
opal_mc_tlb_types[evt.u.tlb_error.tlb_error_type]
: "Unknown";
printk("%s Error type: TLB [%s]\n", level, subtype);
if (evt.u.tlb_error.effective_address_provided)
printk("%s Effective address: %016llx\n",
level, evt.u.tlb_error.effective_address);
break;
default:
case OpalMCE_ERROR_TYPE_UNKNOWN:
printk("%s Error type: Unknown\n", level);
break;
}
return evt.severity == OpalMCE_SEV_FATAL ? 0 : 1;
}

static irqreturn_t opal_interrupt(int irq, void *data)
{
uint64_t events;
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/powerpc/platforms/powernv/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ static void __init pnv_setup_machdep_opal(void)
ppc_md.restart = pnv_restart;
ppc_md.power_off = pnv_power_off;
ppc_md.halt = pnv_halt;
ppc_md.machine_check_exception = opal_machine_check;
}

#ifdef CONFIG_PPC_POWERNV_RTAS
Expand Down

0 comments on commit bfe43cf

Please sign in to comment.