aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/xmon/xmon.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-04-05 03:54:50 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2017-04-10 07:41:34 -0400
commit243e25112d06b348f087a6f7aba4bbc288285bdd (patch)
treec4f605e98e6e8cf6dbe730c946142943b82ac38e /arch/powerpc/xmon/xmon.c
parenta978e13965a40ac07163643cc3fa0ddb0d354198 (diff)
powerpc/xive: Native exploitation of the XIVE interrupt controller
The XIVE interrupt controller is the new interrupt controller found in POWER9. It supports advanced virtualization capabilities among other things. Currently we use a set of firmware calls that simulate the old "XICS" interrupt controller but this is fairly inefficient. This adds the framework for using XIVE along with a native backend which OPAL for configuration. Later, a backend allowing the use in a KVM or PowerVM guest will also be provided. This disables some fast path for interrupts in KVM when XIVE is enabled as these rely on the firmware emulation code which is no longer available when the XIVE is used natively by Linux. A latter patch will make KVM also directly exploit the XIVE, thus recovering the lost performance (and more). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> [mpe: Fixup pr_xxx("XIVE:"...), don't split pr_xxx() strings, tweak Kconfig so XIVE_NATIVE selects XIVE and depends on POWERNV, fix build errors when SMP=n, fold in fixes from Ben: Don't call cpu_online() on an invalid CPU number Fix irq target selection returning out of bounds cpu# Extra sanity checks on cpu numbers ] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/xmon/xmon.c')
-rw-r--r--arch/powerpc/xmon/xmon.c94
1 files changed, 92 insertions, 2 deletions
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 16321ad9e70c..67435b9bf98d 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -30,6 +30,7 @@
30#include <linux/ctype.h> 30#include <linux/ctype.h>
31 31
32#include <asm/ptrace.h> 32#include <asm/ptrace.h>
33#include <asm/smp.h>
33#include <asm/string.h> 34#include <asm/string.h>
34#include <asm/prom.h> 35#include <asm/prom.h>
35#include <asm/machdep.h> 36#include <asm/machdep.h>
@@ -48,7 +49,7 @@
48#include <asm/reg.h> 49#include <asm/reg.h>
49#include <asm/debug.h> 50#include <asm/debug.h>
50#include <asm/hw_breakpoint.h> 51#include <asm/hw_breakpoint.h>
51 52#include <asm/xive.h>
52#include <asm/opal.h> 53#include <asm/opal.h>
53#include <asm/firmware.h> 54#include <asm/firmware.h>
54 55
@@ -232,7 +233,13 @@ Commands:\n\
232 "\ 233 "\
233 dr dump stream of raw bytes\n\ 234 dr dump stream of raw bytes\n\
234 dt dump the tracing buffers (uses printk)\n\ 235 dt dump the tracing buffers (uses printk)\n\
235 e print exception information\n\ 236"
237#ifdef CONFIG_PPC_POWERNV
238" dx# dump xive on CPU #\n\
239 dxi# dump xive irq state #\n\
240 dxa dump xive on all CPUs\n"
241#endif
242" e print exception information\n\
236 f flush cache\n\ 243 f flush cache\n\
237 la lookup symbol+offset of specified address\n\ 244 la lookup symbol+offset of specified address\n\
238 ls lookup address of specified symbol\n\ 245 ls lookup address of specified symbol\n\
@@ -2338,6 +2345,81 @@ static void dump_pacas(void)
2338} 2345}
2339#endif 2346#endif
2340 2347
2348#ifdef CONFIG_PPC_POWERNV
2349static void dump_one_xive(int cpu)
2350{
2351 unsigned int hwid = get_hard_smp_processor_id(cpu);
2352
2353 opal_xive_dump(XIVE_DUMP_TM_HYP, hwid);
2354 opal_xive_dump(XIVE_DUMP_TM_POOL, hwid);
2355 opal_xive_dump(XIVE_DUMP_TM_OS, hwid);
2356 opal_xive_dump(XIVE_DUMP_TM_USER, hwid);
2357 opal_xive_dump(XIVE_DUMP_VP, hwid);
2358 opal_xive_dump(XIVE_DUMP_EMU_STATE, hwid);
2359
2360 if (setjmp(bus_error_jmp) != 0) {
2361 catch_memory_errors = 0;
2362 printf("*** Error dumping xive on cpu %d\n", cpu);
2363 return;
2364 }
2365
2366 catch_memory_errors = 1;
2367 sync();
2368 xmon_xive_do_dump(cpu);
2369 sync();
2370 __delay(200);
2371 catch_memory_errors = 0;
2372}
2373
2374static void dump_all_xives(void)
2375{
2376 int cpu;
2377
2378 if (num_possible_cpus() == 0) {
2379 printf("No possible cpus, use 'dx #' to dump individual cpus\n");
2380 return;
2381 }
2382
2383 for_each_possible_cpu(cpu)
2384 dump_one_xive(cpu);
2385}
2386
2387static void dump_one_xive_irq(u32 num)
2388{
2389 s64 rc;
2390 __be64 vp;
2391 u8 prio;
2392 __be32 lirq;
2393
2394 rc = opal_xive_get_irq_config(num, &vp, &prio, &lirq);
2395 xmon_printf("IRQ 0x%x config: vp=0x%llx prio=%d lirq=0x%x (rc=%lld)\n",
2396 num, be64_to_cpu(vp), prio, be32_to_cpu(lirq), rc);
2397}
2398
2399static void dump_xives(void)
2400{
2401 unsigned long num;
2402 int c;
2403
2404 c = inchar();
2405 if (c == 'a') {
2406 dump_all_xives();
2407 return;
2408 } else if (c == 'i') {
2409 if (scanhex(&num))
2410 dump_one_xive_irq(num);
2411 return;
2412 }
2413
2414 termch = c; /* Put c back, it wasn't 'a' */
2415
2416 if (scanhex(&num))
2417 dump_one_xive(num);
2418 else
2419 dump_one_xive(xmon_owner);
2420}
2421#endif /* CONFIG_PPC_POWERNV */
2422
2341static void dump_by_size(unsigned long addr, long count, int size) 2423static void dump_by_size(unsigned long addr, long count, int size)
2342{ 2424{
2343 unsigned char temp[16]; 2425 unsigned char temp[16];
@@ -2386,6 +2468,14 @@ dump(void)
2386 return; 2468 return;
2387 } 2469 }
2388#endif 2470#endif
2471#ifdef CONFIG_PPC_POWERNV
2472 if (c == 'x') {
2473 xmon_start_pagination();
2474 dump_xives();
2475 xmon_end_pagination();
2476 return;
2477 }
2478#endif
2389 2479
2390 if (c == '\n') 2480 if (c == '\n')
2391 termch = c; 2481 termch = c;