* [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework
@ 2016-05-16 7:57 Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 01/10] lib: xstr: allow multiple args Andrew Jones
` (10 more replies)
0 siblings, 11 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Import defines, and steal enough helper functions, from Linux to
enable programming of the gic (v2 and v3). Then use the framework
to add an initial test (an ipi test; self, target-list, broadcast).
It's my hope that this framework will be a suitable base on which
more tests may be easily added, particularly because we have
vgic-new and tcg gicv3 emulation getting close to merge.
To run it, along with other tests, just do
./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ]
make
export QEMU=$PATH_TO_QEMU
./run_tests.sh
To run it separately do, e.g.
$QEMU -machine virt,accel=tcg -cpu cortex-a57 \
-device virtio-serial-device \
-device virtconsole,chardev=ctd -chardev testdev,id=ctd \
-display none -serial stdio \
-kernel arm/gic.flat \
-smp 123 -machine gic-version=3 -append ipi
^^ note, we can go nuts with nr-cpus on TCG :-)
Or, a KVM example using a different "sender" cpu and irq (other than zero)
$QEMU -machine virt,accel=kvm -cpu host \
-device virtio-serial-device \
-device virtconsole,chardev=ctd -chardev testdev,id=ctd \
-display none -serial stdio \
-kernel arm/gic.flat \
-smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1'
Patches:
01-05: fixes and functionality needed by the later gic patches
06-07: code theft from Linux (defines, helper functions)
08-10: arm/gic.flat (the base of the gic unit test), currently just IPI
Available here: https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic
Andrew Jones (10):
lib: xstr: allow multiple args
arm64: fix get_"sysreg32" and make MPIDR 64bit
arm/arm64: smp: support more than 8 cpus
arm/arm64: add some delay routines
arm/arm64: irq enable/disable
arm/arm64: add initial gicv2 support
arm64: add initial gicv3 support
arm/arm64: gicv2: add an IPI test
arm/arm64: gicv3: add an IPI test
arm/arm64: gic: don't just use zero
arm/Makefile.common | 7 +-
arm/gic.c | 338 +++++++++++++++++++++++++++++++++++++++++++++
arm/run | 19 ++-
arm/selftest.c | 5 +-
arm/unittests.cfg | 13 ++
lib/arm/asm/arch_gicv3.h | 184 ++++++++++++++++++++++++
lib/arm/asm/gic-v2.h | 74 ++++++++++
lib/arm/asm/gic-v3.h | 320 ++++++++++++++++++++++++++++++++++++++++++
lib/arm/asm/gic.h | 21 +++
lib/arm/asm/processor.h | 38 ++++-
lib/arm/asm/setup.h | 4 +-
lib/arm/gic.c | 127 +++++++++++++++++
lib/arm/processor.c | 15 ++
lib/arm/setup.c | 12 +-
lib/arm64/asm/arch_gicv3.h | 169 +++++++++++++++++++++++
lib/arm64/asm/gic-v2.h | 1 +
lib/arm64/asm/gic-v3.h | 1 +
lib/arm64/asm/gic.h | 1 +
lib/arm64/asm/processor.h | 53 +++++--
lib/arm64/asm/sysreg.h | 44 ++++++
lib/arm64/processor.c | 15 ++
lib/libcflat.h | 4 +-
22 files changed, 1439 insertions(+), 26 deletions(-)
create mode 100644 arm/gic.c
create mode 100644 lib/arm/asm/arch_gicv3.h
create mode 100644 lib/arm/asm/gic-v2.h
create mode 100644 lib/arm/asm/gic-v3.h
create mode 100644 lib/arm/asm/gic.h
create mode 100644 lib/arm/gic.c
create mode 100644 lib/arm64/asm/arch_gicv3.h
create mode 100644 lib/arm64/asm/gic-v2.h
create mode 100644 lib/arm64/asm/gic-v3.h
create mode 100644 lib/arm64/asm/gic.h
create mode 100644 lib/arm64/asm/sysreg.h
--
2.4.11
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 01/10] lib: xstr: allow multiple args
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 02/10] arm64: fix get_"sysreg32" and make MPIDR 64bit Andrew Jones
` (9 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/libcflat.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/libcflat.h b/lib/libcflat.h
index df50615b43666..ba29041b731e2 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -27,8 +27,8 @@
#define __unused __attribute__((__unused__))
-#define xstr(s) xxstr(s)
-#define xxstr(s) #s
+#define xstr(s...) xxstr(s)
+#define xxstr(s...) #s
#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1)
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 02/10] arm64: fix get_"sysreg32" and make MPIDR 64bit
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 01/10] lib: xstr: allow multiple args Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 03/10] arm/arm64: smp: support more than 8 cpus Andrew Jones
` (8 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
mrs is always 64bit, so we should always use a 64bit register.
Sometimes we'll only want to return the lower 32, but not for
MPIDR, as that does define fields in the upper 32.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/arm64/asm/processor.h | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 84d5c7ce752b0..9a208ff729b7e 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -66,14 +66,17 @@ static inline unsigned long current_level(void)
return el & 0xc;
}
-#define DEFINE_GET_SYSREG32(reg) \
-static inline unsigned int get_##reg(void) \
+#define DEFINE_GET_SYSREG(reg, type) \
+static inline type get_##reg(void) \
{ \
- unsigned int reg; \
- asm volatile("mrs %0, " #reg "_el1" : "=r" (reg)); \
- return reg; \
+ unsigned long r; \
+ asm volatile("mrs %0, " #reg "_el1" : "=r" (r)); \
+ return (type)r; \
}
-DEFINE_GET_SYSREG32(mpidr)
+#define DEFINE_GET_SYSREG32(reg) DEFINE_GET_SYSREG(reg, unsigned int)
+#define DEFINE_GET_SYSREG64(reg) DEFINE_GET_SYSREG(reg, unsigned long)
+
+DEFINE_GET_SYSREG64(mpidr)
/* Only support Aff0 for now, gicv2 only */
#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 03/10] arm/arm64: smp: support more than 8 cpus
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 01/10] lib: xstr: allow multiple args Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 02/10] arm64: fix get_"sysreg32" and make MPIDR 64bit Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 04/10] arm/arm64: add some delay routines Andrew Jones
` (7 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
arm/run | 19 ++++++++++++-------
arm/selftest.c | 5 ++++-
lib/arm/asm/processor.h | 9 +++++++--
lib/arm/asm/setup.h | 4 ++--
lib/arm/setup.c | 12 +++++++++++-
lib/arm64/asm/processor.h | 9 +++++++--
6 files changed, 43 insertions(+), 15 deletions(-)
diff --git a/arm/run b/arm/run
index ebf703d5757c7..119bd1eee3651 100755
--- a/arm/run
+++ b/arm/run
@@ -31,13 +31,6 @@ if [ -z "$ACCEL" ]; then
fi
fi
-if [ "$HOST" = "aarch64" ] && [ "$ACCEL" = "kvm" ]; then
- processor="host"
- if [ "$ARCH" = "arm" ]; then
- processor+=",aarch64=off"
- fi
-fi
-
qemu="${QEMU:-qemu-system-$ARCH_NAME}"
qpath=$(which $qemu 2>/dev/null)
@@ -53,6 +46,18 @@ fi
M='-machine virt'
+if [ "$ACCEL" = "kvm" ]; then
+ if $qemu $M,\? 2>&1 | grep gic-version > /dev/null; then
+ M+=',gic-version=host'
+ fi
+ if [ "$HOST" = "aarch64" ]; then
+ processor="host"
+ if [ "$ARCH" = "arm" ]; then
+ processor+=",aarch64=off"
+ fi
+ fi
+fi
+
if ! $qemu $M -device '?' 2>&1 | grep virtconsole > /dev/null; then
echo "$qpath doesn't support virtio-console for chr-testdev. Exiting."
exit 2
diff --git a/arm/selftest.c b/arm/selftest.c
index 75dc91faab69a..6c97900daf532 100644
--- a/arm/selftest.c
+++ b/arm/selftest.c
@@ -313,9 +313,10 @@ static bool psci_check(void)
static cpumask_t smp_reported;
static void cpu_report(void)
{
+ unsigned long mpidr = get_mpidr();
int cpu = smp_processor_id();
- report("CPU%d online", true, cpu);
+ report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == cpu, cpu, mpidr);
cpumask_set_cpu(cpu, &smp_reported);
halt();
}
@@ -344,6 +345,7 @@ int main(int argc, char **argv)
} else if (strcmp(argv[0], "smp") == 0) {
+ unsigned long mpidr = get_mpidr();
int cpu;
report("PSCI version", psci_check());
@@ -354,6 +356,7 @@ int main(int argc, char **argv)
smp_boot_secondary(cpu, cpu_report);
}
+ report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == 0, 0, mpidr);
cpumask_set_cpu(0, &smp_reported);
while (!cpumask_full(&smp_reported))
cpu_relax();
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index f25e7eee3666c..d2048f5f5f7e6 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -40,8 +40,13 @@ static inline unsigned int get_mpidr(void)
return mpidr;
}
-/* Only support Aff0 for now, up to 4 cpus */
-#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
+#define MPIDR_HWID_BITMASK 0xffffff
+extern int mpidr_to_cpu(unsigned long mpidr);
+
+#define MPIDR_LEVEL_SHIFT(level) \
+ (((1 << level) >> 1) << 3)
+#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
+ ((mpidr >> MPIDR_LEVEL_SHIFT(level)) & 0xff)
extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
extern bool is_user(void);
diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
index cb8fdbd38dd5d..c501c6ddd8657 100644
--- a/lib/arm/asm/setup.h
+++ b/lib/arm/asm/setup.h
@@ -10,8 +10,8 @@
#include <asm/page.h>
#include <asm/pgtable-hwdef.h>
-#define NR_CPUS 8
-extern u32 cpus[NR_CPUS];
+#define NR_CPUS 255
+extern u64 cpus[NR_CPUS];
extern int nr_cpus;
#define NR_MEM_REGIONS 8
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
index 8c6172ff94106..1d6b6949c920e 100644
--- a/lib/arm/setup.c
+++ b/lib/arm/setup.c
@@ -24,12 +24,22 @@ extern unsigned long stacktop;
extern void io_init(void);
extern void setup_args(const char *args);
-u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) };
+u64 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) };
int nr_cpus;
struct mem_region mem_regions[NR_MEM_REGIONS];
phys_addr_t __phys_offset, __phys_end;
+int mpidr_to_cpu(unsigned long mpidr)
+{
+ int i;
+
+ for (i = 0; i < nr_cpus; ++i)
+ if (cpus[i] == (mpidr & MPIDR_HWID_BITMASK))
+ return i;
+ return -1;
+}
+
static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused)
{
int cpu = nr_cpus++;
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 9a208ff729b7e..7e448dc81a6aa 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -78,8 +78,13 @@ static inline type get_##reg(void) \
DEFINE_GET_SYSREG64(mpidr)
-/* Only support Aff0 for now, gicv2 only */
-#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
+#define MPIDR_HWID_BITMASK 0xff00ffffff
+extern int mpidr_to_cpu(unsigned long mpidr);
+
+#define MPIDR_LEVEL_SHIFT(level) \
+ (((1 << level) >> 1) << 3)
+#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
+ ((mpidr >> MPIDR_LEVEL_SHIFT(level)) & 0xff)
extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
extern bool is_user(void);
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 04/10] arm/arm64: add some delay routines
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
` (2 preceding siblings ...)
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 03/10] arm/arm64: smp: support more than 8 cpus Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 05/10] arm/arm64: irq enable/disable Andrew Jones
` (6 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Allow a thread to wait some specified amount of time. Can
specify in cycles, usecs, and msecs.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/arm/asm/processor.h | 19 +++++++++++++++++++
lib/arm/processor.c | 15 +++++++++++++++
lib/arm64/asm/processor.h | 19 +++++++++++++++++++
lib/arm64/processor.c | 15 +++++++++++++++
4 files changed, 68 insertions(+)
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index d2048f5f5f7e6..afc903ca7d4ab 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -5,7 +5,9 @@
*
* This work is licensed under the terms of the GNU LGPL, version 2.
*/
+#include <libcflat.h>
#include <asm/ptrace.h>
+#include <asm/barrier.h>
enum vector {
EXCPTN_RST,
@@ -51,4 +53,21 @@ extern int mpidr_to_cpu(unsigned long mpidr);
extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
extern bool is_user(void);
+static inline u64 get_cntvct(void)
+{
+ u64 vct;
+ isb();
+ asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (vct));
+ return vct;
+}
+
+extern void delay(u64 cycles);
+extern void udelay(unsigned long usecs);
+
+static inline void mdelay(unsigned long msecs)
+{
+ while (msecs--)
+ udelay(1000);
+}
+
#endif /* _ASMARM_PROCESSOR_H_ */
diff --git a/lib/arm/processor.c b/lib/arm/processor.c
index 54fdb87ef0196..c2ee360df6884 100644
--- a/lib/arm/processor.c
+++ b/lib/arm/processor.c
@@ -9,6 +9,7 @@
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
+#include <asm/barrier.h>
static const char *processor_modes[] = {
"USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" ,
@@ -141,3 +142,17 @@ bool is_user(void)
{
return current_thread_info()->flags & TIF_USER_MODE;
}
+
+void delay(u64 cycles)
+{
+ u64 start = get_cntvct();
+ while ((get_cntvct() - start) < cycles)
+ cpu_relax();
+}
+
+void udelay(unsigned long usec)
+{
+ unsigned int frq;
+ asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (frq));
+ delay((u64)usec * frq / 1000000);
+}
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 7e448dc81a6aa..94f7ce35b65c1 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -17,8 +17,10 @@
#define SCTLR_EL1_M (1 << 0)
#ifndef __ASSEMBLY__
+#include <libcflat.h>
#include <asm/ptrace.h>
#include <asm/esr.h>
+#include <asm/barrier.h>
enum vector {
EL1T_SYNC,
@@ -89,5 +91,22 @@ extern int mpidr_to_cpu(unsigned long mpidr);
extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
extern bool is_user(void);
+static inline u64 get_cntvct(void)
+{
+ u64 vct;
+ isb();
+ asm volatile("mrs %0, cntvct_el0" : "=r" (vct));
+ return vct;
+}
+
+extern void delay(u64 cycles);
+extern void udelay(unsigned long usecs);
+
+static inline void mdelay(unsigned long msecs)
+{
+ while (msecs--)
+ udelay(1000);
+}
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASMARM64_PROCESSOR_H_ */
diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c
index deeab4ec9c8ac..50fa835c6f1e3 100644
--- a/lib/arm64/processor.c
+++ b/lib/arm64/processor.c
@@ -9,6 +9,7 @@
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
+#include <asm/barrier.h>
static const char *vector_names[] = {
"el1t_sync",
@@ -253,3 +254,17 @@ bool is_user(void)
{
return current_thread_info()->flags & TIF_USER_MODE;
}
+
+void delay(u64 cycles)
+{
+ u64 start = get_cntvct();
+ while ((get_cntvct() - start) < cycles)
+ cpu_relax();
+}
+
+void udelay(unsigned long usec)
+{
+ unsigned int frq;
+ asm volatile("mrs %0, cntfrq_el0" : "=r" (frq));
+ delay((u64)usec * frq / 1000000);
+}
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 05/10] arm/arm64: irq enable/disable
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
` (3 preceding siblings ...)
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 04/10] arm/arm64: add some delay routines Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 06/10] arm/arm64: add initial gicv2 support Andrew Jones
` (5 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/arm/asm/processor.h | 10 ++++++++++
lib/arm64/asm/processor.h | 10 ++++++++++
2 files changed, 20 insertions(+)
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index afc903ca7d4ab..75a8d08b89330 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -35,6 +35,16 @@ static inline unsigned long current_cpsr(void)
#define current_mode() (current_cpsr() & MODE_MASK)
+static inline void local_irq_enable(void)
+{
+ asm volatile("cpsie i" : : : "memory", "cc");
+}
+
+static inline void local_irq_disable(void)
+{
+ asm volatile("cpsid i" : : : "memory", "cc");
+}
+
static inline unsigned int get_mpidr(void)
{
unsigned int mpidr;
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 94f7ce35b65c1..d54a4ed1c1876 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -68,6 +68,16 @@ static inline unsigned long current_level(void)
return el & 0xc;
}
+static inline void local_irq_enable(void)
+{
+ asm volatile("msr daifclr, #2" : : : "memory");
+}
+
+static inline void local_irq_disable(void)
+{
+ asm volatile("msr daifset, #2" : : : "memory");
+}
+
#define DEFINE_GET_SYSREG(reg, type) \
static inline type get_##reg(void) \
{ \
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 06/10] arm/arm64: add initial gicv2 support
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
` (4 preceding siblings ...)
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 05/10] arm/arm64: irq enable/disable Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 07/10] arm64: add initial gicv3 support Andrew Jones
` (4 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Add some gicv2 support. This just adds init and enable
functions, allowing unit tests to start messing with it.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
arm/Makefile.common | 1 +
lib/arm/asm/gic-v2.h | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++
lib/arm/asm/gic.h | 20 ++++++++++++++
lib/arm/gic.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++
lib/arm64/asm/gic-v2.h | 1 +
lib/arm64/asm/gic.h | 1 +
6 files changed, 166 insertions(+)
create mode 100644 lib/arm/asm/gic-v2.h
create mode 100644 lib/arm/asm/gic.h
create mode 100644 lib/arm/gic.c
create mode 100644 lib/arm64/asm/gic-v2.h
create mode 100644 lib/arm64/asm/gic.h
diff --git a/arm/Makefile.common b/arm/Makefile.common
index a786fcf94154f..13a185f7d4473 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -42,6 +42,7 @@ cflatobjs += lib/arm/mmu.o
cflatobjs += lib/arm/bitops.o
cflatobjs += lib/arm/psci.o
cflatobjs += lib/arm/smp.o
+cflatobjs += lib/arm/gic.o
libeabi = lib/arm/libeabi.a
eabiobjs = lib/arm/eabi_compat.o
diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h
new file mode 100644
index 0000000000000..973c2bf3cc796
--- /dev/null
+++ b/lib/arm/asm/gic-v2.h
@@ -0,0 +1,74 @@
+/*
+ * All GIC* defines are lifted from include/linux/irqchip/arm-gic.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_V2_H_
+#define _ASMARM_GIC_V2_H_
+
+#define GIC_CPU_CTRL 0x00
+#define GIC_CPU_PRIMASK 0x04
+#define GIC_CPU_BINPOINT 0x08
+#define GIC_CPU_INTACK 0x0c
+#define GIC_CPU_EOI 0x10
+#define GIC_CPU_RUNNINGPRI 0x14
+#define GIC_CPU_HIGHPRI 0x18
+#define GIC_CPU_ALIAS_BINPOINT 0x1c
+#define GIC_CPU_ACTIVEPRIO 0xd0
+#define GIC_CPU_IDENT 0xfc
+#define GIC_CPU_DEACTIVATE 0x1000
+
+#define GICC_ENABLE 0x1
+#define GICC_INT_PRI_THRESHOLD 0xf0
+
+#define GIC_CPU_CTRL_EOImodeNS (1 << 9)
+
+#define GICC_IAR_INT_ID_MASK 0x3ff
+#define GICC_INT_SPURIOUS 1023
+#define GICC_DIS_BYPASS_MASK 0x1e0
+
+#define GIC_DIST_CTRL 0x000
+#define GIC_DIST_CTR 0x004
+#define GIC_DIST_IGROUP 0x080
+#define GIC_DIST_ENABLE_SET 0x100
+#define GIC_DIST_ENABLE_CLEAR 0x180
+#define GIC_DIST_PENDING_SET 0x200
+#define GIC_DIST_PENDING_CLEAR 0x280
+#define GIC_DIST_ACTIVE_SET 0x300
+#define GIC_DIST_ACTIVE_CLEAR 0x380
+#define GIC_DIST_PRI 0x400
+#define GIC_DIST_TARGET 0x800
+#define GIC_DIST_CONFIG 0xc00
+#define GIC_DIST_SOFTINT 0xf00
+#define GIC_DIST_SGI_PENDING_CLEAR 0xf10
+#define GIC_DIST_SGI_PENDING_SET 0xf20
+
+#define GICD_ENABLE 0x1
+#define GICD_DISABLE 0x0
+#define GICD_INT_ACTLOW_LVLTRIG 0x0
+#define GICD_INT_EN_CLR_X32 0xffffffff
+#define GICD_INT_EN_SET_SGI 0x0000ffff
+#define GICD_INT_EN_CLR_PPI 0xffff0000
+#define GICD_INT_DEF_PRI 0xa0
+#define GICD_INT_DEF_PRI_X4 ((GICD_INT_DEF_PRI << 24) |\
+ (GICD_INT_DEF_PRI << 16) |\
+ (GICD_INT_DEF_PRI << 8) |\
+ GICD_INT_DEF_PRI)
+#ifndef __ASSEMBLY__
+
+struct gicv2_data {
+ void *dist_base;
+ void *cpu_base;
+};
+extern struct gicv2_data gicv2_data;
+
+#define gicv2_dist_base() (gicv2_data.dist_base)
+#define gicv2_cpu_base() (gicv2_data.cpu_base)
+
+extern int gicv2_init(void);
+extern void gicv2_enable_defaults(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_V2_H_ */
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
new file mode 100644
index 0000000000000..b1237d1c5ef22
--- /dev/null
+++ b/lib/arm/asm/gic.h
@@ -0,0 +1,20 @@
+/*
+ * 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_H_
+#define _ASMARM_GIC_H_
+
+#include <asm/gic-v2.h>
+
+/*
+ * gic_init will try to find all known gics, and then
+ * initialize the gic data for the one found.
+ * returns
+ * 0 : no gic was found
+ * > 0 : the gic version of the gic found
+ */
+extern int gic_init(void);
+
+#endif /* _ASMARM_GIC_H_ */
diff --git a/lib/arm/gic.c b/lib/arm/gic.c
new file mode 100644
index 0000000000000..64a3049c9e8ce
--- /dev/null
+++ b/lib/arm/gic.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include <libcflat.h>
+#include <devicetree.h>
+#include <asm/gic.h>
+#include <asm/smp.h>
+#include <asm/io.h>
+
+struct gicv2_data gicv2_data;
+
+/*
+ * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
+ */
+static bool
+gic_get_dt_bases(const char *compatible, void **base1, void **base2)
+{
+ struct dt_pbus_reg reg;
+ struct dt_device gic;
+ struct dt_bus bus;
+ int node, ret;
+
+ dt_bus_init_defaults(&bus);
+ dt_device_init(&gic, &bus, NULL);
+
+ node = dt_device_find_compatible(&gic, compatible);
+ assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
+
+ if (node == -FDT_ERR_NOTFOUND)
+ return false;
+
+ dt_device_bind_node(&gic, node);
+
+ ret = dt_pbus_translate(&gic, 0, ®);
+ assert(ret == 0);
+ *base1 = ioremap(reg.addr, reg.size);
+
+ ret = dt_pbus_translate(&gic, 1, ®);
+ assert(ret == 0);
+ *base2 = ioremap(reg.addr, reg.size);
+
+ return true;
+}
+
+int gicv2_init(void)
+{
+ return gic_get_dt_bases("arm,cortex-a15-gic",
+ &gicv2_data.dist_base, &gicv2_data.cpu_base);
+}
+
+int gic_init(void)
+{
+ if (gicv2_init())
+ return 2;
+ return 0;
+}
+
+void gicv2_enable_defaults(void)
+{
+ if (smp_processor_id() == 0) {
+ writel(GICD_INT_DEF_PRI_X4, gicv2_dist_base() + GIC_DIST_PRI);
+ writel(GICD_INT_EN_SET_SGI, gicv2_dist_base() + GIC_DIST_ENABLE_SET);
+ writel(GICD_ENABLE, gicv2_dist_base() + GIC_DIST_CTRL);
+ }
+ writel(GICC_INT_PRI_THRESHOLD, gicv2_cpu_base() + GIC_CPU_PRIMASK);
+ writel(GICC_ENABLE, gicv2_cpu_base() + GIC_CPU_CTRL);
+}
diff --git a/lib/arm64/asm/gic-v2.h b/lib/arm64/asm/gic-v2.h
new file mode 100644
index 0000000000000..52226624a2092
--- /dev/null
+++ b/lib/arm64/asm/gic-v2.h
@@ -0,0 +1 @@
+#include "../../arm/asm/gic-v2.h"
diff --git a/lib/arm64/asm/gic.h b/lib/arm64/asm/gic.h
new file mode 100644
index 0000000000000..e5eb302a31b4d
--- /dev/null
+++ b/lib/arm64/asm/gic.h
@@ -0,0 +1 @@
+#include "../../arm/asm/gic.h"
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 07/10] arm64: add initial gicv3 support
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
` (5 preceding siblings ...)
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 06/10] arm/arm64: add initial gicv2 support Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 08/10] arm/arm64: gicv2: add an IPI test Andrew Jones
` (3 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/arm/asm/arch_gicv3.h | 184 ++++++++++++++++++++++++++
lib/arm/asm/gic-v3.h | 320 +++++++++++++++++++++++++++++++++++++++++++++
lib/arm/asm/gic.h | 1 +
lib/arm/gic.c | 58 ++++++++
lib/arm64/asm/arch_gicv3.h | 169 ++++++++++++++++++++++++
lib/arm64/asm/gic-v3.h | 1 +
lib/arm64/asm/sysreg.h | 44 +++++++
7 files changed, 777 insertions(+)
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 0000000000000..d529a7eb62807
--- /dev/null
+++ b/lib/arm/asm/arch_gicv3.h
@@ -0,0 +1,184 @@
+/*
+ * 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 __ACCESS_CP15_64(Op1, CRm) p15, Op1, %Q0, %R0, CRm
+
+#define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1)
+#define ICC_DIR __ACCESS_CP15(c12, 0, c11, 1)
+#define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0)
+#define ICC_SGI1R __ACCESS_CP15_64(0, c12)
+#define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0)
+#define ICC_CTLR __ACCESS_CP15(c12, 0, c12, 4)
+#define ICC_SRE __ACCESS_CP15(c12, 0, c12, 5)
+#define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7)
+
+#define ICC_HSRE __ACCESS_CP15(c12, 4, c9, 5)
+
+#define ICH_VSEIR __ACCESS_CP15(c12, 4, c9, 4)
+#define ICH_HCR __ACCESS_CP15(c12, 4, c11, 0)
+#define ICH_VTR __ACCESS_CP15(c12, 4, c11, 1)
+#define ICH_MISR __ACCESS_CP15(c12, 4, c11, 2)
+#define ICH_EISR __ACCESS_CP15(c12, 4, c11, 3)
+#define ICH_ELSR __ACCESS_CP15(c12, 4, c11, 5)
+#define ICH_VMCR __ACCESS_CP15(c12, 4, c11, 7)
+
+#define __LR0(x) __ACCESS_CP15(c12, 4, c12, x)
+#define __LR8(x) __ACCESS_CP15(c12, 4, c13, x)
+
+#define ICH_LR0 __LR0(0)
+#define ICH_LR1 __LR0(1)
+#define ICH_LR2 __LR0(2)
+#define ICH_LR3 __LR0(3)
+#define ICH_LR4 __LR0(4)
+#define ICH_LR5 __LR0(5)
+#define ICH_LR6 __LR0(6)
+#define ICH_LR7 __LR0(7)
+#define ICH_LR8 __LR8(0)
+#define ICH_LR9 __LR8(1)
+#define ICH_LR10 __LR8(2)
+#define ICH_LR11 __LR8(3)
+#define ICH_LR12 __LR8(4)
+#define ICH_LR13 __LR8(5)
+#define ICH_LR14 __LR8(6)
+#define ICH_LR15 __LR8(7)
+
+/* LR top half */
+#define __LRC0(x) __ACCESS_CP15(c12, 4, c14, x)
+#define __LRC8(x) __ACCESS_CP15(c12, 4, c15, x)
+
+#define ICH_LRC0 __LRC0(0)
+#define ICH_LRC1 __LRC0(1)
+#define ICH_LRC2 __LRC0(2)
+#define ICH_LRC3 __LRC0(3)
+#define ICH_LRC4 __LRC0(4)
+#define ICH_LRC5 __LRC0(5)
+#define ICH_LRC6 __LRC0(6)
+#define ICH_LRC7 __LRC0(7)
+#define ICH_LRC8 __LRC8(0)
+#define ICH_LRC9 __LRC8(1)
+#define ICH_LRC10 __LRC8(2)
+#define ICH_LRC11 __LRC8(3)
+#define ICH_LRC12 __LRC8(4)
+#define ICH_LRC13 __LRC8(5)
+#define ICH_LRC14 __LRC8(6)
+#define ICH_LRC15 __LRC8(7)
+
+#define __AP0Rx(x) __ACCESS_CP15(c12, 4, c8, x)
+#define ICH_AP0R0 __AP0Rx(0)
+#define ICH_AP0R1 __AP0Rx(1)
+#define ICH_AP0R2 __AP0Rx(2)
+#define ICH_AP0R3 __AP0Rx(3)
+
+#define __AP1Rx(x) __ACCESS_CP15(c12, 4, c9, x)
+#define ICH_AP1R0 __AP1Rx(0)
+#define ICH_AP1R1 __AP1Rx(1)
+#define ICH_AP1R2 __AP1Rx(2)
+#define ICH_AP1R3 __AP1Rx(3)
+
+/* Low-level accessors */
+
+static inline void gicv3_write_eoir(u32 irq)
+{
+ asm volatile("mcr " __stringify(ICC_EOIR1) : : "r" (irq));
+ isb();
+}
+
+static inline void gicv3_write_dir(u32 val)
+{
+ asm volatile("mcr " __stringify(ICC_DIR) : : "r" (val));
+ isb();
+}
+
+static inline u32 gicv3_read_iar(void)
+{
+ u32 irqstat;
+
+ asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat));
+ dsb(sy);
+ return irqstat;
+}
+
+static inline void gicv3_write_pmr(u32 val)
+{
+ asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val));
+}
+
+static inline void gicv3_write_ctlr(u32 val)
+{
+ asm volatile("mcr " __stringify(ICC_CTLR) : : "r" (val));
+ isb();
+}
+
+static inline void gicv3_write_grpen1(u32 val)
+{
+ asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val));
+ isb();
+}
+
+static inline void gicv3_write_sgi1r(u64 val)
+{
+ asm volatile("mcrr " __stringify(ICC_SGI1R) : : "r" (val));
+}
+
+static inline u32 gicv3_read_sre(void)
+{
+ u32 val;
+
+ asm volatile("mrc " __stringify(ICC_SRE) : "=r" (val));
+ return val;
+}
+
+static inline void gicv3_write_sre(u32 val)
+{
+ asm volatile("mcr " __stringify(ICC_SRE) : : "r" (val));
+ isb();
+}
+
+/*
+ * Even in 32bit systems that use LPAE, there is no guarantee that the I/O
+ * interface provides true 64bit atomic accesses, so using strd/ldrd doesn't
+ * make much sense.
+ * Moreover, 64bit I/O emulation is extremely difficult to implement on
+ * AArch32, since the syndrome register doesn't provide any information for
+ * them.
+ * Consequently, the following IO helpers use 32bit accesses.
+ *
+ * There are only two registers that need 64bit accesses in this driver:
+ * - GICD_IROUTERn, contain the affinity values associated to each interrupt.
+ * The upper-word (aff3) will always be 0, so there is no need for a lock.
+ * - GICR_TYPER is an ID register and doesn't need atomicity.
+ */
+static inline void gicv3_write_irouter(u64 val, volatile void __iomem *addr)
+{
+ writel((u32)val, addr);
+ writel((u32)(val >> 32), addr + 4);
+}
+
+static inline u64 gicv3_read_typer(const volatile void __iomem *addr)
+{
+ u64 val;
+
+ val = readl(addr);
+ 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 0000000000000..d5e58596f7918
--- /dev/null
+++ b/lib/arm/asm/gic-v3.h
@@ -0,0 +1,320 @@
+/*
+ * 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_
+
+/*
+ * Distributor registers. We assume we're running non-secure, with ARE
+ * being set. Secure-only and non-ARE registers are not described.
+ */
+#define GICD_CTLR 0x0000
+#define GICD_TYPER 0x0004
+#define GICD_IIDR 0x0008
+#define GICD_STATUSR 0x0010
+#define GICD_SETSPI_NSR 0x0040
+#define GICD_CLRSPI_NSR 0x0048
+#define GICD_SETSPI_SR 0x0050
+#define GICD_CLRSPI_SR 0x0058
+#define GICD_SEIR 0x0068
+#define GICD_IGROUPR 0x0080
+#define GICD_ISENABLER 0x0100
+#define GICD_ICENABLER 0x0180
+#define GICD_ISPENDR 0x0200
+#define GICD_ICPENDR 0x0280
+#define GICD_ISACTIVER 0x0300
+#define GICD_ICACTIVER 0x0380
+#define GICD_IPRIORITYR 0x0400
+#define GICD_ICFGR 0x0C00
+#define GICD_IGRPMODR 0x0D00
+#define GICD_NSACR 0x0E00
+#define GICD_IROUTER 0x6000
+#define GICD_IDREGS 0xFFD0
+#define GICD_PIDR2 0xFFE8
+
+/*
+ * Those registers are actually from GICv2, but the spec demands that they
+ * are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3).
+ */
+#define GICD_ITARGETSR 0x0800
+#define GICD_SGIR 0x0F00
+#define GICD_CPENDSGIR 0x0F10
+#define GICD_SPENDSGIR 0x0F20
+
+#define GICD_CTLR_RWP (1U << 31)
+#define GICD_CTLR_DS (1U << 6)
+#define GICD_CTLR_ARE_NS (1U << 4)
+#define GICD_CTLR_ENABLE_G1A (1U << 1)
+#define GICD_CTLR_ENABLE_G1 (1U << 0)
+
+/*
+ * In systems with a single security state (what we emulate in KVM)
+ * the meaning of the interrupt group enable bits is slightly different
+ */
+#define GICD_CTLR_ENABLE_SS_G1 (1U << 1)
+#define GICD_CTLR_ENABLE_SS_G0 (1U << 0)
+
+#define GICD_TYPER_LPIS (1U << 17)
+#define GICD_TYPER_MBIS (1U << 16)
+
+#define GICD_TYPER_ID_BITS(typer) ((((typer) >> 19) & 0x1f) + 1)
+#define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32)
+#define GICD_TYPER_LPIS (1U << 17)
+
+#define GICD_IROUTER_SPI_MODE_ONE (0U << 31)
+#define GICD_IROUTER_SPI_MODE_ANY (1U << 31)
+
+#define GIC_PIDR2_ARCH_MASK 0xf0
+#define GIC_PIDR2_ARCH_GICv3 0x30
+#define GIC_PIDR2_ARCH_GICv4 0x40
+
+#define GIC_V3_DIST_SIZE 0x10000
+
+/*
+ * Re-Distributor registers, offsets from RD_base
+ */
+#define GICR_CTLR GICD_CTLR
+#define GICR_IIDR 0x0004
+#define GICR_TYPER 0x0008
+#define GICR_STATUSR GICD_STATUSR
+#define GICR_WAKER 0x0014
+#define GICR_SETLPIR 0x0040
+#define GICR_CLRLPIR 0x0048
+#define GICR_SEIR GICD_SEIR
+#define GICR_PROPBASER 0x0070
+#define GICR_PENDBASER 0x0078
+#define GICR_INVLPIR 0x00A0
+#define GICR_INVALLR 0x00B0
+#define GICR_SYNCR 0x00C0
+#define GICR_MOVLPIR 0x0100
+#define GICR_MOVALLR 0x0110
+#define GICR_ISACTIVER GICD_ISACTIVER
+#define GICR_ICACTIVER GICD_ICACTIVER
+#define GICR_IDREGS GICD_IDREGS
+#define GICR_PIDR2 GICD_PIDR2
+
+#define GICR_CTLR_ENABLE_LPIS (1UL << 0)
+
+#define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff)
+
+#define GICR_WAKER_ProcessorSleep (1U << 1)
+#define GICR_WAKER_ChildrenAsleep (1U << 2)
+
+#define GICR_PROPBASER_NonShareable (0U << 10)
+#define GICR_PROPBASER_InnerShareable (1U << 10)
+#define GICR_PROPBASER_OuterShareable (2U << 10)
+#define GICR_PROPBASER_SHAREABILITY_MASK (3UL << 10)
+#define GICR_PROPBASER_nCnB (0U << 7)
+#define GICR_PROPBASER_nC (1U << 7)
+#define GICR_PROPBASER_RaWt (2U << 7)
+#define GICR_PROPBASER_RaWb (3U << 7)
+#define GICR_PROPBASER_WaWt (4U << 7)
+#define GICR_PROPBASER_WaWb (5U << 7)
+#define GICR_PROPBASER_RaWaWt (6U << 7)
+#define GICR_PROPBASER_RaWaWb (7U << 7)
+#define GICR_PROPBASER_CACHEABILITY_MASK (7U << 7)
+#define GICR_PROPBASER_IDBITS_MASK (0x1f)
+
+#define GICR_PENDBASER_NonShareable (0U << 10)
+#define GICR_PENDBASER_InnerShareable (1U << 10)
+#define GICR_PENDBASER_OuterShareable (2U << 10)
+#define GICR_PENDBASER_SHAREABILITY_MASK (3UL << 10)
+#define GICR_PENDBASER_nCnB (0U << 7)
+#define GICR_PENDBASER_nC (1U << 7)
+#define GICR_PENDBASER_RaWt (2U << 7)
+#define GICR_PENDBASER_RaWb (3U << 7)
+#define GICR_PENDBASER_WaWt (4U << 7)
+#define GICR_PENDBASER_WaWb (5U << 7)
+#define GICR_PENDBASER_RaWaWt (6U << 7)
+#define GICR_PENDBASER_RaWaWb (7U << 7)
+#define GICR_PENDBASER_CACHEABILITY_MASK (7U << 7)
+
+/*
+ * Re-Distributor registers, offsets from SGI_base
+ */
+#define GICR_IGROUPR0 GICD_IGROUPR
+#define GICR_ISENABLER0 GICD_ISENABLER
+#define GICR_ICENABLER0 GICD_ICENABLER
+#define GICR_ISPENDR0 GICD_ISPENDR
+#define GICR_ICPENDR0 GICD_ICPENDR
+#define GICR_ISACTIVER0 GICD_ISACTIVER
+#define GICR_ICACTIVER0 GICD_ICACTIVER
+#define GICR_IPRIORITYR0 GICD_IPRIORITYR
+#define GICR_ICFGR0 GICD_ICFGR
+#define GICR_IGRPMODR0 GICD_IGRPMODR
+#define GICR_NSACR GICD_NSACR
+
+#define GICR_TYPER_PLPIS (1U << 0)
+#define GICR_TYPER_VLPIS (1U << 1)
+#define GICR_TYPER_LAST (1U << 4)
+
+#define GIC_V3_REDIST_SIZE 0x20000
+
+#define LPI_PROP_GROUP1 (1 << 1)
+#define LPI_PROP_ENABLED (1 << 0)
+
+/*
+ * ITS registers, offsets from ITS_base
+ */
+#define GITS_CTLR 0x0000
+#define GITS_IIDR 0x0004
+#define GITS_TYPER 0x0008
+#define GITS_CBASER 0x0080
+#define GITS_CWRITER 0x0088
+#define GITS_CREADR 0x0090
+#define GITS_BASER 0x0100
+#define GITS_PIDR2 GICR_PIDR2
+
+#define GITS_TRANSLATER 0x10040
+
+#define GITS_CTLR_ENABLE (1U << 0)
+#define GITS_CTLR_QUIESCENT (1U << 31)
+
+#define GITS_TYPER_DEVBITS_SHIFT 13
+#define GITS_TYPER_DEVBITS(r) ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
+#define GITS_TYPER_PTA (1UL << 19)
+
+#define GITS_CBASER_VALID (1UL << 63)
+#define GITS_CBASER_nCnB (0UL << 59)
+#define GITS_CBASER_nC (1UL << 59)
+#define GITS_CBASER_RaWt (2UL << 59)
+#define GITS_CBASER_RaWb (3UL << 59)
+#define GITS_CBASER_WaWt (4UL << 59)
+#define GITS_CBASER_WaWb (5UL << 59)
+#define GITS_CBASER_RaWaWt (6UL << 59)
+#define GITS_CBASER_RaWaWb (7UL << 59)
+#define GITS_CBASER_CACHEABILITY_MASK (7UL << 59)
+#define GITS_CBASER_NonShareable (0UL << 10)
+#define GITS_CBASER_InnerShareable (1UL << 10)
+#define GITS_CBASER_OuterShareable (2UL << 10)
+#define GITS_CBASER_SHAREABILITY_MASK (3UL << 10)
+
+#define GITS_BASER_NR_REGS 8
+
+#define GITS_BASER_VALID (1UL << 63)
+#define GITS_BASER_nCnB (0UL << 59)
+#define GITS_BASER_nC (1UL << 59)
+#define GITS_BASER_RaWt (2UL << 59)
+#define GITS_BASER_RaWb (3UL << 59)
+#define GITS_BASER_WaWt (4UL << 59)
+#define GITS_BASER_WaWb (5UL << 59)
+#define GITS_BASER_RaWaWt (6UL << 59)
+#define GITS_BASER_RaWaWb (7UL << 59)
+#define GITS_BASER_CACHEABILITY_MASK (7UL << 59)
+#define GITS_BASER_TYPE_SHIFT (56)
+#define GITS_BASER_TYPE(r) (((r) >> GITS_BASER_TYPE_SHIFT) & 7)
+#define GITS_BASER_ENTRY_SIZE_SHIFT (48)
+#define GITS_BASER_ENTRY_SIZE(r) ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0xff) + 1)
+#define GITS_BASER_NonShareable (0UL << 10)
+#define GITS_BASER_InnerShareable (1UL << 10)
+#define GITS_BASER_OuterShareable (2UL << 10)
+#define GITS_BASER_SHAREABILITY_SHIFT (10)
+#define GITS_BASER_SHAREABILITY_MASK (3UL << GITS_BASER_SHAREABILITY_SHIFT)
+#define GITS_BASER_PAGE_SIZE_SHIFT (8)
+#define GITS_BASER_PAGE_SIZE_4K (0UL << GITS_BASER_PAGE_SIZE_SHIFT)
+#define GITS_BASER_PAGE_SIZE_16K (1UL << GITS_BASER_PAGE_SIZE_SHIFT)
+#define GITS_BASER_PAGE_SIZE_64K (2UL << GITS_BASER_PAGE_SIZE_SHIFT)
+#define GITS_BASER_PAGE_SIZE_MASK (3UL << GITS_BASER_PAGE_SIZE_SHIFT)
+#define GITS_BASER_PAGES_MAX 256
+
+#define GITS_BASER_TYPE_NONE 0
+#define GITS_BASER_TYPE_DEVICE 1
+#define GITS_BASER_TYPE_VCPU 2
+#define GITS_BASER_TYPE_CPU 3
+#define GITS_BASER_TYPE_COLLECTION 4
+#define GITS_BASER_TYPE_RESERVED5 5
+#define GITS_BASER_TYPE_RESERVED6 6
+#define GITS_BASER_TYPE_RESERVED7 7
+
+/*
+ * ITS commands
+ */
+#define GITS_CMD_MAPD 0x08
+#define GITS_CMD_MAPC 0x09
+#define GITS_CMD_MAPVI 0x0a
+#define GITS_CMD_MOVI 0x01
+#define GITS_CMD_DISCARD 0x0f
+#define GITS_CMD_INV 0x0c
+#define GITS_CMD_MOVALL 0x0e
+#define GITS_CMD_INVALL 0x0d
+#define GITS_CMD_INT 0x03
+#define GITS_CMD_CLEAR 0x04
+#define GITS_CMD_SYNC 0x05
+
+/*
+ * CPU interface registers
+ */
+#define ICC_CTLR_EL1_EOImode_drop_dir (0U << 1)
+#define ICC_CTLR_EL1_EOImode_drop (1U << 1)
+#define ICC_SRE_EL1_SRE (1U << 0)
+
+#include <asm/arch_gicv3.h>
+
+#define SZ_64K 0x10000
+
+#ifndef __ASSEMBLY__
+#include <libcflat.h>
+#include <asm/processor.h>
+#include <asm/setup.h>
+#include <asm/smp.h>
+#include <asm/io.h>
+
+struct gicv3_data {
+ void *dist_base;
+ void *redist_base[NR_CPUS];
+};
+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);
+
+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 b1237d1c5ef22..849d17cb36a4e 100644
--- a/lib/arm/asm/gic.h
+++ b/lib/arm/asm/gic.h
@@ -7,6 +7,7 @@
#define _ASMARM_GIC_H_
#include <asm/gic-v2.h>
+#include <asm/gic-v3.h>
/*
* gic_init will try to find all known gics, and then
diff --git a/lib/arm/gic.c b/lib/arm/gic.c
index 64a3049c9e8ce..25272f157fbe6 100644
--- a/lib/arm/gic.c
+++ b/lib/arm/gic.c
@@ -10,9 +10,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)
@@ -50,10 +52,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;
}
@@ -67,3 +77,51 @@ void gicv2_enable_defaults(void)
writel(GICC_INT_PRI_THRESHOLD, gicv2_cpu_base() + GIC_CPU_PRIMASK);
writel(GICC_ENABLE, gicv2_cpu_base() + GIC_CPU_CTRL);
}
+
+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);
+}
+
+void gicv3_enable_defaults(void)
+{
+ void *dist = gicv3_dist_base();
+ void *sgi_base;
+ int i;
+
+ if (smp_processor_id() == 0) {
+ 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();
+ }
+
+ if (!gicv3_redist_base())
+ gicv3_set_redist_base();
+ sgi_base = gicv3_sgi_base();
+
+ writel(GICD_INT_EN_CLR_X32, sgi_base + GIC_DIST_ACTIVE_CLEAR);
+ writel(GICD_INT_EN_CLR_PPI, sgi_base + GIC_DIST_ENABLE_CLEAR);
+ writel(GICD_INT_EN_SET_SGI, sgi_base + GIC_DIST_ENABLE_SET);
+
+ for (i = 0; i < 32; i += 4)
+ writel(GICD_INT_DEF_PRI_X4, sgi_base + GIC_DIST_PRI + i);
+ gicv3_redist_wait_for_rwp();
+
+ gicv3_write_pmr(0xf0);
+ gicv3_write_ctlr(ICC_CTLR_EL1_EOImode_drop_dir);
+ 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 0000000000000..eff2efdfe2d4d
--- /dev/null
+++ b/lib/arm64/asm/arch_gicv3.h
@@ -0,0 +1,169 @@
+/*
+ * 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_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1)
+#define ICC_DIR_EL1 sys_reg(3, 0, 12, 11, 1)
+#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
+#define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
+#define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
+#define ICC_CTLR_EL1 sys_reg(3, 0, 12, 12, 4)
+#define ICC_SRE_EL1 sys_reg(3, 0, 12, 12, 5)
+#define ICC_GRPEN1_EL1 sys_reg(3, 0, 12, 12, 7)
+
+#define ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5)
+
+/*
+ * System register definitions
+ */
+#define ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4)
+#define ICH_HCR_EL2 sys_reg(3, 4, 12, 11, 0)
+#define ICH_VTR_EL2 sys_reg(3, 4, 12, 11, 1)
+#define ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2)
+#define ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3)
+#define ICH_ELSR_EL2 sys_reg(3, 4, 12, 11, 5)
+#define ICH_VMCR_EL2 sys_reg(3, 4, 12, 11, 7)
+
+#define __LR0_EL2(x) sys_reg(3, 4, 12, 12, x)
+#define __LR8_EL2(x) sys_reg(3, 4, 12, 13, x)
+
+#define ICH_LR0_EL2 __LR0_EL2(0)
+#define ICH_LR1_EL2 __LR0_EL2(1)
+#define ICH_LR2_EL2 __LR0_EL2(2)
+#define ICH_LR3_EL2 __LR0_EL2(3)
+#define ICH_LR4_EL2 __LR0_EL2(4)
+#define ICH_LR5_EL2 __LR0_EL2(5)
+#define ICH_LR6_EL2 __LR0_EL2(6)
+#define ICH_LR7_EL2 __LR0_EL2(7)
+#define ICH_LR8_EL2 __LR8_EL2(0)
+#define ICH_LR9_EL2 __LR8_EL2(1)
+#define ICH_LR10_EL2 __LR8_EL2(2)
+#define ICH_LR11_EL2 __LR8_EL2(3)
+#define ICH_LR12_EL2 __LR8_EL2(4)
+#define ICH_LR13_EL2 __LR8_EL2(5)
+#define ICH_LR14_EL2 __LR8_EL2(6)
+#define ICH_LR15_EL2 __LR8_EL2(7)
+
+#define __AP0Rx_EL2(x) sys_reg(3, 4, 12, 8, x)
+#define ICH_AP0R0_EL2 __AP0Rx_EL2(0)
+#define ICH_AP0R1_EL2 __AP0Rx_EL2(1)
+#define ICH_AP0R2_EL2 __AP0Rx_EL2(2)
+#define ICH_AP0R3_EL2 __AP0Rx_EL2(3)
+
+#define __AP1Rx_EL2(x) sys_reg(3, 4, 12, 9, x)
+#define ICH_AP1R0_EL2 __AP1Rx_EL2(0)
+#define ICH_AP1R1_EL2 __AP1Rx_EL2(1)
+#define ICH_AP1R2_EL2 __AP1Rx_EL2(2)
+#define ICH_AP1R3_EL2 __AP1Rx_EL2(3)
+
+#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_eoir(u32 irq)
+{
+ asm volatile("msr_s " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" ((u64)irq));
+ isb();
+}
+
+static inline void gicv3_write_dir(u32 irq)
+{
+ asm volatile("msr_s " __stringify(ICC_DIR_EL1) ", %0" : : "r" ((u64)irq));
+ isb();
+}
+
+static inline u64 gicv3_read_iar_common(void)
+{
+ u64 irqstat;
+
+ asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
+ dsb(sy);
+ return irqstat;
+}
+
+static inline u32 gicv3_read_iar(void)
+{
+ return (u64)gicv3_read_iar_common();
+}
+
+/*
+ * Cavium ThunderX erratum 23154
+ *
+ * The gicv3 of ThunderX requires a modified version for reading the
+ * IAR status to ensure data synchronization (access to icc_iar1_el1
+ * is not sync'ed before and after).
+ */
+static inline u64 gicv3_read_iar_cavium_thunderx(void)
+{
+ u64 irqstat;
+
+ asm volatile(
+ "nop;nop;nop;nop\n\t"
+ "nop;nop;nop;nop\n\t"
+ "mrs_s %0, " __stringify(ICC_IAR1_EL1) "\n\t"
+ "nop;nop;nop;nop"
+ : "=r" (irqstat));
+ mb();
+
+ return irqstat;
+}
+
+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_ctlr(u32 val)
+{
+ asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" ((u64)val));
+ isb();
+}
+
+static inline void gicv3_write_grpen1(u32 val)
+{
+ asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val));
+ isb();
+}
+
+static inline void gicv3_write_sgi1r(u64 val)
+{
+ asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
+}
+
+static inline u32 gicv3_read_sre(void)
+{
+ u64 val;
+
+ asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
+ return val;
+}
+
+static inline void gicv3_write_sre(u32 val)
+{
+ asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" ((u64)val));
+ isb();
+}
+
+#define gicv3_read_typer(c) readq(c)
+#define gicv3_write_irouter(v, c) writeq(v, 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 0000000000000..8ee5d4d9c1819
--- /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 0000000000000..544a46cb8cc59
--- /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_ */
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 08/10] arm/arm64: gicv2: add an IPI test
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
` (6 preceding siblings ...)
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 07/10] arm64: add initial gicv3 support Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 09/10] arm/arm64: gicv3: " Andrew Jones
` (2 subsequent siblings)
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
arm/Makefile.common | 6 +-
arm/gic.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++
arm/unittests.cfg | 7 +++
3 files changed, 175 insertions(+), 3 deletions(-)
create mode 100644 arm/gic.c
diff --git a/arm/Makefile.common b/arm/Makefile.common
index 13a185f7d4473..378fecc910c41 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -9,9 +9,9 @@ ifeq ($(LOADADDR),)
LOADADDR = 0x40000000
endif
-tests-common = \
- $(TEST_DIR)/selftest.flat \
- $(TEST_DIR)/spinlock-test.flat
+tests-common = $(TEST_DIR)/selftest.flat
+tests-common += $(TEST_DIR)/spinlock-test.flat
+tests-common += $(TEST_DIR)/gic.flat
all: test_cases
diff --git a/arm/gic.c b/arm/gic.c
new file mode 100644
index 0000000000000..24be9e0ade369
--- /dev/null
+++ b/arm/gic.c
@@ -0,0 +1,165 @@
+/*
+ * GIC tests
+ *
+ * GICv2
+ * . test sending/receiving IPIs
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include <libcflat.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/gic.h>
+#include <asm/smp.h>
+#include <asm/barrier.h>
+#include <asm/io.h>
+
+static int gic_version;
+static int acked[NR_CPUS];
+static cpumask_t ready;
+
+static void nr_cpu_check(int nr)
+{
+ if (nr_cpus < nr)
+ report_abort("At least %d cpus required", nr);
+}
+
+static void wait_on_ready(void)
+{
+ cpumask_set_cpu(smp_processor_id(), &ready);
+ while (!cpumask_full(&ready))
+ cpu_relax();
+}
+
+static void check_acked(cpumask_t *mask)
+{
+ int nr_pass, cpu, i;
+
+ /* Wait up to 5s for all interrupts to be delivered */
+ for (i = 0; i < 50; ++i) {
+ mdelay(100);
+ nr_pass = 0;
+ for_each_present_cpu(cpu) {
+ smp_rmb();
+ nr_pass += cpumask_test_cpu(cpu, mask) ?
+ acked[cpu] == 1 : acked[cpu] == 0;
+ }
+ if (nr_pass == nr_cpus) {
+ report("completed in < %d ms", true, ++i * 100);
+ return;
+ }
+ }
+ report("timed-out (5s timeout)", false);
+}
+
+static void ipi_handler(struct pt_regs *regs __unused)
+{
+ u32 iar = readl(gicv2_cpu_base() + GIC_CPU_INTACK);
+
+ if (iar != GICC_INT_SPURIOUS) {
+ writel(iar, gicv2_cpu_base() + GIC_CPU_EOI);
+ smp_rmb();
+ ++acked[smp_processor_id()];
+ smp_wmb();
+ }
+}
+
+static void ipi_test_self(void)
+{
+ cpumask_t mask;
+
+ report_prefix_push("self");
+ memset(acked, 0, sizeof(acked));
+ smp_wmb();
+ cpumask_clear(&mask);
+ cpumask_set_cpu(0, &mask);
+ writel(2 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+ check_acked(&mask);
+ report_prefix_pop();
+}
+
+static void ipi_test_smp(void)
+{
+ cpumask_t mask;
+ unsigned long tlist;
+
+ report_prefix_push("target-list");
+ memset(acked, 0, sizeof(acked));
+ smp_wmb();
+ tlist = cpumask_bits(&cpu_present_mask)[0] & 0xaa;
+ cpumask_bits(&mask)[0] = tlist;
+ writel((u8)tlist << 16, gicv2_dist_base() + GIC_DIST_SOFTINT);
+ check_acked(&mask);
+ report_prefix_pop();
+
+ report_prefix_push("broadcast");
+ memset(acked, 0, sizeof(acked));
+ smp_wmb();
+ cpumask_copy(&mask, &cpu_present_mask);
+ cpumask_clear_cpu(0, &mask);
+ writel(1 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+ check_acked(&mask);
+ report_prefix_pop();
+}
+
+static void ipi_enable(void)
+{
+ gicv2_enable_defaults();
+#ifdef __arm__
+ install_exception_handler(EXCPTN_IRQ, ipi_handler);
+#else
+ install_irq_handler(EL1H_IRQ, ipi_handler);
+#endif
+ local_irq_enable();
+}
+
+static void ipi_recv(void)
+{
+ ipi_enable();
+ cpumask_set_cpu(smp_processor_id(), &ready);
+ while (1)
+ wfi();
+}
+
+int main(int argc, char **argv)
+{
+ char pfx[8];
+ int cpu;
+
+ gic_version = gic_init();
+ if (!gic_version)
+ report_abort("No gic present!");
+
+ snprintf(pfx, 8, "gicv%d", gic_version);
+ report_prefix_push(pfx);
+
+ if (argc == 0) {
+
+ report_prefix_push("ipi");
+ ipi_enable();
+ ipi_test_self();
+
+ } else if (!strcmp(argv[0], "ipi")) {
+
+ report_prefix_push(argv[0]);
+ nr_cpu_check(2);
+ ipi_enable();
+
+ for_each_present_cpu(cpu) {
+ if (cpu == 0)
+ continue;
+ smp_boot_secondary(cpu, ipi_recv);
+ }
+ wait_on_ready();
+ ipi_test_self();
+ ipi_test_smp();
+ report_prefix_pop();
+
+ } else {
+ report_abort("Unknown subtest '%s'", argv[0]);
+ }
+
+ return report_summary();
+}
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index ffd12e5794aa0..bb364675043f0 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -51,3 +51,10 @@ file = selftest.flat
smp = $MAX_SMP
extra_params = -append 'smp'
groups = selftest
+
+# Test GIC emulation
+[gicv2-ipi]
+file = gic.flat
+smp = $((($MAX_SMP < 8)?$MAX_SMP:8))
+extra_params = -machine gic-version=2 -append 'ipi'
+groups = gic
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 09/10] arm/arm64: gicv3: add an IPI test
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
` (7 preceding siblings ...)
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 08/10] arm/arm64: gicv2: add an IPI test Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 10/10] arm/arm64: gic: don't just use zero Andrew Jones
2016-05-18 9:07 ` [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Christoffer Dall
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
arm/gic.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++---
arm/unittests.cfg | 6 ++
2 files changed, 157 insertions(+), 9 deletions(-)
diff --git a/arm/gic.c b/arm/gic.c
index 24be9e0ade369..ec8e0a26ff724 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -3,6 +3,8 @@
*
* GICv2
* . test sending/receiving IPIs
+ * GICv3
+ * . test sending/receiving IPIs
*
* Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
*
@@ -16,6 +18,18 @@
#include <asm/barrier.h>
#include <asm/io.h>
+struct gic {
+ struct {
+ void (*enable)(void);
+ void (*send_self)(void);
+ void (*send_tlist)(cpumask_t *);
+ void (*send_broadcast)(void);
+ } ipi;
+ u32 (*read_iar)(void);
+ void (*write_eoi)(u32);
+};
+
+static struct gic *gic;
static int gic_version;
static int acked[NR_CPUS];
static cpumask_t ready;
@@ -54,18 +68,114 @@ static void check_acked(cpumask_t *mask)
report("timed-out (5s timeout)", false);
}
+static u32 gicv2_read_iar(void)
+{
+ return readl(gicv2_cpu_base() + GIC_CPU_INTACK);
+}
+
+static void gicv2_write_eoi(u32 irq)
+{
+ writel(irq, gicv2_cpu_base() + GIC_CPU_EOI);
+}
+
static void ipi_handler(struct pt_regs *regs __unused)
{
- u32 iar = readl(gicv2_cpu_base() + GIC_CPU_INTACK);
+ u32 iar = gic->read_iar();
if (iar != GICC_INT_SPURIOUS) {
- writel(iar, gicv2_cpu_base() + GIC_CPU_EOI);
+ gic->write_eoi(iar);
smp_rmb();
++acked[smp_processor_id()];
smp_wmb();
}
}
+static void gicv2_ipi_send_self(void)
+{
+ writel(2 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+}
+
+static void gicv2_ipi_send_tlist(cpumask_t *mask)
+{
+ u8 tlist = (u8)cpumask_bits(mask)[0];
+
+ writel(tlist << 16, gicv2_dist_base() + GIC_DIST_SOFTINT);
+}
+
+static void gicv2_ipi_send_broadcast(void)
+{
+ writel(1 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+}
+
+#define ICC_SGI1R_AFFINITY_1_SHIFT 16
+#define ICC_SGI1R_AFFINITY_2_SHIFT 32
+#define ICC_SGI1R_AFFINITY_3_SHIFT 48
+#define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \
+ (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT)
+
+static void gicv3_ipi_send_tlist(cpumask_t *mask)
+{
+ u16 tlist;
+ int cpu;
+
+ for_each_cpu(cpu, mask) {
+ u64 mpidr = cpus[cpu], sgi1r;
+ u64 cluster_id = mpidr & ~0xffUL;
+
+ tlist = 0;
+
+ while (cpu < nr_cpus) {
+ if ((mpidr & 0xff) >= 16) {
+ printf("cpu%d MPIDR:aff0 is %d (>= 16)!\n",
+ cpu, (int)(mpidr & 0xff));
+ break;
+ }
+
+ tlist |= 1 << (mpidr & 0xf);
+
+ cpu = cpumask_next(cpu, mask);
+ if (cpu >= nr_cpus)
+ break;
+
+ mpidr = cpus[cpu];
+
+ if (cluster_id != (mpidr & ~0xffUL)) {
+ --cpu;
+ break;
+ }
+ }
+
+ sgi1r = (MPIDR_TO_SGI_AFFINITY(cluster_id, 3) |
+ MPIDR_TO_SGI_AFFINITY(cluster_id, 2) |
+ /* irq << 24 | */
+ MPIDR_TO_SGI_AFFINITY(cluster_id, 1) |
+ tlist);
+
+ gicv3_write_sgi1r(sgi1r);
+ }
+
+ /* Force the above writes to ICC_SGI1R_EL1 to be executed */
+ isb();
+}
+
+static void gicv3_ipi_send_self(void)
+{
+ cpumask_t mask;
+
+ cpumask_clear(&mask);
+ cpumask_set_cpu(smp_processor_id(), &mask);
+ gicv3_ipi_send_tlist(&mask);
+}
+
+static void gicv3_ipi_send_broadcast(void)
+{
+ cpumask_t mask;
+
+ cpumask_copy(&mask, &cpu_present_mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
+ gicv3_ipi_send_tlist(&mask);
+}
+
static void ipi_test_self(void)
{
cpumask_t mask;
@@ -75,7 +185,7 @@ static void ipi_test_self(void)
smp_wmb();
cpumask_clear(&mask);
cpumask_set_cpu(0, &mask);
- writel(2 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+ gic->ipi.send_self();
check_acked(&mask);
report_prefix_pop();
}
@@ -83,14 +193,15 @@ static void ipi_test_self(void)
static void ipi_test_smp(void)
{
cpumask_t mask;
- unsigned long tlist;
+ int i;
report_prefix_push("target-list");
memset(acked, 0, sizeof(acked));
smp_wmb();
- tlist = cpumask_bits(&cpu_present_mask)[0] & 0xaa;
- cpumask_bits(&mask)[0] = tlist;
- writel((u8)tlist << 16, gicv2_dist_base() + GIC_DIST_SOFTINT);
+ cpumask_copy(&mask, &cpu_present_mask);
+ for (i = 0; i < nr_cpus; i += 2)
+ cpumask_clear_cpu(i, &mask);
+ gic->ipi.send_tlist(&mask);
check_acked(&mask);
report_prefix_pop();
@@ -99,14 +210,14 @@ static void ipi_test_smp(void)
smp_wmb();
cpumask_copy(&mask, &cpu_present_mask);
cpumask_clear_cpu(0, &mask);
- writel(1 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+ gic->ipi.send_broadcast();
check_acked(&mask);
report_prefix_pop();
}
static void ipi_enable(void)
{
- gicv2_enable_defaults();
+ gic->ipi.enable();
#ifdef __arm__
install_exception_handler(EXCPTN_IRQ, ipi_handler);
#else
@@ -123,6 +234,28 @@ static void ipi_recv(void)
wfi();
}
+struct gic gicv2 = {
+ .ipi = {
+ .enable = gicv2_enable_defaults,
+ .send_self = gicv2_ipi_send_self,
+ .send_tlist = gicv2_ipi_send_tlist,
+ .send_broadcast = gicv2_ipi_send_broadcast,
+ },
+ .read_iar = gicv2_read_iar,
+ .write_eoi = gicv2_write_eoi,
+};
+
+struct gic gicv3 = {
+ .ipi = {
+ .enable = gicv3_enable_defaults,
+ .send_self = gicv3_ipi_send_self,
+ .send_tlist = gicv3_ipi_send_tlist,
+ .send_broadcast = gicv3_ipi_send_broadcast,
+ },
+ .read_iar = gicv3_read_iar,
+ .write_eoi = gicv3_write_eoir,
+};
+
int main(int argc, char **argv)
{
char pfx[8];
@@ -135,6 +268,15 @@ int main(int argc, char **argv)
snprintf(pfx, 8, "gicv%d", gic_version);
report_prefix_push(pfx);
+ switch (gic_version) {
+ case 2:
+ gic = &gicv2;
+ break;
+ case 3:
+ gic = &gicv3;
+ break;
+ }
+
if (argc == 0) {
report_prefix_push("ipi");
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index bb364675043f0..043a20e26e98c 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -58,3 +58,9 @@ file = gic.flat
smp = $((($MAX_SMP < 8)?$MAX_SMP:8))
extra_params = -machine gic-version=2 -append 'ipi'
groups = gic
+
+[gicv3-ipi]
+file = gic.flat
+smp = $MAX_SMP
+extra_params = -machine gic-version=3 -append 'ipi'
+groups = gic
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [kvm-unit-tests PATCH 10/10] arm/arm64: gic: don't just use zero
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
` (8 preceding siblings ...)
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 09/10] arm/arm64: gicv3: " Andrew Jones
@ 2016-05-16 7:57 ` Andrew Jones
2016-05-18 9:07 ` [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Christoffer Dall
10 siblings, 0 replies; 16+ messages in thread
From: Andrew Jones @ 2016-05-16 7:57 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee
Cc: christoffer.dall, marc.zyngier
Allow user to select who sends ipis and with which irq, rather
than just always sending irq=0 from cpu0.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
arm/gic.c | 53 ++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 42 insertions(+), 11 deletions(-)
diff --git a/arm/gic.c b/arm/gic.c
index ec8e0a26ff724..b76b946f2c106 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -11,6 +11,7 @@
* This work is licensed under the terms of the GNU LGPL, version 2.
*/
#include <libcflat.h>
+#include <util.h>
#include <asm/setup.h>
#include <asm/processor.h>
#include <asm/gic.h>
@@ -31,6 +32,7 @@ struct gic {
static struct gic *gic;
static int gic_version;
+static int sender, irq;
static int acked[NR_CPUS];
static cpumask_t ready;
@@ -92,19 +94,19 @@ static void ipi_handler(struct pt_regs *regs __unused)
static void gicv2_ipi_send_self(void)
{
- writel(2 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+ writel(2 << 24 | irq, gicv2_dist_base() + GIC_DIST_SOFTINT);
}
static void gicv2_ipi_send_tlist(cpumask_t *mask)
{
u8 tlist = (u8)cpumask_bits(mask)[0];
- writel(tlist << 16, gicv2_dist_base() + GIC_DIST_SOFTINT);
+ writel(tlist << 16 | irq, gicv2_dist_base() + GIC_DIST_SOFTINT);
}
static void gicv2_ipi_send_broadcast(void)
{
- writel(1 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+ writel(1 << 24 | irq, gicv2_dist_base() + GIC_DIST_SOFTINT);
}
#define ICC_SGI1R_AFFINITY_1_SHIFT 16
@@ -147,7 +149,7 @@ static void gicv3_ipi_send_tlist(cpumask_t *mask)
sgi1r = (MPIDR_TO_SGI_AFFINITY(cluster_id, 3) |
MPIDR_TO_SGI_AFFINITY(cluster_id, 2) |
- /* irq << 24 | */
+ irq << 24 |
MPIDR_TO_SGI_AFFINITY(cluster_id, 1) |
tlist);
@@ -184,7 +186,7 @@ static void ipi_test_self(void)
memset(acked, 0, sizeof(acked));
smp_wmb();
cpumask_clear(&mask);
- cpumask_set_cpu(0, &mask);
+ cpumask_set_cpu(smp_processor_id(), &mask);
gic->ipi.send_self();
check_acked(&mask);
report_prefix_pop();
@@ -199,7 +201,7 @@ static void ipi_test_smp(void)
memset(acked, 0, sizeof(acked));
smp_wmb();
cpumask_copy(&mask, &cpu_present_mask);
- for (i = 0; i < nr_cpus; i += 2)
+ for (i = smp_processor_id() & 1; i < nr_cpus; i += 2)
cpumask_clear_cpu(i, &mask);
gic->ipi.send_tlist(&mask);
check_acked(&mask);
@@ -209,7 +211,7 @@ static void ipi_test_smp(void)
memset(acked, 0, sizeof(acked));
smp_wmb();
cpumask_copy(&mask, &cpu_present_mask);
- cpumask_clear_cpu(0, &mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
gic->ipi.send_broadcast();
check_acked(&mask);
report_prefix_pop();
@@ -226,6 +228,15 @@ static void ipi_enable(void)
local_irq_enable();
}
+static void ipi_send(void)
+{
+ ipi_enable();
+ wait_on_ready();
+ ipi_test_self();
+ ipi_test_smp();
+ exit(report_summary());
+}
+
static void ipi_recv(void)
{
ipi_enable();
@@ -284,6 +295,19 @@ int main(int argc, char **argv)
ipi_test_self();
} else if (!strcmp(argv[0], "ipi")) {
+ int off, i = 0;
+ long val;
+
+ while (--argc) {
+ off = parse_keyval(argv[++i], &val);
+ if (off == -1)
+ continue;
+ argv[i][off] = '\0';
+ if (strcmp(argv[i], "sender") == 0)
+ sender = val;
+ else if (strcmp(argv[i], "irq") == 0)
+ irq = val;
+ }
report_prefix_push(argv[0]);
nr_cpu_check(2);
@@ -292,11 +316,18 @@ int main(int argc, char **argv)
for_each_present_cpu(cpu) {
if (cpu == 0)
continue;
- smp_boot_secondary(cpu, ipi_recv);
+ if (cpu == sender)
+ smp_boot_secondary(cpu, ipi_send);
+ else
+ smp_boot_secondary(cpu, ipi_recv);
+ }
+ if (sender == 0) {
+ wait_on_ready();
+ ipi_test_self();
+ ipi_test_smp();
+ } else {
+ ipi_recv();
}
- wait_on_ready();
- ipi_test_self();
- ipi_test_smp();
report_prefix_pop();
} else {
--
2.4.11
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
` (9 preceding siblings ...)
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 10/10] arm/arm64: gic: don't just use zero Andrew Jones
@ 2016-05-18 9:07 ` Christoffer Dall
2016-05-23 15:24 ` Andrew Jones
10 siblings, 1 reply; 16+ messages in thread
From: Christoffer Dall @ 2016-05-18 9:07 UTC (permalink / raw)
To: Andrew Jones
Cc: kvm, kvmarm, qemu-devel, qemu-arm, andre.przywara, peter.maydell,
alex.bennee, marc.zyngier
Hi Drew,
Thanks for doing this. I'm happy to see some tests for the GIC.
I've been pondering with how to write unit tests for all the MMIO
implementations. If you have some thoughts on how that could be easily
fitted into this framework, that would probably be a good place to do it
;)
-Christoffer
On Mon, May 16, 2016 at 09:57:14AM +0200, Andrew Jones wrote:
> Import defines, and steal enough helper functions, from Linux to
> enable programming of the gic (v2 and v3). Then use the framework
> to add an initial test (an ipi test; self, target-list, broadcast).
>
> It's my hope that this framework will be a suitable base on which
> more tests may be easily added, particularly because we have
> vgic-new and tcg gicv3 emulation getting close to merge.
>
> To run it, along with other tests, just do
>
> ./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ]
> make
> export QEMU=$PATH_TO_QEMU
> ./run_tests.sh
>
> To run it separately do, e.g.
>
> $QEMU -machine virt,accel=tcg -cpu cortex-a57 \
> -device virtio-serial-device \
> -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
> -display none -serial stdio \
> -kernel arm/gic.flat \
> -smp 123 -machine gic-version=3 -append ipi
>
> ^^ note, we can go nuts with nr-cpus on TCG :-)
>
> Or, a KVM example using a different "sender" cpu and irq (other than zero)
>
> $QEMU -machine virt,accel=kvm -cpu host \
> -device virtio-serial-device \
> -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
> -display none -serial stdio \
> -kernel arm/gic.flat \
> -smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1'
>
>
> Patches:
> 01-05: fixes and functionality needed by the later gic patches
> 06-07: code theft from Linux (defines, helper functions)
> 08-10: arm/gic.flat (the base of the gic unit test), currently just IPI
>
> Available here: https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic
>
>
> Andrew Jones (10):
> lib: xstr: allow multiple args
> arm64: fix get_"sysreg32" and make MPIDR 64bit
> arm/arm64: smp: support more than 8 cpus
> arm/arm64: add some delay routines
> arm/arm64: irq enable/disable
> arm/arm64: add initial gicv2 support
> arm64: add initial gicv3 support
> arm/arm64: gicv2: add an IPI test
> arm/arm64: gicv3: add an IPI test
> arm/arm64: gic: don't just use zero
>
> arm/Makefile.common | 7 +-
> arm/gic.c | 338 +++++++++++++++++++++++++++++++++++++++++++++
> arm/run | 19 ++-
> arm/selftest.c | 5 +-
> arm/unittests.cfg | 13 ++
> lib/arm/asm/arch_gicv3.h | 184 ++++++++++++++++++++++++
> lib/arm/asm/gic-v2.h | 74 ++++++++++
> lib/arm/asm/gic-v3.h | 320 ++++++++++++++++++++++++++++++++++++++++++
> lib/arm/asm/gic.h | 21 +++
> lib/arm/asm/processor.h | 38 ++++-
> lib/arm/asm/setup.h | 4 +-
> lib/arm/gic.c | 127 +++++++++++++++++
> lib/arm/processor.c | 15 ++
> lib/arm/setup.c | 12 +-
> lib/arm64/asm/arch_gicv3.h | 169 +++++++++++++++++++++++
> lib/arm64/asm/gic-v2.h | 1 +
> lib/arm64/asm/gic-v3.h | 1 +
> lib/arm64/asm/gic.h | 1 +
> lib/arm64/asm/processor.h | 53 +++++--
> lib/arm64/asm/sysreg.h | 44 ++++++
> lib/arm64/processor.c | 15 ++
> lib/libcflat.h | 4 +-
> 22 files changed, 1439 insertions(+), 26 deletions(-)
> create mode 100644 arm/gic.c
> create mode 100644 lib/arm/asm/arch_gicv3.h
> create mode 100644 lib/arm/asm/gic-v2.h
> create mode 100644 lib/arm/asm/gic-v3.h
> create mode 100644 lib/arm/asm/gic.h
> create mode 100644 lib/arm/gic.c
> create mode 100644 lib/arm64/asm/arch_gicv3.h
> create mode 100644 lib/arm64/asm/gic-v2.h
> create mode 100644 lib/arm64/asm/gic-v3.h
> create mode 100644 lib/arm64/asm/gic.h
> create mode 100644 lib/arm64/asm/sysreg.h
>
> --
> 2.4.11
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework
2016-05-18 9:07 ` [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Christoffer Dall
@ 2016-05-23 15:24 ` Andrew Jones
2016-05-24 11:58 ` Christoffer Dall
0 siblings, 1 reply; 16+ messages in thread
From: Andrew Jones @ 2016-05-23 15:24 UTC (permalink / raw)
To: Christoffer Dall
Cc: peter.maydell, kvm, marc.zyngier, andre.przywara, qemu-devel,
qemu-arm, alex.bennee, kvmarm
On Wed, May 18, 2016 at 11:07:14AM +0200, Christoffer Dall wrote:
> Hi Drew,
>
> Thanks for doing this. I'm happy to see some tests for the GIC.
>
> I've been pondering with how to write unit tests for all the MMIO
> implementations. If you have some thoughts on how that could be easily
> fitted into this framework, that would probably be a good place to do it
> ;)
Hi Christoffer,
Sorry for my slow response, I've been on vacation. For MMIO
implementations, are you referring to the emulation done for
gicv2 accesses and for gicv3 legacy accesses? And, if so, is
your question how we might be able to use the same test
framework for both? And, if that's so, then I think this series
gets us pretty close already. If I'm completely off-base, then
please give me a quick high-level description of what you'd like
to be able to do.
Thanks,
drew
> -Christoffer
>
> On Mon, May 16, 2016 at 09:57:14AM +0200, Andrew Jones wrote:
> > Import defines, and steal enough helper functions, from Linux to
> > enable programming of the gic (v2 and v3). Then use the framework
> > to add an initial test (an ipi test; self, target-list, broadcast).
> >
> > It's my hope that this framework will be a suitable base on which
> > more tests may be easily added, particularly because we have
> > vgic-new and tcg gicv3 emulation getting close to merge.
> >
> > To run it, along with other tests, just do
> >
> > ./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ]
> > make
> > export QEMU=$PATH_TO_QEMU
> > ./run_tests.sh
> >
> > To run it separately do, e.g.
> >
> > $QEMU -machine virt,accel=tcg -cpu cortex-a57 \
> > -device virtio-serial-device \
> > -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
> > -display none -serial stdio \
> > -kernel arm/gic.flat \
> > -smp 123 -machine gic-version=3 -append ipi
> >
> > ^^ note, we can go nuts with nr-cpus on TCG :-)
> >
> > Or, a KVM example using a different "sender" cpu and irq (other than zero)
> >
> > $QEMU -machine virt,accel=kvm -cpu host \
> > -device virtio-serial-device \
> > -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
> > -display none -serial stdio \
> > -kernel arm/gic.flat \
> > -smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1'
> >
> >
> > Patches:
> > 01-05: fixes and functionality needed by the later gic patches
> > 06-07: code theft from Linux (defines, helper functions)
> > 08-10: arm/gic.flat (the base of the gic unit test), currently just IPI
> >
> > Available here: https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic
> >
> >
> > Andrew Jones (10):
> > lib: xstr: allow multiple args
> > arm64: fix get_"sysreg32" and make MPIDR 64bit
> > arm/arm64: smp: support more than 8 cpus
> > arm/arm64: add some delay routines
> > arm/arm64: irq enable/disable
> > arm/arm64: add initial gicv2 support
> > arm64: add initial gicv3 support
> > arm/arm64: gicv2: add an IPI test
> > arm/arm64: gicv3: add an IPI test
> > arm/arm64: gic: don't just use zero
> >
> > arm/Makefile.common | 7 +-
> > arm/gic.c | 338 +++++++++++++++++++++++++++++++++++++++++++++
> > arm/run | 19 ++-
> > arm/selftest.c | 5 +-
> > arm/unittests.cfg | 13 ++
> > lib/arm/asm/arch_gicv3.h | 184 ++++++++++++++++++++++++
> > lib/arm/asm/gic-v2.h | 74 ++++++++++
> > lib/arm/asm/gic-v3.h | 320 ++++++++++++++++++++++++++++++++++++++++++
> > lib/arm/asm/gic.h | 21 +++
> > lib/arm/asm/processor.h | 38 ++++-
> > lib/arm/asm/setup.h | 4 +-
> > lib/arm/gic.c | 127 +++++++++++++++++
> > lib/arm/processor.c | 15 ++
> > lib/arm/setup.c | 12 +-
> > lib/arm64/asm/arch_gicv3.h | 169 +++++++++++++++++++++++
> > lib/arm64/asm/gic-v2.h | 1 +
> > lib/arm64/asm/gic-v3.h | 1 +
> > lib/arm64/asm/gic.h | 1 +
> > lib/arm64/asm/processor.h | 53 +++++--
> > lib/arm64/asm/sysreg.h | 44 ++++++
> > lib/arm64/processor.c | 15 ++
> > lib/libcflat.h | 4 +-
> > 22 files changed, 1439 insertions(+), 26 deletions(-)
> > create mode 100644 arm/gic.c
> > create mode 100644 lib/arm/asm/arch_gicv3.h
> > create mode 100644 lib/arm/asm/gic-v2.h
> > create mode 100644 lib/arm/asm/gic-v3.h
> > create mode 100644 lib/arm/asm/gic.h
> > create mode 100644 lib/arm/gic.c
> > create mode 100644 lib/arm64/asm/arch_gicv3.h
> > create mode 100644 lib/arm64/asm/gic-v2.h
> > create mode 100644 lib/arm64/asm/gic-v3.h
> > create mode 100644 lib/arm64/asm/gic.h
> > create mode 100644 lib/arm64/asm/sysreg.h
> >
> > --
> > 2.4.11
> >
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework
2016-05-23 15:24 ` Andrew Jones
@ 2016-05-24 11:58 ` Christoffer Dall
2016-05-24 12:23 ` Andrew Jones
0 siblings, 1 reply; 16+ messages in thread
From: Christoffer Dall @ 2016-05-24 11:58 UTC (permalink / raw)
To: Andrew Jones
Cc: peter.maydell, kvm, marc.zyngier, andre.przywara, qemu-devel,
qemu-arm, alex.bennee, kvmarm
On Mon, May 23, 2016 at 05:24:23PM +0200, Andrew Jones wrote:
> On Wed, May 18, 2016 at 11:07:14AM +0200, Christoffer Dall wrote:
> > Hi Drew,
> >
> > Thanks for doing this. I'm happy to see some tests for the GIC.
> >
> > I've been pondering with how to write unit tests for all the MMIO
> > implementations. If you have some thoughts on how that could be easily
> > fitted into this framework, that would probably be a good place to do it
> > ;)
>
> Hi Christoffer,
>
> Sorry for my slow response, I've been on vacation. For MMIO
> implementations, are you referring to the emulation done for
> gicv2 accesses and for gicv3 legacy accesses? And, if so, is
> your question how we might be able to use the same test
> framework for both? And, if that's so, then I think this series
> gets us pretty close already. If I'm completely off-base, then
> please give me a quick high-level description of what you'd like
> to be able to do.
>
What I meant was testing all the MMIO accesses to the various
distributor MMIO regions.
For example, writing full words to all registers (some value) reading
back the value, correcting for RAZ/WI semantics, and testing that byte
accesses to those registers where that's allowed also works.
If adding that on top of this series sounds like a good idea, someone
should add it to the bottom of their (presumably already long) todo
list, myself included.
Thanks,
-Christoffer
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework
2016-05-24 11:58 ` Christoffer Dall
@ 2016-05-24 12:23 ` Andrew Jones
2016-05-24 12:39 ` Christoffer Dall
0 siblings, 1 reply; 16+ messages in thread
From: Andrew Jones @ 2016-05-24 12:23 UTC (permalink / raw)
To: Christoffer Dall
Cc: peter.maydell, kvm, marc.zyngier, andre.przywara, qemu-devel,
qemu-arm, alex.bennee, kvmarm
On Tue, May 24, 2016 at 01:58:19PM +0200, Christoffer Dall wrote:
> On Mon, May 23, 2016 at 05:24:23PM +0200, Andrew Jones wrote:
> > On Wed, May 18, 2016 at 11:07:14AM +0200, Christoffer Dall wrote:
> > > Hi Drew,
> > >
> > > Thanks for doing this. I'm happy to see some tests for the GIC.
> > >
> > > I've been pondering with how to write unit tests for all the MMIO
> > > implementations. If you have some thoughts on how that could be easily
> > > fitted into this framework, that would probably be a good place to do it
> > > ;)
> >
> > Hi Christoffer,
> >
> > Sorry for my slow response, I've been on vacation. For MMIO
> > implementations, are you referring to the emulation done for
> > gicv2 accesses and for gicv3 legacy accesses? And, if so, is
> > your question how we might be able to use the same test
> > framework for both? And, if that's so, then I think this series
> > gets us pretty close already. If I'm completely off-base, then
> > please give me a quick high-level description of what you'd like
> > to be able to do.
> >
> What I meant was testing all the MMIO accesses to the various
> distributor MMIO regions.
>
> For example, writing full words to all registers (some value) reading
> back the value, correcting for RAZ/WI semantics, and testing that byte
> accesses to those registers where that's allowed also works.
OK, understood. We can build a table that describes each distributor
offset's allowed access types and expected read-back results for the
"default enablement" of the gic. Then, we'd run through that table
doing a refresh of the gic enabling before each offset test. This
series provides everything needed for that, except the offset table.
It should be pretty easy to add.
Now, configuring the gic differently will result in some offsets
producing different values, so we'll eventually want to extend the
table to check the same offsets using different gic enable functions
as well, but that would be pretty easy to do too.
>
> If adding that on top of this series sounds like a good idea, someone
> should add it to the bottom of their (presumably already long) todo
> list, myself included.
They do sound like good tests to have. I've added it to the middle
of my long TODO. If somebody beats me to it, I won't complain :-)
Thanks,
drew
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework
2016-05-24 12:23 ` Andrew Jones
@ 2016-05-24 12:39 ` Christoffer Dall
0 siblings, 0 replies; 16+ messages in thread
From: Christoffer Dall @ 2016-05-24 12:39 UTC (permalink / raw)
To: Andrew Jones
Cc: peter.maydell, kvm, marc.zyngier, andre.przywara, qemu-devel,
qemu-arm, alex.bennee, kvmarm
On Tue, May 24, 2016 at 02:23:43PM +0200, Andrew Jones wrote:
> On Tue, May 24, 2016 at 01:58:19PM +0200, Christoffer Dall wrote:
> > On Mon, May 23, 2016 at 05:24:23PM +0200, Andrew Jones wrote:
> > > On Wed, May 18, 2016 at 11:07:14AM +0200, Christoffer Dall wrote:
> > > > Hi Drew,
> > > >
> > > > Thanks for doing this. I'm happy to see some tests for the GIC.
> > > >
> > > > I've been pondering with how to write unit tests for all the MMIO
> > > > implementations. If you have some thoughts on how that could be easily
> > > > fitted into this framework, that would probably be a good place to do it
> > > > ;)
> > >
> > > Hi Christoffer,
> > >
> > > Sorry for my slow response, I've been on vacation. For MMIO
> > > implementations, are you referring to the emulation done for
> > > gicv2 accesses and for gicv3 legacy accesses? And, if so, is
> > > your question how we might be able to use the same test
> > > framework for both? And, if that's so, then I think this series
> > > gets us pretty close already. If I'm completely off-base, then
> > > please give me a quick high-level description of what you'd like
> > > to be able to do.
> > >
> > What I meant was testing all the MMIO accesses to the various
> > distributor MMIO regions.
> >
> > For example, writing full words to all registers (some value) reading
> > back the value, correcting for RAZ/WI semantics, and testing that byte
> > accesses to those registers where that's allowed also works.
>
> OK, understood. We can build a table that describes each distributor
> offset's allowed access types and expected read-back results for the
> "default enablement" of the gic. Then, we'd run through that table
> doing a refresh of the gic enabling before each offset test. This
> series provides everything needed for that, except the offset table.
> It should be pretty easy to add.
>
> Now, configuring the gic differently will result in some offsets
> producing different values, so we'll eventually want to extend the
> table to check the same offsets using different gic enable functions
> as well, but that would be pretty easy to do too.
>
> >
> > If adding that on top of this series sounds like a good idea, someone
> > should add it to the bottom of their (presumably already long) todo
> > list, myself included.
>
> They do sound like good tests to have. I've added it to the middle
> of my long TODO. If somebody beats me to it, I won't complain :-)
>
Awesome, thanks!
-Christoffer
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2016-05-24 12:39 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-16 7:57 [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 01/10] lib: xstr: allow multiple args Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 02/10] arm64: fix get_"sysreg32" and make MPIDR 64bit Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 03/10] arm/arm64: smp: support more than 8 cpus Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 04/10] arm/arm64: add some delay routines Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 05/10] arm/arm64: irq enable/disable Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 06/10] arm/arm64: add initial gicv2 support Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 07/10] arm64: add initial gicv3 support Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 08/10] arm/arm64: gicv2: add an IPI test Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 09/10] arm/arm64: gicv3: " Andrew Jones
2016-05-16 7:57 ` [Qemu-devel] [kvm-unit-tests PATCH 10/10] arm/arm64: gic: don't just use zero Andrew Jones
2016-05-18 9:07 ` [Qemu-devel] [kvm-unit-tests PATCH 00/10] arm/arm64: add gic framework Christoffer Dall
2016-05-23 15:24 ` Andrew Jones
2016-05-24 11:58 ` Christoffer Dall
2016-05-24 12:23 ` Andrew Jones
2016-05-24 12:39 ` Christoffer Dall
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).