Skip to content

Commit eac1e73

Browse files
legoatermpe
authored andcommitted
powerpc/xive: guest exploitation of the XIVE interrupt controller
This is the framework for using XIVE in a PowerVM guest. The support is very similar to the native one in a much simpler form. Each source is associated with an Event State Buffer (ESB). This is a two bit state machine which is used to trigger events. The bits are named "P" (pending) and "Q" (queued) and can be controlled by MMIO. The Guest OS registers event (or notifications) queues on which the HW will post event data for a target to notify. Instead of OPAL calls, a set of Hypervisors call are used to configure the interrupt sources and the event/notification queues of the guest: - H_INT_GET_SOURCE_INFO used to obtain the address of the MMIO page of the Event State Buffer (PQ bits) entry associated with the source. - H_INT_SET_SOURCE_CONFIG assigns a source to a "target". - H_INT_GET_SOURCE_CONFIG determines to which "target" and "priority" is assigned to a source - H_INT_GET_QUEUE_INFO returns the address of the notification management page associated with the specified "target" and "priority". - H_INT_SET_QUEUE_CONFIG sets or resets the event queue for a given "target" and "priority". It is also used to set the notification config associated with the queue, only unconditional notification for the moment. Reset is performed with a queue size of 0 and queueing is disabled in that case. - H_INT_GET_QUEUE_CONFIG returns the queue settings for a given "target" and "priority". - H_INT_RESET resets all of the partition's interrupt exploitation structures to their initial state, losing all configuration set via the hcalls H_INT_SET_SOURCE_CONFIG and H_INT_SET_QUEUE_CONFIG. - H_INT_SYNC issue a synchronisation on a source to make sure sure all notifications have reached their queue. As for XICS, the XIVE interface for the guest is described in the device tree under the "interrupt-controller" node. A couple of new properties are specific to XIVE : - "reg" contains the base address and size of the thread interrupt managnement areas (TIMA), also called rings, for the User level and for the Guest OS level. Only the Guest OS level is taken into account today. - "ibm,xive-eq-sizes" the size of the event queues. One cell per size supported, contains log2 of size, in ascending order. - "ibm,xive-lisn-ranges" the interrupt numbers ranges assigned to the guest. These are allocated using a simple bitmap. and also : - "/ibm,plat-res-int-priorities" contains a list of priorities that the hypervisor has reserved for its own use. Tested with a QEMU XIVE model for pseries and with the Power hypervisor. Signed-off-by: Cédric Le Goater <[email protected]> Acked-by: Benjamin Herrenschmidt <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 994ea2f commit eac1e73

File tree

11 files changed

+698
-8
lines changed

11 files changed

+698
-8
lines changed

arch/powerpc/include/asm/hvcall.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,18 @@
280280
#define H_RESIZE_HPT_COMMIT 0x370
281281
#define H_REGISTER_PROC_TBL 0x37C
282282
#define H_SIGNAL_SYS_RESET 0x380
283-
#define MAX_HCALL_OPCODE H_SIGNAL_SYS_RESET
283+
#define H_INT_GET_SOURCE_INFO 0x3A8
284+
#define H_INT_SET_SOURCE_CONFIG 0x3AC
285+
#define H_INT_GET_SOURCE_CONFIG 0x3B0
286+
#define H_INT_GET_QUEUE_INFO 0x3B4
287+
#define H_INT_SET_QUEUE_CONFIG 0x3B8
288+
#define H_INT_GET_QUEUE_CONFIG 0x3BC
289+
#define H_INT_SET_OS_REPORTING_LINE 0x3C0
290+
#define H_INT_GET_OS_REPORTING_LINE 0x3C4
291+
#define H_INT_ESB 0x3C8
292+
#define H_INT_SYNC 0x3CC
293+
#define H_INT_RESET 0x3D0
294+
#define MAX_HCALL_OPCODE H_INT_RESET
284295

285296
/* H_VIOCTL functions */
286297
#define H_GET_VIOA_DUMP_SIZE 0x01

arch/powerpc/include/asm/xive.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,13 @@ extern bool __xive_enabled;
110110

