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

brl_emu.c (5189B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  Emulation of the "brl" instruction for IA64 processors that
      4 *  don't support it in hardware.
      5 *  Author: Stephan Zeisset, Intel Corp. <Stephan.Zeisset@intel.com>
      6 *
      7 *    02/22/02	D. Mosberger	Clear si_flgs, si_isr, and si_imm to avoid
      8 *				leaking kernel bits.
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/sched/signal.h>
     13#include <linux/uaccess.h>
     14#include <asm/processor.h>
     15
     16extern char ia64_set_b1, ia64_set_b2, ia64_set_b3, ia64_set_b4, ia64_set_b5;
     17
     18struct illegal_op_return {
     19	unsigned long fkt, arg1, arg2, arg3;
     20};
     21
     22/*
     23 *  The unimplemented bits of a virtual address must be set
     24 *  to the value of the most significant implemented bit.
     25 *  unimpl_va_mask includes all unimplemented bits and
     26 *  the most significant implemented bit, so the result
     27 *  of an and operation with the mask must be all 0's
     28 *  or all 1's for the address to be valid.
     29 */
     30#define unimplemented_virtual_address(va) (						\
     31	((va) & local_cpu_data->unimpl_va_mask) != 0 &&					\
     32	((va) & local_cpu_data->unimpl_va_mask) != local_cpu_data->unimpl_va_mask	\
     33)
     34
     35/*
     36 *  The unimplemented bits of a physical address must be 0.
     37 *  unimpl_pa_mask includes all unimplemented bits, so the result
     38 *  of an and operation with the mask must be all 0's for the
     39 *  address to be valid.
     40 */
     41#define unimplemented_physical_address(pa) (		\
     42	((pa) & local_cpu_data->unimpl_pa_mask) != 0	\
     43)
     44
     45/*
     46 *  Handle an illegal operation fault that was caused by an
     47 *  unimplemented "brl" instruction.
     48 *  If we are not successful (e.g because the illegal operation
     49 *  wasn't caused by a "brl" after all), we return -1.
     50 *  If we are successful, we return either 0 or the address
     51 *  of a "fixup" function for manipulating preserved register
     52 *  state.
     53 */
     54
     55struct illegal_op_return
     56ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec)
     57{
     58	unsigned long bundle[2];
     59	unsigned long opcode, btype, qp, offset, cpl;
     60	unsigned long next_ip;
     61	struct illegal_op_return rv;
     62	long tmp_taken, unimplemented_address;
     63
     64	rv.fkt = (unsigned long) -1;
     65
     66	/*
     67	 *  Decode the instruction bundle.
     68	 */
     69
     70	if (copy_from_user(bundle, (void *) (regs->cr_iip), sizeof(bundle)))
     71		return rv;
     72
     73	next_ip = (unsigned long) regs->cr_iip + 16;
     74
     75	/* "brl" must be in slot 2. */
     76	if (ia64_psr(regs)->ri != 1) return rv;
     77
     78	/* Must be "mlx" template */
     79	if ((bundle[0] & 0x1e) != 0x4) return rv;
     80
     81	opcode = (bundle[1] >> 60);
     82	btype = ((bundle[1] >> 29) & 0x7);
     83	qp = ((bundle[1] >> 23) & 0x3f);
     84	offset = ((bundle[1] & 0x0800000000000000L) << 4)
     85		| ((bundle[1] & 0x00fffff000000000L) >> 32)
     86		| ((bundle[1] & 0x00000000007fffffL) << 40)
     87		| ((bundle[0] & 0xffff000000000000L) >> 24);
     88
     89	tmp_taken = regs->pr & (1L << qp);
     90
     91	switch(opcode) {
     92
     93		case 0xC:
     94			/*
     95			 *  Long Branch.
     96			 */
     97			if (btype != 0) return rv;
     98			rv.fkt = 0;
     99			if (!(tmp_taken)) {
    100				/*
    101				 *  Qualifying predicate is 0.
    102				 *  Skip instruction.
    103				 */
    104				regs->cr_iip = next_ip;
    105				ia64_psr(regs)->ri = 0;
    106				return rv;
    107			}
    108			break;
    109
    110		case 0xD:
    111			/*
    112			 *  Long Call.
    113			 */
    114			rv.fkt = 0;
    115			if (!(tmp_taken)) {
    116				/*
    117				 *  Qualifying predicate is 0.
    118				 *  Skip instruction.
    119				 */
    120				regs->cr_iip = next_ip;
    121				ia64_psr(regs)->ri = 0;
    122				return rv;
    123			}
    124
    125			/*
    126			 *  BR[btype] = IP+16
    127			 */
    128			switch(btype) {
    129				case 0:
    130					regs->b0 = next_ip;
    131					break;
    132				case 1:
    133					rv.fkt = (unsigned long) &ia64_set_b1;
    134					break;
    135				case 2:
    136					rv.fkt = (unsigned long) &ia64_set_b2;
    137					break;
    138				case 3:
    139					rv.fkt = (unsigned long) &ia64_set_b3;
    140					break;
    141				case 4:
    142					rv.fkt = (unsigned long) &ia64_set_b4;
    143					break;
    144				case 5:
    145					rv.fkt = (unsigned long) &ia64_set_b5;
    146					break;
    147				case 6:
    148					regs->b6 = next_ip;
    149					break;
    150				case 7:
    151					regs->b7 = next_ip;
    152					break;
    153			}
    154			rv.arg1 = next_ip;
    155
    156			/*
    157			 *  AR[PFS].pfm = CFM
    158			 *  AR[PFS].pec = AR[EC]
    159			 *  AR[PFS].ppl = PSR.cpl
    160			 */
    161			cpl = ia64_psr(regs)->cpl;
    162			regs->ar_pfs = ((regs->cr_ifs & 0x3fffffffff)
    163					| (ar_ec << 52) | (cpl << 62));
    164
    165			/*
    166			 *  CFM.sof -= CFM.sol
    167			 *  CFM.sol = 0
    168			 *  CFM.sor = 0
    169			 *  CFM.rrb.gr = 0
    170			 *  CFM.rrb.fr = 0
    171			 *  CFM.rrb.pr = 0
    172			 */
    173			regs->cr_ifs = ((regs->cr_ifs & 0xffffffc00000007f)
    174					- ((regs->cr_ifs >> 7) & 0x7f));
    175
    176			break;
    177
    178		default:
    179			/*
    180			 *  Unknown opcode.
    181			 */
    182			return rv;
    183
    184	}
    185
    186	regs->cr_iip += offset;
    187	ia64_psr(regs)->ri = 0;
    188
    189	if (ia64_psr(regs)->it == 0)
    190		unimplemented_address = unimplemented_physical_address(regs->cr_iip);
    191	else
    192		unimplemented_address = unimplemented_virtual_address(regs->cr_iip);
    193
    194	if (unimplemented_address) {
    195		/*
    196		 *  The target address contains unimplemented bits.
    197		 */
    198		printk(KERN_DEBUG "Woah! Unimplemented Instruction Address Trap!\n");
    199		force_sig_fault(SIGILL, ILL_BADIADDR, (void __user *)NULL,
    200				0, 0, 0);
    201	} else if (ia64_psr(regs)->tb) {
    202		/*
    203		 *  Branch Tracing is enabled.
    204		 *  Force a taken branch signal.
    205		 */
    206		force_sig_fault(SIGTRAP, TRAP_BRANCH, (void __user *)NULL,
    207				0, 0, 0);
    208	} else if (ia64_psr(regs)->ss) {
    209		/*
    210		 *  Single Step is enabled.
    211		 *  Force a trace signal.
    212		 */
    213		force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)NULL,
    214				0, 0, 0);
    215	}
    216	return rv;
    217}