commit d5c3c24a28a4cbe19afe43cc879b4c95eda08027 Author: Stacey Son Date: Tue Jan 13 10:48:05 2015 -0600 Add userlevel mechanism to flush contents of instruction/data cache. This change adds an userlevel mechanism to flush the contents of the instruction cache and to writeback and invalidate the data cache via the sysarch() system call. For convenience, mips_cacheflush() is provided in machine/cachectl.h. diff --git a/sys/mips/include/cachectl.h b/sys/mips/include/cachectl.h new file mode 100644 index 0000000..d5a4675 --- /dev/null +++ b/sys/mips/include/cachectl.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2015 Stacey D. Son + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_CACHECTL_H_ +#define _MACHINE_CACHECTL_H_ + +#define MIPS_CF_ICACHE 0x00000001 /* invalidate I-cache */ +#define MIPS_CF_DCACHE 0x00000002 /* writeback and invalidate D-cache */ +#define MIPS_CF_BCACHE (MIPS_CF_ICACHE | MIPS_CF_DCACHE) /* invalidate both */ + +#define MIPS_CF_ALLF 0x80000000 /* invalidate entire cache flag bit */ +#define MIPS_CF_ICACHE_ALL (MIPS_CF_ALLF | MIPS_CF_ICACHE) /* Entire I-cache */ +#define MIPS_CF_DCACHE_ALL (MIPS_CF_ALLF | MIPS_CF_DCACHE) /* Entire D-cache */ +#define MIPS_CF_BCACHE_ALL (MIPS_CF_ALLF | MIPS_CF_BCACHE) /* Entire both */ + +#if !defined(_KERNEL) +static inline int +mips_cacheflush(void *addr, size_t nbytes, unsigned whichcache) +{ + struct mips_cacheflush_args cfa; + + cfa.addr = addr; + cfa.nbytes = nbytes; + cfa.whichcache = whichcache; + + return (sysarch(MIPS_CACHEFLUSH, (void *)&cfa)); +} + +/* IRIX API compatible aliases. */ +#define ICACHE MIPS_CF_ICACHE +#define DCACHE MIPS_CF_DCACHE +#define BCACHE MIPS_CF_BCACHE + +static inline int +cacheflush(void *addr, int nbytes, int whichcache) +{ + + return (mips_cacheflush(addr, (size_t)nbytes, whichcache)); +} + +static inline int +_flush_cache(char *addr, int nbytes, int whichcache) +{ + + return (mips_cacheflush((void *)addr, (size_t)nbytes, whichcache)); +} +#endif /* ! _KERNEL */ +#endif /* _MACHINE_CACHECTL_H_ */ diff --git a/sys/mips/include/sysarch.h b/sys/mips/include/sysarch.h index 8a488fca..27e7caf 100644 --- a/sys/mips/include/sysarch.h +++ b/sys/mips/include/sysarch.h @@ -53,6 +53,17 @@ #define CHERI_GET_STACK 4 #define CHERI_SET_STACK 5 +/* + * sysarch() to flush the cache from userspace. + */ +#define MIPS_CACHEFLUSH 6 + +struct mips_cacheflush_args { + void *addr; + size_t nbytes; + unsigned whichcache; +}; + #ifndef _KERNEL #include diff --git a/sys/mips/mips/sys_machdep.c b/sys/mips/mips/sys_machdep.c index ba50bdd..c3dbd50 100644 --- a/sys/mips/mips/sys_machdep.c +++ b/sys/mips/mips/sys_machdep.c @@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #include #include #include @@ -52,6 +54,56 @@ struct sysarch_args { }; #endif +static int +mips_sysarch_cacheflush(struct thread *td __unused, struct sysarch_args *uap) +{ + struct mips_cacheflush_args cfua; + vm_offset_t va; + vm_size_t nbytes; + + if (copyin(uap->parms, &cfua, sizeof(cfua)) != 0) + return (EFAULT); + + va = (vm_offset_t)cfua.addr; + nbytes = (vm_size_t)cfua.nbytes; + + if ((cfua.whichcache & MIPS_CF_ALLF) == 0 && nbytes == 0) + return (0); + + switch (cfua.whichcache) { + case MIPS_CF_ICACHE: + mips_icache_sync_range(va, nbytes); + break; + + case MIPS_CF_DCACHE: + mips_dcache_wbinv_range(va, nbytes); + break; + + case MIPS_CF_BCACHE: + mips_icache_sync_range(va, nbytes); + mips_dcache_wbinv_range(va, nbytes); + break; + + case MIPS_CF_ICACHE_ALL: + mips_icache_sync_all(); + break; + + case MIPS_CF_DCACHE_ALL: + mips_dcache_wbinv_all(); + break; + + case MIPS_CF_BCACHE_ALL: + mips_icache_sync_all(); + mips_dcache_wbinv_all(); + break; + + default: + return (EINVAL); + } + + return (0); +} + int sysarch(struct thread *td, struct sysarch_args *uap) { @@ -67,9 +119,6 @@ sysarch(struct thread *td, struct sysarch_args *uap) * update it as well. Add the TLS and TCB offsets so the * value in this register is adjusted like in the case of the * rdhwr trap() instruction handler. - * - * XXXSS For more information why this offset is required see: - * 'git show c6be4f4d2d1b71c04de5d3bbb6933ce2dbcdb317' */ if (cpuinfo.userlocal_reg == true) { #if defined(__mips_n64) && defined(COMPAT_FREEBSD32) @@ -98,6 +147,8 @@ sysarch(struct thread *td, struct sysarch_args *uap) case CHERI_SET_STACK: return (cheri_sysarch_setstack(td, uap)); #endif + case MIPS_CACHEFLUSH: + return (mips_sysarch_cacheflush(td, uap)); default: break;