111111
static inline bool xive_enabled(void) { return __xive_enabled; }
112112

113+
extern bool xive_spapr_init(void);
113114
extern bool xive_native_init(void);
114115
extern void xive_smp_probe(void);
115116
extern int xive_smp_prepare_cpu(unsigned int cpu);
116117
extern void xive_smp_setup_cpu(void);
117118
extern void xive_smp_disable_cpu(void);
119+
extern void xive_teardown_cpu(void);
118120
extern void xive_kexec_teardown_cpu(int secondary);
119121
extern void xive_shutdown(void);
120122
extern void xive_flush_interrupt(void);
@@ -147,6 +149,7 @@ extern int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id)
147149

148150
static inline bool xive_enabled(void) { return false; }
149151

152+
static inline bool xive_spapr_init(void) { return false; }
150153
static inline bool xive_native_init(void) { return false; }
151154
static inline void xive_smp_probe(void) { }
152155
extern inline int xive_smp_prepare_cpu(unsigned int cpu) { return -EINVAL; }

arch/powerpc/platforms/pseries/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ config PPC_PSERIES
77
select PCI
88
select PCI_MSI
99
select PPC_XICS
10+
select PPC_XIVE_SPAPR
1011
select PPC_ICP_NATIVE
1112
select PPC_ICP_HV
1213
select PPC_ICS_RTAS

arch/powerpc/platforms/pseries/hotplug-cpu.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <asm/machdep.h>
3535
#include <asm/vdso_datapage.h>
3636
#include <asm/xics.h>
37+
#include <asm/xive.h>
3738
#include <asm/plpar_wrappers.h>
3839

3940
#include "pseries.h"
@@ -109,7 +110,10 @@ static void pseries_mach_cpu_die(void)
109110

110111
local_irq_disable();
111112
idle_task_exit();
112-
xics_teardown_cpu();
113+
if (xive_enabled())
114+
xive_teardown_cpu();
115+
else
116+
xics_teardown_cpu();
113117

114118
if (get_preferred_offline_state(cpu) == CPU_STATE_INACTIVE) {
115119
set_cpu_current_state(cpu, CPU_STATE_INACTIVE);
@@ -174,7 +178,10 @@ static int pseries_cpu_disable(void)
174178
boot_cpuid = cpumask_any(cpu_online_mask);
175179

176180
/* FIXME: abstract this to not be platform specific later on */
177-
xics_migrate_irqs_away();
181+
if (xive_enabled())
182+
xive_smp_disable_cpu();
183+
else
184+
xics_migrate_irqs_away();
178185
return 0;
179186
}
180187

arch/powerpc/platforms/pseries/kexec.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <asm/firmware.h>
1616
#include <asm/kexec.h>
1717
#include <asm/xics.h>
18+
#include <asm/xive.h>
1819
#include <asm/smp.h>
1920
#include <asm/plpar_wrappers.h>
2021

@@ -51,5 +52,8 @@ void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
5152
}
5253
}
5354

54-
xics_kexec_teardown_cpu(secondary);
55+
if (xive_enabled())
56+
xive_kexec_teardown_cpu(secondary);
57+
else
58+
xics_kexec_teardown_cpu(secondary);
5559
}

arch/powerpc/platforms/pseries/setup.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include <asm/nvram.h>
5858
#include <asm/pmc.h>
5959
#include <asm/xics.h>
60+
#include <asm/xive.h>
6061
#include <asm/ppc-pci.h>
6162
#include <asm/i8259.h>
6263
#include <asm/udbg.h>
@@ -176,8 +177,11 @@ static void __init pseries_setup_i8259_cascade(void)
176177

177178
static void __init pseries_init_irq(void)
178179
{
179-
xics_init();
180-
pseries_setup_i8259_cascade();
180+
/* Try using a XIVE if available, otherwise use a XICS */
181+
if (!xive_spapr_init()) {
182+
xics_init();
183+
pseries_setup_i8259_cascade();
184+
}
181185
}
182186

183187
static void pseries_lpar_enable_pmcs(void)

