--- v3
+++ v5
@@ -1,49 +1,77 @@
-Look in .note.gnu.property of an ELF file and check if Indirect
-Branch Tracking needs to be enabled for the task.
+Indirect branch tracking provides an optional legacy code bitmap
+that indicates locations of non-IBT compatible code. When set,
+each bit in the bitmap represents a page in the linear address is
+legacy code.
-Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
+We allocate the bitmap only when the application requests it.
+Most applications do not need the bitmap.
+
Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
---
- arch/x86/include/uapi/asm/elf_property.h | 1 +
- arch/x86/kernel/elf.c | 8 +++++++-
- 2 files changed, 8 insertions(+), 1 deletion(-)
+ arch/x86/kernel/cet.c | 47 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 47 insertions(+)
-diff --git a/arch/x86/include/uapi/asm/elf_property.h b/arch/x86/include/uapi/asm/elf_property.h
-index af361207718c..343a871b8fc1 100644
---- a/arch/x86/include/uapi/asm/elf_property.h
-+++ b/arch/x86/include/uapi/asm/elf_property.h
-@@ -11,5 +11,6 @@
- * Bits for GNU_PROPERTY_X86_FEATURE_1_AND
- */
- #define GNU_PROPERTY_X86_FEATURE_1_SHSTK (0x00000002)
-+#define GNU_PROPERTY_X86_FEATURE_1_IBT (0x00000001)
+diff --git a/arch/x86/kernel/cet.c b/arch/x86/kernel/cet.c
+index 40c4c08e5e31..77ae4eaa9dea 100644
+--- a/arch/x86/kernel/cet.c
++++ b/arch/x86/kernel/cet.c
+@@ -21,6 +21,7 @@
+ #include <asm/compat.h>
+ #include <asm/cet.h>
+ #include <asm/special_insns.h>
++#include <asm/elf.h>
- #endif /* _UAPI_ASM_X86_ELF_PROPERTY_H */
-diff --git a/arch/x86/kernel/elf.c b/arch/x86/kernel/elf.c
-index a2c41bf39c58..41957f1bd9d0 100644
---- a/arch/x86/kernel/elf.c
-+++ b/arch/x86/kernel/elf.c
-@@ -298,7 +298,8 @@ int arch_setup_features(void *ehdr_p, void *phdr_p,
-
- struct elf64_hdr *ehdr64 = ehdr_p;
-
-- if (!cpu_feature_enabled(X86_FEATURE_SHSTK))
-+ if (!cpu_feature_enabled(X86_FEATURE_SHSTK) &&
-+ !cpu_feature_enabled(X86_FEATURE_IBT))
- return 0;
-
- if (ehdr64->e_ident[EI_CLASS] == ELFCLASS64) {
-@@ -333,6 +334,11 @@ int arch_setup_features(void *ehdr_p, void *phdr_p,
- }
- }
-
-+ if (cpu_feature_enabled(X86_FEATURE_IBT)) {
-+ if (feature & GNU_PROPERTY_X86_FEATURE_1_IBT)
-+ err = cet_setup_ibt();
+ static int set_shstk_ptr(unsigned long addr)
+ {
+@@ -327,3 +328,49 @@ void cet_disable_ibt(void)
+ wrmsrl(MSR_IA32_U_CET, r);
+ current->thread.cet.ibt_enabled = 0;
+ }
++
++int cet_setup_ibt_bitmap(void)
++{
++ u64 r;
++ unsigned long bitmap;
++ unsigned long size;
++
++ if (!cpu_feature_enabled(X86_FEATURE_IBT))
++ return -EOPNOTSUPP;
++
++ if (!current->thread.cet.ibt_bitmap_addr) {
++ /*
++ * Calculate size and put in thread header.
++ * may_expand_vm() needs this information.
++ */
++ size = in_compat_syscall() ? task_size_32bit() : task_size_64bit(1);
++ size = size / PAGE_SIZE / BITS_PER_BYTE;
++ current->thread.cet.ibt_bitmap_size = size;
++ bitmap = do_mmap_locked(0, size, PROT_READ | PROT_WRITE,
++ MAP_ANONYMOUS | MAP_PRIVATE,
++ VM_DONTDUMP);
++
++ if ((bitmap >= TASK_SIZE) || (bitmap < size)) {
++ current->thread.cet.ibt_bitmap_size = 0;
++ return -ENOMEM;
++ }
++
++ current->thread.cet.ibt_bitmap_addr = bitmap;
++
++ /*
++ * Lower bits of MSR_IA32_CET_LEG_IW_EN are for IBT
++ * settings. Clear lower bits even bitmap is already
++ * page-aligned.
++ */
++ bitmap &= PAGE_MASK;
++
++ /*
++ * Turn on IBT legacy bitmap.
++ */
++ rdmsrl(MSR_IA32_U_CET, r);
++ r |= (MSR_IA32_CET_LEG_IW_EN | bitmap);
++ wrmsrl(MSR_IA32_U_CET, r);
+ }
+
- out:
- return err;
- }
++ return 0;
++}
--
2.17.1