The stub always requests ARM_DRTM_LAUNCH_DMA_COMPLETE. On a system
with an SMMU the COMPLETE option is sanely implemented using the SMMU
global abort register. DMA_COMPLETE should be mostly a no-op. It
seems to be designed for the region protection mode that Linux does
not use.

However, the FW can still do something interesting under it and we
should call it. Choose late_initcall as we know the SMMU drivers are
loaded by then. If some platform does actually block DMA beyond the
SMMU, then this would result in a noisy failure of built-in driver
DMA, not a silent security gap.

The platforms I'm aware of are OK with this placement, and it is a
reasonable place to start.

Signed-off-by: Jason Gunthorpe <[email protected]>
---
 arch/arm64/kernel/drtm.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/arch/arm64/kernel/drtm.c b/arch/arm64/kernel/drtm.c
index 14493948a27f0d..3d1af2d34c987e 100644
--- a/arch/arm64/kernel/drtm.c
+++ b/arch/arm64/kernel/drtm.c
@@ -3,8 +3,47 @@
  *
  * Support functions for ARM DEN 0113 "DRTM Architecture for Arm"
  */
+#include <linux/bug.h>
 #include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/printk.h>
 
 #include <asm/drtm.h>
 
 struct arm64_drtm_handoff arm64_drtm_handoff __efi_data_handoff;
+
+static int __init arm64_drtm_unprotect_memory(void)
+{
+       s64 status;
+
+       if (!arm64_drtm_handoff.drtm_enabled)
+               return 0;
+
+       /*
+        * Currently Linux can only fully support a DRTM implementation that
+        * relies only the SMMU. This should be called directly after attaching
+        * a driver to every SMMU but before binding any drivers that want to
+        * use devices attached to the SMMU. Our boot flow does not have a way
+        * to do that, so for now call it here.
+        *
+        * For SMMU based implementations their UNPROTECT_MEMORY is probably a
+        * NOP since touching the SMMU here is forbidden, but they may still do
+        * something interesting so be sure to call it at least.
+        *
+        * The stub excludes the most likely case of non-SMMU by only using
+        * ARM_DRTM_LAUNCH_DMA_COMPLETE, which is defined as:
+        *    Complete DMA protection is hardware-based enforcement at the SMMU
+        *    that blocks all DMA from Non- secure devices."
+        *
+        * For now if people have such systems they cannot include built-in
+        * drivers for any DMA devices, those have to be modules to be ordered
+        * after this.
+        */
+       status = arm_drtm_unprotect_memory();
+       WARN(status != ARM_DRTM_SUCCESS,
+            "DRTM: failed to unprotect memory (x0=%lld)", status);
+       if (status == ARM_DRTM_SUCCESS)
+               pr_info("DRTM: launch completed\n");
+       return 0;
+}
+late_initcall_sync(arm64_drtm_unprotect_memory);
-- 
2.43.0


Reply via email to