All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Andrew Jones <drjones@redhat.com>
Cc: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu,
	qemu-devel@nongnu.org, qemu-arm@nongnu.org, pbonzini@redhat.com,
	andre.przywara@arm.com, peter.maydell@linaro.org,
	marc.zyngier@arm.com, eric.auger@redhat.com,
	christoffer.dall@linaro.org
Subject: Re: [kvm-unit-tests PATCH v5 09/11] arm/arm64: add initial gicv3 support
Date: Fri, 11 Nov 2016 15:35:44 +0000	[thread overview]
Message-ID: <87r36i6ncf.fsf@linaro.org> (raw)
In-Reply-To: <1478798481-25030-10-git-send-email-drjones@redhat.com>


Andrew Jones <drjones@redhat.com> writes:

> Signed-off-by: Andrew Jones <drjones@redhat.com>
>
> ---
> v5: use modern register names [Andre]
> v4:
>  - only take defines from kernel we need now [Andre]
>  - simplify enable by not caring if we reinit the distributor [drew]
> v2:
>  - configure irqs as NS GRP1
> ---
>  lib/arm/asm/arch_gicv3.h   | 42 +++++++++++++++++++++
>  lib/arm/asm/gic-v3.h       | 94 ++++++++++++++++++++++++++++++++++++++++++++++
>  lib/arm/asm/gic.h          |  6 ++-
>  lib/arm/gic.c              | 65 ++++++++++++++++++++++++++++++++
>  lib/arm64/asm/arch_gicv3.h | 44 ++++++++++++++++++++++
>  lib/arm64/asm/gic-v3.h     |  1 +
>  lib/arm64/asm/sysreg.h     | 44 ++++++++++++++++++++++
>  7 files changed, 294 insertions(+), 2 deletions(-)
>  create mode 100644 lib/arm/asm/arch_gicv3.h
>  create mode 100644 lib/arm/asm/gic-v3.h
>  create mode 100644 lib/arm64/asm/arch_gicv3.h
>  create mode 100644 lib/arm64/asm/gic-v3.h
>  create mode 100644 lib/arm64/asm/sysreg.h
>
> diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h
> new file mode 100644
> index 000000000000..81a1e5f6c29c
> --- /dev/null
> +++ b/lib/arm/asm/arch_gicv3.h
> @@ -0,0 +1,42 @@
> +/*
> + * All ripped off from arch/arm/include/asm/arch_gicv3.h
> + *
> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#ifndef _ASMARM_ARCH_GICV3_H_
> +#define _ASMARM_ARCH_GICV3_H_
> +
> +#ifndef __ASSEMBLY__
> +#include <libcflat.h>
> +#include <asm/barrier.h>
> +#include <asm/io.h>
> +
> +#define __stringify xstr
> +
> +#define __ACCESS_CP15(CRn, Op1, CRm, Op2)	p15, Op1, %0, CRn, CRm, Op2
> +
> +#define ICC_PMR				__ACCESS_CP15(c4, 0, c6, 0)
> +#define ICC_IGRPEN1			__ACCESS_CP15(c12, 0, c12, 7)
> +
> +static inline void gicv3_write_pmr(u32 val)
> +{
> +	asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val));
> +}
> +
> +static inline void gicv3_write_grpen1(u32 val)
> +{
> +	asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val));
> +	isb();
> +}
> +
> +static inline u64 gicv3_read_typer(const volatile void __iomem *addr)
> +{
> +	u64 val = readl(addr);
> +	val |= (u64)readl(addr + 4) << 32;

I'd be tempted to wrap the cast in additional parentheses for clarity:

  val |= ((u64)readl(addr + 4)) << 32;

> +	return val;
> +}
> +
> +#endif /* !__ASSEMBLY__ */
> +#endif /* _ASMARM_ARCH_GICV3_H_ */
> diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h
> new file mode 100644
> index 000000000000..e0f303d82508
> --- /dev/null
> +++ b/lib/arm/asm/gic-v3.h
> @@ -0,0 +1,94 @@
> +/*
> + * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h
> + *
> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#ifndef _ASMARM_GIC_V3_H_
> +#define _ASMARM_GIC_V3_H_
> +
> +#ifndef _ASMARM_GIC_H_
> +#error Do not directly include <asm/gic-v3.h>. Include <asm/gic.h>
> +#endif
> +
> +#define GICD_CTLR_RWP			(1U << 31)
> +#define GICD_CTLR_ARE_NS		(1U << 4)
> +#define GICD_CTLR_ENABLE_G1A		(1U << 1)
> +#define GICD_CTLR_ENABLE_G1		(1U << 0)

I got confused when looking at the data sheet until I noticed Secure and
Non-secure worlds have subtly different bit positions. It might be worth
making that clear in a comment.

> +
> +/* Re-Distributor registers, offsets from RD_base */
> +#define GICR_TYPER			0x0008
> +
> +#define GICR_TYPER_LAST			(1U << 4)
> +
> +/* Re-Distributor registers, offsets from SGI_base */
> +#define GICR_IGROUPR0			GICD_IGROUPR
> +#define GICR_ISENABLER0			GICD_ISENABLER
> +#define GICR_IPRIORITYR0		GICD_IPRIORITYR
> +
> +#include <asm/arch_gicv3.h>
> +
> +#ifndef __ASSEMBLY__
> +#include <asm/setup.h>
> +#include <asm/smp.h>
> +#include <asm/processor.h>
> +#include <asm/io.h>
> +
> +struct gicv3_data {
> +	void *dist_base;
> +	void *redist_base[NR_CPUS];
> +	unsigned int irq_nr;
> +};
> +extern struct gicv3_data gicv3_data;
> +
> +#define gicv3_dist_base()		(gicv3_data.dist_base)
> +#define gicv3_redist_base()		(gicv3_data.redist_base[smp_processor_id()])
> +#define gicv3_sgi_base()		(gicv3_data.redist_base[smp_processor_id()] + SZ_64K)
> +
> +extern int gicv3_init(void);
> +extern void gicv3_enable_defaults(void);
> +extern void gicv3_set_redist_base(void);
> +
> +static inline void gicv3_do_wait_for_rwp(void *base)
> +{
> +	int count = 100000;	/* 1s */
> +
> +	while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) {
> +		if (!--count) {
> +			printf("GICv3: RWP timeout!\n");
> +			abort();
> +		}
> +		cpu_relax();
> +		udelay(10);
> +	};
> +}
> +
> +static inline void gicv3_dist_wait_for_rwp(void)
> +{
> +	gicv3_do_wait_for_rwp(gicv3_dist_base());
> +}
> +
> +static inline void gicv3_redist_wait_for_rwp(void)
> +{
> +	gicv3_do_wait_for_rwp(gicv3_redist_base());
> +}
> +
> +static inline u32 mpidr_compress(u64 mpidr)
> +{
> +	u64 compressed = mpidr & MPIDR_HWID_BITMASK;
> +
> +	compressed = (((compressed >> 32) & 0xff) << 24) | compressed;
> +	return compressed;
> +}
> +
> +static inline u64 mpidr_uncompress(u32 compressed)
> +{
> +	u64 mpidr = ((u64)compressed >> 24) << 32;
> +
> +	mpidr |= compressed & MPIDR_HWID_BITMASK;
> +	return mpidr;
> +}
> +
> +#endif /* !__ASSEMBLY__ */
> +#endif /* _ASMARM_GIC_V3_H_ */
> diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
> index a16645708c35..981518620d18 100644
> --- a/lib/arm/asm/gic.h
> +++ b/lib/arm/asm/gic.h
> @@ -6,10 +6,9 @@
>  #ifndef _ASMARM_GIC_H_
>  #define _ASMARM_GIC_H_
>
> -#include <asm/gic-v2.h>
> -
>  #define GICD_CTLR			0x0000
>  #define GICD_TYPER			0x0004
> +#define GICD_IGROUPR			0x0080
>  #define GICD_ISENABLER			0x0100
>  #define GICD_IPRIORITYR			0x0400
>  #define GICD_SGIR			0x0f00
> @@ -26,6 +25,9 @@
>  #define GICC_INT_PRI_THRESHOLD		0xf0
>  #define GICC_INT_SPURIOUS		0x3ff
>
> +#include <asm/gic-v2.h>
> +#include <asm/gic-v3.h>
> +
>  #ifndef __ASSEMBLY__
>
>  /*
> diff --git a/lib/arm/gic.c b/lib/arm/gic.c
> index d655105e058b..d929d3f0fa05 100644
> --- a/lib/arm/gic.c
> +++ b/lib/arm/gic.c
> @@ -8,9 +8,11 @@
>  #include <asm/io.h>
>
>  struct gicv2_data gicv2_data;
> +struct gicv3_data gicv3_data;
>
>  /*
>   * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
> + * Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
>   */
>  static bool
>  gic_get_dt_bases(const char *compatible, void **base1, void **base2)
> @@ -48,10 +50,18 @@ int gicv2_init(void)
>  			&gicv2_data.dist_base, &gicv2_data.cpu_base);
>  }
>
> +int gicv3_init(void)
> +{
> +	return gic_get_dt_bases("arm,gic-v3", &gicv3_data.dist_base,
> +			&gicv3_data.redist_base[0]);
> +}
> +
>  int gic_init(void)
>  {
>  	if (gicv2_init())
>  		return 2;
> +	else if (gicv3_init())
> +		return 3;
>  	return 0;
>  }
>
> @@ -74,3 +84,58 @@ void gicv2_enable_defaults(void)
>  	writel(GICC_INT_PRI_THRESHOLD, cpu_base + GICC_PMR);
>  	writel(GICC_ENABLE, cpu_base + GICC_CTLR);
>  }
> +
> +void gicv3_set_redist_base(void)
> +{
> +	u32 aff = mpidr_compress(get_mpidr());
> +	void *ptr = gicv3_data.redist_base[0];
> +	u64 typer;
> +
> +	do {
> +		typer = gicv3_read_typer(ptr + GICR_TYPER);
> +		if ((typer >> 32) == aff) {
> +			gicv3_redist_base() = ptr;
> +			return;
> +		}
> +		ptr += SZ_64K * 2; /* skip RD_base and SGI_base */
> +	} while (!(typer & GICR_TYPER_LAST));
> +	assert(0);

Maybe:

  /* should never reach here */
  assert(false);

> +}
> +
> +void gicv3_enable_defaults(void)
> +{
> +	void *dist = gicv3_dist_base();
> +	void *sgi_base;
> +	unsigned int i;
> +
> +	gicv3_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER));
> +	if (gicv3_data.irq_nr > 1020)
> +		gicv3_data.irq_nr = 1020;
> +
> +	writel(0, dist + GICD_CTLR);
> +	gicv3_dist_wait_for_rwp();
> +
> +	writel(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
> +	       dist + GICD_CTLR);
> +	gicv3_dist_wait_for_rwp();
> +
> +	for (i = 0; i < gicv3_data.irq_nr; i += 4)
> +		writel(~0, dist + GICD_IGROUPR + i);
> +	gicv3_dist_wait_for_rwp();
> +
> +	if (!gicv3_redist_base())
> +		gicv3_set_redist_base();
> +	sgi_base = gicv3_sgi_base();
> +
> +	writel(~0, sgi_base + GICR_IGROUPR0);
> +
> +	for (i = 0; i < 16; i += 4)
> +		writel(GICD_INT_DEF_PRI_X4, sgi_base + GICR_IPRIORITYR0 + i);
> +
> +	writel(GICD_INT_EN_SET_SGI, sgi_base + GICR_ISENABLER0);
> +
> +	gicv3_redist_wait_for_rwp();
> +
> +	gicv3_write_pmr(GICC_INT_PRI_THRESHOLD);
> +	gicv3_write_grpen1(1);
> +}
> diff --git a/lib/arm64/asm/arch_gicv3.h b/lib/arm64/asm/arch_gicv3.h
> new file mode 100644
> index 000000000000..6d353567f56a
> --- /dev/null
> +++ b/lib/arm64/asm/arch_gicv3.h
> @@ -0,0 +1,44 @@
> +/*
> + * All ripped off from arch/arm64/include/asm/arch_gicv3.h
> + *
> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#ifndef _ASMARM64_ARCH_GICV3_H_
> +#define _ASMARM64_ARCH_GICV3_H_
> +
> +#include <asm/sysreg.h>
> +
> +#define ICC_PMR_EL1			sys_reg(3, 0, 4, 6, 0)
> +#define ICC_GRPEN1_EL1			sys_reg(3, 0, 12, 12, 7)
> +
> +#ifndef __ASSEMBLY__
> +
> +#include <libcflat.h>
> +#include <asm/barrier.h>
> +
> +#define __stringify xstr
> +
> +/*
> + * Low-level accessors
> + *
> + * These system registers are 32 bits, but we make sure that the compiler
> + * sets the GP register's most significant bits to 0 with an explicit cast.
> + */
> +
> +static inline void gicv3_write_pmr(u32 val)
> +{
> +	asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" ((u64)val));
> +}
> +
> +static inline void gicv3_write_grpen1(u32 val)
> +{
> +	asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val));
> +	isb();
> +}
> +
> +#define gicv3_read_typer(c)		readq(c)
> +
> +#endif /* __ASSEMBLY__ */
> +#endif /* _ASMARM64_ARCH_GICV3_H_ */
> diff --git a/lib/arm64/asm/gic-v3.h b/lib/arm64/asm/gic-v3.h
> new file mode 100644
> index 000000000000..8ee5d4d9c181
> --- /dev/null
> +++ b/lib/arm64/asm/gic-v3.h
> @@ -0,0 +1 @@
> +#include "../../arm/asm/gic-v3.h"
> diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
> new file mode 100644
> index 000000000000..544a46cb8cc5
> --- /dev/null
> +++ b/lib/arm64/asm/sysreg.h
> @@ -0,0 +1,44 @@
> +/*
> + * Ripped off from arch/arm64/include/asm/sysreg.h
> + *
> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#ifndef _ASMARM64_SYSREG_H_
> +#define _ASMARM64_SYSREG_H_
> +
> +#define sys_reg(op0, op1, crn, crm, op2) \
> +	((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))
> +
> +#ifdef __ASSEMBLY__
> +	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
> +	.equ	.L__reg_num_x\num, \num
> +	.endr
> +	.equ	.L__reg_num_xzr, 31
> +
> +	.macro	mrs_s, rt, sreg
> +	.inst	0xd5200000|(\sreg)|(.L__reg_num_\rt)
> +	.endm
> +
> +	.macro	msr_s, sreg, rt
> +	.inst	0xd5000000|(\sreg)|(.L__reg_num_\rt)
> +	.endm
> +#else
> +asm(
> +"	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n"
> +"	.equ	.L__reg_num_x\\num, \\num\n"
> +"	.endr\n"
> +"	.equ	.L__reg_num_xzr, 31\n"
> +"\n"
> +"	.macro	mrs_s, rt, sreg\n"
> +"	.inst	0xd5200000|(\\sreg)|(.L__reg_num_\\rt)\n"
> +"	.endm\n"
> +"\n"
> +"	.macro	msr_s, sreg, rt\n"
> +"	.inst	0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n"
> +"	.endm\n"
> +);
> +#endif
> +
> +#endif /* _ASMARM64_SYSREG_H_ */

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

