arch: arm64: take top-byte-ignore into account when checking addresses

Test: boot
Change-Id: I724a5d22ebfa7fe93bd0538f3409e625173a480b
diff --git a/arch/arm/include/arch/tbi.h b/arch/arm/include/arch/tbi.h
new file mode 100644
index 0000000..16d1239
--- /dev/null
+++ b/arch/arm/include/arch/tbi.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022, Google Inc. All rights reserved
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+
+static inline vaddr_t arch_adjusted_vaddr(vaddr_t addr, __UNUSED bool kernel)
+{
+    return addr;
+}
diff --git a/arch/arm64/include/arch/tbi.h b/arch/arm64/include/arch/tbi.h
new file mode 100644
index 0000000..5198bc5
--- /dev/null
+++ b/arch/arm64/include/arch/tbi.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022, Google Inc. All rights reserved
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+
+#include "arch/arm64.h"
+
+static inline vaddr_t arch_adjusted_vaddr(vaddr_t addr, bool kernel)
+{
+    if (ARM64_READ_SYSREG(tcr_el1) & (kernel ? MMU_TCR_TBI1 : MMU_TCR_TBI0)) {
+        if (addr & 0x0080000000000000) {
+            return addr | 0xff00000000000000;
+        } else {
+            return addr & 0x00ffffffffffffff;
+        }
+    }
+    return addr;
+}
diff --git a/arch/arm64/mmu.c b/arch/arm64/mmu.c
index 186b734..d2c63a1 100644
--- a/arch/arm64/mmu.c
+++ b/arch/arm64/mmu.c
@@ -61,8 +61,14 @@
     return aspace->asid & BIT_MASK(ARM64_ASID_BITS);
 }
 
+static inline vaddr_t adjusted_vaddr(arch_aspace_t *aspace, vaddr_t vaddr)
+{
+    return arch_adjusted_vaddr(vaddr, aspace->flags & ARCH_ASPACE_FLAG_KERNEL);
+}
+
 static inline bool is_valid_vaddr(arch_aspace_t *aspace, vaddr_t vaddr)
 {
+    vaddr = adjusted_vaddr(aspace, vaddr);
     return (vaddr >= aspace->base && vaddr <= aspace->base + (aspace->size - 1));
 }
 
@@ -140,6 +146,7 @@
     if (!is_valid_vaddr(aspace, vaddr))
         return ERR_OUT_OF_RANGE;
 
+    vaddr = adjusted_vaddr(aspace, vaddr);
     /* compute shift values based on if this address space is for kernel or user space */
     if (aspace->flags & ARCH_ASPACE_FLAG_KERNEL) {
         index_shift = MMU_KERNEL_TOP_SHIFT;
@@ -572,6 +579,8 @@
     if (!is_valid_vaddr(aspace, vaddr))
         return ERR_OUT_OF_RANGE;
 
+    vaddr = adjusted_vaddr(aspace, vaddr);
+
     /* paddr and vaddr must be aligned */
     DEBUG_ASSERT(IS_PAGE_ALIGNED(vaddr));
     DEBUG_ASSERT(IS_PAGE_ALIGNED(paddr));
@@ -617,6 +626,8 @@
     if (!is_valid_vaddr(aspace, vaddr))
         return ERR_OUT_OF_RANGE;
 
+    vaddr = adjusted_vaddr(aspace, vaddr);
+
     DEBUG_ASSERT(IS_PAGE_ALIGNED(vaddr));
     if (!IS_PAGE_ALIGNED(vaddr))
         return ERR_INVALID_ARGS;
diff --git a/arch/x86/include/arch/tbi.h b/arch/x86/include/arch/tbi.h
new file mode 100644
index 0000000..16d1239
--- /dev/null
+++ b/arch/x86/include/arch/tbi.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022, Google Inc. All rights reserved
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <sys/types.h>
+
+static inline vaddr_t arch_adjusted_vaddr(vaddr_t addr, __UNUSED bool kernel)
+{
+    return addr;
+}
diff --git a/include/kernel/vm.h b/include/kernel/vm.h
index afcbb74..3977184 100644
--- a/include/kernel/vm.h
+++ b/include/kernel/vm.h
@@ -52,6 +52,7 @@
 #include <stdlib.h>
 #include <arch.h>
 #include <arch/mmu.h>
+#include <arch/tbi.h>
 #include <kernel/vm_obj.h>
 #include <lib/binary_search_tree.h>
 #include <lk/reflist.h>
@@ -106,6 +107,7 @@
 
 static inline bool is_kernel_address(vaddr_t va)
 {
+    va = arch_adjusted_vaddr(va, true);
     return (va >= (vaddr_t)KERNEL_ASPACE_BASE && va <= ((vaddr_t)KERNEL_ASPACE_BASE + ((vaddr_t)KERNEL_ASPACE_SIZE - 1)));
 }
 
@@ -121,6 +123,7 @@
 
 static inline bool is_user_address(vaddr_t va)
 {
+    va = arch_adjusted_vaddr(va, false);
     return (va >= USER_ASPACE_BASE && va <= (USER_ASPACE_BASE + (USER_ASPACE_SIZE - 1)));
 }