Author: cognet
Date: Sun Jan 13 23:29:46 2019
New Revision: 343006
URL: https://svnweb.freebsd.org/changeset/base/343006

Log:
  Introduce cpu_icache_sync_range_checked(), that does the same thing as
  cpu_icache_sync_range(), except that it sets pcb_onfault to catch any page
  fault, as doing cache maintenance operations for non-mapped generates a
  data abort, and use it in freebsd32_sysarch(), so that a userland program
  attempting to sync the icache with unmapped addresses doesn't crash the
  kernel.
  
  Spotted out by:       andrew

Modified:
  head/sys/arm64/arm64/cpufunc_asm.S
  head/sys/arm64/arm64/freebsd32_machdep.c
  head/sys/arm64/include/cpufunc.h

Modified: head/sys/arm64/arm64/cpufunc_asm.S
==============================================================================
--- head/sys/arm64/arm64/cpufunc_asm.S  Sun Jan 13 20:33:54 2019        
(r343005)
+++ head/sys/arm64/arm64/cpufunc_asm.S  Sun Jan 13 23:29:46 2019        
(r343006)
@@ -147,3 +147,24 @@ ENTRY(arm64_icache_sync_range)
        ic      ialluis
        dsb     ish
 END(arm64_icache_sync_range)
+
+/*
+ * int arm64_icache_sync_range_checked(vm_offset_t, vm_size_t)
+ */
+ENTRY(arm64_icache_sync_range_checked)
+       adr     x5, cache_maint_fault
+       SET_FAULT_HANDLER(x5, x6)
+       /* XXX: See comment in arm64_icache_sync_range */
+       cache_handle_range      dcop = cvau
+       ic      ialluis
+       dsb ish
+       SET_FAULT_HANDLER(xzr, x6)
+       mov     x0, #0
+       ret
+END(arm64_icache_sync_range_checked)
+
+ENTRY(cache_maint_fault)
+       SET_FAULT_HANDLER(xzr, x1)
+       mov     x0, #EFAULT
+       ret
+END(cache_maint_fault)

Modified: head/sys/arm64/arm64/freebsd32_machdep.c
==============================================================================
--- head/sys/arm64/arm64/freebsd32_machdep.c    Sun Jan 13 20:33:54 2019        
(r343005)
+++ head/sys/arm64/arm64/freebsd32_machdep.c    Sun Jan 13 23:29:46 2019        
(r343006)
@@ -85,7 +85,7 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_
                                return (error);
                        if ((uint64_t)args.addr + (uint64_t)args.size > 
0xffffffff)
                                return (EINVAL);
-                       cpu_icache_sync_range(args.addr, args.size);
+                       cpu_icache_sync_range_checked(args.addr, args.size);
                        return 0;
                }
        case ARM_GET_VFPSTATE:

Modified: head/sys/arm64/include/cpufunc.h
==============================================================================
--- head/sys/arm64/include/cpufunc.h    Sun Jan 13 20:33:54 2019        
(r343005)
+++ head/sys/arm64/include/cpufunc.h    Sun Jan 13 23:29:46 2019        
(r343006)
@@ -138,12 +138,14 @@ extern int64_t dczva_line_size;
 
 #define        cpu_idcache_wbinv_range(a, s)   arm64_idcache_wbinv_range((a), 
(s))
 #define        cpu_icache_sync_range(a, s)     arm64_icache_sync_range((a), 
(s))
+#define cpu_icache_sync_range_checked(a, s) 
arm64_icache_sync_range_checked((a), (s))
 
 void arm64_nullop(void);
 void arm64_setttb(vm_offset_t);
 void arm64_tlb_flushID(void);
 void arm64_tlb_flushID_SE(vm_offset_t);
 void arm64_icache_sync_range(vm_offset_t, vm_size_t);
+int arm64_icache_sync_range_checked(vm_offset_t, vm_size_t);
 void arm64_idcache_wbinv_range(vm_offset_t, vm_size_t);
 void arm64_dcache_wbinv_range(vm_offset_t, vm_size_t);
 void arm64_dcache_inv_range(vm_offset_t, vm_size_t);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to