--
Alex Bennée

WARNING: multiple messages have this Message-ID (diff)
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Andrew Jones <drjones@redhat.com>
Cc: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu,
	qemu-devel@nongnu.org, qemu-arm@nongnu.org, pbonzini@redhat.com,
	andre.przywara@arm.com, peter.maydell@linaro.org,
	marc.zyngier@arm.com, eric.auger@redhat.com,
	christoffer.dall@linaro.org
Subject: Re: [Qemu-devel] [kvm-unit-tests PATCH v5 09/11] arm/arm64: add initial gicv3 support
Date: Fri, 11 Nov 2016 15:35:44 +0000	[thread overview]
Message-ID: <87r36i6ncf.fsf@linaro.org> (raw)
In-Reply-To: <1478798481-25030-10-git-send-email-drjones@redhat.com>


Andrew Jones <drjones@redhat.com> writes:

> Signed-off-by: Andrew Jones <drjones@redhat.com>
>
> ---
> v5: use modern register names [Andre]
> v4:
>  - only take defines from kernel we need now [Andre]
>  - simplify enable by not caring if we reinit the distributor [drew]
> v2:
>  - configure irqs as NS GRP1
> ---
>  lib/arm/asm/arch_gicv3.h   | 42 +++++++++++++++++++++
>  lib/arm/asm/gic-v3.h       | 94 ++++++++++++++++++++++++++++++++++++++++++++++
>  lib/arm/asm/gic.h          |  6 ++-
>  lib/arm/gic.c              | 65 ++++++++++++++++++++++++++++++++
>  lib/arm64/asm/arch_gicv3.h | 44 ++++++++++++++++++++++
>  lib/arm64/asm/gic-v3.h     |  1 +
>  lib/arm64/asm/sysreg.h     | 44 ++++++++++++++++++++++
>  7 files changed, 294 insertions(+), 2 deletions(-)
>  create mode 100644 lib/arm/asm/arch_gicv3.h
>  create mode 100644 lib/arm/asm/gic-v3.h
>  create mode 100644 lib/arm64/asm/arch_gicv3.h
>  create mode 100644 lib/arm64/asm/gic-v3.h
>  create mode 100644 lib/arm64/asm/sysreg.h
>
> diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h
> new file mode 100644
> index 000000000000..81a1e5f6c29c
> --- /dev/null
> +++ b/lib/arm/asm/arch_gicv3.h
> @@ -0,0 +1,42 @@
> +/*
> + * All ripped off from arch/arm/include/asm/arch_gicv3.h
> + *
> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#ifndef _ASMARM_ARCH_GICV3_H_
> +#define _ASMARM_ARCH_GICV3_H_
> +
> +#ifndef __ASSEMBLY__
> +#include <libcflat.h>
> +#include <asm/barrier.h>
> +#include <asm/io.h>
> +
> +#define __stringify xstr
> +
> +#define __ACCESS_CP15(CRn, Op1, CRm, Op2)	p15, Op1, %0, CRn, CRm, Op2
> +
> +#define ICC_PMR				__ACCESS_CP15(c4, 0, c6, 0)
> +#define ICC_IGRPEN1			__ACCESS_CP15(c12, 0, c12, 7)
> +
> +static inline void gicv3_write_pmr(u32 val)
> +{
> +	asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val));
> +}
> +
> +static inline void gicv3_write_grpen1(u32 val)
> +{
> +	asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val));
> +	isb();
> +}
> +
> +static inline u64 gicv3_read_typer(const volatile void __iomem *addr)
> +{
> +	u64 val = readl(addr);
> +	val |= (u64)readl(addr + 4) << 32;

I'd be tempted to wrap the cast in additional parentheses for clarity:

  val |= ((u64)readl(addr + 4)) << 32;

> +	return val;
> +}
> +
> +#endif /* !__ASSEMBLY__ */
> +#endif /* _ASMARM_ARCH_GICV3_H_ */
> diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h
> new file mode 100644
> index 000000000000..e0f303d82508
> --- /dev/null
> +++ b/lib/arm/asm/gic-v3.h
> @@ -0,0 +1,94 @@
> +/*
> + * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h
> + *
> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#ifndef _ASMARM_GIC_V3_H_
> +#define _ASMARM_GIC_V3_H_
> +
> +#ifndef _ASMARM_GIC_H_
> +#error Do not directly include <asm/gic-v3.h>. Include <asm/gic.h>
> +#endif
> +
> +#define GICD_CTLR_RWP			(1U << 31)
> +#define GICD_CTLR_ARE_NS		(1U << 4)
> +#define GICD_CTLR_ENABLE_G1A		(1U << 1)
> +#define GICD_CTLR_ENABLE_G1		(1U << 0)

I got confused when looking at the data sheet until I noticed Secure and
Non-secure worlds have subtly different bit positions. It might be worth
making that clear in a comment.

> +
> +/* Re-Distributor registers, offsets from RD_base */
> +#define GICR_TYPER			0x0008
> +
> +#define GICR_TYPER_LAST			(1U << 4)
> +
> +/* Re-Distributor registers, offsets from SGI_base */
> +#define GICR_IGROUPR0			GICD_IGROUPR
> +#define GICR_ISENABLER0			GICD_ISENABLER
> +#define GICR_IPRIORITYR0		GICD_IPRIORITYR
> +
> +#include <asm/arch_gicv3.h>
> +
> +#ifndef __ASSEMBLY__
> +#include <asm/setup.h>
> +#include <asm/smp.h>
> +#include <asm/processor.h>
> +#include <asm/io.h>
> +
> +struct gicv3_data {
> +	void *dist_base;
> +	void *redist_base[NR_CPUS];
> +	unsigned int irq_nr;
> +};
> +extern struct gicv3_data gicv3_data;
> +
> +#define gicv3_dist_base()		(gicv3_data.dist_base)
> +#define gicv3_redist_base()		(gicv3_data.redist_base[smp_processor_id()])
> +#define gicv3_sgi_base()		(gicv3_data.redist_base[smp_processor_id()] + SZ_64K)
> +
> +extern int gicv3_init(void);
> +extern void gicv3_enable_defaults(void);
> +extern void gicv3_set_redist_base(void);
> +
> +static inline void gicv3_do_wait_for_rwp(void *base)
> +{
> +	int count = 100000;	/* 1s */
> +
> +	while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) {
> +		if (!--count) {
> +			printf("GICv3: RWP timeout!\n");
> +			abort();
> +		}
> +		cpu_relax();
> +		udelay(10);
> +	};
> +}
> +
> +static inline void gicv3_dist_wait_for_rwp(void)
> +{
> +	gicv3_do_wait_for_rwp(gicv3_dist_base());
> +}
> +
> +static inline void gicv3_redist_wait_for_rwp(void)
> +{
> +	gicv3_do_wait_for_rwp(gicv3_redist_base());
> +}
> +
> +static inline u32 mpidr_compress(u64 mpidr)
> +{
> +	u64 compressed = mpidr & MPIDR_HWID_BITMASK;
> +
> +	compressed = (((compressed >> 32) & 0xff) << 24) | compressed;
> +	return compressed;
> +}
> +
> +static inline u64 mpidr_uncompress(u32 compressed)
> +{
> +	u64 mpidr = ((u64)compressed >> 24) << 32;
> +
> +	mpidr |= compressed & MPIDR_HWID_BITMASK;
> +	return mpidr;
> +}
> +
> +#endif /* !__ASSEMBLY__ */
> +#endif /* _ASMARM_GIC_V3_H_ */
> diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
> index a16645708c35..981518620d18 100644
> --- a/lib/arm/asm/gic.h
> +++ b/lib/arm/asm/gic.h
> @@ -6,10 +6,9 @@
>  #ifndef _ASMARM_GIC_H_
>  #define _ASMARM_GIC_H_
>
> -#include <asm/gic-v2.h>
> -
>  #define GICD_CTLR			0x0000
>  #define GICD_TYPER			0x0004
> +#define GICD_IGROUPR			0x0080
>  #define GICD_ISENABLER			0x0100
>  #define GICD_IPRIORITYR			0x0400
>  #define GICD_SGIR			0x0f00
> @@ -26,6 +25,9 @@
>  #define GICC_INT_PRI_THRESHOLD		0xf0
>  #define GICC_INT_SPURIOUS		0x3ff
>
> +#include <asm/gic-v2.h>
> +#include <asm/gic-v3.h>
> +
>  #ifndef __ASSEMBLY__
>
>  /*
> diff --git a/lib/arm/gic.c b/lib/arm/gic.c
> index d655105e058b..d929d3f0fa05 100644
> --- a/lib/arm/gic.c
> +++ b/lib/arm/gic.c
> @@ -8,9 +8,11 @@
>  #include <asm/io.h>
>
>  struct gicv2_data gicv2_data;
> +struct gicv3_data gicv3_data;
>
>  /*
>   * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
> + * Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
>   */
>  static bool
>  gic_get_dt_bases(const char *compatible, void **base1, void **base2)
> @@ -48,10 +50,18 @@ int gicv2_init(void)
>  			&gicv2_data.dist_base, &gicv2_data.cpu_base);
>  }
>
> +int gicv3_init(void)
> +{
> +	return gic_get_dt_bases("arm,gic-v3", &gicv3_data.dist_base,
> +			&gicv3_data.redist_base[0]);
> +}
> +
>  int gic_init(void)
>  {
>  	if (gicv2_init())
>  		return 2;
> +	else if (gicv3_init())
> +		return 3;
>  	return 0;
>  }
>
> @@ -74,3 +84,58 @@ void gicv2_enable_defaults(void)
>  	writel(GICC_INT_PRI_THRESHOLD, cpu_base + GICC_PMR);
>  	writel(GICC_ENABLE, cpu_base + GICC_CTLR);
>  }
> +
> +void gicv3_set_redist_base(void)
> +{
> +	u32 aff = mpidr_compress(get_mpidr());
> +	void *ptr = gicv3_data.redist_base[0];
> +	u64 typer;
> +
> +	do {
> +		typer = gicv3_read_typer(ptr + GICR_TYPER);
> +		if ((typer >> 32) == aff) {
> +			gicv3_redist_base() = ptr;
> +			return;
> +		}
> +		ptr += SZ_64K * 2; /* skip RD_base and SGI_base */
> +	} while (!(typer & GICR_TYPER_LAST));
> +	assert(0);

Maybe:

  /* should never reach here */
  assert(false);

> +}
> +
> +void gicv3_enable_defaults(void)
> +{
> +	void *dist = gicv3_dist_base();
> +	void *sgi_base;
> +	unsigned int i;
> +
> +	gicv3_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER));
> +	if (gicv3_data.irq_nr > 1020)
> +		gicv3_data.irq_nr = 1020;
> +
> +	writel(0, dist + GICD_CTLR);
> +	gicv3_dist_wait_for_rwp();
> +
> +	writel(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
> +	       dist + GICD_CTLR);
> +	gicv3_dist_wait_for_rwp();
> +
> +	for (i = 0; i < gicv3_data.irq_nr; i += 4)
> +		writel(~0, dist + GICD_IGROUPR + i);
> +	gicv3_dist_wait_for_rwp();
> +
> +	if (!gicv3_redist_base())
> +		gicv3_set_redist_base();
> +	sgi_base = gicv3_sgi_base();
> +
> +	writel(~0, sgi_base + GICR_IGROUPR0);
> +
> +	for (i = 0; i < 16; i += 4)
> +		writel(GICD_INT_DEF_PRI_X4, sgi_base + GICR_IPRIORITYR0 + i);
> +
> +	writel(GICD_INT_EN_SET_SGI, sgi_base + GICR_ISENABLER0);
> +
> +	gicv3_redist_wait_for_rwp();
> +
> +	gicv3_write_pmr(GICC_INT_PRI_THRESHOLD);
> +	gicv3_write_grpen1(1);
> +}
> diff --git a/lib/arm64/asm/arch_gicv3.h b/lib/arm64/asm/arch_gicv3.h
> new file mode 100644
> index 000000000000..6d353567f56a
> --- /dev/null
> +++ b/lib/arm64/asm/arch_gicv3.h
> @@ -0,0 +1,44 @@
> +/*
> + * All ripped off from arch/arm64/include/asm/arch_gicv3.h
> + *
> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#ifndef _ASMARM64_ARCH_GICV3_H_
> +#define _ASMARM64_ARCH_GICV3_H_
> +
> +#include <asm/sysreg.h>
> +
> +#define ICC_PMR_EL1			sys_reg(3, 0, 4, 6, 0)
> +#define ICC_GRPEN1_EL1			sys_reg(3, 0, 12, 12, 7)
> +
> +#ifndef __ASSEMBLY__
> +
> +#include <libcflat.h>
> +#include <asm/barrier.h>
> +
> +#define __stringify xstr
> +
> +/*
> + * Low-level accessors
> + *
> + * These system registers are 32 bits, but we make sure that the compiler
> + * sets the GP register's most significant bits to 0 with an explicit cast.
> + */
> +
> +static inline void gicv3_write_pmr(u32 val)
> +{
> +	asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" ((u64)val));
> +}
> +
> +static inline void gicv3_write_grpen1(u32 val)
> +{
> +	asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val));
> +	isb();
> +}
> +
> +#define gicv3_read_typer(c)		readq(c)
> +
> +#endif /* __ASSEMBLY__ */
> +#endif /* _ASMARM64_ARCH_GICV3_H_ */
> diff --git a/lib/arm64/asm/gic-v3.h b/lib/arm64/asm/gic-v3.h
> new file mode 100644
> index 000000000000..8ee5d4d9c181
> --- /dev/null
> +++ b/lib/arm64/asm/gic-v3.h
> @@ -0,0 +1 @@
> +#include "../../arm/asm/gic-v3.h"
> diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
> new file mode 100644
> index 000000000000..544a46cb8cc5
> --- /dev/null
> +++ b/lib/arm64/asm/sysreg.h
> @@ -0,0 +1,44 @@
> +/*
> + * Ripped off from arch/arm64/include/asm/sysreg.h
> + *
> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#ifndef _ASMARM64_SYSREG_H_
> +#define _ASMARM64_SYSREG_H_
> +
> +#define sys_reg(op0, op1, crn, crm, op2) \
> +	((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))
> +
> +#ifdef __ASSEMBLY__
> +	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
> +	.equ	.L__reg_num_x\num, \num
> +	.endr
> +	.equ	.L__reg_num_xzr, 31
> +
> +	.macro	mrs_s, rt, sreg
> +	.inst	0xd5200000|(\sreg)|(.L__reg_num_\rt)
> +	.endm
> +
> +	.macro	msr_s, sreg, rt
> +	.inst	0xd5000000|(\sreg)|(.L__reg_num_\rt)
> +	.endm
> +#else
> +asm(
> +"	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n"
> +"	.equ	.L__reg_num_x\\num, \\num\n"
> +"	.endr\n"
> +"	.equ	.L__reg_num_xzr, 31\n"
> +"\n"
> +"	.macro	mrs_s, rt, sreg\n"
> +"	.inst	0xd5200000|(\\sreg)|(.L__reg_num_\\rt)\n"
> +"	.endm\n"
> +"\n"
> +"	.macro	msr_s, sreg, rt\n"
> +"	.inst	0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n"
> +"	.endm\n"
> +);
> +#endif
> +
> +#endif /* _ASMARM64_SYSREG_H_ */

