From: Mostafa Saleh <smostafa@google.com>
To: Tao Tang <tangtao1634@phytium.com.cn>
Cc: qemu-arm@nongnu.org, qemu-devel@nongnu.org,
"Eric Auger" <eric.auger@redhat.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Chen Baozi" <chenbaozi@phytium.com.cn>,
"Pierrick Bouvier" <pierrick.bouvier@linaro.org>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
jean-philippe@linaro.org
Subject: Re: [RFC 02/11] hw/arm/smmuv3: Implement read/write logic for secure registers
Date: Sat, 23 Aug 2025 10:41:59 +0000 [thread overview]
Message-ID: <aKma98hlAWG9M4h_@google.com> (raw)
In-Reply-To: <53607fe8-0555-4408-bfa6-e4b95d44e230@phytium.com.cn>
On Wed, Aug 20, 2025 at 11:21:02PM +0800, Tao Tang wrote:
>
> On 2025/8/19 05:24, Mostafa Saleh wrote:
> > On Wed, Aug 06, 2025 at 11:11:25PM +0800, Tao Tang wrote:
> > > This patch builds upon the previous introduction of secure register
> > > definitions by providing the functional implementation for their access.
> > >
> > > The availability of the secure programming interface is now correctly
> > > gated by the S_IDR1.SECURE_IMPL bit. When this bit indicates that
> > > secure functionality is enabled, the I/O handlers (smmuv3_read and
> > > smmuv3_write) will correctly dispatch accesses to the secure
> > > register space.
> > >
> > > Signed-off-by: Tao Tang <tangtao1634@phytium.com.cn>
> > > ---
> > > hw/arm/smmuv3-internal.h | 5 +
> > > hw/arm/smmuv3.c | 451 +++++++++++++++++++++++++++++++++++++++
> > > 2 files changed, 456 insertions(+)
> > >
> > > diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
> > > index 483aaa915e..1a8b1cb204 100644
> > > --- a/hw/arm/smmuv3-internal.h
> > > +++ b/hw/arm/smmuv3-internal.h
> > > @@ -122,6 +122,11 @@ REG32(CR0, 0x20)
> > > #define SMMU_CR0_RESERVED 0xFFFFFC20
> > > +/*
> > > + * BIT1 and BIT4 are RES0 in SMMU_S_CRO
> > > + */
> > > +#define SMMU_S_CR0_RESERVED 0xFFFFFC12
> > > +
> > > REG32(CR0ACK, 0x24)
> > > REG32(CR1, 0x28)
> > > REG32(CR2, 0x2c)
> > > diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
> > > index ab67972353..619180d204 100644
> > > --- a/hw/arm/smmuv3.c
> > > +++ b/hw/arm/smmuv3.c
> > > @@ -317,6 +317,18 @@ static void smmuv3_init_regs(SMMUv3State *s)
> > > s->gerrorn = 0;
> > > s->statusr = 0;
> > > s->gbpa = SMMU_GBPA_RESET_VAL;
> > > +
> > > + /* Initialize secure state */
> > > + memset(s->secure_idr, 0, sizeof(s->secure_idr));
> > > + /* Secure EL2 and Secure stage 2 support */
> > > + s->secure_idr[1] = FIELD_DP32(s->secure_idr[1], S_IDR1, SEL2, 1);
> > AFAIU, this is wrong, SEL2 means that the SMMU has dual stage-2,
> > one for secure (S_S2TTB) and one for non-secure IPAs(S2TTB).
> > Which is not implemented in this series.
>
>
> Hi Mostafa,
>
> Thank you for the very detailed and helpful review. Your feedback is spot
> on, and I'd like to address your points and ask for a quick confirmation on
> them.
>
> Regarding the SEL2 bit, you are absolutely right, my understanding was
> incorrect. I've spent the last few days reviewing the manual to better
> understand the selection between Secure and Non-secure Stage 2 translations.
> I would be very grateful if you could confirm if my new understanding is
> correct:
>
> - In Stage 2-only mode (Stage 1 bypassed), the choice between a Secure or
> Non-secure IPA translation is determined solely by STE.NSCFG.
>
Yes, but that's only with SMMU_IDR1.ATTR_PERMS_OVR which Qemu doesn't
advertise, so in our case it's always secure.
> - In Stage 1-enabled mode, STE.NSCFG is ignored. The choice is determined by
> the translation process, starting from CD.NSCFGx, with the output NS
> attribute being the result of intermediate NSTable flags and the final
> descriptor.NS bit (TTD.NSTable, TTD.NS).
>
You have to differentiate between the security state of the translation and
the security state of the translation table access.
For stage-1, the security state is determined by the NS bit in the last
level PTE, which in case of nested translation it will choose between S2TTB
or S_S2TTB.
Also, note that the stage-2 also have an NS which define the final attribute
of the transaction.
You have to also be careful around things such as NSCFG{0,1} as it might
change which stage-2 is used for the stage-1 TTB walk.
I see, in your patches, all the page-table access is done using the secure
state of the SID which is not correct.
> Based on this, I plan to have an internal flag, perhaps named
> target_ipa_is_ns in SMMUTransCfg.SMMUS2Cfg struct, to track the outcome of
> this process. This flag will then determine whether S_S2TTB or S2TTB is used
> for the Stage 2 translation.
>
I am worried that it's not that simple for a single secure nested translation
you can have multiple stage-2 walks where some might be secure and others not,
so I imagine this some how will be determined from each stage-1 walk and
some how returned (maybe in the TLB struct) which is then the stage-2
walk looks into.
I am not sure how complicated it is to manage 2 stage-2 with the current code
base, so my advice would be to split the problem; for now you can drop SEL2
from this series and rely on NS stage-2.
And later, it can be added separately, but that’s up to you and the maintainers
on how they want to do this, I will try to review as much as I can.
Also, according to the spec:
"STT is 1 in implementations where SMMU_S_IDR1.SEL2 == 1."
which requires extra work in the translation table code to support this
feature.
>
> >
> > > + /* Secure state implemented */
> > > + s->secure_idr[1] = FIELD_DP32(s->secure_idr[1], S_IDR1,
> > > + SECURE_IMPL, 1);
> > > + s->secure_idr[1] = FIELD_DP32(s->secure_idr[1], S_IDR1,
> > > + S_SIDSIZE, SMMU_IDR1_SIDSIZE);
> > > +
> > > + s->secure_gbpa = SMMU_GBPA_RESET_VAL;
> > > }
> > > static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
> > > @@ -1278,6 +1290,12 @@ static void smmuv3_range_inval(SMMUState *s, Cmd *cmd, SMMUStage stage)
> > > }
> > > }
> > > +/* Check if the SMMU hardware itself implements secure state features */
> > > +static inline bool smmu_hw_secure_implemented(SMMUv3State *s)
> > > +{
> > > + return FIELD_EX32(s->secure_idr[1], S_IDR1, SECURE_IMPL);
> > > +}
> > > +
> > I see that the secure SMMU support is unconditional. So, is this always true?
> > Also, how that looks with migration?
>
> For the v2 series, my plan is to make SECURE_IMPL a user-configurable device
> property. I will add a "secure-enabled" property to smmuv3_properties and
> ensure all necessary states are added to the VMStateDescription to handle
> migration correctly. Does this approach sound reasonable to you?
Yes, that makes sense.
>
>
> >
> > > static int smmuv3_cmdq_consume(SMMUv3State *s)
> > > {
> > > SMMUState *bs = ARM_SMMU(s);
> > > @@ -1508,9 +1526,91 @@ static int smmuv3_cmdq_consume(SMMUv3State *s)
> > > return 0;
> > > }
> > > +/* Helper function for secure register write validation */
> > > +static bool smmu_validate_secure_write(MemTxAttrs attrs, bool secure_impl,
> > > + hwaddr offset, const char *reg_name)
> > > +{
> > > + if (!attrs.secure || !secure_impl) {
> > > + const char *reason = !attrs.secure ?
> > > + "Non-secure write attempt" :
> > > + "SMMU didn't implement Security State";
> > > + qemu_log_mask(LOG_GUEST_ERROR,
> > > + "%s: %s at offset 0x%" PRIx64 " (%s, WI)\n",
> > > + __func__, reason, offset, reg_name);
> > > + return false;
> > > + }
> > > + return true;
> > > +}
> > > +
> > > +/* Helper function for secure register read validation */
> > > +static bool smmu_validate_secure_read(MemTxAttrs attrs, bool secure_impl,
> > > + hwaddr offset, const char *reg_name,
> > > + uint64_t *data)
> > > +{
> > > + if (!attrs.secure || !secure_impl) {
> > > + const char *reason = !attrs.secure ?
> > > + "Non-secure read attempt" :
> > > + "SMMU didn't implement Security State";
> > > + qemu_log_mask(LOG_GUEST_ERROR,
> > > + "%s: %s at offset 0x%" PRIx64 " (%s, RAZ)\n",
> > > + __func__, reason, offset, reg_name);
> > > + *data = 0; /* RAZ */
> > > + return false;
> > > + }
> > > + return true;
> > > +}
> > > +
> > > +/* Macro for secure write validation - returns early if validation fails */
> > > +#define SMMU_CHECK_SECURE_WRITE(reg_name) \
> > > + do { \
> > > + if (!smmu_validate_secure_write(attrs, secure_impl, offset, \
> > > + reg_name)) { \
> > > + return MEMTX_OK; \
> > > + } \
> > > + } while (0)
> > > +
> > > +/* Macro for attrs.secure only validation */
> > > +#define SMMU_CHECK_ATTRS_SECURE(reg_name) \
> > > + do { \
> > > + if (!attrs.secure) { \
> > > + qemu_log_mask(LOG_GUEST_ERROR, \
> > > + "%s: Non-secure write attempt at offset " \
> > > + "0x%" PRIx64 " (%s, WI)\n", \
> > > + __func__, offset, reg_name); \
> > > + return MEMTX_OK; \
> > > + } \
> > > + } while (0)
> > > +
> > > +/* Macro for secure read validation - returns RAZ if validation fails */
> > > +#define SMMU_CHECK_SECURE_READ(reg_name) \
> > > + do { \
> > > + if (!smmu_validate_secure_read(attrs, secure_impl, offset, \
> > > + reg_name, data)) { \
> > > + return MEMTX_OK; \
> > > + } \
> > > + } while (0)
> > > +
> > > +/* Macro for attrs.secure only validation (read) */
> > > +#define SMMU_CHECK_ATTRS_SECURE_READ(reg_name) \
> > > + do { \
> > > + if (!attrs.secure) { \
> > > + qemu_log_mask(LOG_GUEST_ERROR, \
> > > + "%s: Non-secure read attempt at offset " \
> > > + "0x%" PRIx64 " (%s, RAZ)\n", \
> > > + __func__, offset, reg_name); \
> > > + *data = 0; \
> > > + return MEMTX_OK; \
> > > + } \
> > > + } while (0)
> > > +
> > >
> > Can’t we just have one check? If the access > SMMU_SECURE_BASE_OFFSET, just
> > check the security state?
> >
> > And then based on banking, many of those switches will be common with
> > non secure cases.
> >
> > Thanks,
> > Mostafa
>
>
> I have already refactored this part in my v2 series, exactly as you
> proposed. This also addresses your earlier feedback on patch #1 regarding
> the overall structure:
>
> > As Philippe mentioned, this would be better the secure state is separated
> > in another instance of the struct, that seems it would reduce a lot of the
> > duplication later around the logic of MMIO and queues... in the next
> > patches.
>
> The new code performs a single, necessary security state check at the entry
> point of the MMIO handlers. The rest of the logic relies on the banking
> mechanism, which makes the implementation generic for Non-secure, Secure,
> and future states like Realm/Root. The new structure looks like this:
>
> /* Structure for one register bank */
> typedef struct SMMUv3Bank {
> uint32_t idr[6]; /* IDR0-IDR5, note: IDR5 only used for NS bank */
> uint32_t cr[3]; /* CR0-CR2 */
> uint32_t cr0ack;
> uint32_t init; /* S_INIT register (secure only), reserved for NS
> */
> uint32_t gbpa;
>
> ......
>
> SMMUQueue eventq, cmdq;
> } SMMUv3Bank;
>
> struct SMMUv3State {
> SMMUState smmu_state;
>
> /* Shared (non-banked) registers and state */
> uint32_t features;
> uint8_t sid_size;
> uint8_t sid_split;
>
> ......
>
> /* Banked registers for all access */
> SMMUv3Bank bank[SMMU_SEC_IDX_NUM];
> ......
> };
>
Yes, IMO,that’s the right approach. Although that might make the
migration code more complicated as we changed the state struct.
Thanks,
Mostafa
>
> Thanks again for your valuable feedback. I've outlined my proposed plan
> above and would be grateful for any thoughts on it to ensure I'm on the
> right track for v2.
>
> Best regards,
>
> Tao
>
>
>
>
>
next prev parent reply other threads:[~2025-08-23 10:42 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-06 15:11 [RFC 00/11] hw/arm/smmuv3: Add initial support for Secure State Tao Tang
2025-08-06 15:11 ` [RFC 01/11] hw/arm/smmuv3: Introduce secure registers and commands Tao Tang
2025-08-11 10:22 ` Philippe Mathieu-Daudé
2025-08-11 10:43 ` Philippe Mathieu-Daudé
2025-08-18 21:21 ` Mostafa Saleh
2025-08-06 15:11 ` [RFC 02/11] hw/arm/smmuv3: Implement read/write logic for secure registers Tao Tang
2025-08-06 21:53 ` Pierrick Bouvier
2025-08-10 16:54 ` Tao Tang
2025-08-12 17:12 ` Pierrick Bouvier
2025-08-18 21:24 ` Mostafa Saleh
2025-08-20 15:21 ` Tao Tang
2025-08-23 10:41 ` Mostafa Saleh [this message]
2025-09-11 15:27 ` Tao Tang
2025-09-15 9:14 ` Mostafa Saleh
2025-09-15 9:34 ` Eric Auger
2025-08-06 15:11 ` [RFC 03/11] hw/arm/smmuv3: Implement S_INIT for secure initialization Tao Tang
2025-08-18 21:26 ` Mostafa Saleh
2025-08-20 16:01 ` Tao Tang
2025-08-06 15:11 ` [RFC 04/11] hw/arm/smmuv3: Enable command processing for the Secure state Tao Tang
2025-08-06 21:55 ` Pierrick Bouvier
2025-08-10 16:59 ` Tao Tang
2025-08-11 10:34 ` Philippe Mathieu-Daudé
2025-08-12 17:27 ` Pierrick Bouvier
2025-08-12 17:39 ` Philippe Mathieu-Daudé
2025-08-12 18:42 ` Peter Maydell
2025-08-15 6:02 ` Tao Tang
2025-08-15 14:53 ` Peter Maydell
2025-08-17 3:46 ` Tao Tang
2025-08-06 15:11 ` [RFC 05/11] hw/arm/smmuv3: Support secure event queue and error handling Tao Tang
2025-08-11 10:41 ` Philippe Mathieu-Daudé
2025-08-06 15:11 ` [RFC 06/11] hw/arm/smmuv3: Plumb security state through core functions Tao Tang
2025-08-18 21:28 ` Mostafa Saleh
2025-08-20 16:25 ` Tao Tang
2025-08-23 10:43 ` Mostafa Saleh
2025-08-06 15:11 ` [RFC 07/11] hw/arm/smmuv3: Add separate address space for secure SMMU accesses Tao Tang
2025-08-06 15:11 ` [RFC 08/11] hw/arm/smmuv3: Enable secure-side stage 2 TLB invalidations Tao Tang
2025-08-06 15:11 ` [RFC 09/11] hw/arm/smmuv3: Make the configuration cache security-state aware Tao Tang
2025-08-06 15:11 ` [RFC 10/11] hw/arm/smmuv3: Differentiate secure TLB entries via keying Tao Tang
2025-08-06 21:11 ` [RFC 00/11] hw/arm/smmuv3: Add initial support for Secure State Pierrick Bouvier
2025-08-06 21:28 ` Pierrick Bouvier
2025-08-10 16:11 ` Tao Tang
2025-08-11 10:26 ` Philippe Mathieu-Daudé
2025-08-12 17:50 ` Pierrick Bouvier
2025-08-12 18:04 ` Pierrick Bouvier
2025-08-15 5:49 ` Tao Tang
2025-09-30 4:04 ` Tao Tang
2025-08-18 21:52 ` Mostafa Saleh
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=aKma98hlAWG9M4h_@google.com \
--to=smostafa@google.com \
--cc=chenbaozi@phytium.com.cn \
--cc=eric.auger@redhat.com \
--cc=jean-philippe@linaro.org \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=pierrick.bouvier@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=tangtao1634@phytium.com.cn \
/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.