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


      1// SPDX-License-Identifier: GPL-2.0
      2
      3#include <linux/bitfield.h>
      4#include <linux/extable.h>
      5#include <linux/string.h>
      6#include <linux/errno.h>
      7#include <linux/panic.h>
      8#include <asm/asm-extable.h>
      9#include <asm/extable.h>
     10
     11const struct exception_table_entry *s390_search_extables(unsigned long addr)
     12{
     13	const struct exception_table_entry *fixup;
     14	size_t num;
     15
     16	fixup = search_exception_tables(addr);
     17	if (fixup)
     18		return fixup;
     19	num = __stop_amode31_ex_table - __start_amode31_ex_table;
     20	return search_extable(__start_amode31_ex_table, num, addr);
     21}
     22
     23static bool ex_handler_fixup(const struct exception_table_entry *ex, struct pt_regs *regs)
     24{
     25	regs->psw.addr = extable_fixup(ex);
     26	return true;
     27}
     28
     29static bool ex_handler_ua_store(const struct exception_table_entry *ex, struct pt_regs *regs)
     30{
     31	unsigned int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
     32
     33	regs->gprs[reg_err] = -EFAULT;
     34	regs->psw.addr = extable_fixup(ex);
     35	return true;
     36}
     37
     38static bool ex_handler_ua_load_mem(const struct exception_table_entry *ex, struct pt_regs *regs)
     39{
     40	unsigned int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
     41	unsigned int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
     42	size_t len = FIELD_GET(EX_DATA_LEN, ex->data);
     43
     44	regs->gprs[reg_err] = -EFAULT;
     45	memset((void *)regs->gprs[reg_addr], 0, len);
     46	regs->psw.addr = extable_fixup(ex);
     47	return true;
     48}
     49
     50static bool ex_handler_ua_load_reg(const struct exception_table_entry *ex, struct pt_regs *regs)
     51{
     52	unsigned int reg_zero = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
     53	unsigned int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
     54
     55	regs->gprs[reg_err] = -EFAULT;
     56	regs->gprs[reg_zero] = 0;
     57	regs->psw.addr = extable_fixup(ex);
     58	return true;
     59}
     60
     61bool fixup_exception(struct pt_regs *regs)
     62{
     63	const struct exception_table_entry *ex;
     64
     65	ex = s390_search_extables(instruction_pointer(regs));
     66	if (!ex)
     67		return false;
     68	switch (ex->type) {
     69	case EX_TYPE_FIXUP:
     70		return ex_handler_fixup(ex, regs);
     71	case EX_TYPE_BPF:
     72		return ex_handler_bpf(ex, regs);
     73	case EX_TYPE_UA_STORE:
     74		return ex_handler_ua_store(ex, regs);
     75	case EX_TYPE_UA_LOAD_MEM:
     76		return ex_handler_ua_load_mem(ex, regs);
     77	case EX_TYPE_UA_LOAD_REG:
     78		return ex_handler_ua_load_reg(ex, regs);
     79	}
     80	panic("invalid exception table entry");
     81}