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 (1887B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Based on arch/arm/mm/extable.c
      4 */
      5
      6#include <linux/bitfield.h>
      7#include <linux/extable.h>
      8#include <linux/uaccess.h>
      9
     10#include <asm/asm-extable.h>
     11#include <asm/ptrace.h>
     12
     13static inline unsigned long
     14get_ex_fixup(const struct exception_table_entry *ex)
     15{
     16	return ((unsigned long)&ex->fixup + ex->fixup);
     17}
     18
     19static bool ex_handler_fixup(const struct exception_table_entry *ex,
     20			     struct pt_regs *regs)
     21{
     22	regs->pc = get_ex_fixup(ex);
     23	return true;
     24}
     25
     26static bool ex_handler_uaccess_err_zero(const struct exception_table_entry *ex,
     27					struct pt_regs *regs)
     28{
     29	int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
     30	int reg_zero = FIELD_GET(EX_DATA_REG_ZERO, ex->data);
     31
     32	pt_regs_write_reg(regs, reg_err, -EFAULT);
     33	pt_regs_write_reg(regs, reg_zero, 0);
     34
     35	regs->pc = get_ex_fixup(ex);
     36	return true;
     37}
     38
     39static bool
     40ex_handler_load_unaligned_zeropad(const struct exception_table_entry *ex,
     41				  struct pt_regs *regs)
     42{
     43	int reg_data = FIELD_GET(EX_DATA_REG_DATA, ex->data);
     44	int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
     45	unsigned long data, addr, offset;
     46
     47	addr = pt_regs_read_reg(regs, reg_addr);
     48
     49	offset = addr & 0x7UL;
     50	addr &= ~0x7UL;
     51
     52	data = *(unsigned long*)addr;
     53
     54#ifndef __AARCH64EB__
     55	data >>= 8 * offset;
     56#else
     57	data <<= 8 * offset;
     58#endif
     59
     60	pt_regs_write_reg(regs, reg_data, data);
     61
     62	regs->pc = get_ex_fixup(ex);
     63	return true;
     64}
     65
     66bool fixup_exception(struct pt_regs *regs)
     67{
     68	const struct exception_table_entry *ex;
     69
     70	ex = search_exception_tables(instruction_pointer(regs));
     71	if (!ex)
     72		return false;
     73
     74	switch (ex->type) {
     75	case EX_TYPE_FIXUP:
     76		return ex_handler_fixup(ex, regs);
     77	case EX_TYPE_BPF:
     78		return ex_handler_bpf(ex, regs);
     79	case EX_TYPE_UACCESS_ERR_ZERO:
     80		return ex_handler_uaccess_err_zero(ex, regs);
     81	case EX_TYPE_LOAD_UNALIGNED_ZEROPAD:
     82		return ex_handler_load_unaligned_zeropad(ex, regs);
     83	}
     84
     85	BUG();
     86}