1*8382c668SSean Christopherson // SPDX-License-Identifier: GPL-2.0 2*8382c668SSean Christopherson #include <linux/err.h> 3*8382c668SSean Christopherson #include <linux/mm.h> 4*8382c668SSean Christopherson #include <asm/current.h> 5*8382c668SSean Christopherson #include <asm/traps.h> 6*8382c668SSean Christopherson #include <asm/vdso.h> 7*8382c668SSean Christopherson 8*8382c668SSean Christopherson struct vdso_exception_table_entry { 9*8382c668SSean Christopherson int insn, fixup; 10*8382c668SSean Christopherson }; 11*8382c668SSean Christopherson fixup_vdso_exception(struct pt_regs * regs,int trapnr,unsigned long error_code,unsigned long fault_addr)12*8382c668SSean Christophersonbool fixup_vdso_exception(struct pt_regs *regs, int trapnr, 13*8382c668SSean Christopherson unsigned long error_code, unsigned long fault_addr) 14*8382c668SSean Christopherson { 15*8382c668SSean Christopherson const struct vdso_image *image = current->mm->context.vdso_image; 16*8382c668SSean Christopherson const struct vdso_exception_table_entry *extable; 17*8382c668SSean Christopherson unsigned int nr_entries, i; 18*8382c668SSean Christopherson unsigned long base; 19*8382c668SSean Christopherson 20*8382c668SSean Christopherson /* 21*8382c668SSean Christopherson * Do not attempt to fixup #DB or #BP. It's impossible to identify 22*8382c668SSean Christopherson * whether or not a #DB/#BP originated from within an SGX enclave and 23*8382c668SSean Christopherson * SGX enclaves are currently the only use case for vDSO fixup. 24*8382c668SSean Christopherson */ 25*8382c668SSean Christopherson if (trapnr == X86_TRAP_DB || trapnr == X86_TRAP_BP) 26*8382c668SSean Christopherson return false; 27*8382c668SSean Christopherson 28*8382c668SSean Christopherson if (!current->mm->context.vdso) 29*8382c668SSean Christopherson return false; 30*8382c668SSean Christopherson 31*8382c668SSean Christopherson base = (unsigned long)current->mm->context.vdso + image->extable_base; 32*8382c668SSean Christopherson nr_entries = image->extable_len / (sizeof(*extable)); 33*8382c668SSean Christopherson extable = image->extable; 34*8382c668SSean Christopherson 35*8382c668SSean Christopherson for (i = 0; i < nr_entries; i++) { 36*8382c668SSean Christopherson if (regs->ip == base + extable[i].insn) { 37*8382c668SSean Christopherson regs->ip = base + extable[i].fixup; 38*8382c668SSean Christopherson regs->di = trapnr; 39*8382c668SSean Christopherson regs->si = error_code; 40*8382c668SSean Christopherson regs->dx = fault_addr; 41*8382c668SSean Christopherson return true; 42*8382c668SSean Christopherson } 43*8382c668SSean Christopherson } 44*8382c668SSean Christopherson 45*8382c668SSean Christopherson return false; 46*8382c668SSean Christopherson } 47