^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Event entry/exit for Hexagon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/asm-offsets.h> /* assembly-safer versions of C defines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/mem-layout.h> /* sigh, except for page_offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/hexagon_vm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/thread_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Entry into guest-mode Linux under Hexagon Virtual Machine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Stack pointer points to event record - build pt_regs on top of it,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * set up a plausible C stack frame, and dispatch to the C handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * On return, do vmrte virtual instruction with SP where we started.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * VM Spec 0.5 uses a trap to fetch HVM record now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Save full register state, while setting up thread_info struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * pointer derived from kernel stack pointer in THREADINFO_REG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * register, putting prior thread_info.regs pointer in a callee-save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * register (R24, which had better not ever be assigned to THREADINFO_REG),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * and updating thread_info.regs to point to current stack frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * so as to support nested events in kernel mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * As this is common code, we set the pt_regs system call number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * to -1 for all events. It will be replaced with the system call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * number in the case where we decode a system call (trap0(#1)).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #if CONFIG_HEXAGON_ARCH_VERSION < 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define save_pt_regs()\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) memd(R0 + #_PT_R3130) = R31:30; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) { memw(R0 + #_PT_R2928) = R28; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) R31 = memw(R0 + #_PT_ER_VMPSP); }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) { memw(R0 + #(_PT_R2928 + 4)) = R31; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) R31 = ugp; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { memd(R0 + #_PT_R2726) = R27:26; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) R30 = gp ; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) memd(R0 + #_PT_R2524) = R25:24; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) memd(R0 + #_PT_R2322) = R23:22; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) memd(R0 + #_PT_R2120) = R21:20; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) memd(R0 + #_PT_R1918) = R19:18; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) memd(R0 + #_PT_R1716) = R17:16; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) memd(R0 + #_PT_R1514) = R15:14; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) memd(R0 + #_PT_R1312) = R13:12; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { memd(R0 + #_PT_R1110) = R11:10; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) R15 = lc0; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { memd(R0 + #_PT_R0908) = R9:8; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) R14 = sa0; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { memd(R0 + #_PT_R0706) = R7:6; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) R13 = lc1; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { memd(R0 + #_PT_R0504) = R5:4; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) R12 = sa1; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { memd(R0 + #_PT_GPUGP) = R31:30; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) R11 = m1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) R2.H = #HI(_THREAD_SIZE); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { memd(R0 + #_PT_LC0SA0) = R15:14; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) R10 = m0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) R2.L = #LO(_THREAD_SIZE); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { memd(R0 + #_PT_LC1SA1) = R13:12; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) R15 = p3:0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) R2 = neg(R2); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { memd(R0 + #_PT_M1M0) = R11:10; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) R14 = usr; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) R2 = and(R0,R2); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) { memd(R0 + #_PT_PREDSUSR) = R15:14; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) THREADINFO_REG = R2; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) R2 = #-1; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { memw(R0 + #_PT_SYSCALL_NR) = R2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) R30 = #0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* V4+ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* the # ## # syntax inserts a literal ## */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define save_pt_regs()\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { memd(R0 + #_PT_R3130) = R31:30; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) R30 = memw(R0 + #_PT_ER_VMPSP); }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { memw(R0 + #_PT_R2928) = R28; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) memw(R0 + #(_PT_R2928 + 4)) = R30; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { R31:30 = C11:10; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) memd(R0 + #_PT_R2726) = R27:26; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) memd(R0 + #_PT_R2524) = R25:24; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { memd(R0 + #_PT_R2322) = R23:22; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) memd(R0 + #_PT_R2120) = R21:20; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { memd(R0 + #_PT_R1918) = R19:18; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) memd(R0 + #_PT_R1716) = R17:16; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { memd(R0 + #_PT_R1514) = R15:14; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) memd(R0 + #_PT_R1312) = R13:12; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) R17:16 = C13:12; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) { memd(R0 + #_PT_R1110) = R11:10; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) memd(R0 + #_PT_R0908) = R9:8; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) R15:14 = C1:0; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { memd(R0 + #_PT_R0706) = R7:6; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) memd(R0 + #_PT_R0504) = R5:4; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) R13:12 = C3:2; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { memd(R0 + #_PT_GPUGP) = R31:30; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) memd(R0 + #_PT_LC0SA0) = R15:14; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) R11:10 = C7:6; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) { THREADINFO_REG = and(R0, # ## #-_THREAD_SIZE); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) memd(R0 + #_PT_LC1SA1) = R13:12; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) R15 = p3:0; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { memd(R0 + #_PT_M1M0) = R11:10; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) memw(R0 + #_PT_PREDSUSR + 4) = R15; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) R2 = #-1; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { memw(R0 + #_PT_SYSCALL_NR) = R2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) memd(R0 + #_PT_CS1CS0) = R17:16; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) R30 = #0; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Restore registers and thread_info.regs state. THREADINFO_REG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * is assumed to still be sane, and R24 to have been correctly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * preserved. Don't restore R29 (SP) until later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #if CONFIG_HEXAGON_ARCH_VERSION < 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define restore_pt_regs() \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) R15:14 = memd(R0 + #_PT_PREDSUSR); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { R11:10 = memd(R0 + #_PT_M1M0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) p3:0 = R15; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { R13:12 = memd(R0 + #_PT_LC1SA1); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) usr = R14; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { R15:14 = memd(R0 + #_PT_LC0SA0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) m1 = R11; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { R3:2 = memd(R0 + #_PT_R0302); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) m0 = R10; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) { R5:4 = memd(R0 + #_PT_R0504); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) lc1 = R13; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) { R7:6 = memd(R0 + #_PT_R0706); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) sa1 = R12; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) { R9:8 = memd(R0 + #_PT_R0908); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) lc0 = R15; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) { R11:10 = memd(R0 + #_PT_R1110); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) sa0 = R14; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) { R13:12 = memd(R0 + #_PT_R1312); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) R15:14 = memd(R0 + #_PT_R1514); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) { R17:16 = memd(R0 + #_PT_R1716); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) R19:18 = memd(R0 + #_PT_R1918); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { R21:20 = memd(R0 + #_PT_R2120); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) R23:22 = memd(R0 + #_PT_R2322); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) { R25:24 = memd(R0 + #_PT_R2524); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) R27:26 = memd(R0 + #_PT_R2726); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) R31:30 = memd(R0 + #_PT_GPUGP); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { R28 = memw(R0 + #_PT_R2928); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ugp = R31; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) { R31:30 = memd(R0 + #_PT_R3130); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) gp = R30; }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* V4+ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #define restore_pt_regs() \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) { memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) R15:14 = memd(R0 + #_PT_PREDSUSR); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) { R11:10 = memd(R0 + #_PT_M1M0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) R13:12 = memd(R0 + #_PT_LC1SA1); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) p3:0 = R15; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { R15:14 = memd(R0 + #_PT_LC0SA0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) R3:2 = memd(R0 + #_PT_R0302); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) usr = R14; } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) { R5:4 = memd(R0 + #_PT_R0504); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) R7:6 = memd(R0 + #_PT_R0706); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) C7:6 = R11:10; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) { R9:8 = memd(R0 + #_PT_R0908); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) R11:10 = memd(R0 + #_PT_R1110); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) C3:2 = R13:12; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) { R13:12 = memd(R0 + #_PT_R1312); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) R15:14 = memd(R0 + #_PT_R1514); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) C1:0 = R15:14; }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) { R17:16 = memd(R0 + #_PT_R1716); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) R19:18 = memd(R0 + #_PT_R1918); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) { R21:20 = memd(R0 + #_PT_R2120); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) R23:22 = memd(R0 + #_PT_R2322); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) { R25:24 = memd(R0 + #_PT_R2524); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) R27:26 = memd(R0 + #_PT_R2726); } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) R31:30 = memd(R0 + #_PT_CS1CS0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { C13:12 = R31:30; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) R31:30 = memd(R0 + #_PT_GPUGP) ; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) R28 = memw(R0 + #_PT_R2928); }\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { C11:10 = R31:30; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) R31:30 = memd(R0 + #_PT_R3130); }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * Clears off enough space for the rest of pt_regs; evrec is a part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * of pt_regs in HVM mode. Save R0/R1, set handler's address in R1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * R0 is the address of pt_regs and is the parameter to save_pt_regs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * Since the HVM isn't automagically pushing the EVREC onto the stack anymore,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * we'll subract the entire size out and then fill it in ourselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * Need to save off R0, R1, R2, R3 immediately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) #if CONFIG_HEXAGON_ARCH_VERSION < 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #define vm_event_entry(CHandler) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) R29 = add(R29, #-(_PT_REGS_SIZE)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) memd(R29 +#_PT_R0302) = R3:2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) trap1(#HVM_TRAP1_VMGETREGS); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) memd(R29 + #_PT_ER_VMEL) = R1:0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) R0 = R29; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) R1.L = #LO(CHandler); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) memd(R29 + #_PT_ER_VMPSP) = R3:2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) R1.H = #HI(CHandler); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) jump event_dispatch; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* V4+ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* turn on I$ prefetch early */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* the # ## # syntax inserts a literal ## */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #define vm_event_entry(CHandler) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) R29 = add(R29, #-(_PT_REGS_SIZE)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) memd(R29 + #(_PT_R0302 + -_PT_REGS_SIZE)) = R3:2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) R0 = usr; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) memw(R29 + #_PT_PREDSUSR) = R0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) R0 = setbit(R0, #16); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) usr = R0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) R1:0 = G1:0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) memd(R29 + #_PT_ER_VMEL) = R1:0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) R1 = # ## #(CHandler); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) R3:2 = G3:2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) R0 = R29; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) memd(R29 + #_PT_ER_VMPSP) = R3:2; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) jump event_dispatch; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * Do bulk save/restore in one place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * Adds a jump to dispatch latency, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * saves hundreds of bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) event_dispatch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) save_pt_regs()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) callr r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * Coming back from the C-world, our thread info pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * should be in the designated register (usually R19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * If we were in kernel mode, we don't need to check scheduler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * or signals if CONFIG_PREEMPTION is not set. If set, then it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * to jump to a need_resched kind of block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * BTW, CONFIG_PREEMPTION is not supported yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #ifdef CONFIG_PREEMPTION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) R0 = #VM_INT_DISABLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) trap1(#HVM_TRAP1_VMSETIE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* "Nested control path" -- if the previous mode was kernel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) R0 = memw(R29 + #_PT_ER_VMEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) R26.L = #LO(do_work_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!P0.new) jump:nt restore_all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) R26.H = #HI(do_work_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) R0 = #VM_INT_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * Check also the return from fork/system call, normally coming back from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * user mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * R26 needs to have do_work_pending, and R0 should have VM_INT_DISABLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) check_work_pending:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* Disable interrupts while checking TIF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) trap1(#HVM_TRAP1_VMSETIE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) R0 = R29; /* regs should still be at top of stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) R1 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) callr R26;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) P0 = cmp.eq(R0, #0); if (!P0.new) jump:nt check_work_pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) R0 = #VM_INT_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) restore_all:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * Disable interrupts, if they weren't already, before reg restore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * R0 gets preloaded with #VM_INT_DISABLE before we get here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) trap1(#HVM_TRAP1_VMSETIE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* do the setregs here for VM 0.5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /* R29 here should already be pointing at pt_regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) R1:0 = memd(R29 + #_PT_ER_VMEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) R3:2 = memd(R29 + #_PT_ER_VMPSP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) #if CONFIG_HEXAGON_ARCH_VERSION < 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) trap1(#HVM_TRAP1_VMSETREGS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) G1:0 = R1:0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) G3:2 = R3:2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) R0 = R29
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) restore_pt_regs()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) R1:0 = memd(R29 + #_PT_R0100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) R29 = add(R29, #_PT_REGS_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) trap1(#HVM_TRAP1_VMRTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* Notreached */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .globl _K_enter_genex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) _K_enter_genex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) vm_event_entry(do_genex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) .globl _K_enter_interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) _K_enter_interrupt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) vm_event_entry(arch_do_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) .globl _K_enter_trap0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) _K_enter_trap0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) vm_event_entry(do_trap0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .globl _K_enter_machcheck
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) _K_enter_machcheck:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) vm_event_entry(do_machcheck)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) .globl _K_enter_debug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) _K_enter_debug:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) vm_event_entry(do_debug_exception)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) .globl ret_from_fork
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ret_from_fork:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) call schedule_tail
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) R26.H = #HI(do_work_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) P0 = cmp.eq(R24, #0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) R26.L = #LO(do_work_pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) R0 = #VM_INT_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (P0) jump check_work_pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) R0 = R25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) callr R24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) jump check_work_pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) R0 = #VM_INT_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }