Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb7dcf72 authored by Paul Mackerras's avatar Paul Mackerras
Browse files

Merge remote-tracking branch 'remotes/powerpc/topic/xive' into kvm-ppc-next



This merges in the powerpc topic/xive branch to bring in the code for
the in-kernel XICS interrupt controller emulation to use the new XIVE
(eXternal Interrupt Virtualization Engine) hardware in the POWER9 chip
directly, rather than via a XICS emulation in firmware.

Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parents db4b0dfa 5af50993
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -55,6 +55,14 @@
#define PPC_BITEXTRACT(bits, ppc_bit, dst_bit)			\
	((((bits) >> PPC_BITLSHIFT(ppc_bit)) & 1) << (dst_bit))

#define PPC_BITLSHIFT32(be)	(32 - 1 - (be))
#define PPC_BIT32(bit)		(1UL << PPC_BITLSHIFT32(bit))
#define PPC_BITMASK32(bs, be)	((PPC_BIT32(bs) - PPC_BIT32(be))|PPC_BIT32(bs))

#define PPC_BITLSHIFT8(be)	(8 - 1 - (be))
#define PPC_BIT8(bit)		(1UL << PPC_BITLSHIFT8(bit))
#define PPC_BITMASK8(bs, be)	((PPC_BIT8(bs) - PPC_BIT8(be))|PPC_BIT8(bs))

#include <asm/barrier.h>

/* Macro for generating the ***_bits() functions */
+51 −47
Original line number Diff line number Diff line
@@ -192,24 +192,8 @@ DEF_MMIO_OUT_D(out_le32, 32, stw);

#endif /* __BIG_ENDIAN */

/*
 * Cache inhibitied accessors for use in real mode, you don't want to use these
 * unless you know what you're doing.
 *
 * NB. These use the cpu byte ordering.
 */
DEF_MMIO_OUT_X(out_rm8,   8, stbcix);
DEF_MMIO_OUT_X(out_rm16, 16, sthcix);
DEF_MMIO_OUT_X(out_rm32, 32, stwcix);
DEF_MMIO_IN_X(in_rm8,   8, lbzcix);
DEF_MMIO_IN_X(in_rm16, 16, lhzcix);
DEF_MMIO_IN_X(in_rm32, 32, lwzcix);

#ifdef __powerpc64__

DEF_MMIO_OUT_X(out_rm64, 64, stdcix);
DEF_MMIO_IN_X(in_rm64, 64, ldcix);

#ifdef __BIG_ENDIAN__
DEF_MMIO_OUT_D(out_be64, 64, std);
DEF_MMIO_IN_D(in_be64, 64, ld);
@@ -242,35 +226,6 @@ static inline void out_be64(volatile u64 __iomem *addr, u64 val)
#endif
#endif /* __powerpc64__ */


/*
 * Simple Cache inhibited accessors
 * Unlike the DEF_MMIO_* macros, these don't include any h/w memory
 * barriers, callers need to manage memory barriers on their own.
 * These can only be used in hypervisor real mode.
 */

static inline u32 _lwzcix(unsigned long addr)
{
	u32 ret;

	__asm__ __volatile__("lwzcix %0,0, %1"
			     : "=r" (ret) : "r" (addr) : "memory");
	return ret;
}

static inline void _stbcix(u64 addr, u8 val)
{
	__asm__ __volatile__("stbcix %0,0,%1"
		: : "r" (val), "r" (addr) : "memory");
}

static inline void _stwcix(u64 addr, u32 val)
{
	__asm__ __volatile__("stwcix %0,0,%1"
		: : "r" (val), "r" (addr) : "memory");
}

/*
 * Low level IO stream instructions are defined out of line for now
 */
@@ -417,15 +372,64 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
}

/*
 * Real mode version of the above. stdcix is only supposed to be used
 * in hypervisor real mode as per the architecture spec.
 * Real mode versions of the above. Those instructions are only supposed
 * to be used in hypervisor real mode as per the architecture spec.
 */
static inline void __raw_rm_writeb(u8 val, volatile void __iomem *paddr)
{
	__asm__ __volatile__("stbcix %0,0,%1"
		: : "r" (val), "r" (paddr) : "memory");
}

static inline void __raw_rm_writew(u16 val, volatile void __iomem *paddr)
{
	__asm__ __volatile__("sthcix %0,0,%1"
		: : "r" (val), "r" (paddr) : "memory");
}

static inline void __raw_rm_writel(u32 val, volatile void __iomem *paddr)
{
	__asm__ __volatile__("stwcix %0,0,%1"
		: : "r" (val), "r" (paddr) : "memory");
}

static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr)
{
	__asm__ __volatile__("stdcix %0,0,%1"
		: : "r" (val), "r" (paddr) : "memory");
}

static inline u8 __raw_rm_readb(volatile void __iomem *paddr)
{
	u8 ret;
	__asm__ __volatile__("lbzcix %0,0, %1"
			     : "=r" (ret) : "r" (paddr) : "memory");
	return ret;
}

static inline u16 __raw_rm_readw(volatile void __iomem *paddr)
{
	u16 ret;
	__asm__ __volatile__("lhzcix %0,0, %1"
			     : "=r" (ret) : "r" (paddr) : "memory");
	return ret;
}

static inline u32 __raw_rm_readl(volatile void __iomem *paddr)
{
	u32 ret;
	__asm__ __volatile__("lwzcix %0,0, %1"
			     : "=r" (ret) : "r" (paddr) : "memory");
	return ret;
}

static inline u64 __raw_rm_readq(volatile void __iomem *paddr)
{
	u64 ret;
	__asm__ __volatile__("ldcix %0,0, %1"
			     : "=r" (ret) : "r" (paddr) : "memory");
	return ret;
}
#endif /* __powerpc64__ */

/*
+3 −1
Original line number Diff line number Diff line
@@ -110,7 +110,9 @@ struct kvmppc_host_state {
	u8 ptid;
	struct kvm_vcpu *kvm_vcpu;
	struct kvmppc_vcore *kvm_vcore;
	unsigned long xics_phys;
	void __iomem *xics_phys;
	void __iomem *xive_tima_phys;
	void __iomem *xive_tima_virt;
	u32 saved_xirr;
	u64 dabr;
	u64 host_mmcr[7];	/* MMCR 0,1,A, SIAR, SDAR, MMCR2, SIER */
+27 −1
Original line number Diff line number Diff line
@@ -210,6 +210,12 @@ struct kvmppc_spapr_tce_table {
/* XICS components, defined in book3s_xics.c */
struct kvmppc_xics;
struct kvmppc_icp;
extern struct kvm_device_ops kvm_xics_ops;

/* XIVE components, defined in book3s_xive.c */
struct kvmppc_xive;
struct kvmppc_xive_vcpu;
extern struct kvm_device_ops kvm_xive_ops;

struct kvmppc_passthru_irqmap;

@@ -298,6 +304,7 @@ struct kvm_arch {
#endif
#ifdef CONFIG_KVM_XICS
	struct kvmppc_xics *xics;
	struct kvmppc_xive *xive;
	struct kvmppc_passthru_irqmap *pimap;
#endif
	struct kvmppc_ops *kvm_ops;
@@ -427,7 +434,7 @@ struct kvmppc_passthru_irqmap {

#define KVMPPC_IRQ_DEFAULT	0
#define KVMPPC_IRQ_MPIC		1
#define KVMPPC_IRQ_XICS		2
#define KVMPPC_IRQ_XICS		2 /* Includes a XIVE option */

#define MMIO_HPTE_CACHE_SIZE	4

@@ -454,6 +461,21 @@ struct mmio_hpte_cache {

struct openpic;

/* W0 and W1 of a XIVE thread management context */
union xive_tma_w01 {
	struct {
		u8	nsr;
		u8	cppr;
		u8	ipb;
		u8	lsmfb;
		u8	ack;
		u8	inc;
		u8	age;
		u8	pipr;
	};
	__be64 w01;
};

struct kvm_vcpu_arch {
	ulong host_stack;
	u32 host_pid;
@@ -714,6 +736,10 @@ struct kvm_vcpu_arch {
	struct openpic *mpic;	/* KVM_IRQ_MPIC */
#ifdef CONFIG_KVM_XICS
	struct kvmppc_icp *icp; /* XICS presentation controller */
	struct kvmppc_xive_vcpu *xive_vcpu; /* XIVE virtual CPU data */
	__be32 xive_cam_word;    /* Cooked W2 in proper endian with valid bit */
	u32 xive_pushed;	 /* Is the VP pushed on the physical CPU ? */
	union xive_tma_w01 xive_saved_state; /* W0..1 of XIVE thread state */
#endif

#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+75 −9
Original line number Diff line number Diff line
@@ -240,6 +240,7 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);
extern int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp);
extern int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu);
extern void kvmppc_rtas_tokens_free(struct kvm *kvm);

extern int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server,
				u32 priority);
extern int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server,
@@ -425,7 +426,15 @@ struct openpic;
extern void kvm_cma_reserve(void) __init;
static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
{
	paca[cpu].kvm_hstate.xics_phys = addr;
	paca[cpu].kvm_hstate.xics_phys = (void __iomem *)addr;
}

static inline void kvmppc_set_xive_tima(int cpu,
					unsigned long phys_addr,
					void __iomem *virt_addr)
{
	paca[cpu].kvm_hstate.xive_tima_phys = (void __iomem *)phys_addr;
	paca[cpu].kvm_hstate.xive_tima_virt = virt_addr;
}

static inline u32 kvmppc_get_xics_latch(void)
@@ -458,6 +467,11 @@ static inline void __init kvm_cma_reserve(void)
static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
{}

static inline void kvmppc_set_xive_tima(int cpu,
					unsigned long phys_addr,
					void __iomem *virt_addr)
{}

static inline u32 kvmppc_get_xics_latch(void)
{
	return 0;
@@ -494,8 +508,6 @@ extern void kvmppc_free_host_rm_ops(void);
extern void kvmppc_free_pimap(struct kvm *kvm);
extern int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall);
extern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu);
extern int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu, unsigned long server);
extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args);
extern int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd);
extern u64 kvmppc_xics_get_icp(struct kvm_vcpu *vcpu);
extern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
@@ -510,6 +522,10 @@ extern long kvmppc_deliver_irq_passthru(struct kvm_vcpu *vcpu, __be32 xirr,
					struct kvmppc_irq_map *irq_map,
					struct kvmppc_passthru_irqmap *pimap,
					bool *again);

