cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

extable.c (1696B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
      4 *  Lennox Wu <lennox.wu@sunplusct.com>
      5 *  Chen Liqin <liqin.chen@sunplusct.com>
      6 * Copyright (C) 2013 Regents of the University of California
      7 */
      8
      9
     10#include <linux/bitfield.h>
     11#include <linux/extable.h>
     12#include <linux/module.h>
     13#include <linux/uaccess.h>
     14#include <asm/asm-extable.h>
     15#include <asm/ptrace.h>
     16
     17static inline unsigned long
     18get_ex_fixup(const struct exception_table_entry *ex)
     19{
     20	return ((unsigned long)&ex->fixup + ex->fixup);
     21}
     22
     23static bool ex_handler_fixup(const struct exception_table_entry *ex,
     24			     struct pt_regs *regs)
     25{
     26	regs->epc = get_ex_fixup(ex);
     27	return true;
     28}
     29
     30static inline void regs_set_gpr(struct pt_regs *regs, unsigned int offset,
     31				unsigned long val)
     32{
     33	if (unlikely(offset > MAX_REG_OFFSET))
     34		return;
     35
     36	if (offset)
     37		*(unsigned long *)((unsigned long)regs + offset) = val;
     38}
     39
     40static bool ex_handler_uaccess_err_zero(const struct exception_table_entry *ex,
     41					struct pt_regs *regs)
     42{
     43	int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
     44	int reg_zero = FIELD_GET(EX_DATA_REG_ZERO, ex->data);
     45
     46	regs_set_gpr(regs, reg_err * sizeof(unsigned long), -EFAULT);
     47	regs_set_gpr(regs, reg_zero * sizeof(unsigned long), 0);
     48
     49	regs->epc = get_ex_fixup(ex);
     50	return true;
     51}
     52
     53bool fixup_exception(struct pt_regs *regs)
     54{
     55	const struct exception_table_entry *ex;
     56
     57	ex = search_exception_tables(regs->epc);
     58	if (!ex)
     59		return false;
     60
     61	switch (ex->type) {
     62	case EX_TYPE_FIXUP:
     63		return ex_handler_fixup(ex, regs);
     64	case EX_TYPE_BPF:
     65		return ex_handler_bpf(ex, regs);
     66	case EX_TYPE_UACCESS_ERR_ZERO:
     67		return ex_handler_uaccess_err_zero(ex, regs);
     68	}
     69
     70	BUG();
     71}