Otherwise:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

--
Alex Bennée

  reply	other threads:[~2016-11-11 15:35 UTC|newest]

Thread overview: 78+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-10 17:21 [kvm-unit-tests PATCH v5 00/11] arm/arm64: add gic framework Andrew Jones
2016-11-10 17:21 ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21 ` Andrew Jones
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 01/11] lib: xstr: allow multiple args Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21   ` Andrew Jones
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 02/11] arm64: fix get_"sysreg32" and make MPIDR 64bit Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 03/11] arm/arm64: smp: support more than 8 cpus Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21   ` Andrew Jones
2016-11-11 15:27   ` Andre Przywara
2016-11-11 15:27     ` [Qemu-devel] " Andre Przywara
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 04/11] arm/arm64: add some delay routines Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 05/11] arm/arm64: irq enable/disable Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21   ` Andrew Jones
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 06/11] arm/arm64: add initial gicv2 support Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-11 14:52   ` Alex Bennée
2016-11-11 14:52     ` [Qemu-devel] " Alex Bennée
2016-11-11 14:52     ` Alex Bennée
2016-11-11 15:17     ` Andre Przywara
2016-11-11 15:17       ` [Qemu-devel] " Andre Przywara
2016-11-11 15:30       ` Andrew Jones
2016-11-11 15:24     ` Andrew Jones
2016-11-11 15:34   ` Andre Przywara
2016-11-11 15:34     ` [Qemu-devel] " Andre Przywara
2016-11-11 15:34     ` Andre Przywara
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 07/11] arm/arm64: gicv2: add an IPI test Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21   ` Andrew Jones
2016-11-11 11:13   ` Andre Przywara
2016-11-11 11:13     ` [Qemu-devel] " Andre Przywara
2016-11-11 11:13     ` Andre Przywara
2016-11-11 13:13     ` [Qemu-devel] " Andrew Jones
2016-11-11 13:13       ` Andrew Jones
2016-11-14 14:12       ` Andrew Jones
2016-11-14 14:12         ` Andrew Jones
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 08/11] libcflat: add IS_ALIGNED() macro, and page sizes Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-11 15:02   ` Alex Bennée
2016-11-11 15:02     ` [Qemu-devel] " Alex Bennée
2016-11-11 15:35     ` Andrew Jones
2016-11-11 15:35       ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 09/11] arm/arm64: add initial gicv3 support Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21   ` Andrew Jones
2016-11-11 15:35   ` Alex Bennée [this message]
2016-11-11 15:35     ` [Qemu-devel] " Alex Bennée
2016-11-11 16:31   ` Andre Przywara
2016-11-11 16:31     ` [Qemu-devel] " Andre Przywara
2016-11-11 16:31     ` Andre Przywara
2016-11-14 15:17     ` [Qemu-devel] " Andrew Jones
2016-11-14 15:17       ` Andrew Jones
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 10/11] arm/arm64: gicv3: add an IPI test Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones
2016-11-10 17:21   ` Andrew Jones
2016-11-10 19:53   ` Alex Bennée
2016-11-10 19:53     ` [Qemu-devel] " Alex Bennée
2016-11-10 20:37     ` Andrew Jones
2016-11-10 20:37       ` Andrew Jones
2016-11-11 10:02       ` Alex Bennée
2016-11-11 10:02         ` Alex Bennée
2016-11-11 13:54         ` Andrew Jones
2016-11-11 13:54           ` Andrew Jones
2016-11-11 14:53           ` Alex Bennée
2016-11-11 15:20             ` Andre Przywara
2016-11-11 15:20               ` Andre Przywara
2016-11-11  9:21     ` Andre Przywara
2016-11-11  9:21       ` [Qemu-devel] " Andre Przywara
2016-11-11  9:21       ` Andre Przywara
2016-11-11 10:00       ` Alex Bennée
2016-11-11 10:00         ` [Qemu-devel] " Alex Bennée
2016-11-11 10:00         ` Alex Bennée
2016-11-10 17:21 ` [kvm-unit-tests PATCH v5 11/11] arm/arm64: gic: don't just use zero Andrew Jones
2016-11-10 17:21   ` [Qemu-devel] " Andrew Jones

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87r36i6ncf.fsf@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=andre.przywara@arm.com \
    --cc=christoffer.dall@linaro.org \
    --cc=drjones@redhat.com \
    --cc=eric.auger@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=marc.zyngier@arm.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.