Hi Steve,
On 02/18/2019 10:32 PM, Steve Capper wrote:
When running with a 52-bit userspace VA and a 48-bit kernel VA we offset
ttbr1_el1 to allow the kernel pagetables with a 52-bit PTRS_PER_PGD to
be used for both userspace and kernel.
Moving on to a 52-bit kernel VA we no longer require this offset to
ttbr1_el1 should we be running on a system with HW support for 52-bit
VAs.
This patch introduces alternative logic to offset_ttbr1 and expands out
the very early case in head.S. We need to use the alternative framework
as offset_ttbr1 is used in places in the kernel where it is not possible
to safely adrp address kernel constants (such as the kpti paths); thus
code patching is the safer route.
Signed-off-by: Steve Capper <steve.capper@xxxxxxx>
---
arch/arm64/include/asm/assembler.h | 10 +++++++++-
arch/arm64/include/asm/cpucaps.h | 3 ++-
arch/arm64/kernel/cpufeature.c | 18 ++++++++++++++++++
arch/arm64/kernel/head.S | 14 +++++++++++++-
arch/arm64/kernel/hibernate-asm.S | 1 +
5 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 4feb6119c3c9..58ed5d086e1e 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -551,6 +551,14 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
.macro offset_ttbr1, ttbr
#ifdef CONFIG_ARM64_USER_VA_BITS_52
orr \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET
+#endif
+
+#ifdef CONFIG_ARM64_USER_KERNEL_VA_BITS_52
+alternative_if_not ARM64_HAS_52BIT_VA
+ orr \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET
+alternative_else
+ nop
+alternative_endif
#endif
.endm
@@ -560,7 +568,7 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
* to be nop'ed out when dealing with 52-bit kernel VAs.
*/
.macro restore_ttbr1, ttbr
-#ifdef CONFIG_ARM64_USER_VA_BITS_52
+#if defined(CONFIG_ARM64_USER_VA_BITS_52) || defined(CONFIG_ARM64_KERNEL_VA_BITS_52)
bic \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET
#endif
.endm
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 82e9099834ae..d71aecb6d6db 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -60,7 +60,8 @@
#define ARM64_HAS_ADDRESS_AUTH_IMP_DEF 39
#define ARM64_HAS_GENERIC_AUTH_ARCH 40
#define ARM64_HAS_GENERIC_AUTH_IMP_DEF 41
+#define ARM64_HAS_52BIT_VA 42
-#define ARM64_NCAPS 42
+#define ARM64_NCAPS 43
#endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index f6d84e2c92fe..2e150c564f2a 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -944,6 +944,16 @@ has_useable_cnp(const struct arm64_cpu_capabilities *entry, int scope)
return has_cpuid_feature(entry, scope);
}
+#ifdef CONFIG_ARM64_USER_KERNEL_VA_BITS_52
+extern u64 vabits_actual;
+static bool __maybe_unused
+has_52bit_kernel_va(const struct arm64_cpu_capabilities *entry, int scope)
+{
+ return vabits_actual == 52;
+}
+
+#endif /* CONFIG_ARM64_USER_KERNEL_VA_BITS_52 */
+
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
@@ -1480,6 +1490,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.matches = has_cpuid_feature,
},
#endif /* CONFIG_ARM64_PTR_AUTH */
+#ifdef CONFIG_ARM64_USER_KERNEL_VA_BITS_52
+ {
+ .desc = "52-bit kernel VA",
+ .capability = ARM64_HAS_52BIT_VA,
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .matches = has_52bit_kernel_va,
+ },
+#endif /* CONFIG_ARM64_USER_KERNEL_VA_BITS_52 */
{},
};
Right, so now the question is how do we export the 52-bit VA properties
(that we select in the kernel) to user-space. There are two things to
consider:
a). CPUs which support ARMv8.2-LVA + newer kernels which export 52-bit
address capabilities:
- Right now, neither the cpu-feature-registers interface (see [1]) nor
the HWCAPS interface (see [2]), provide a mechanism to export these
properties to the user-space.
- I had shared a patch in the past for enabling atleast LVA and LPA
extension bits to be exported via the cpu-feature-registers interface
(See:
http://lists.infradead.org/pipermail/kexec/2019-January/022371.html),
but we didn't make much progress on the same.
May be Suzuki (in Cc), will have more comments on the same.
[1].
https://www.kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt
[2]. https://www.kernel.org/doc/Documentation/arm64/elf_hwcaps.txt
b). CPUs which do not support ARMv8.2-LVA + newer kernels which export
52-bit address capabilities:
- Right now, for older CPUs running with kernels with
CONFIG_ARM64_USER_KERNEL_VA_BITS_52=y, if we have:
VA_BITS = 52,
VA_BITS_ACTUAL = vabits_actual = 48,
VA_BITS_MIN = min (48, VA_BITS) = 48.
Now, we need to make user-space aware of the VA_BITS_ACTUAL value, so
that it can process virtual addresses. Let's consider two different
use-cases which are normally used to debug live-kernel or debug crashes
(via kdump):
- Calculating 'vaddr_to_paddr' for a given vaddr (provided to user-space
for e.g from /proc/kcore file).
A). An essential part of the calculation is to know if the provided
vaddr lies in the linear map range. In kernel, we use the following
computation to determine whether an address lies in the linear map range:
#define __is_lm_address(addr) (!((addr) & BIT(VA_BITS_ACTUAL - 1)))
A similar check is performed in user-space utilities while performing
live debugging to determine paddr value for a given vaddr (for
performing a page-table walk).
So, we need a mechanism to have the VA_BITS_ACTUAL value in user-space.
Reading kernel CONFIG flags, vmlinux information and /proc/kallsyms is
not a portable approach for all user-space use-cases, hence we need a
standard method of exporting this information to user-space.
May be something like a
'/sys/devices/system/cpu/addressing-capabilities' node? (similar to
'/sys/devices/system/cpu/vulnerabilities' we added for sideband
vulnerabilities).
I understand that it may be difficult to standardize a 'sysfs'
placeholder for different archs for addressing ranges, but I am just
thinking out loud here.
May be something like:
+ssize_t cpu_show_address_capabilities(struct device *dev, struct
device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "va_bits_actual: %ld\n", vabits_actual);
+}
and more..
See
<https://github.com/torvalds/linux/blob/master/arch/x86/kernel/cpu/bugs.c#L1188>
for an example.
B). Debugging a crash dump obtained on one arm64 system (say a
reporter's machine with VA_BITS_ACTUAL = 48) on another arm64 system
(say the maintainer's machine with VA_BITS_ACTUAL = 52)
So, we again need a mechanism to have the VA_BITS_ACTUAL value in crash
vmcore dump'ed on the reporter's machine.
Note, that reading kernel CONFIG flags, vmlinux information or
/proc/kallsyms on the maintainer's machine will not help in such cases
as they can be different from the configuration on the reporter's machine.
In such case, it is _mandatory_ to have VA_BITS_ACTUAL information
exported in vmcoreinfo. Also since commit 23c85094fe18 ("proc/kcore: add
vmcoreinfo note to /proc/kcore"), we have the same information available
in kcore.
So, it would make sense to have the following patch for exporting
VA_BITS_ACTUAL information in vmcoreinfo. I would suggest that we have
the same added in the re-worked version v2 of the patchset so that the
user-space works as expected:
----------------------------x
From 0a4f30357932bf2addd1dda66acde8c26ecd3f75 Mon Sep 17 00:00:00 2001
From: Bhupesh Sharma <bhsharma@xxxxxxxxxx>
Date: Wed, 3 Apr 2019 16:27:10 +0530
Subject: [PATCH] arm64/crash_core: Export VA_BITS_ACTUAL in vmcoreinfo
VA_BITS_ACTUAL indicates the actual VA_BITS detected at boot time which
is required for determining 52-bit kernel address support at boot time.
User-space utilities like makedumpfile and crash-utility, need to
read/write this value from/to vmcoreinfo for determining if a virtual
address lies in the linear map range.
The user-space computation for determining whether an address lies in
the linear map range is the same as we have in kernel-space:
#define __is_lm_address(addr) (!((addr) & BIT(VA_BITS_ACTUAL - 1)))
Signed-off-by: Bhupesh Sharma <bhsharma@xxxxxxxxxx>
---
Documentation/kdump/vmcoreinfo.txt | 7 +++++++
arch/arm64/kernel/crash_core.c | 1 +
2 files changed, 8 insertions(+)
diff --git a/Documentation/kdump/vmcoreinfo.txt
b/Documentation/kdump/vmcoreinfo.txt
index bb94a4bd597a..a23ae95e3a93 100644
--- a/Documentation/kdump/vmcoreinfo.txt
+++ b/Documentation/kdump/vmcoreinfo.txt
@@ -376,6 +376,13 @@ VA_BITS
The maximum number of bits for virtual addresses. Used to compute the
virtual memory ranges.
+VA_BITS_ACTUAL
+--------------
+
+Indicates the actual VA_BITS detected at boot time, i.e. the maximum
+number of bits for virtual addresses. Required for determing 52-bit kernel
+address support at boot time.
+
kimage_voffset
--------------
diff --git a/arch/arm64/kernel/crash_core.c b/arch/arm64/kernel/crash_core.c
index ca4c3e12d8c5..1cde442ce8b2 100644
--- a/arch/arm64/kernel/crash_core.c
+++ b/arch/arm64/kernel/crash_core.c
@@ -10,6 +10,7 @@
void arch_crash_save_vmcoreinfo(void)
{
VMCOREINFO_NUMBER(VA_BITS);
+ VMCOREINFO_NUMBER(VA_BITS_ACTUAL);
/* Please note VMCOREINFO_NUMBER() uses "%d", not "%x" */
vmcoreinfo_append_str("NUMBER(kimage_voffset)=0x%llx\n",
kimage_voffset);
--
2.7.4
Please let me know your views.
Thanks,
Bhupesh
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 68c391b26858..4877b82d2091 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -789,7 +789,19 @@ ENTRY(__enable_mmu)
phys_to_ttbr x1, x1
phys_to_ttbr x2, x2
msr ttbr0_el1, x2 // load TTBR0
- offset_ttbr1 x1
+
+#if defined(CONFIG_ARM64_USER_VA_BITS_52)
+ orr x1, x1, #TTBR1_BADDR_4852_OFFSET
+#endif
+
+#if defined(CONFIG_ARM64_USER_KERNEL_VA_BITS_52)
+ ldr_l x3, vabits_actual
+ cmp x3, #52
+ b.eq 1f
+ orr x1, x1, #TTBR1_BADDR_4852_OFFSET
+1:
+#endif
+
msr ttbr1_el1, x1 // load TTBR1
isb
msr sctlr_el1, x0
diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernate-asm.S
index fe36d85c60bd..d32725a2b77f 100644
--- a/arch/arm64/kernel/hibernate-asm.S
+++ b/arch/arm64/kernel/hibernate-asm.S
@@ -19,6 +19,7 @@
#include <linux/linkage.h>
#include <linux/errno.h>
+#include <asm/alternative.h>
#include <asm/asm-offsets.h>
#include <asm/assembler.h>
#include <asm/cputype.h>
_______________________________________________
kexec mailing list
kexec@xxxxxxxxxxxxxxxxxxx
http://lists.infradead.org/mailman/listinfo/kexec