arch/powerpc/platforms/pseries/smp.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <asm/vdso_datapage.h>
4242
#include <asm/cputhreads.h>
4343
#include <asm/xics.h>
44+
#include <asm/xive.h>
4445
#include <asm/dbell.h>
4546
#include <asm/plpar_wrappers.h>
4647
#include <asm/code-patching.h>
@@ -136,7 +137,9 @@ static inline int smp_startup_cpu(unsigned int lcpu)
136137

137138
static void smp_setup_cpu(int cpu)
138139
{
139-
if (cpu != boot_cpuid)
140+
if (xive_enabled())
141+
xive_smp_setup_cpu();
142+
else if (cpu != boot_cpuid)
140143
xics_setup_cpu();
141144

142145
if (firmware_has_feature(FW_FEATURE_SPLPAR))
@@ -181,6 +184,13 @@ static int smp_pSeries_kick_cpu(int nr)
181184
return 0;
182185
}
183186

187+
static int pseries_smp_prepare_cpu(int cpu)
188+
{
189+
if (xive_enabled())
190+
return xive_smp_prepare_cpu(cpu);
191+
return 0;
192+
}
193+
184194
static void smp_pseries_cause_ipi(int cpu)
185195
{
186196
/* POWER9 should not use this handler */
@@ -211,7 +221,7 @@ static int pseries_cause_nmi_ipi(int cpu)
211221
return 0;
212222
}
213223

214-
static __init void pSeries_smp_probe(void)
224+
static __init void pSeries_smp_probe_xics(void)
215225
{
216226
xics_smp_probe();
217227

@@ -221,11 +231,24 @@ static __init void pSeries_smp_probe(void)
221231
smp_ops->cause_ipi = icp_ops->cause_ipi;
222232
}
223233

234+
static __init void pSeries_smp_probe(void)
235+
{
236+
if (xive_enabled())
237+
/*
238+
* Don't use P9 doorbells when XIVE is enabled. IPIs
239+
* using MMIOs should be faster
240+
*/
241+
xive_smp_probe();
242+
else
243+
pSeries_smp_probe_xics();
244+
}
245+
224246
static struct smp_ops_t pseries_smp_ops = {
225247
.message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
226248
.cause_ipi = NULL, /* Filled at runtime by pSeries_smp_probe() */
227249
.cause_nmi_ipi = pseries_cause_nmi_ipi,
228250
.probe = pSeries_smp_probe,
251+
.prepare_cpu = pseries_smp_prepare_cpu,
229252
.kick_cpu = smp_pSeries_kick_cpu,
230253
.setup_cpu = smp_setup_cpu,
231254
.cpu_bootable = smp_generic_cpu_bootable,

arch/powerpc/sysdev/xive/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,8 @@ config PPC_XIVE_NATIVE
99
default n
1010
select PPC_XIVE
1111
depends on PPC_POWERNV
12+
13+
config PPC_XIVE_SPAPR
14+
bool
15+
default n
16+
select PPC_XIVE

arch/powerpc/sysdev/xive/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
22

33
obj-y += common.o
44
obj-$(CONFIG_PPC_XIVE_NATIVE) += native.o
5+
obj-$(CONFIG_PPC_XIVE_SPAPR) += spapr.o

arch/powerpc/sysdev/xive/common.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,19 @@ void xive_flush_interrupt(void)
13721372

13731373
#endif /* CONFIG_SMP */
13741374

1375+
void xive_teardown_cpu(void)
1376+
{
1377+
struct xive_cpu *xc = __this_cpu_read(xive_cpu);
1378+
unsigned int cpu = smp_processor_id();
1379+
1380+
/* Set CPPR to 0 to disable flow of interrupts */
1381+
xc->cppr = 0;
1382+
out_8(xive_tima + xive_tima_offset + TM_CPPR, 0);
1383+
1384+
if (xive_ops->teardown_cpu)
1385+
xive_ops->teardown_cpu(cpu, xc);
1386+
}
1387+
13751388
void xive_kexec_teardown_cpu(int secondary)
13761389
{
13771390
struct xive_cpu *xc = __this_cpu_read(xive_cpu);

0 commit comments

Comments
 (0)