162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Event entry/exit for Hexagon 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <asm/asm-offsets.h> /* assembly-safer versions of C defines */ 962306a36Sopenharmony_ci#include <asm/mem-layout.h> /* sigh, except for page_offset */ 1062306a36Sopenharmony_ci#include <asm/hexagon_vm.h> 1162306a36Sopenharmony_ci#include <asm/thread_info.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * Entry into guest-mode Linux under Hexagon Virtual Machine. 1562306a36Sopenharmony_ci * Stack pointer points to event record - build pt_regs on top of it, 1662306a36Sopenharmony_ci * set up a plausible C stack frame, and dispatch to the C handler. 1762306a36Sopenharmony_ci * On return, do vmrte virtual instruction with SP where we started. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * VM Spec 0.5 uses a trap to fetch HVM record now. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * Save full register state, while setting up thread_info struct 2462306a36Sopenharmony_ci * pointer derived from kernel stack pointer in THREADINFO_REG 2562306a36Sopenharmony_ci * register, putting prior thread_info.regs pointer in a callee-save 2662306a36Sopenharmony_ci * register (R24, which had better not ever be assigned to THREADINFO_REG), 2762306a36Sopenharmony_ci * and updating thread_info.regs to point to current stack frame, 2862306a36Sopenharmony_ci * so as to support nested events in kernel mode. 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * As this is common code, we set the pt_regs system call number 3162306a36Sopenharmony_ci * to -1 for all events. It will be replaced with the system call 3262306a36Sopenharmony_ci * number in the case where we decode a system call (trap0(#1)). 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#if CONFIG_HEXAGON_ARCH_VERSION < 4 3662306a36Sopenharmony_ci#define save_pt_regs()\ 3762306a36Sopenharmony_ci memd(R0 + #_PT_R3130) = R31:30; \ 3862306a36Sopenharmony_ci { memw(R0 + #_PT_R2928) = R28; \ 3962306a36Sopenharmony_ci R31 = memw(R0 + #_PT_ER_VMPSP); }\ 4062306a36Sopenharmony_ci { memw(R0 + #(_PT_R2928 + 4)) = R31; \ 4162306a36Sopenharmony_ci R31 = ugp; } \ 4262306a36Sopenharmony_ci { memd(R0 + #_PT_R2726) = R27:26; \ 4362306a36Sopenharmony_ci R30 = gp ; } \ 4462306a36Sopenharmony_ci memd(R0 + #_PT_R2524) = R25:24; \ 4562306a36Sopenharmony_ci memd(R0 + #_PT_R2322) = R23:22; \ 4662306a36Sopenharmony_ci memd(R0 + #_PT_R2120) = R21:20; \ 4762306a36Sopenharmony_ci memd(R0 + #_PT_R1918) = R19:18; \ 4862306a36Sopenharmony_ci memd(R0 + #_PT_R1716) = R17:16; \ 4962306a36Sopenharmony_ci memd(R0 + #_PT_R1514) = R15:14; \ 5062306a36Sopenharmony_ci memd(R0 + #_PT_R1312) = R13:12; \ 5162306a36Sopenharmony_ci { memd(R0 + #_PT_R1110) = R11:10; \ 5262306a36Sopenharmony_ci R15 = lc0; } \ 5362306a36Sopenharmony_ci { memd(R0 + #_PT_R0908) = R9:8; \ 5462306a36Sopenharmony_ci R14 = sa0; } \ 5562306a36Sopenharmony_ci { memd(R0 + #_PT_R0706) = R7:6; \ 5662306a36Sopenharmony_ci R13 = lc1; } \ 5762306a36Sopenharmony_ci { memd(R0 + #_PT_R0504) = R5:4; \ 5862306a36Sopenharmony_ci R12 = sa1; } \ 5962306a36Sopenharmony_ci { memd(R0 + #_PT_GPUGP) = R31:30; \ 6062306a36Sopenharmony_ci R11 = m1; \ 6162306a36Sopenharmony_ci R2.H = #HI(_THREAD_SIZE); } \ 6262306a36Sopenharmony_ci { memd(R0 + #_PT_LC0SA0) = R15:14; \ 6362306a36Sopenharmony_ci R10 = m0; \ 6462306a36Sopenharmony_ci R2.L = #LO(_THREAD_SIZE); } \ 6562306a36Sopenharmony_ci { memd(R0 + #_PT_LC1SA1) = R13:12; \ 6662306a36Sopenharmony_ci R15 = p3:0; \ 6762306a36Sopenharmony_ci R2 = neg(R2); } \ 6862306a36Sopenharmony_ci { memd(R0 + #_PT_M1M0) = R11:10; \ 6962306a36Sopenharmony_ci R14 = usr; \ 7062306a36Sopenharmony_ci R2 = and(R0,R2); } \ 7162306a36Sopenharmony_ci { memd(R0 + #_PT_PREDSUSR) = R15:14; \ 7262306a36Sopenharmony_ci THREADINFO_REG = R2; } \ 7362306a36Sopenharmony_ci { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \ 7462306a36Sopenharmony_ci memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \ 7562306a36Sopenharmony_ci R2 = #-1; } \ 7662306a36Sopenharmony_ci { memw(R0 + #_PT_SYSCALL_NR) = R2; \ 7762306a36Sopenharmony_ci R30 = #0; } 7862306a36Sopenharmony_ci#else 7962306a36Sopenharmony_ci/* V4+ */ 8062306a36Sopenharmony_ci/* the # ## # syntax inserts a literal ## */ 8162306a36Sopenharmony_ci#define save_pt_regs()\ 8262306a36Sopenharmony_ci { memd(R0 + #_PT_R3130) = R31:30; \ 8362306a36Sopenharmony_ci R30 = memw(R0 + #_PT_ER_VMPSP); }\ 8462306a36Sopenharmony_ci { memw(R0 + #_PT_R2928) = R28; \ 8562306a36Sopenharmony_ci memw(R0 + #(_PT_R2928 + 4)) = R30; }\ 8662306a36Sopenharmony_ci { R31:30 = C11:10; \ 8762306a36Sopenharmony_ci memd(R0 + #_PT_R2726) = R27:26; \ 8862306a36Sopenharmony_ci memd(R0 + #_PT_R2524) = R25:24; }\ 8962306a36Sopenharmony_ci { memd(R0 + #_PT_R2322) = R23:22; \ 9062306a36Sopenharmony_ci memd(R0 + #_PT_R2120) = R21:20; }\ 9162306a36Sopenharmony_ci { memd(R0 + #_PT_R1918) = R19:18; \ 9262306a36Sopenharmony_ci memd(R0 + #_PT_R1716) = R17:16; }\ 9362306a36Sopenharmony_ci { memd(R0 + #_PT_R1514) = R15:14; \ 9462306a36Sopenharmony_ci memd(R0 + #_PT_R1312) = R13:12; \ 9562306a36Sopenharmony_ci R17:16 = C13:12; }\ 9662306a36Sopenharmony_ci { memd(R0 + #_PT_R1110) = R11:10; \ 9762306a36Sopenharmony_ci memd(R0 + #_PT_R0908) = R9:8; \ 9862306a36Sopenharmony_ci R15:14 = C1:0; } \ 9962306a36Sopenharmony_ci { memd(R0 + #_PT_R0706) = R7:6; \ 10062306a36Sopenharmony_ci memd(R0 + #_PT_R0504) = R5:4; \ 10162306a36Sopenharmony_ci R13:12 = C3:2; } \ 10262306a36Sopenharmony_ci { memd(R0 + #_PT_GPUGP) = R31:30; \ 10362306a36Sopenharmony_ci memd(R0 + #_PT_LC0SA0) = R15:14; \ 10462306a36Sopenharmony_ci R11:10 = C7:6; }\ 10562306a36Sopenharmony_ci { THREADINFO_REG = and(R0, # ## #-_THREAD_SIZE); \ 10662306a36Sopenharmony_ci memd(R0 + #_PT_LC1SA1) = R13:12; \ 10762306a36Sopenharmony_ci R15 = p3:0; }\ 10862306a36Sopenharmony_ci { memd(R0 + #_PT_M1M0) = R11:10; \ 10962306a36Sopenharmony_ci memw(R0 + #_PT_PREDSUSR + 4) = R15; }\ 11062306a36Sopenharmony_ci { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \ 11162306a36Sopenharmony_ci memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \ 11262306a36Sopenharmony_ci R2 = #-1; } \ 11362306a36Sopenharmony_ci { memw(R0 + #_PT_SYSCALL_NR) = R2; \ 11462306a36Sopenharmony_ci memd(R0 + #_PT_CS1CS0) = R17:16; \ 11562306a36Sopenharmony_ci R30 = #0; } 11662306a36Sopenharmony_ci#endif 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/* 11962306a36Sopenharmony_ci * Restore registers and thread_info.regs state. THREADINFO_REG 12062306a36Sopenharmony_ci * is assumed to still be sane, and R24 to have been correctly 12162306a36Sopenharmony_ci * preserved. Don't restore R29 (SP) until later. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#if CONFIG_HEXAGON_ARCH_VERSION < 4 12562306a36Sopenharmony_ci#define restore_pt_regs() \ 12662306a36Sopenharmony_ci { memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \ 12762306a36Sopenharmony_ci R15:14 = memd(R0 + #_PT_PREDSUSR); } \ 12862306a36Sopenharmony_ci { R11:10 = memd(R0 + #_PT_M1M0); \ 12962306a36Sopenharmony_ci p3:0 = R15; } \ 13062306a36Sopenharmony_ci { R13:12 = memd(R0 + #_PT_LC1SA1); \ 13162306a36Sopenharmony_ci usr = R14; } \ 13262306a36Sopenharmony_ci { R15:14 = memd(R0 + #_PT_LC0SA0); \ 13362306a36Sopenharmony_ci m1 = R11; } \ 13462306a36Sopenharmony_ci { R3:2 = memd(R0 + #_PT_R0302); \ 13562306a36Sopenharmony_ci m0 = R10; } \ 13662306a36Sopenharmony_ci { R5:4 = memd(R0 + #_PT_R0504); \ 13762306a36Sopenharmony_ci lc1 = R13; } \ 13862306a36Sopenharmony_ci { R7:6 = memd(R0 + #_PT_R0706); \ 13962306a36Sopenharmony_ci sa1 = R12; } \ 14062306a36Sopenharmony_ci { R9:8 = memd(R0 + #_PT_R0908); \ 14162306a36Sopenharmony_ci lc0 = R15; } \ 14262306a36Sopenharmony_ci { R11:10 = memd(R0 + #_PT_R1110); \ 14362306a36Sopenharmony_ci sa0 = R14; } \ 14462306a36Sopenharmony_ci { R13:12 = memd(R0 + #_PT_R1312); \ 14562306a36Sopenharmony_ci R15:14 = memd(R0 + #_PT_R1514); } \ 14662306a36Sopenharmony_ci { R17:16 = memd(R0 + #_PT_R1716); \ 14762306a36Sopenharmony_ci R19:18 = memd(R0 + #_PT_R1918); } \ 14862306a36Sopenharmony_ci { R21:20 = memd(R0 + #_PT_R2120); \ 14962306a36Sopenharmony_ci R23:22 = memd(R0 + #_PT_R2322); } \ 15062306a36Sopenharmony_ci { R25:24 = memd(R0 + #_PT_R2524); \ 15162306a36Sopenharmony_ci R27:26 = memd(R0 + #_PT_R2726); } \ 15262306a36Sopenharmony_ci R31:30 = memd(R0 + #_PT_GPUGP); \ 15362306a36Sopenharmony_ci { R28 = memw(R0 + #_PT_R2928); \ 15462306a36Sopenharmony_ci ugp = R31; } \ 15562306a36Sopenharmony_ci { R31:30 = memd(R0 + #_PT_R3130); \ 15662306a36Sopenharmony_ci gp = R30; } 15762306a36Sopenharmony_ci#else 15862306a36Sopenharmony_ci/* V4+ */ 15962306a36Sopenharmony_ci#define restore_pt_regs() \ 16062306a36Sopenharmony_ci { memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \ 16162306a36Sopenharmony_ci R15:14 = memd(R0 + #_PT_PREDSUSR); } \ 16262306a36Sopenharmony_ci { R11:10 = memd(R0 + #_PT_M1M0); \ 16362306a36Sopenharmony_ci R13:12 = memd(R0 + #_PT_LC1SA1); \ 16462306a36Sopenharmony_ci p3:0 = R15; } \ 16562306a36Sopenharmony_ci { R15:14 = memd(R0 + #_PT_LC0SA0); \ 16662306a36Sopenharmony_ci R3:2 = memd(R0 + #_PT_R0302); \ 16762306a36Sopenharmony_ci usr = R14; } \ 16862306a36Sopenharmony_ci { R5:4 = memd(R0 + #_PT_R0504); \ 16962306a36Sopenharmony_ci R7:6 = memd(R0 + #_PT_R0706); \ 17062306a36Sopenharmony_ci C7:6 = R11:10; }\ 17162306a36Sopenharmony_ci { R9:8 = memd(R0 + #_PT_R0908); \ 17262306a36Sopenharmony_ci R11:10 = memd(R0 + #_PT_R1110); \ 17362306a36Sopenharmony_ci C3:2 = R13:12; }\ 17462306a36Sopenharmony_ci { R13:12 = memd(R0 + #_PT_R1312); \ 17562306a36Sopenharmony_ci R15:14 = memd(R0 + #_PT_R1514); \ 17662306a36Sopenharmony_ci C1:0 = R15:14; }\ 17762306a36Sopenharmony_ci { R17:16 = memd(R0 + #_PT_R1716); \ 17862306a36Sopenharmony_ci R19:18 = memd(R0 + #_PT_R1918); } \ 17962306a36Sopenharmony_ci { R21:20 = memd(R0 + #_PT_R2120); \ 18062306a36Sopenharmony_ci R23:22 = memd(R0 + #_PT_R2322); } \ 18162306a36Sopenharmony_ci { R25:24 = memd(R0 + #_PT_R2524); \ 18262306a36Sopenharmony_ci R27:26 = memd(R0 + #_PT_R2726); } \ 18362306a36Sopenharmony_ci R31:30 = memd(R0 + #_PT_CS1CS0); \ 18462306a36Sopenharmony_ci { C13:12 = R31:30; \ 18562306a36Sopenharmony_ci R31:30 = memd(R0 + #_PT_GPUGP) ; \ 18662306a36Sopenharmony_ci R28 = memw(R0 + #_PT_R2928); }\ 18762306a36Sopenharmony_ci { C11:10 = R31:30; \ 18862306a36Sopenharmony_ci R31:30 = memd(R0 + #_PT_R3130); } 18962306a36Sopenharmony_ci#endif 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci /* 19262306a36Sopenharmony_ci * Clears off enough space for the rest of pt_regs; evrec is a part 19362306a36Sopenharmony_ci * of pt_regs in HVM mode. Save R0/R1, set handler's address in R1. 19462306a36Sopenharmony_ci * R0 is the address of pt_regs and is the parameter to save_pt_regs. 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci/* 19862306a36Sopenharmony_ci * Since the HVM isn't automagically pushing the EVREC onto the stack anymore, 19962306a36Sopenharmony_ci * we'll subract the entire size out and then fill it in ourselves. 20062306a36Sopenharmony_ci * Need to save off R0, R1, R2, R3 immediately. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci#if CONFIG_HEXAGON_ARCH_VERSION < 4 20462306a36Sopenharmony_ci#define vm_event_entry(CHandler) \ 20562306a36Sopenharmony_ci { \ 20662306a36Sopenharmony_ci R29 = add(R29, #-(_PT_REGS_SIZE)); \ 20762306a36Sopenharmony_ci memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \ 20862306a36Sopenharmony_ci } \ 20962306a36Sopenharmony_ci { \ 21062306a36Sopenharmony_ci memd(R29 +#_PT_R0302) = R3:2; \ 21162306a36Sopenharmony_ci } \ 21262306a36Sopenharmony_ci trap1(#HVM_TRAP1_VMGETREGS); \ 21362306a36Sopenharmony_ci { \ 21462306a36Sopenharmony_ci memd(R29 + #_PT_ER_VMEL) = R1:0; \ 21562306a36Sopenharmony_ci R0 = R29; \ 21662306a36Sopenharmony_ci R1.L = #LO(CHandler); \ 21762306a36Sopenharmony_ci } \ 21862306a36Sopenharmony_ci { \ 21962306a36Sopenharmony_ci memd(R29 + #_PT_ER_VMPSP) = R3:2; \ 22062306a36Sopenharmony_ci R1.H = #HI(CHandler); \ 22162306a36Sopenharmony_ci jump event_dispatch; \ 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci#else 22462306a36Sopenharmony_ci/* V4+ */ 22562306a36Sopenharmony_ci/* turn on I$ prefetch early */ 22662306a36Sopenharmony_ci/* the # ## # syntax inserts a literal ## */ 22762306a36Sopenharmony_ci#define vm_event_entry(CHandler) \ 22862306a36Sopenharmony_ci { \ 22962306a36Sopenharmony_ci R29 = add(R29, #-(_PT_REGS_SIZE)); \ 23062306a36Sopenharmony_ci memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \ 23162306a36Sopenharmony_ci memd(R29 + #(_PT_R0302 + -_PT_REGS_SIZE)) = R3:2; \ 23262306a36Sopenharmony_ci R0 = usr; \ 23362306a36Sopenharmony_ci } \ 23462306a36Sopenharmony_ci { \ 23562306a36Sopenharmony_ci memw(R29 + #_PT_PREDSUSR) = R0; \ 23662306a36Sopenharmony_ci R0 = setbit(R0, #16); \ 23762306a36Sopenharmony_ci } \ 23862306a36Sopenharmony_ci usr = R0; \ 23962306a36Sopenharmony_ci R1:0 = G1:0; \ 24062306a36Sopenharmony_ci { \ 24162306a36Sopenharmony_ci memd(R29 + #_PT_ER_VMEL) = R1:0; \ 24262306a36Sopenharmony_ci R1 = # ## #(CHandler); \ 24362306a36Sopenharmony_ci R3:2 = G3:2; \ 24462306a36Sopenharmony_ci } \ 24562306a36Sopenharmony_ci { \ 24662306a36Sopenharmony_ci R0 = R29; \ 24762306a36Sopenharmony_ci memd(R29 + #_PT_ER_VMPSP) = R3:2; \ 24862306a36Sopenharmony_ci jump event_dispatch; \ 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci#endif 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci.text 25362306a36Sopenharmony_ci /* 25462306a36Sopenharmony_ci * Do bulk save/restore in one place. 25562306a36Sopenharmony_ci * Adds a jump to dispatch latency, but 25662306a36Sopenharmony_ci * saves hundreds of bytes. 25762306a36Sopenharmony_ci */ 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cievent_dispatch: 26062306a36Sopenharmony_ci save_pt_regs() 26162306a36Sopenharmony_ci callr r1 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* 26462306a36Sopenharmony_ci * Coming back from the C-world, our thread info pointer 26562306a36Sopenharmony_ci * should be in the designated register (usually R19) 26662306a36Sopenharmony_ci * 26762306a36Sopenharmony_ci * If we were in kernel mode, we don't need to check scheduler 26862306a36Sopenharmony_ci * or signals if CONFIG_PREEMPTION is not set. If set, then it has 26962306a36Sopenharmony_ci * to jump to a need_resched kind of block. 27062306a36Sopenharmony_ci * BTW, CONFIG_PREEMPTION is not supported yet. 27162306a36Sopenharmony_ci */ 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci#ifdef CONFIG_PREEMPTION 27462306a36Sopenharmony_ci R0 = #VM_INT_DISABLE 27562306a36Sopenharmony_ci trap1(#HVM_TRAP1_VMSETIE) 27662306a36Sopenharmony_ci#endif 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci /* "Nested control path" -- if the previous mode was kernel */ 27962306a36Sopenharmony_ci { 28062306a36Sopenharmony_ci R0 = memw(R29 + #_PT_ER_VMEST); 28162306a36Sopenharmony_ci R26.L = #LO(do_work_pending); 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci { 28462306a36Sopenharmony_ci P0 = tstbit(R0, #HVM_VMEST_UM_SFT); 28562306a36Sopenharmony_ci if (!P0.new) jump:nt restore_all; 28662306a36Sopenharmony_ci R26.H = #HI(do_work_pending); 28762306a36Sopenharmony_ci R0 = #VM_INT_DISABLE; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci /* 29162306a36Sopenharmony_ci * Check also the return from fork/system call, normally coming back from 29262306a36Sopenharmony_ci * user mode 29362306a36Sopenharmony_ci * 29462306a36Sopenharmony_ci * R26 needs to have do_work_pending, and R0 should have VM_INT_DISABLE 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cicheck_work_pending: 29862306a36Sopenharmony_ci /* Disable interrupts while checking TIF */ 29962306a36Sopenharmony_ci trap1(#HVM_TRAP1_VMSETIE) 30062306a36Sopenharmony_ci { 30162306a36Sopenharmony_ci R0 = R29; /* regs should still be at top of stack */ 30262306a36Sopenharmony_ci R1 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS); 30362306a36Sopenharmony_ci callr R26; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci { 30762306a36Sopenharmony_ci P0 = cmp.eq(R0, #0); if (!P0.new) jump:nt check_work_pending; 30862306a36Sopenharmony_ci R0 = #VM_INT_DISABLE; 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cirestore_all: 31262306a36Sopenharmony_ci /* 31362306a36Sopenharmony_ci * Disable interrupts, if they weren't already, before reg restore. 31462306a36Sopenharmony_ci * R0 gets preloaded with #VM_INT_DISABLE before we get here. 31562306a36Sopenharmony_ci */ 31662306a36Sopenharmony_ci trap1(#HVM_TRAP1_VMSETIE) 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci /* do the setregs here for VM 0.5 */ 31962306a36Sopenharmony_ci /* R29 here should already be pointing at pt_regs */ 32062306a36Sopenharmony_ci { 32162306a36Sopenharmony_ci R1:0 = memd(R29 + #_PT_ER_VMEL); 32262306a36Sopenharmony_ci R3:2 = memd(R29 + #_PT_ER_VMPSP); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci#if CONFIG_HEXAGON_ARCH_VERSION < 4 32562306a36Sopenharmony_ci trap1(#HVM_TRAP1_VMSETREGS); 32662306a36Sopenharmony_ci#else 32762306a36Sopenharmony_ci G1:0 = R1:0; 32862306a36Sopenharmony_ci G3:2 = R3:2; 32962306a36Sopenharmony_ci#endif 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci R0 = R29 33262306a36Sopenharmony_ci restore_pt_regs() 33362306a36Sopenharmony_ci { 33462306a36Sopenharmony_ci R1:0 = memd(R29 + #_PT_R0100); 33562306a36Sopenharmony_ci R29 = add(R29, #_PT_REGS_SIZE); 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci trap1(#HVM_TRAP1_VMRTE) 33862306a36Sopenharmony_ci /* Notreached */ 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci .globl _K_enter_genex 34262306a36Sopenharmony_ci_K_enter_genex: 34362306a36Sopenharmony_ci vm_event_entry(do_genex) 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci .globl _K_enter_interrupt 34662306a36Sopenharmony_ci_K_enter_interrupt: 34762306a36Sopenharmony_ci vm_event_entry(arch_do_IRQ) 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci .globl _K_enter_trap0 35062306a36Sopenharmony_ci_K_enter_trap0: 35162306a36Sopenharmony_ci vm_event_entry(do_trap0) 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci .globl _K_enter_machcheck 35462306a36Sopenharmony_ci_K_enter_machcheck: 35562306a36Sopenharmony_ci vm_event_entry(do_machcheck) 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci .globl _K_enter_debug 35862306a36Sopenharmony_ci_K_enter_debug: 35962306a36Sopenharmony_ci vm_event_entry(do_debug_exception) 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci .globl ret_from_fork 36262306a36Sopenharmony_ciret_from_fork: 36362306a36Sopenharmony_ci { 36462306a36Sopenharmony_ci call schedule_tail 36562306a36Sopenharmony_ci R26.H = #HI(do_work_pending); 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci { 36862306a36Sopenharmony_ci P0 = cmp.eq(R24, #0); 36962306a36Sopenharmony_ci R26.L = #LO(do_work_pending); 37062306a36Sopenharmony_ci R0 = #VM_INT_DISABLE; 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci if (P0) jump check_work_pending 37362306a36Sopenharmony_ci { 37462306a36Sopenharmony_ci R0 = R25; 37562306a36Sopenharmony_ci callr R24 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci { 37862306a36Sopenharmony_ci jump check_work_pending 37962306a36Sopenharmony_ci R0 = #VM_INT_DISABLE; 38062306a36Sopenharmony_ci } 381