From 983e3630e3058b2deac4be17f3b8ee9dc6769f41 Mon Sep 17 00:00:00 2001
From: Ayyappa Ch <ayyappa.chandolu@amd.com>
Date: Tue, 28 Apr 2015 12:33:28 +0530
Subject: [PATCH] RT patch for AMD platform on top of 3.18.9-rt5 RT Kernel

---
 arch/arm64/Kconfig                   |   7 +-
 arch/arm64/Makefile                  |   2 +-
 arch/arm64/include/asm/cmpxchg.h     |   2 +
 arch/arm64/include/asm/thread_info.h |   3 +
 arch/arm64/include/asm/unistd32.h    |   2 +-
 arch/arm64/kernel/process.c          |  41 ++++++++++++
 arch/arm64/kernel/sys32.c            |   5 ++
 arch/arm64/mm/fault.c                |   4 +-
 include/linux/syscalls.h             |   8 ++-
 18 files changed, 280 insertions(+), 131 deletions(-)
 create mode 100644 arch/arm64/kernel/entry32.S

Index: linux-4.18.5-rt3/arch/arm64/Kconfig
===================================================================
--- linux-4.18.5-rt3.orig/arch/arm64/Kconfig
+++ linux-4.18.5-rt3/arch/arm64/Kconfig
@@ -623,6 +623,7 @@ endchoice
 choice
        prompt "Virtual address space size"
        default ARM64_VA_BITS_39 if ARM64_4K_PAGES
+       default ARM64_VA_BITS_48 if ARM64_4K_PAGES
        default ARM64_VA_BITS_47 if ARM64_16K_PAGES
        default ARM64_VA_BITS_42 if ARM64_64K_PAGES
        help
@@ -648,6 +649,7 @@ config ARM64_VA_BITS_47
 
 config ARM64_VA_BITS_48
        bool "48-bit"
+       depends on ARM64_4K_PAGES
 
 endchoice
 
@@ -1280,7 +1282,7 @@ source "fs/Kconfig.binfmt"
 
 config COMPAT
        bool "Kernel support for 32-bit EL0"
-       depends on ARM64_4K_PAGES || EXPERT
+       depends on EXPERT
        select COMPAT_BINFMT_ELF if BINFMT_ELF
        select HAVE_UID16
        select OLD_SIGSUSPEND3
Index: linux-4.18.5-rt3/arch/arm64/include/asm/cmpxchg.h
===================================================================
--- linux-4.18.5-rt3.orig/arch/arm64/include/asm/cmpxchg.h
+++ linux-4.18.5-rt3/arch/arm64/include/asm/cmpxchg.h
@@ -115,6 +115,7 @@ __XCHG_GEN(_mb)
 #define xchg_release(...)      __xchg_wrapper(_rel, __VA_ARGS__)
 #define xchg(...)              __xchg_wrapper( _mb, __VA_ARGS__)
 
+#define __HAVE_ARCH_CMPXCHG 1
 #define __CMPXCHG_GEN(sfx)                                             \
 static inline unsigned long __cmpxchg##sfx(volatile void *ptr,         \
                                           unsigned long old,           \
Index: linux-4.18.5-rt3/arch/arm64/kernel/process.c
===================================================================
--- linux-4.18.5-rt3.orig/arch/arm64/kernel/process.c
+++ linux-4.18.5-rt3/arch/arm64/kernel/process.c
@@ -478,6 +478,46 @@ unsigned long arch_align_stack(unsigned
        return sp & ~0xf;
 }
 
+/*
+ * CONFIG_SPLIT_PTLOCK_CPUS results in a page->ptl lock.  If the lock is not
+ * initialized by pgtable_page_ctor() then a coredump of the vector page will
+ * fail.
+ */
+
+static int __init vectors_user_mapping_init_page(void)
+{
+        pgd_t *pgd;
+        pud_t *pud;
+        pmd_t *pmd;
+        struct page *page;
+               unsigned long addr = UL(0xffffffffffffffff);
+
+        if ((((long)addr) >> VA_BITS) != -1UL)
+                return 0;
+
+        pgd = pgd_offset_k(addr);
+        if (pgd_none(*pgd))
+                return 0;
+
+        pud = pud_offset(pgd, addr);
+        if (pud_none(*pud))
+                return 0;
+
+        if (pud_sect(*pud))
+                return pfn_valid(pud_pfn(*pud));
+
+        pmd = pmd_offset(pud, addr);
+        if (pmd_none(*pmd))
+                return 0;
+
+        page = pmd_page(*(pmd));
+
+               pgtable_page_ctor(page);
+
+        return 0;
+}
+late_initcall(vectors_user_mapping_init_page);
+
 unsigned long arch_randomize_brk(struct mm_struct *mm)
 {
        if (is_compat_task())
Index: linux-4.18.5-rt3/arch/arm64/kernel/sys32.c
===================================================================
--- linux-4.18.5-rt3.orig/arch/arm64/kernel/sys32.c
+++ linux-4.18.5-rt3/arch/arm64/kernel/sys32.c
@@ -24,6 +24,7 @@
 
 #include <linux/compiler.h>
 #include <linux/syscalls.h>
+#include <asm/page.h>
 
 asmlinkage long compat_sys_sigreturn_wrapper(void);
 asmlinkage long compat_sys_rt_sigreturn_wrapper(void);
@@ -37,7 +38,11 @@ asmlinkage long compat_sys_readahead_wra
 asmlinkage long compat_sys_fadvise64_64_wrapper(void);
 asmlinkage long compat_sys_sync_file_range2_wrapper(void);
 asmlinkage long compat_sys_fallocate_wrapper(void);
+#if PAGE_SHIFT > 12
 asmlinkage long compat_sys_mmap2_wrapper(void);
+#else
+#define compat_sys_mmap2_wrapper sys_mmap_pgoff
+#endif
 
 #undef __SYSCALL
 #define __SYSCALL(nr, sym)     [nr] = sym,
Index: linux-4.18.5-rt3/arch/arm64/mm/fault.c
===================================================================
--- linux-4.18.5-rt3.orig/arch/arm64/mm/fault.c
+++ linux-4.18.5-rt3/arch/arm64/mm/fault.c
@@ -607,6 +607,8 @@ static int __kprobes do_translation_faul
        if (addr < TASK_SIZE)
                return do_page_fault(addr, esr, regs);
 
+       if (interrupts_enabled(regs))
+               local_irq_enable();
        do_bad_area(addr, esr, regs);
        return 0;
 }
Index: linux-4.18.5-rt3/arch/arm64/kernel/entry32.S
===================================================================
--- linux-4.18.5-rt3.orig/arch/arm64/kernel/entry32.S
+++ linux-4.18.5-rt3/arch/arm64/kernel/entry32.S
@@ -70,6 +70,21 @@ ENTRY(compat_sys_mmap2_wrapper)
 ENDPROC(compat_sys_mmap2_wrapper)
 
 /*
+ * Note: off_4k (w5) is always units of 4K.  If we can't do the requested
+ * offset, we return EINVAL.
+ */
+#if PAGE_SHIFT > 12
+ENTRY(compat_sys_mmap2_wrapper)
+       tst     w5, #~PAGE_MASK >> 12
+       b.ne    1f
+       lsr     w5, w5, #PAGE_SHIFT - 12
+       b       sys_mmap_pgoff
+1:     mov     x0, #-EINVAL
+       ret     lr
+ENDPROC(compat_sys_mmap2_wrapper)
+#endif
+
+/*
  * Wrappers for AArch32 syscalls that either take 64-bit parameters
  * in registers or that take 32-bit parameters which require sign
  * extension.