extern int kvmppc_xics_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
			       int level, bool line_status);

extern int h_ipi_redirect;
#else
static inline struct kvmppc_passthru_irqmap *kvmppc_get_passthru_irqmap(
@@ -523,16 +539,64 @@ static inline int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall)
static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
	{ return 0; }
static inline void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) { }
static inline int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu,
					 unsigned long server)
	{ return -EINVAL; }
static inline int kvm_vm_ioctl_xics_irq(struct kvm *kvm,
					struct kvm_irq_level *args)
	{ return -ENOTTY; }
static inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
	{ return 0; }
#endif

#ifdef CONFIG_KVM_XIVE
/*
 * Below the first "xive" is the "eXternal Interrupt Virtualization Engine"
 * ie. P9 new interrupt controller, while the second "xive" is the legacy
 * "eXternal Interrupt Vector Entry" which is the configuration of an
 * interrupt on the "xics" interrupt controller on P8 and earlier. Those
 * two function consume or produce a legacy "XIVE" state from the
 * new "XIVE" interrupt controller.
 */
extern int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
				u32 priority);
extern int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
				u32 *priority);
extern int kvmppc_xive_int_on(struct kvm *kvm, u32 irq);
extern int kvmppc_xive_int_off(struct kvm *kvm, u32 irq);
extern void kvmppc_xive_init_module(void);
extern void kvmppc_xive_exit_module(void);

extern int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
				    struct kvm_vcpu *vcpu, u32 cpu);
extern void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu);
extern int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
				  struct irq_desc *host_desc);
extern int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
				  struct irq_desc *host_desc);
extern u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu);
extern int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval);

extern int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
			       int level, bool line_status);
#else
static inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
				       u32 priority) { return -1; }
static inline int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
				       u32 *priority) { return -1; }
static inline int kvmppc_xive_int_on(struct kvm *kvm, u32 irq) { return -1; }
static inline int kvmppc_xive_int_off(struct kvm *kvm, u32 irq) { return -1; }
static inline void kvmppc_xive_init_module(void) { }
static inline void kvmppc_xive_exit_module(void) { }

static inline int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
					   struct kvm_vcpu *vcpu, u32 cpu) { return -EBUSY; }
static inline void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu) { }
static inline int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
					 struct irq_desc *host_desc) { return -ENODEV; }
static inline int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
					 struct irq_desc *host_desc) { return -ENODEV; }
static inline u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu) { return 0; }
static inline int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval) { return -ENOENT; }

static inline int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
				      int level, bool line_status) { return -ENODEV; }
#endif /* CONFIG_KVM_XIVE */

/*
 * Prototypes for functions called only from assembler code.
 * Having prototypes reduces sparse errors.
@@ -570,6 +634,8 @@ long kvmppc_h_clear_mod(struct kvm_vcpu *vcpu, unsigned long flags,
long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
                          unsigned long slb_v, unsigned int status, bool data);
unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu);
unsigned long kvmppc_rm_h_xirr_x(struct kvm_vcpu *vcpu);
unsigned long kvmppc_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server);
int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
                    unsigned long mfrr);
int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr);
Loading