aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Hogan <jhogan@kernel.org>2017-11-22 06:30:28 -0500
committerJames Hogan <jhogan@kernel.org>2018-01-22 15:51:37 -0500
commit00b4eb408aaff21aeb806de24c5ff25b398083a4 (patch)
treef7e20d8d48d0c6761cec47fddca6fd38f59c6c40
parentfc62f53bb2f1a436fa69c42c82e207a7c7062efc (diff)
MIPS: VZ: Update helpers to use new asm macros
Update VZ guest register & guest TLB access helpers to use the new assembly macros for parsing register names and creating custom assembly macro instructions, which has a number of advantages: - Better code can be generated on toolchains which don't support VZ, more closely matching those which do, since there is no need to bounce values via the $at register. Some differences still remain due to the inability to safely fill branch delay slots and R6 compact branch forbidden slots with explicitly encoded instructions, resulting in some extra NOPs added by the assembler. - Some code duplication between toolchains which do and don't support VZ instructions is removed, since the helpers are only implemented once. When the toolchain doesn't implement the instruction an assembly macro implements it instead. - Instruction encodings are kept together in the source. On a generic kernel with KVM VZ support enabled this change saves about 2.5KiB of kernel code when TOOLCHAIN_SUPPORTS_VIRT=n, bringing it down to about 0.5KiB more than when TOOLCHAIN_SUPPORTS_VIRT=y on r6, and just 68 bytes more on r2. Signed-off-by: James Hogan <jhogan@kernel.org> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/17772/
-rw-r--r--arch/mips/include/asm/mipsregs.h164
1 files changed, 37 insertions, 127 deletions
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index ac70613fd3b8..23d96f814814 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1930,14 +1930,40 @@ do { \
1930 * Macros to access the guest system control coprocessor 1930 * Macros to access the guest system control coprocessor
1931 */ 1931 */
1932 1932
1933#ifdef TOOLCHAIN_SUPPORTS_VIRT 1933#ifndef TOOLCHAIN_SUPPORTS_VIRT
1934_ASM_MACRO_2R_1S(mfgc0, rt, rs, sel,
1935 _ASM_INSN_IF_MIPS(0x40600000 | __rt << 16 | __rs << 11 | \\sel)
1936 _ASM_INSN32_IF_MM(0x000004fc | __rt << 21 | __rs << 16 | \\sel << 11));
1937_ASM_MACRO_2R_1S(dmfgc0, rt, rs, sel,
1938 _ASM_INSN_IF_MIPS(0x40600100 | __rt << 16 | __rs << 11 | \\sel)
1939 _ASM_INSN32_IF_MM(0x580004fc | __rt << 21 | __rs << 16 | \\sel << 11));
1940_ASM_MACRO_2R_1S(mtgc0, rt, rd, sel,
1941 _ASM_INSN_IF_MIPS(0x40600200 | __rt << 16 | __rd << 11 | \\sel)
1942 _ASM_INSN32_IF_MM(0x000006fc | __rt << 21 | __rd << 16 | \\sel << 11));
1943_ASM_MACRO_2R_1S(dmtgc0, rt, rd, sel,
1944 _ASM_INSN_IF_MIPS(0x40600300 | __rt << 16 | __rd << 11 | \\sel)
1945 _ASM_INSN32_IF_MM(0x580006fc | __rt << 21 | __rd << 16 | \\sel << 11));
1946_ASM_MACRO_0(tlbgp, _ASM_INSN_IF_MIPS(0x42000010)
1947 _ASM_INSN32_IF_MM(0x0000017c));
1948_ASM_MACRO_0(tlbgr, _ASM_INSN_IF_MIPS(0x42000009)
1949 _ASM_INSN32_IF_MM(0x0000117c));
1950_ASM_MACRO_0(tlbgwi, _ASM_INSN_IF_MIPS(0x4200000a)
1951 _ASM_INSN32_IF_MM(0x0000217c));
1952_ASM_MACRO_0(tlbgwr, _ASM_INSN_IF_MIPS(0x4200000e)
1953 _ASM_INSN32_IF_MM(0x0000317c));
1954_ASM_MACRO_0(tlbginvf, _ASM_INSN_IF_MIPS(0x4200000c)
1955 _ASM_INSN32_IF_MM(0x0000517c));
1956#define _ASM_SET_VIRT ""
1957#else /* !TOOLCHAIN_SUPPORTS_VIRT */
1958#define _ASM_SET_VIRT ".set\tvirt\n\t"
1959#endif
1934 1960
1935#define __read_32bit_gc0_register(source, sel) \ 1961#define __read_32bit_gc0_register(source, sel) \
1936({ int __res; \ 1962({ int __res; \
1937 __asm__ __volatile__( \ 1963 __asm__ __volatile__( \
1938 ".set\tpush\n\t" \ 1964 ".set\tpush\n\t" \
1939 ".set\tmips32r2\n\t" \ 1965 ".set\tmips32r2\n\t" \
1940 ".set\tvirt\n\t" \ 1966 _ASM_SET_VIRT \
1941 "mfgc0\t%0, $%1, %2\n\t" \ 1967 "mfgc0\t%0, $%1, %2\n\t" \
1942 ".set\tpop" \ 1968 ".set\tpop" \
1943 : "=r" (__res) \ 1969 : "=r" (__res) \
@@ -1950,8 +1976,8 @@ do { \
1950 __asm__ __volatile__( \ 1976 __asm__ __volatile__( \
1951 ".set\tpush\n\t" \ 1977 ".set\tpush\n\t" \
1952 ".set\tmips64r2\n\t" \ 1978 ".set\tmips64r2\n\t" \
1953 ".set\tvirt\n\t" \ 1979 _ASM_SET_VIRT \
1954 "dmfgc0\t%0, $%1, %2\n\t" \ 1980 "dmfgc0\t%0, $%1, %2\n\t" \
1955 ".set\tpop" \ 1981 ".set\tpop" \
1956 : "=r" (__res) \ 1982 : "=r" (__res) \
1957 : "i" (source), "i" (sel)); \ 1983 : "i" (source), "i" (sel)); \
@@ -1963,7 +1989,7 @@ do { \
1963 __asm__ __volatile__( \ 1989 __asm__ __volatile__( \
1964 ".set\tpush\n\t" \ 1990 ".set\tpush\n\t" \
1965 ".set\tmips32r2\n\t" \ 1991 ".set\tmips32r2\n\t" \
1966 ".set\tvirt\n\t" \ 1992 _ASM_SET_VIRT \
1967 "mtgc0\t%z0, $%1, %2\n\t" \ 1993 "mtgc0\t%z0, $%1, %2\n\t" \
1968 ".set\tpop" \ 1994 ".set\tpop" \
1969 : : "Jr" ((unsigned int)(value)), \ 1995 : : "Jr" ((unsigned int)(value)), \
@@ -1975,75 +2001,13 @@ do { \
1975 __asm__ __volatile__( \ 2001 __asm__ __volatile__( \
1976 ".set\tpush\n\t" \ 2002 ".set\tpush\n\t" \
1977 ".set\tmips64r2\n\t" \ 2003 ".set\tmips64r2\n\t" \
1978 ".set\tvirt\n\t" \ 2004 _ASM_SET_VIRT \
1979 "dmtgc0\t%z0, $%1, %2\n\t" \ 2005 "dmtgc0\t%z0, $%1, %2\n\t" \
1980 ".set\tpop" \ 2006 ".set\tpop" \
1981 : : "Jr" (value), \ 2007 : : "Jr" (value), \
1982 "i" (register), "i" (sel)); \ 2008 "i" (register), "i" (sel)); \
1983} while (0) 2009} while (0)
1984 2010
1985#else /* TOOLCHAIN_SUPPORTS_VIRT */
1986
1987#define __read_32bit_gc0_register(source, sel) \
1988({ int __res; \
1989 __asm__ __volatile__( \
1990 ".set\tpush\n\t" \
1991 ".set\tnoat\n\t" \
1992 "# mfgc0\t$1, $%1, %2\n\t" \
1993 _ASM_INSN_IF_MIPS(0x40610000 | %1 << 11 | %2) \
1994 _ASM_INSN32_IF_MM(0x002004fc | %1 << 16 | %2 << 11) \
1995 "move\t%0, $1\n\t" \
1996 ".set\tpop" \
1997 : "=r" (__res) \
1998 : "i" (source), "i" (sel)); \
1999 __res; \
2000})
2001
2002#define __read_64bit_gc0_register(source, sel) \
2003({ unsigned long long __res; \
2004 __asm__ __volatile__( \
2005 ".set\tpush\n\t" \
2006 ".set\tnoat\n\t" \
2007 "# dmfgc0\t$1, $%1, %2\n\t" \
2008 _ASM_INSN_IF_MIPS(0x40610100 | %1 << 11 | %2) \
2009 _ASM_INSN32_IF_MM(0x582004fc | %1 << 16 | %2 << 11) \
2010 "move\t%0, $1\n\t" \
2011 ".set\tpop" \
2012 : "=r" (__res) \
2013 : "i" (source), "i" (sel)); \
2014 __res; \
2015})
2016
2017#define __write_32bit_gc0_register(register, sel, value) \
2018do { \
2019 __asm__ __volatile__( \
2020 ".set\tpush\n\t" \
2021 ".set\tnoat\n\t" \
2022 "move\t$1, %z0\n\t" \
2023 "# mtgc0\t$1, $%1, %2\n\t" \
2024 _ASM_INSN_IF_MIPS(0x40610200 | %1 << 11 | %2) \
2025 _ASM_INSN32_IF_MM(0x002006fc | %1 << 16 | %2 << 11) \
2026 ".set\tpop" \
2027 : : "Jr" ((unsigned int)(value)), \
2028 "i" (register), "i" (sel)); \
2029} while (0)
2030
2031#define __write_64bit_gc0_register(register, sel, value) \
2032do { \
2033 __asm__ __volatile__( \
2034 ".set\tpush\n\t" \
2035 ".set\tnoat\n\t" \
2036 "move\t$1, %z0\n\t" \
2037 "# dmtgc0\t$1, $%1, %2\n\t" \
2038 _ASM_INSN_IF_MIPS(0x40610300 | %1 << 11 | %2) \
2039 _ASM_INSN32_IF_MM(0x582006fc | %1 << 16 | %2 << 11) \
2040 ".set\tpop" \
2041 : : "Jr" (value), \
2042 "i" (register), "i" (sel)); \
2043} while (0)
2044
2045#endif /* !TOOLCHAIN_SUPPORTS_VIRT */
2046
2047#define __read_ulong_gc0_register(reg, sel) \ 2011#define __read_ulong_gc0_register(reg, sel) \
2048 ((sizeof(unsigned long) == 4) ? \ 2012 ((sizeof(unsigned long) == 4) ? \
2049 (unsigned long) __read_32bit_gc0_register(reg, sel) : \ 2013 (unsigned long) __read_32bit_gc0_register(reg, sel) : \
@@ -2681,8 +2645,6 @@ static inline void tlb_write_random(void)
2681 ".set reorder"); 2645 ".set reorder");
2682} 2646}
2683 2647
2684#ifdef TOOLCHAIN_SUPPORTS_VIRT
2685
2686/* 2648/*
2687 * Guest TLB operations. 2649 * Guest TLB operations.
2688 * 2650 *
@@ -2693,7 +2655,7 @@ static inline void guest_tlb_probe(void)
2693 __asm__ __volatile__( 2655 __asm__ __volatile__(
2694 ".set push\n\t" 2656 ".set push\n\t"
2695 ".set noreorder\n\t" 2657 ".set noreorder\n\t"
2696 ".set virt\n\t" 2658 _ASM_SET_VIRT
2697 "tlbgp\n\t" 2659 "tlbgp\n\t"
2698 ".set pop"); 2660 ".set pop");
2699} 2661}
@@ -2703,7 +2665,7 @@ static inline void guest_tlb_read(void)
2703 __asm__ __volatile__( 2665 __asm__ __volatile__(
2704 ".set push\n\t" 2666 ".set push\n\t"
2705 ".set noreorder\n\t" 2667 ".set noreorder\n\t"
2706 ".set virt\n\t" 2668 _ASM_SET_VIRT
2707 "tlbgr\n\t" 2669 "tlbgr\n\t"
2708 ".set pop"); 2670 ".set pop");
2709} 2671}
@@ -2713,7 +2675,7 @@ static inline void guest_tlb_write_indexed(void)
2713 __asm__ __volatile__( 2675 __asm__ __volatile__(
2714 ".set push\n\t" 2676 ".set push\n\t"
2715 ".set noreorder\n\t" 2677 ".set noreorder\n\t"
2716 ".set virt\n\t" 2678 _ASM_SET_VIRT
2717 "tlbgwi\n\t" 2679 "tlbgwi\n\t"
2718 ".set pop"); 2680 ".set pop");
2719} 2681}
@@ -2723,7 +2685,7 @@ static inline void guest_tlb_write_random(void)
2723 __asm__ __volatile__( 2685 __asm__ __volatile__(
2724 ".set push\n\t" 2686 ".set push\n\t"
2725 ".set noreorder\n\t" 2687 ".set noreorder\n\t"
2726 ".set virt\n\t" 2688 _ASM_SET_VIRT
2727 "tlbgwr\n\t" 2689 "tlbgwr\n\t"
2728 ".set pop"); 2690 ".set pop");
2729} 2691}
@@ -2736,63 +2698,11 @@ static inline void guest_tlbinvf(void)
2736 __asm__ __volatile__( 2698 __asm__ __volatile__(
2737 ".set push\n\t" 2699 ".set push\n\t"
2738 ".set noreorder\n\t" 2700 ".set noreorder\n\t"
2739 ".set virt\n\t" 2701 _ASM_SET_VIRT
2740 "tlbginvf\n\t" 2702 "tlbginvf\n\t"
2741 ".set pop"); 2703 ".set pop");
2742} 2704}
2743 2705
2744#else /* TOOLCHAIN_SUPPORTS_VIRT */
2745
2746/*
2747 * Guest TLB operations.
2748 *
2749 * It is responsibility of the caller to take care of any TLB hazards.
2750 */
2751static inline void guest_tlb_probe(void)
2752{
2753 __asm__ __volatile__(
2754 "# tlbgp\n\t"
2755 _ASM_INSN_IF_MIPS(0x42000010)
2756 _ASM_INSN32_IF_MM(0x0000017c));
2757}
2758
2759static inline void guest_tlb_read(void)
2760{
2761 __asm__ __volatile__(
2762 "# tlbgr\n\t"
2763 _ASM_INSN_IF_MIPS(0x42000009)
2764 _ASM_INSN32_IF_MM(0x0000117c));
2765}
2766
2767static inline void guest_tlb_write_indexed(void)
2768{
2769 __asm__ __volatile__(
2770 "# tlbgwi\n\t"
2771 _ASM_INSN_IF_MIPS(0x4200000a)
2772 _ASM_INSN32_IF_MM(0x0000217c));
2773}
2774
2775static inline void guest_tlb_write_random(void)
2776{
2777 __asm__ __volatile__(
2778 "# tlbgwr\n\t"
2779 _ASM_INSN_IF_MIPS(0x4200000e)
2780 _ASM_INSN32_IF_MM(0x0000317c));
2781}
2782
2783/*
2784 * Guest TLB Invalidate Flush
2785 */
2786static inline void guest_tlbinvf(void)
2787{
2788 __asm__ __volatile__(
2789 "# tlbginvf\n\t"
2790 _ASM_INSN_IF_MIPS(0x4200000c)
2791 _ASM_INSN32_IF_MM(0x0000517c));
2792}
2793
2794#endif /* !TOOLCHAIN_SUPPORTS_VIRT */
2795
2796/* 2706/*
2797 * Manipulate bits in a register. 2707 * Manipulate bits in a register.
2798 */ 2708 */