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

opcodes.c (2127B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  linux/arch/arm/kernel/opcodes.c
      4 *
      5 *  A32 condition code lookup feature moved from nwfpe/fpopcode.c
      6 */
      7
      8#include <linux/module.h>
      9#include <asm/opcodes.h>
     10
     11#define ARM_OPCODE_CONDITION_UNCOND 0xf
     12
     13/*
     14 * condition code lookup table
     15 * index into the table is test code: EQ, NE, ... LT, GT, AL, NV
     16 *
     17 * bit position in short is condition code: NZCV
     18 */
     19static const unsigned short cc_map[16] = {
     20	0xF0F0,			/* EQ == Z set            */
     21	0x0F0F,			/* NE                     */
     22	0xCCCC,			/* CS == C set            */
     23	0x3333,			/* CC                     */
     24	0xFF00,			/* MI == N set            */
     25	0x00FF,			/* PL                     */
     26	0xAAAA,			/* VS == V set            */
     27	0x5555,			/* VC                     */
     28	0x0C0C,			/* HI == C set && Z clear */
     29	0xF3F3,			/* LS == C clear || Z set */
     30	0xAA55,			/* GE == (N==V)           */
     31	0x55AA,			/* LT == (N!=V)           */
     32	0x0A05,			/* GT == (!Z && (N==V))   */
     33	0xF5FA,			/* LE == (Z || (N!=V))    */
     34	0xFFFF,			/* AL always              */
     35	0			/* NV                     */
     36};
     37
     38/*
     39 * Returns:
     40 * ARM_OPCODE_CONDTEST_FAIL   - if condition fails
     41 * ARM_OPCODE_CONDTEST_PASS   - if condition passes (including AL)
     42 * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional
     43 *                              opcode space from v5 onwards
     44 *
     45 * Code that tests whether a conditional instruction would pass its condition
     46 * check should check that return value == ARM_OPCODE_CONDTEST_PASS.
     47 *
     48 * Code that tests if a condition means that the instruction would be executed
     49 * (regardless of conditional or unconditional) should instead check that the
     50 * return value != ARM_OPCODE_CONDTEST_FAIL.
     51 */
     52asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr)
     53{
     54	u32 cc_bits  = opcode >> 28;
     55	u32 psr_cond = psr >> 28;
     56	unsigned int ret;
     57
     58	if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
     59		if ((cc_map[cc_bits] >> (psr_cond)) & 1)
     60			ret = ARM_OPCODE_CONDTEST_PASS;
     61		else
     62			ret = ARM_OPCODE_CONDTEST_FAIL;
     63	} else {
     64		ret = ARM_OPCODE_CONDTEST_UNCOND;
     65	}
     66
     67	return ret;
     68}
     69EXPORT_SYMBOL_GPL(arm_check_condition);