# HG changeset patch # Parent 456e98c2eb1aa14070ef0e5139a43471d1fd9440 Add new hazard interface for MIPS to make things a little more fine-grained and accurate to replace the two different systems we have in the tree right now. This should allow us to have a better code generation, especially for the TLB path, but actual improvements there will be forthcoming... diff -r 456e98c2eb1a sys/mips/include/hazard.h --- /dev/null +++ b/sys/mips/include/hazard.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2013 Warner Losh. All Rights Reserved. + * + * 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. + * + * $FreeBSD$ + */ + +#ifndef _MIPS_HAZARD_H +#define _MIPS_HAZARD_H + +/* + * Extra instructions for binutils portability and/or ability to assemble at lower + * mips ISA levels + */ +#define __ssnop sll $0, $0, 1 +#define __ehb sll $0, $0, 3 + +/* + * Conventions used in this file. + * +-------------------------------------------------------------------------------- + * _foo - A #define of the assembler instructions to implement foo() + * foo - when building .s: sequence of instructions that can be dropped into + * an instruction sequence. + * foo - when building .c: static inline __asm__ function with _foo inside. + * __X - the X instruction + * + +/* + * With MIPS CPUs, there are different 'CPU' hazards that exists. These hazards + * vary across the generations of MIPS hardware, but generally involve needing to + * flush the pipeline in one way or another to ensure that the changes just made + * don't affect the pipeline, or to give changes a chance to take effect before + * the data is used. + * + * hazard_mtc0_tlbw - Padding between mtc0 instructions affecting EntryHi, EntryLo0, + * EntryLo1, PageMask and Random or Index and a tlbwr or tlbwi instruction. + * + * hazard_tlbw_use - Padding after a tlbwr or tlbwi and a tlbp, load/store through + * that address. This does not cover tlbwX to I-Fetch, which is unused in FreeBSD. + * + * hazard_tlbp_use - Padding after a tlbp before the cp0 Index can be read. + * + * hazard_ei - Padding after enabling interrupts (with EI or mtc0 Status) + * + * hazard_di - Padding after disabling interrupts (with DI or mtc0 Status) + * + * hazard_c0c0 - Padding between back-to-back CP0 register accesses + * + * hazard_epc_eret - Padding between mtc0 EPC and eret (unneeded in FreeBSD?) + * + * hazard_status_eret - Padding between mtc0 Statusand eret (unneeded in FreeBSD?) + * + * hazard_instruction - Instruction hazard padding + */ + +#if defined(CPU_MIPS32) || defined(CPU_MIPS64) +/* + * We add the MIPSr2 ehb as the last nop here so mipsr1 kernels could + * work on mipsr2 and newer CPUs + */ +#define _hazard_mtc0_tlbw __ssnop; __ehb +#define _hazard_tlbw_use __ssnop; __ssnop; __ehb +#define _hazard_tlbp_use __ssnop; __ssnop; __ehb +#define _hazard_ei __ssnop; __ssnop; __ehb +#define _hazard_di __ssnop; __ssnop; __ehb +#define _hazard_c0c0 __ssnop; __ssnop; __ehb +#define _hazard_epc_eret __ssnop; __ehb +#define _hazard_status_eret __ssnop; __ssnop; __ehb + +#elif defined(CPU_MIPS32_R2) || defined(CPU_MIPS64_R2) +/* + * All MIPS32r2 and MIPS64r2 CPUs are easy... + */ +#define _hazard_mtc0_tlbw __ehb +#define _hazard_tlbw_use __ehb +#define _hazard_tlbp_use __ehb +#define _hazard_ei __ehb +#define _hazard_di __ehb +#define _hazard_c0c0 __ehb +#define _hazard_epc_eret __ehb +#define _hazard_status_eret __ehb + +static inline hazard_instruction() +{ + unsigned long r; + + __asm __volatile ( + "dla %0, 1f \n" + "jr.hb %0 \n" + "1: \n" + : "=r" r); +} + +#elif defined(CPU_NLM) +#elif defined(CPU_RMI) || defined(CPU_CNMIPS) || defined(CPU_R10000) +/* + * R10000, RMI and Octeon rock! They handle all the CP0 hazards in hardware. + */ +#define _hazard_mtc0_tlbw +#define _hazard_tlbw_use +#define _hazard_tlbp_use +#define _hazard_ei +#define _hazard_di +#define _hazard_c0c0 +#define _hazard_epc_eret +#define _hazard_status_eret +#define hazard_instruction() do { } while (0) + +#elif defined(CPU_SB1) +/* + * SB1 almost gets all the hazards right in hardware +#define _hazard_mtc0_tlbw +#define _hazard_tlbw_use +#define _hazard_tlbp_use +#define _hazard_ei +#define _hazard_di __ssnop; __ssnop; __ssnop +#define _hazard_c0c0 +#define _hazard_epc_eret +#define _hazard_status_eret +#define hazard_instruction() do { } while (0) +#else +/* + * Default values that should work on most other MIPS R4000-like CPUs. We use + * the + */ +#define _hazard_mtc0_tlbw __ssnop; __ssnop +#define _hazard_tlbw_use __ssnop; __ssnop; __ssnop +#define _hazard_tlbp_use __ssnop; __ssnop; __ssnop +#define _hazard_ei __ssnop; __ssnop; __ssnop +#define _hazard_di __ssnop; __ssnop; __ssnop +#define _hazard_c0c0 __ssnop; __ssnop; __ssnop +#define _hazard_epc_eret __ssnop; __ssnop +#define _hazard_status_eret __ssnop; __ssnop; __ssnop +#define hazard_instruction() do { } while (0) +#endif + +#ifdef __ASSEMBLER__ +#define hazard_mtc0_tlbw _hazard_mtc0_tlbw +#define hazard_tlbw_use _hazard_tlbw_use +#define hazard_tlbp_use _hazard_tlbp_use +#define hazard_ei _hazard_ei +#define hazard_di _hazard_di +#define hazard_c0c0 _hazard_c0c0 +#define hazard_epc_eret _hazard_epc_eret +#define hazard_status_eret _hazard_status_eret +/* hazard_instruction cannot be used */ +#else +#define _hazard_gen(y) do {__asm __volatile(__XSTRING(y)) } while (0) +#define hazard_mtc0_tlbw _hazard_gen(_hazard_mtc0_tlbw) +#define hazard_tlbw_use _hazard_gen(_hazard_tlbw_use) +#define hazard_tlbp_use _hazard_gen(_hazard_tlbp_use) +#define hazard_ei _hazard_gen(_hazard_ei) +#define hazard_di _hazard_gen(_hazard_di) +#define hazard_c0c0 _hazard_gen(_hazard_c0c0) +#define hazard_epc_eret _hazard_gen(_hazard_epc_eret) +#define hazard_status_eret _hazard_gen(_hazard_status_eret) +#endif + +/* + * fpu hazards + * + * hazard_fpu_enable - Padding after enabling CP1 to flush pipeline + * + * hazard_fpu_disable - Padding after disabling CP1 to flush pipeline + */ + +#endif