On Thu, Mar 12, 2026 at 11:05:36AM -0700, Shameer Kolothum Thodi wrote:
> > I understand. But guest works in HYP_OWN mode as it sets the HYP_OWN
> > bit. So resetting it looks like a hack to me, not documented in any way
> > in the spec. Besides, as tegra241_guest_vcmdq_supports_cmd() forces to
> > send on the cmdqv cmdq only legal cmds I don't see any problem leaving
> > the bit to 1. What is important is that the host does the check (and the
> > host sets HYP_OWN to 0 for that cmdq). I did the trial to comment
> >         //value &= ~R_VINTF0_CONFIG_HYP_OWN_MASK;
> > 
> > and it seems to work properly
> 
> Ah.. that’s interesting. .I was under the impression that we are toggling
> the HYP_OWN so that guest does sets the tegra241_guest_vcmdq_supports_cmd()
> correctly and delegates the supported cmds through that queue.
> 
> See, 
>     tegra241_cmdqv_init_structures()
>         tegra241_vintf_alloc_lvcmdq()
>           tegra241_vcmdq_alloc_smmu_cmdq()
>           {
>                .... 
>                 if (!vcmdq->vintf->hyp_own)
>                       cmdq->supports_cmd = tegra241_guest_vcmdq_supports_cmd;
>             
> However, it looks like the above happens before tegra241_vintf_hw_init(),
> which sets HYP_OWN. That may explain why toggling the bit here does not
> make any difference.

Well, looks like we exposed a kernel bug...

It seems that the sequence of setting hyp_own and supports_cmd got
inverted during a rework when I got the driver upstream.

It turned out that both host and guest kernels sets supports_cmd to
tegra241_guest_vcmdq_supports_cmd().. IOW, the host is sending non-
invalidation commands to the SMMU CMDQ rather than the HYP_OWNed
VCMDQ, although this is completely harmless and probably does not
affect host performance at all since non-invalidation commands are
not that frequently issued.

This explains why Eric's experiment didn't fail. I'll submit a fix.

With that being said, in QEMU we do need to wire HYP_OWN bit to 0.
This is not decided by the spec, but by the host SW implementation:

 550         /*
 551          * Note that HYP_OWN bit is wired to zero when running in guest 
kernel,
 552          * whether enabling it here or not, as !HYP_OWN cmdq HWs only 
support a
 553          * restricted set of supported commands.
 554          */
 555         regval = FIELD_PREP(VINTF_HYP_OWN, hyp_own) | 
 556                  FIELD_PREP(VINTF_VMID, vintf->vsmmu.vmid);
 557         writel(regval, REG_VINTF(vintf, CONFIG));
 558
 559         ret = vintf_write_config(vintf, regval | VINTF_EN);
 560         if (ret)
 561                 return ret;
 562         /*
 563          * As being mentioned above, HYP_OWN bit is wired to zero for a 
guest
 564          * kernel, so read it back from HW to ensure that reflects in 
hyp_own
 565          */
 566         vintf->hyp_own = !!(VINTF_HYP_OWN & readl(REG_VINTF(vintf, 
CONFIG)));

This should have been mentioned in the uAPI header. I'll submit a
patch to add this line near IOMMU_VIOMMU_TYPE_TEGRA241_CMDQV.

One thing we need to get our head around is that a guest hardware
is different than the host hardware:
 - Host HW is backed by a VINTF (HYP_OWN=1)
 - Guest HW is backed by a VINTF (HYP_OWN=0)
This is a fixed configuration, decided by the hardware and the spec
also.

Thus, the guest version of the VINTF must align with its underlying
hardware, so QEMU cannot allow setting HYP_OWN=1.

Otherwise, guest OS would have no idea this is a guest version of
hardware and would issue unsupported commands that will fail.

Nicolin

Reply via email to