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
This commit is contained in:
parent
7dff7eda1a
commit
9cd27257d5
@ -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)
|
||||
|
@ -85,7 +85,7 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
|
||||
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:
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user