diff mbox series

[3/3] hw/arm/smmuv3: Advertise support for SMMUv3.2-BBML2

Message ID 20220426160422.2353158-4-peter.maydell@linaro.org
State New
Headers show
Series target/arm, hw/arm/smmuv3: Advertise TTL and BBM features | expand

Commit Message

Peter Maydell April 26, 2022, 4:04 p.m. UTC
The Arm SMMUv3 includes an optional feature equivalent to the CPU
FEAT_BBM, which permits an OS to switch a range of memory between
"covered by a huge page" and "covered by a sequence of normal pages"
without having to engage in the traditional 'break-before-make'
dance. (This is particularly important for the SMMU, because devices
performing I/O through an SMMU are less likely to be able to cope with
the window in the sequence where an access results in a translation
fault.)  The SMMU spec explicitly notes that one of the valid ways to
be a BBM level 2 compliant implementation is:
 * if there are multiple entries in the TLB for an address,
   choose one of them and use it, ignoring the others

Our SMMU TLB implementation (unlike our CPU TLB) does allow multiple
TLB entries for an address, because the translation table level is
part of the SMMUIOTLBKey, and so our IOTLB hashtable can include
entries for the same address where the leaf was at different levels
(i.e. both hugepage and normal page). Our TLB lookup implementation in
smmu_iotlb_lookup() will always find the entry with the lowest level
(i.e. it prefers the hugepage over the normal page) and ignore any
others. TLB invalidation correctly removes all TLB entries matching
the specified address or address range (unless the guest specifies the
leaf level explicitly, in which case it gets what it asked for). So we
can validly advertise support for BBML level 2.

Note that we still can't yet advertise ourselves as an SMMU v3.2,
because v3.2 requires support for the S2FWB feature, which we don't
yet implement.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 hw/arm/smmuv3-internal.h | 1 +
 hw/arm/smmuv3.c          | 1 +
 2 files changed, 2 insertions(+)

Comments

Eric Auger April 28, 2022, 8:37 a.m. UTC | #1
Hi Peter,

On 4/26/22 18:04, Peter Maydell wrote:
> The Arm SMMUv3 includes an optional feature equivalent to the CPU
> FEAT_BBM, which permits an OS to switch a range of memory between
> "covered by a huge page" and "covered by a sequence of normal pages"
> without having to engage in the traditional 'break-before-make'
> dance. (This is particularly important for the SMMU, because devices
> performing I/O through an SMMU are less likely to be able to cope with
> the window in the sequence where an access results in a translation
> fault.)  The SMMU spec explicitly notes that one of the valid ways to
> be a BBM level 2 compliant implementation is:
>  * if there are multiple entries in the TLB for an address,
>    choose one of them and use it, ignoring the others
>
> Our SMMU TLB implementation (unlike our CPU TLB) does allow multiple
> TLB entries for an address, because the translation table level is
> part of the SMMUIOTLBKey, and so our IOTLB hashtable can include
> entries for the same address where the leaf was at different levels
> (i.e. both hugepage and normal page). Our TLB lookup implementation in
> smmu_iotlb_lookup() will always find the entry with the lowest level
> (i.e. it prefers the hugepage over the normal page) and ignore any
> others. TLB invalidation correctly removes all TLB entries matching
> the specified address or address range (unless the guest specifies the
> leaf level explicitly, in which case it gets what it asked for). So we
"

unless the guest specifies the
leaf level explicitly, in which case it gets what it asked for

"
This is the less obvious part as the spec says:

"A TLB invalidation operation removes all matching TLB entries even if
overlapping entries exist for a given
address."

I failed to find further precisions about the range invalidation & BBML.

If you are confident about this, it looks good to me.
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric




