19
#include "smmuv3-internal.h"
20
#include "smmuv3-accel.h"
21
#include "system/system.h"
22
+#include "tegra241-cmdqv.h"
23
24
/*
25
* The root region aliases the global system memory, and shared_as_sysmem
571
Error **errp)
572
{
573
SMMUv3AccelState *accel = s->s_accel;
574
+ const SMMUv3AccelCmdqvOps *cmdqv_ops = accel->cmdqv_ops;
575
struct iommu_hwpt_arm_smmuv3 bypass_data = {
576
.ste = { SMMU_STE_CFG_BYPASS | SMMU_STE_VALID, 0x0ULL },
577
};
582
uint32_t viommu_id, hwpt_id;
583
IOMMUFDViommu *viommu;
584
583
- if (!iommufd_backend_alloc_viommu(hiodi->iommufd, hiodi->devid,
584
- IOMMU_VIOMMU_TYPE_ARM_SMMUV3, s2_hwpt_id,
585
- NULL, 0, &viommu_id, errp)) {
586
- return false;
585
+ if (cmdqv_ops) {
586
+ if (!cmdqv_ops->alloc_viommu(s, hiodi, &viommu_id, errp)) {
587
+ return false;
588
+ }
589
+ } else {
590
+ if (!iommufd_backend_alloc_viommu(hiodi->iommufd, hiodi->devid,
591
+ IOMMU_VIOMMU_TYPE_ARM_SMMUV3,
592
+ s2_hwpt_id, NULL, 0, &viommu_id,
593
+ errp)) {
594
+ return false;
595
+ }
596
}
597
598
viommu = g_new0(IOMMUFDViommu, 1);
638
free_abort_hwpt:
639
iommufd_backend_free_id(hiodi->iommufd, accel->abort_hwpt_id);
640
free_viommu:
632
- iommufd_backend_free_id(hiodi->iommufd, viommu->viommu_id);
641
+ if (cmdqv_ops && cmdqv_ops->free_viommu) {
642
+ cmdqv_ops->free_viommu(s);
643
+ } else {
644
+ iommufd_backend_free_id(hiodi->iommufd, viommu->viommu_id);
645
+ }
646
g_free(viommu);
647
accel->viommu = NULL;
648
return false;
649
}
650
651
+static const SMMUv3AccelCmdqvOps *
652
+smmuv3_accel_probe_cmdqv(SMMUv3State *s, HostIOMMUDeviceIOMMUFD *idev,
653
+ Error **errp)
654
+{
655
+ const SMMUv3AccelCmdqvOps *ops = tegra241_cmdqv_get_ops();
656
+
657
+ if (!ops) {
658
+ error_setg(errp, "No CMDQV ops found");
659
+ return NULL;
660
+ }
661
+ g_assert(ops->probe);
662
+ g_assert(ops->alloc_viommu);
663
+
664
+ if (!ops->probe(s, idev, errp)) {
665
+ return NULL;
666
+ }
667
+ return ops;
668
+}
669
+
670
+static bool
671
+smmuv3_accel_select_cmdqv(SMMUv3State *s, HostIOMMUDeviceIOMMUFD *idev,
672
+ Error **errp)
673
+{
674
+ const SMMUv3AccelCmdqvOps *ops = NULL;
675
+
676
+ if (s->s_accel->cmdqv_ops) {
677
+ return true;
678
+ }
679
+
680
+ switch (s->cmdqv) {
681
+ case ON_OFF_AUTO_OFF:
682
+ s->s_accel->cmdqv_ops = NULL;
683
+ return true;
684
+ case ON_OFF_AUTO_AUTO:
685
+ ops = smmuv3_accel_probe_cmdqv(s, idev, NULL);
686
+ break;
687
+ case ON_OFF_AUTO_ON:
688
+ ops = smmuv3_accel_probe_cmdqv(s, idev, errp);
689
+ if (!ops) {
690
+ error_append_hint(errp, "CMDQV requested but not supported");
691
+ return false;
692
+ }
693
+ break;
694
+ default:
695
+ g_assert_not_reached();
696
+ }
697
+
698
+ if (ops && ops->init && !ops->init(s, errp)) {
699
+ return false;
700
+ }
701
+ s->s_accel->cmdqv_ops = ops;
702
+ return true;
703
+}
704
+
705
static bool smmuv3_accel_set_iommu_device(PCIBus *bus, void *opaque, int devfn,
706
HostIOMMUDevice *hiod, Error **errp)
707
{
736
goto done;
737
}
738
739
+ if (!smmuv3_accel_select_cmdqv(s, hiodi, errp)) {
740
+ return false;
741
+ }
742
+
743
if (!smmuv3_accel_alloc_viommu(s, hiodi, errp)) {
744
error_append_hint(errp, "Unable to alloc vIOMMU: hiodi devid 0x%x: ",
745
hiodi->devid);
1017
1018
void smmuv3_accel_reset(SMMUv3State *s)
1019
{
949
- /* Attach a HWPT based on GBPA reset value */
950
- smmuv3_accel_attach_gbpa_hwpt(s, NULL);
1020
+ SMMUv3AccelState *accel = s->s_accel;
1021
+
1022
+ if (!accel) {
1023
+ return;
1024
+ }
1025
+ /* Attach a HWPT based on GBPA reset value */
1026
+ smmuv3_accel_attach_gbpa_hwpt(s, NULL);
1027
+
1028
+ if (accel->cmdqv_ops && accel->cmdqv_ops->reset) {
1029
+ accel->cmdqv_ops->reset(s);
1030
+ }
1031
}
1032
1033
static void smmuv3_accel_as_init(SMMUv3State *s)