1 /* 2 * PowerNV OPAL high level interfaces 3 * 4 * Copyright 2011 IBM Corp. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #undef DEBUG 13 14 #include <linux/types.h> 15 #include <linux/of.h> 16 #include <linux/of_platform.h> 17 #include <linux/interrupt.h> 18 #include <asm/opal.h> 19 #include <asm/firmware.h> 20 21 #include "powernv.h" 22 23 struct opal { 24 u64 base; 25 u64 entry; 26 } opal; 27 28 static struct device_node *opal_node; 29 static DEFINE_SPINLOCK(opal_write_lock); 30 extern u64 opal_mc_secondary_handler[]; 31 32 int __init early_init_dt_scan_opal(unsigned long node, 33 const char *uname, int depth, void *data) 34 { 35 const void *basep, *entryp; 36 unsigned long basesz, entrysz; 37 u64 glue; 38 39 if (depth != 1 || strcmp(uname, "ibm,opal") != 0) 40 return 0; 41 42 basep = of_get_flat_dt_prop(node, "opal-base-address", &basesz); 43 entryp = of_get_flat_dt_prop(node, "opal-entry-address", &entrysz); 44 45 if (!basep || !entryp) 46 return 1; 47 48 opal.base = of_read_number(basep, basesz/4); 49 opal.entry = of_read_number(entryp, entrysz/4); 50 51 pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n", 52 opal.base, basep, basesz); 53 pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n", 54 opal.entry, entryp, entrysz); 55 56 powerpc_firmware_features |= FW_FEATURE_OPAL; 57 if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { 58 powerpc_firmware_features |= FW_FEATURE_OPALv2; 59 printk("OPAL V2 detected !\n"); 60 } else { 61 printk("OPAL V1 detected !\n"); 62 } 63 64 /* Hookup some exception handlers. We use the fwnmi area at 0x7000 65 * to provide the glue space to OPAL 66 */ 67 glue = 0x7000; 68 opal_register_exception_handler(OPAL_MACHINE_CHECK_HANDLER, 69 __pa(opal_mc_secondary_handler[0]), 70 glue); 71 glue += 128; 72 opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER, 73 0, glue); 74 glue += 128; 75 opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); 76 77 return 1; 78 } 79 80 int opal_get_chars(uint32_t vtermno, char *buf, int count) 81 { 82 s64 len, rc; 83 u64 evt; 84 85 if (!opal.entry) 86 return -ENODEV; 87 opal_poll_events(&evt); 88 if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0) 89 return 0; 90 len = count; 91 rc = opal_console_read(vtermno, &len, buf); 92 if (rc == OPAL_SUCCESS) 93 return len; 94 return 0; 95 } 96 97 int opal_put_chars(uint32_t vtermno, const char *data, int total_len) 98 { 99 int written = 0; 100 s64 len, rc; 101 unsigned long flags; 102 u64 evt; 103 104 if (!opal.entry) 105 return -ENODEV; 106 107 /* We want put_chars to be atomic to avoid mangling of hvsi 108 * packets. To do that, we first test for room and return 109 * -EAGAIN if there isn't enough. 110 * 111 * Unfortunately, opal_console_write_buffer_space() doesn't 112 * appear to work on opal v1, so we just assume there is 113 * enough room and be done with it 114 */ 115 spin_lock_irqsave(&opal_write_lock, flags); 116 if (firmware_has_feature(FW_FEATURE_OPALv2)) { 117 rc = opal_console_write_buffer_space(vtermno, &len); 118 if (rc || len < total_len) { 119 spin_unlock_irqrestore(&opal_write_lock, flags); 120 /* Closed -> drop characters */ 121 if (rc) 122 return total_len; 123 opal_poll_events(&evt); 124 return -EAGAIN; 125 } 126 } 127 128 /* We still try to handle partial completions, though they 129 * should no longer happen. 130 */ 131 rc = OPAL_BUSY; 132 while(total_len > 0 && (rc == OPAL_BUSY || 133 rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { 134 len = total_len; 135 rc = opal_console_write(vtermno, &len, data); 136 if (rc == OPAL_SUCCESS) { 137 total_len -= len; 138 data += len; 139 written += len; 140 } 141 /* This is a bit nasty but we need that for the console to 142 * flush when there aren't any interrupts. We will clean 143 * things a bit later to limit that to synchronous path 144 * such as the kernel console and xmon/udbg 145 */ 146 do 147 opal_poll_events(&evt); 148 while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT)); 149 } 150 spin_unlock_irqrestore(&opal_write_lock, flags); 151 return written; 152 } 153 154 int opal_machine_check(struct pt_regs *regs) 155 { 156 struct opal_machine_check_event *opal_evt = get_paca()->opal_mc_evt; 157 struct opal_machine_check_event evt; 158 const char *level, *sevstr, *subtype; 159 static const char *opal_mc_ue_types[] = { 160 "Indeterminate", 161 "Instruction fetch", 162 "Page table walk ifetch", 163 "Load/Store", 164 "Page table walk Load/Store", 165 }; 166 static const char *opal_mc_slb_types[] = { 167 "Indeterminate", 168 "Parity", 169 "Multihit", 170 }; 171 static const char *opal_mc_erat_types[] = { 172 "Indeterminate", 173 "Parity", 174 "Multihit", 175 }; 176 static const char *opal_mc_tlb_types[] = { 177 "Indeterminate", 178 "Parity", 179 "Multihit", 180 }; 181 182 /* Copy the event structure and release the original */ 183 evt = *opal_evt; 184 opal_evt->in_use = 0; 185 186 /* Print things out */ 187 if (evt.version != OpalMCE_V1) { 188 pr_err("Machine Check Exception, Unknown event version %d !\n", 189 evt.version); 190 return 0; 191 } 192 switch(evt.severity) { 193 case OpalMCE_SEV_NO_ERROR: 194 level = KERN_INFO; 195 sevstr = "Harmless"; 196 break; 197 case OpalMCE_SEV_WARNING: 198 level = KERN_WARNING; 199 sevstr = ""; 200 break; 201 case OpalMCE_SEV_ERROR_SYNC: 202 level = KERN_ERR; 203 sevstr = "Severe"; 204 break; 205 case OpalMCE_SEV_FATAL: 206 default: 207 level = KERN_ERR; 208 sevstr = "Fatal"; 209 break; 210 } 211 212 printk("%s%s Machine check interrupt [%s]\n", level, sevstr, 213 evt.disposition == OpalMCE_DISPOSITION_RECOVERED ? 214 "Recovered" : "[Not recovered"); 215 printk("%s Initiator: %s\n", level, 216 evt.initiator == OpalMCE_INITIATOR_CPU ? "CPU" : "Unknown"); 217 switch(evt.error_type) { 218 case OpalMCE_ERROR_TYPE_UE: 219 subtype = evt.u.ue_error.ue_error_type < 220 ARRAY_SIZE(opal_mc_ue_types) ? 221 opal_mc_ue_types[evt.u.ue_error.ue_error_type] 222 : "Unknown"; 223 printk("%s Error type: UE [%s]\n", level, subtype); 224 if (evt.u.ue_error.effective_address_provided) 225 printk("%s Effective address: %016llx\n", 226 level, evt.u.ue_error.effective_address); 227 if (evt.u.ue_error.physical_address_provided) 228 printk("%s Physial address: %016llx\n", 229 level, evt.u.ue_error.physical_address); 230 break; 231 case OpalMCE_ERROR_TYPE_SLB: 232 subtype = evt.u.slb_error.slb_error_type < 233 ARRAY_SIZE(opal_mc_slb_types) ? 234 opal_mc_slb_types[evt.u.slb_error.slb_error_type] 235 : "Unknown"; 236 printk("%s Error type: SLB [%s]\n", level, subtype); 237 if (evt.u.slb_error.effective_address_provided) 238 printk("%s Effective address: %016llx\n", 239 level, evt.u.slb_error.effective_address); 240 break; 241 case OpalMCE_ERROR_TYPE_ERAT: 242 subtype = evt.u.erat_error.erat_error_type < 243 ARRAY_SIZE(opal_mc_erat_types) ? 244 opal_mc_erat_types[evt.u.erat_error.erat_error_type] 245 : "Unknown"; 246 printk("%s Error type: ERAT [%s]\n", level, subtype); 247 if (evt.u.erat_error.effective_address_provided) 248 printk("%s Effective address: %016llx\n", 249 level, evt.u.erat_error.effective_address); 250 break; 251 case OpalMCE_ERROR_TYPE_TLB: 252 subtype = evt.u.tlb_error.tlb_error_type < 253 ARRAY_SIZE(opal_mc_tlb_types) ? 254 opal_mc_tlb_types[evt.u.tlb_error.tlb_error_type] 255 : "Unknown"; 256 printk("%s Error type: TLB [%s]\n", level, subtype); 257 if (evt.u.tlb_error.effective_address_provided) 258 printk("%s Effective address: %016llx\n", 259 level, evt.u.tlb_error.effective_address); 260 break; 261 default: 262 case OpalMCE_ERROR_TYPE_UNKNOWN: 263 printk("%s Error type: Unknown\n", level); 264 break; 265 } 266 return evt.severity == OpalMCE_SEV_FATAL ? 0 : 1; 267 } 268 269 static irqreturn_t opal_interrupt(int irq, void *data) 270 { 271 uint64_t events; 272 273 opal_handle_interrupt(virq_to_hw(irq), &events); 274 275 /* XXX TODO: Do something with the events */ 276 277 return IRQ_HANDLED; 278 } 279 280 static int __init opal_init(void) 281 { 282 struct device_node *np, *consoles; 283 const u32 *irqs; 284 int rc, i, irqlen; 285 286 opal_node = of_find_node_by_path("/ibm,opal"); 287 if (!opal_node) { 288 pr_warn("opal: Node not found\n"); 289 return -ENODEV; 290 } 291 if (firmware_has_feature(FW_FEATURE_OPALv2)) 292 consoles = of_find_node_by_path("/ibm,opal/consoles"); 293 else 294 consoles = of_node_get(opal_node); 295 296 /* Register serial ports */ 297 for_each_child_of_node(consoles, np) { 298 if (strcmp(np->name, "serial")) 299 continue; 300 of_platform_device_create(np, NULL, NULL); 301 } 302 of_node_put(consoles); 303 304 /* Find all OPAL interrupts and request them */ 305 irqs = of_get_property(opal_node, "opal-interrupts", &irqlen); 306 pr_debug("opal: Found %d interrupts reserved for OPAL\n", 307 irqs ? (irqlen / 4) : 0); 308 for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) { 309 unsigned int hwirq = be32_to_cpup(irqs); 310 unsigned int irq = irq_create_mapping(NULL, hwirq); 311 if (irq == NO_IRQ) { 312 pr_warning("opal: Failed to map irq 0x%x\n", hwirq); 313 continue; 314 } 315 rc = request_irq(irq, opal_interrupt, 0, "opal", NULL); 316 if (rc) 317 pr_warning("opal: Error %d requesting irq %d" 318 " (0x%x)\n", rc, irq, hwirq); 319 } 320 return 0; 321 } 322 subsys_initcall(opal_init); 323