> can validly advertise support for BBML level 2.
>
> Note that we still can't yet advertise ourselves as an SMMU v3.2,
> because v3.2 requires support for the S2FWB feature, which we don't
> yet implement.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  hw/arm/smmuv3-internal.h | 1 +
>  hw/arm/smmuv3.c          | 1 +
>  2 files changed, 2 insertions(+)
>
> diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
> index d1885ae3f25..e9150a6ff33 100644
> --- a/hw/arm/smmuv3-internal.h
> +++ b/hw/arm/smmuv3-internal.h
> @@ -56,6 +56,7 @@ REG32(IDR2,                0x8)
>  REG32(IDR3,                0xc)
>       FIELD(IDR3, HAD,         2, 1);
>       FIELD(IDR3, RIL,        10, 1);
> +     FIELD(IDR3, BBML,       11, 2);
>  REG32(IDR4,                0x10)
>  REG32(IDR5,                0x14)
>       FIELD(IDR5, OAS,         0, 3);
> diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
> index 707eb430c23..74bc2e85ee4 100644
> --- a/hw/arm/smmuv3.c
> +++ b/hw/arm/smmuv3.c
> @@ -259,6 +259,7 @@ static void smmuv3_init_regs(SMMUv3State *s)
>  
>      s->idr[3] = FIELD_DP32(s->idr[3], IDR3, RIL, 1);
>      s->idr[3] = FIELD_DP32(s->idr[3], IDR3, HAD, 1);
> +    s->idr[3] = FIELD_DP32(s->idr[3], IDR3, BBML, 2);
>  
>      /* 4K, 16K and 64K granule support */
>      s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1);
Peter Maydell April 28, 2022, 9:26 a.m. UTC | #2
On Thu, 28 Apr 2022 at 09:37, Eric Auger <eric.auger@redhat.com> wrote:
> On 4/26/22 18:04, Peter Maydell wrote:
> >  TLB invalidation correctly removes all TLB entries matching
> > the specified address or address range (unless the guest specifies the
> > leaf level explicitly, in which case it gets what it asked for). So we
> "
>
> unless the guest specifies the
> leaf level explicitly, in which case it gets what it asked for
>
> "
> This is the less obvious part as the spec says:
>
> "A TLB invalidation operation removes all matching TLB entries even if
> overlapping entries exist for a given
> address."
>
> I failed to find further precisions about the range invalidation & BBML.

If the invalidate says "level 2" then a TLB entry that wasn't
put in at level 2 doesn't match the TLB invalidate request and so
isn't removed (whether it overlaps a matching one at the same
address or not). This is defined as part of the behaviour of TLB
invalidates which specify a TTL, eg on page 142.

An implementation which did something like "find the first entry
that matches the address, then notice that it doesn't match
the specified TTL, so ignore it and do nothing" wouldn't be
correct. But "invalidate all the entries which match for
both address and TTL and ignore the ones which don't match
on TTL" is fine.

> If you are confident about this, it looks good to me.
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks.

-- PMM
Eric Auger April 28, 2022, 10:06 a.m. UTC | #3
On 4/28/22 11:26, Peter Maydell wrote:
> On Thu, 28 Apr 2022 at 09:37, Eric Auger <eric.auger@redhat.com> wrote:
>> On 4/26/22 18:04, Peter Maydell wrote:
>>>  TLB invalidation correctly removes all TLB entries matching
>>> the specified address or address range (unless the guest specifies the
>>> leaf level explicitly, in which case it gets what it asked for). So we
>> "
>>
>> unless the guest specifies the
>> leaf level explicitly, in which case it gets what it asked for
>>
>> "
>> This is the less obvious part as the spec says:
>>
>> "A TLB invalidation operation removes all matching TLB entries even if
>> overlapping entries exist for a given
>> address."
>>
>> I failed to find further precisions about the range invalidation & BBML.
> If the invalidate says "level 2" then a TLB entry that wasn't
> put in at level 2 doesn't match the TLB invalidate request and so
> isn't removed (whether it overlaps a matching one at the same
> address or not). This is defined as part of the behaviour of TLB
> invalidates which specify a TTL, eg on page 142.
>
> An implementation which did something like "find the first entry
> that matches the address, then notice that it doesn't match
> the specified TTL, so ignore it and do nothing" wouldn't be
> correct. But "invalidate all the entries which match for
> both address and TTL and ignore the ones which don't match
> on TTL" is fine.

OK Thanks

Eric
>
>> If you are confident about this, it looks good to me.
>> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> Thanks.
>
> -- PMM
>
diff mbox series

Patch

diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index d1885ae3f25..e9150a6ff33 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -56,6 +56,7 @@  REG32(IDR2,                0x8)
 REG32(IDR3,                0xc)
      FIELD(IDR3, HAD,         2, 1);
      FIELD(IDR3, RIL,        10, 1);
+     FIELD(IDR3, BBML,       11, 2);
 REG32(IDR4,                0x10)
 REG32(IDR5,                0x14)
      FIELD(IDR5, OAS,         0, 3);
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 707eb430c23..74bc2e85ee4 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -259,6 +259,7 @@  static void smmuv3_init_regs(SMMUv3State *s)
 
     s->idr[3] = FIELD_DP32(s->idr[3], IDR3, RIL, 1);
     s->idr[3] = FIELD_DP32(s->idr[3], IDR3, HAD, 1);
+    s->idr[3] = FIELD_DP32(s->idr[3], IDR3, BBML, 2);
 
     /* 4K, 16K and 64K granule support */
     s->idr[5] = FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1);