platform: generic-arm64: Map MMIO addresses with GUARD

This change adds mapping of MMIO regions of GIC and UART registers using
MMIO GUARD. MMIO Guard is enforced when pvmfw is in use. Without mapping
those regions the pKVM issues a data aborts on each write and read to mmio.
This patch addresses this for GIC and UART.

Bug: 375584439
Test: boot trusty with pvmfw and verify that it boots and UART works
Change-Id: I92d8bc1c56c6d07c152917ce985ac503aa4ea1b1
Signed-off-by: Bartłomiej Grzesik <bgrzesik@google.com>
diff --git a/platform/generic-arm64/debug.c b/platform/generic-arm64/debug.c
index 514791b..84edf82 100644
--- a/platform/generic-arm64/debug.c
+++ b/platform/generic-arm64/debug.c
@@ -27,6 +27,10 @@
 #include <lk/reg.h>
 #include <lk/types.h>
 #include <platform/debug.h>
+#if MMIO_GUARD_ENABLED
+#include <err.h>
+#include <lib/libhypervisor/libhypervisor.h>
+#endif
 
 #include "debug.h"
 
@@ -62,6 +66,19 @@
     if (ret) {
         return;
     }
+
+#if MMIO_GUARD_ENABLED
+    /*
+     * MMIO Guard map UART registers. Ignore not supported which implies that
+     * guard is not used.
+     */
+    ret = hypervisor_mmio_map_region(reg_pbase, PAGE_SIZE);
+    if (ret != NO_ERROR && ret != ERR_NOT_SUPPORTED) {
+        dprintf(CRITICAL, "failed to mmio guard map uart. error=%d\n", ret);
+        return;
+    }
+#endif
+
     uart_type = new_uart_type;
     uart_base = (uint8_t*)page_vaddr + (reg_paddr - reg_pbase);
 }
diff --git a/platform/generic-arm64/platform.c b/platform/generic-arm64/platform.c
index 16568a3..93ce40d 100644
--- a/platform/generic-arm64/platform.c
+++ b/platform/generic-arm64/platform.c
@@ -33,6 +33,9 @@
 #include <sys/types.h>
 #if ARM64_BOOT_PROTOCOL_X0_DTB
 #include <vsock/vsock.h>
+#if MMIO_GUARD_ENABLED
+#include <lib/libhypervisor/libhypervisor.h>
+#endif
 #endif
 
 #include "debug.h"
@@ -246,6 +249,25 @@
                 GICR_SIZE);
         return;
     }
+
+#if MMIO_GUARD_ENABLED
+    /*
+     * MMIO Guard map GIC addresses. Ignore not supported which implies that
+     * guard is not used.
+     */
+    ret = hypervisor_mmio_map_region(gicc, GICC_SIZE);
+    if (ret != NO_ERROR && ret != ERR_NOT_SUPPORTED) {
+        dprintf(CRITICAL, "failed to mmio guard map gicc. error=%d\n", ret);
+    }
+    ret = hypervisor_mmio_map_region(gicd, GICD_SIZE);
+    if (ret != NO_ERROR && ret != ERR_NOT_SUPPORTED) {
+        dprintf(CRITICAL, "failed to mmio guard map gicd. error=%d\n", ret);
+    }
+    ret = hypervisor_mmio_map_region(gicr, GICR_SIZE);
+    if (ret != NO_ERROR && ret != ERR_NOT_SUPPORTED) {
+        dprintf(CRITICAL, "failed to mmio guard map gicr. error=%d\n", ret);
+    }
+#endif
 #else
 #error "Unknown ARM64_BOOT_PROTOCOL"
 #endif
diff --git a/platform/generic-arm64/rules.mk b/platform/generic-arm64/rules.mk
index 02a82ec..3f2d878 100644
--- a/platform/generic-arm64/rules.mk
+++ b/platform/generic-arm64/rules.mk
@@ -106,4 +106,13 @@
 MODULE_DEPS += trusty/kernel/lib/arm_ffa
 endif
 
+# MMIO Guard support
+MMIO_GUARD_ENABLED ?= false
+ifeq (true,$(call TOBOOL,$(MMIO_GUARD_ENABLED)))
+MODULE_DEPS += \
+	$(LKROOT)/lib/libhypervisor
+
+MODULE_DEFINES += MMIO_GUARD_ENABLED=1
+endif
+
 include make/module.mk