From: Ricardo Koller <ricarkol@google.com>
To: Marc Zyngier <maz@kernel.org>
Cc: kvm@vger.kernel.org, shuah@kernel.org, pshier@google.com,
Paolo Bonzini <pbonzini@redhat.com>,
kvmarm@lists.cs.columbia.edu
Subject: Re: [PATCH 02/17] KVM: selftests: aarch64: add function for accessing GICv3 dist and redist registers
Date: Wed, 24 Nov 2021 17:55:11 -0800 [thread overview]
Message-ID: <YZ7s/xeQ1IviLQfp@google.com> (raw)
In-Reply-To: <87h7c2di8v.wl-maz@kernel.org>
On Tue, Nov 23, 2021 at 03:06:08PM +0000, Marc Zyngier wrote:
> On Tue, 09 Nov 2021 02:38:51 +0000,
> Ricardo Koller <ricarkol@google.com> wrote:
> >
> > Add a generic library function for reading and writing GICv3 distributor
> > and redistributor registers. Then adapt some functions to use it; more
> > will come and use it in the next commit.
> >
> > Signed-off-by: Ricardo Koller <ricarkol@google.com>
> > ---
> > .../selftests/kvm/lib/aarch64/gic_v3.c | 124 ++++++++++++++----
> > 1 file changed, 101 insertions(+), 23 deletions(-)
> >
> > diff --git a/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c b/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
> > index 2dbf3339b62e..00e944fd8148 100644
> > --- a/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
> > +++ b/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
> > @@ -19,7 +19,8 @@ struct gicv3_data {
> > unsigned int nr_spis;
> > };
> >
> > -#define sgi_base_from_redist(redist_base) (redist_base + SZ_64K)
> > +#define sgi_base_from_redist(redist_base) (redist_base + SZ_64K)
> > +#define DIST_BIT (1U << 31)
> >
> > enum gicv3_intid_range {
> > SGI_RANGE,
> > @@ -50,6 +51,14 @@ static void gicv3_gicr_wait_for_rwp(void *redist_base)
> > }
> > }
> >
> > +static void gicv3_wait_for_rwp(uint32_t cpu_or_dist)
> > +{
> > + if (cpu_or_dist & DIST_BIT)
> > + gicv3_gicd_wait_for_rwp();
> > + else
> > + gicv3_gicr_wait_for_rwp(gicv3_data.redist_base[cpu_or_dist]);
> > +}
> > +
> > static enum gicv3_intid_range get_intid_range(unsigned int intid)
> > {
> > switch (intid) {
> > @@ -81,39 +90,108 @@ static void gicv3_write_eoir(uint32_t irq)
> > isb();
> > }
> >
> > -static void
> > -gicv3_config_irq(unsigned int intid, unsigned int offset)
> > +uint32_t gicv3_reg_readl(uint32_t cpu_or_dist, uint64_t offset)
> > +{
> > + void *base = cpu_or_dist & DIST_BIT ? gicv3_data.dist_base
> > + : sgi_base_from_redist(gicv3_data.redist_base[cpu_or_dist]);
> > + return readl(base + offset);
> > +}
> > +
> > +void gicv3_reg_writel(uint32_t cpu_or_dist, uint64_t offset, uint32_t reg_val)
> > +{
> > + void *base = cpu_or_dist & DIST_BIT ? gicv3_data.dist_base
> > + : sgi_base_from_redist(gicv3_data.redist_base[cpu_or_dist]);
> > + writel(reg_val, base + offset);
> > +}
> > +
> > +uint32_t gicv3_getl_fields(uint32_t cpu_or_dist, uint64_t offset, uint32_t mask)
> > +{
> > + return gicv3_reg_readl(cpu_or_dist, offset) & mask;
> > +}
> > +
> > +void gicv3_setl_fields(uint32_t cpu_or_dist, uint64_t offset,
> > + uint32_t mask, uint32_t reg_val)
> > +{
> > + uint32_t tmp = gicv3_reg_readl(cpu_or_dist, offset) & ~mask;
> > +
> > + tmp |= (reg_val & mask);
> > + gicv3_reg_writel(cpu_or_dist, offset, tmp);
> > +}
> > +
> > +/*
> > + * We use a single offset for the distributor and redistributor maps as they
> > + * have the same value in both. The only exceptions are registers that only
> > + * exist in one and not the other, like GICR_WAKER that doesn't exist in the
> > + * distributor map. Such registers are conveniently marked as reserved in the
> > + * map that doesn't implement it; like GICR_WAKER's offset of 0x0014 being
> > + * marked as "Reserved" in the Distributor map.
> > + */
> > +static void gicv3_access_reg(uint32_t intid, uint64_t offset,
> > + uint32_t reg_bits, uint32_t bits_per_field,
> > + bool write, uint32_t *val)
> > {
> > uint32_t cpu = guest_get_vcpuid();
> > - uint32_t mask = 1 << (intid % 32);
> > enum gicv3_intid_range intid_range = get_intid_range(intid);
> > - void *reg;
> > -
> > - /* We care about 'cpu' only for SGIs or PPIs */
> > - if (intid_range == SGI_RANGE || intid_range == PPI_RANGE) {
> > - GUEST_ASSERT(cpu < gicv3_data.nr_cpus);
> > -
> > - reg = sgi_base_from_redist(gicv3_data.redist_base[cpu]) +
> > - offset;
> > - writel(mask, reg);
> > - gicv3_gicr_wait_for_rwp(gicv3_data.redist_base[cpu]);
> > - } else if (intid_range == SPI_RANGE) {
> > - reg = gicv3_data.dist_base + offset + (intid / 32) * 4;
> > - writel(mask, reg);
> > - gicv3_gicd_wait_for_rwp();
> > - } else {
> > - GUEST_ASSERT(0);
> > - }
> > + uint32_t fields_per_reg, index, mask, shift;
> > + uint32_t cpu_or_dist;
> > +
> > + GUEST_ASSERT(bits_per_field <= reg_bits);
> > + GUEST_ASSERT(*val < (1U << bits_per_field));
> > + /* Some registers like IROUTER are 64 bit long. Those are currently not
> > + * supported by readl nor writel, so just asserting here until then.
> > + */
> > + GUEST_ASSERT(reg_bits == 32);
>
> IROUTER *does* support 32bit accesses. There are no 64bit MMIO
> registers in the GIC architecture that do not support 32bit accesses,
> if only because there is no guarantee about the width of the MMIO bus
> itself (not to mention the existence of 32bit CPUs!).
>
> See 12.1.3 ("GIC memory-mapped register access") in the GICv3 arch
> spec.
I see, thanks for the pointer. Will update the comment in v2. Although I
might keep the assert as this function doesn't support 64bit accesses
(yet).
Thanks,
Ricardo
> M.
>
> --
> Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
WARNING: multiple messages have this Message-ID (diff)
From: Ricardo Koller <ricarkol@google.com>
To: Marc Zyngier <maz@kernel.org>
Cc: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu,
drjones@redhat.com, eric.auger@redhat.com,
alexandru.elisei@arm.com, Paolo Bonzini <pbonzini@redhat.com>,
oupton@google.com, james.morse@arm.com, suzuki.poulose@arm.com,
shuah@kernel.org, jingzhangos@google.com, pshier@google.com,
rananta@google.com, reijiw@google.com
Subject: Re: [PATCH 02/17] KVM: selftests: aarch64: add function for accessing GICv3 dist and redist registers
Date: Wed, 24 Nov 2021 17:55:11 -0800 [thread overview]
Message-ID: <YZ7s/xeQ1IviLQfp@google.com> (raw)
In-Reply-To: <87h7c2di8v.wl-maz@kernel.org>
On Tue, Nov 23, 2021 at 03:06:08PM +0000, Marc Zyngier wrote:
> On Tue, 09 Nov 2021 02:38:51 +0000,
> Ricardo Koller <ricarkol@google.com> wrote:
> >
> > Add a generic library function for reading and writing GICv3 distributor
> > and redistributor registers. Then adapt some functions to use it; more
> > will come and use it in the next commit.
> >
> > Signed-off-by: Ricardo Koller <ricarkol@google.com>
> > ---
> > .../selftests/kvm/lib/aarch64/gic_v3.c | 124 ++++++++++++++----
> > 1 file changed, 101 insertions(+), 23 deletions(-)
> >
> > diff --git a/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c b/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
> > index 2dbf3339b62e..00e944fd8148 100644
> > --- a/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
> > +++ b/tools/testing/selftests/kvm/lib/aarch64/gic_v3.c
> > @@ -19,7 +19,8 @@ struct gicv3_data {
> > unsigned int nr_spis;
> > };
> >
> > -#define sgi_base_from_redist(redist_base) (redist_base + SZ_64K)
> > +#define sgi_base_from_redist(redist_base) (redist_base + SZ_64K)
> > +#define DIST_BIT (1U << 31)
> >
> > enum gicv3_intid_range {
> > SGI_RANGE,
> > @@ -50,6 +51,14 @@ static void gicv3_gicr_wait_for_rwp(void *redist_base)
> > }
> > }
> >
> > +static void gicv3_wait_for_rwp(uint32_t cpu_or_dist)
> > +{
> > + if (cpu_or_dist & DIST_BIT)
> > + gicv3_gicd_wait_for_rwp();
> > + else
> > + gicv3_gicr_wait_for_rwp(gicv3_data.redist_base[cpu_or_dist]);
> > +}
> > +
> > static enum gicv3_intid_range get_intid_range(unsigned int intid)
> > {
> > switch (intid) {
> > @@ -81,39 +90,108 @@ static void gicv3_write_eoir(uint32_t irq)
> > isb();
> > }
> >
> > -static void
> > -gicv3_config_irq(unsigned int intid, unsigned int offset)
> > +uint32_t gicv3_reg_readl(uint32_t cpu_or_dist, uint64_t offset)
> > +{
> > + void *base = cpu_or_dist & DIST_BIT ? gicv3_data.dist_base
> > + : sgi_base_from_redist(gicv3_data.redist_base[cpu_or_dist]);
> > + return readl(base + offset);
> > +}
> > +
> > +void gicv3_reg_writel(uint32_t cpu_or_dist, uint64_t offset, uint32_t reg_val)
> > +{
> > + void *base = cpu_or_dist & DIST_BIT ? gicv3_data.dist_base
> > + : sgi_base_from_redist(gicv3_data.redist_base[cpu_or_dist]);
> > + writel(reg_val, base + offset);
> > +}
> > +
> > +uint32_t gicv3_getl_fields(uint32_t cpu_or_dist, uint64_t offset, uint32_t mask)
> > +{
> > + return gicv3_reg_readl(cpu_or_dist, offset) & mask;
> > +}
> > +
> > +void gicv3_setl_fields(uint32_t cpu_or_dist, uint64_t offset,
> > + uint32_t mask, uint32_t reg_val)
> > +{
> > + uint32_t tmp = gicv3_reg_readl(cpu_or_dist, offset) & ~mask;
> > +
> > + tmp |= (reg_val & mask);
> > + gicv3_reg_writel(cpu_or_dist, offset, tmp);
> > +}
> > +
> > +/*
> > + * We use a single offset for the distributor and redistributor maps as they
> > + * have the same value in both. The only exceptions are registers that only
> > + * exist in one and not the other, like GICR_WAKER that doesn't exist in the
> > + * distributor map. Such registers are conveniently marked as reserved in the
> > + * map that doesn't implement it; like GICR_WAKER's offset of 0x0014 being
> > + * marked as "Reserved" in the Distributor map.
> > + */
> > +static void gicv3_access_reg(uint32_t intid, uint64_t offset,
> > + uint32_t reg_bits, uint32_t bits_per_field,
> > + bool write, uint32_t *val)
> > {
> > uint32_t cpu = guest_get_vcpuid();
> > - uint32_t mask = 1 << (intid % 32);
> > enum gicv3_intid_range intid_range = get_intid_range(intid);
> > - void *reg;
> > -
> > - /* We care about 'cpu' only for SGIs or PPIs */
> > - if (intid_range == SGI_RANGE || intid_range == PPI_RANGE) {
> > - GUEST_ASSERT(cpu < gicv3_data.nr_cpus);
> > -
> > - reg = sgi_base_from_redist(gicv3_data.redist_base[cpu]) +
> > - offset;
> > - writel(mask, reg);
> > - gicv3_gicr_wait_for_rwp(gicv3_data.redist_base[cpu]);
> > - } else if (intid_range == SPI_RANGE) {
> > - reg = gicv3_data.dist_base + offset + (intid / 32) * 4;
> > - writel(mask, reg);
> > - gicv3_gicd_wait_for_rwp();
> > - } else {
> > - GUEST_ASSERT(0);
> > - }
> > + uint32_t fields_per_reg, index, mask, shift;
> > + uint32_t cpu_or_dist;
> > +
> > + GUEST_ASSERT(bits_per_field <= reg_bits);
> > + GUEST_ASSERT(*val < (1U << bits_per_field));
> > + /* Some registers like IROUTER are 64 bit long. Those are currently not
> > + * supported by readl nor writel, so just asserting here until then.
> > + */
> > + GUEST_ASSERT(reg_bits == 32);
>
> IROUTER *does* support 32bit accesses. There are no 64bit MMIO
> registers in the GIC architecture that do not support 32bit accesses,
> if only because there is no guarantee about the width of the MMIO bus
> itself (not to mention the existence of 32bit CPUs!).
>
> See 12.1.3 ("GIC memory-mapped register access") in the GICv3 arch
> spec.
I see, thanks for the pointer. Will update the comment in v2. Although I
might keep the assert as this function doesn't support 64bit accesses
(yet).
Thanks,
Ricardo
> M.
>
> --
> Without deviation from the norm, progress is not possible.
next prev parent reply other threads:[~2021-11-25 1:55 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-09 2:38 [PATCH 00/17] KVM: selftests: aarch64: Test userspace IRQ injection Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 01/17] KVM: selftests: aarch64: move gic_v3.h to shared headers Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 02/17] KVM: selftests: aarch64: add function for accessing GICv3 dist and redist registers Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-23 15:06 ` Marc Zyngier
2021-11-23 15:06 ` Marc Zyngier
2021-11-25 1:55 ` Ricardo Koller [this message]
2021-11-25 1:55 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 03/17] KVM: selftests: aarch64: add GICv3 register accessor library functions Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 04/17] KVM: selftests: add kvm_irq_line library function Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 05/17] KVM: selftests: aarch64: add vGIC library functions to deal with vIRQ state Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 06/17] KVM: selftests: aarch64: add vgic_irq to test userspace IRQ injection Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 07/17] KVM: selftests: aarch64: abstract the injection functions in vgic_irq Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 08/17] KVM: selftests: aarch64: cmdline arg to set number of IRQs in vgic_irq test Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 09/17] KVM: selftests: aarch64: cmdline arg to set EOI mode in vgic_irq Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:38 ` [PATCH 10/17] KVM: selftests: aarch64: add preemption tests " Ricardo Koller
2021-11-09 2:38 ` Ricardo Koller
2021-11-09 2:39 ` [PATCH 11/17] KVM: selftests: aarch64: level-sensitive interrupts " Ricardo Koller
2021-11-09 2:39 ` Ricardo Koller
2021-11-09 2:39 ` [PATCH 12/17] KVM: selftests: aarch64: add tests for LEVEL_INFO " Ricardo Koller
2021-11-09 2:39 ` Ricardo Koller
2021-11-09 2:39 ` [PATCH 13/17] KVM: selftests: aarch64: add test_inject_fail to vgic_irq Ricardo Koller
2021-11-09 2:39 ` Ricardo Koller
2021-11-09 2:39 ` [PATCH 14/17] KVM: selftests: add IRQ GSI routing library functions Ricardo Koller
2021-11-09 2:39 ` Ricardo Koller
2021-11-09 2:39 ` [PATCH 15/17] KVM: selftests: aarch64: add tests for IRQFD in vgic_irq Ricardo Koller
2021-11-09 2:39 ` Ricardo Koller
2021-11-09 2:39 ` [PATCH 16/17] KVM: selftests: aarch64: add ISPENDR write tests " Ricardo Koller
2021-11-09 2:39 ` Ricardo Koller
2021-11-09 2:39 ` [PATCH 17/17] KVM: selftests: aarch64: add test for restoring active IRQs Ricardo Koller
2021-11-09 2:39 ` Ricardo Koller
2021-11-23 14:25 ` [PATCH 00/17] KVM: selftests: aarch64: Test userspace IRQ injection Andrew Jones
2021-11-23 14:25 ` Andrew Jones
2021-11-25 2:23 ` Ricardo Koller
2021-11-25 2:23 ` Ricardo Koller
2021-12-28 19:57 ` Marc Zyngier
2021-12-28 19:57 ` Marc Zyngier
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=YZ7s/xeQ1IviLQfp@google.com \
--to=ricarkol@google.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=maz@kernel.org \
--cc=pbonzini@redhat.com \
--cc=pshier@google.com \
--cc=shuah@kernel.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.