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

esi.c (4283B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Extensible SAL Interface (ESI) support routines.
      4 *
      5 * Copyright (C) 2006 Hewlett-Packard Co
      6 * 	Alex Williamson <alex.williamson@hp.com>
      7 */
      8#include <linux/kernel.h>
      9#include <linux/init.h>
     10#include <linux/module.h>
     11#include <linux/string.h>
     12
     13#include <asm/esi.h>
     14#include <asm/sal.h>
     15
     16MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
     17MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
     18MODULE_LICENSE("GPL");
     19
     20#define MODULE_NAME	"esi"
     21
     22enum esi_systab_entry_type {
     23	ESI_DESC_ENTRY_POINT = 0
     24};
     25
     26/*
     27 * Entry type:	Size:
     28 *	0	48
     29 */
     30#define ESI_DESC_SIZE(type)	"\060"[(unsigned) (type)]
     31
     32typedef struct ia64_esi_desc_entry_point {
     33	u8 type;
     34	u8 reserved1[15];
     35	u64 esi_proc;
     36	u64 gp;
     37	efi_guid_t guid;
     38} ia64_esi_desc_entry_point_t;
     39
     40struct pdesc {
     41	void *addr;
     42	void *gp;
     43};
     44
     45static struct ia64_sal_systab *esi_systab;
     46
     47extern unsigned long esi_phys;
     48
     49static int __init esi_init (void)
     50{
     51	struct ia64_sal_systab *systab;
     52	char *p;
     53	int i;
     54
     55	if (esi_phys == EFI_INVALID_TABLE_ADDR)
     56		return -ENODEV;
     57
     58	systab = __va(esi_phys);
     59
     60	if (strncmp(systab->signature, "ESIT", 4) != 0) {
     61		printk(KERN_ERR "bad signature in ESI system table!");
     62		return -ENODEV;
     63	}
     64
     65	p = (char *) (systab + 1);
     66	for (i = 0; i < systab->entry_count; i++) {
     67		/*
     68		 * The first byte of each entry type contains the type
     69		 * descriptor.
     70		 */
     71		switch (*p) {
     72		      case ESI_DESC_ENTRY_POINT:
     73			break;
     74		      default:
     75			printk(KERN_WARNING "Unknown table type %d found in "
     76			       "ESI table, ignoring rest of table\n", *p);
     77			return -ENODEV;
     78		}
     79
     80		p += ESI_DESC_SIZE(*p);
     81	}
     82
     83	esi_systab = systab;
     84	return 0;
     85}
     86
     87
     88int ia64_esi_call (efi_guid_t guid, struct ia64_sal_retval *isrvp,
     89		   enum esi_proc_type proc_type, u64 func,
     90		   u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
     91		   u64 arg7)
     92{
     93	struct ia64_fpreg fr[6];
     94	unsigned long flags = 0;
     95	int i;
     96	char *p;
     97
     98	if (!esi_systab)
     99		return -1;
    100
    101	p = (char *) (esi_systab + 1);
    102	for (i = 0; i < esi_systab->entry_count; i++) {
    103		if (*p == ESI_DESC_ENTRY_POINT) {
    104			ia64_esi_desc_entry_point_t *esi = (void *)p;
    105			if (!efi_guidcmp(guid, esi->guid)) {
    106				ia64_sal_handler esi_proc;
    107				struct pdesc pdesc;
    108
    109				pdesc.addr = __va(esi->esi_proc);
    110				pdesc.gp = __va(esi->gp);
    111
    112				esi_proc = (ia64_sal_handler) &pdesc;
    113
    114				ia64_save_scratch_fpregs(fr);
    115				if (proc_type == ESI_PROC_SERIALIZED)
    116					spin_lock_irqsave(&sal_lock, flags);
    117				else if (proc_type == ESI_PROC_MP_SAFE)
    118					local_irq_save(flags);
    119				else
    120					preempt_disable();
    121				*isrvp = (*esi_proc)(func, arg1, arg2, arg3,
    122						     arg4, arg5, arg6, arg7);
    123				if (proc_type == ESI_PROC_SERIALIZED)
    124					spin_unlock_irqrestore(&sal_lock,
    125							       flags);
    126				else if (proc_type == ESI_PROC_MP_SAFE)
    127					local_irq_restore(flags);
    128				else
    129					preempt_enable();
    130				ia64_load_scratch_fpregs(fr);
    131				return 0;
    132			}
    133		}
    134		p += ESI_DESC_SIZE(*p);
    135	}
    136	return -1;
    137}
    138EXPORT_SYMBOL_GPL(ia64_esi_call);
    139
    140int ia64_esi_call_phys (efi_guid_t guid, struct ia64_sal_retval *isrvp,
    141			u64 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
    142			u64 arg5, u64 arg6, u64 arg7)
    143{
    144	struct ia64_fpreg fr[6];
    145	unsigned long flags;
    146	u64 esi_params[8];
    147	char *p;
    148	int i;
    149
    150	if (!esi_systab)
    151		return -1;
    152
    153	p = (char *) (esi_systab + 1);
    154	for (i = 0; i < esi_systab->entry_count; i++) {
    155		if (*p == ESI_DESC_ENTRY_POINT) {
    156			ia64_esi_desc_entry_point_t *esi = (void *)p;
    157			if (!efi_guidcmp(guid, esi->guid)) {
    158				ia64_sal_handler esi_proc;
    159				struct pdesc pdesc;
    160
    161				pdesc.addr = (void *)esi->esi_proc;
    162				pdesc.gp = (void *)esi->gp;
    163
    164				esi_proc = (ia64_sal_handler) &pdesc;
    165
    166				esi_params[0] = func;
    167				esi_params[1] = arg1;
    168				esi_params[2] = arg2;
    169				esi_params[3] = arg3;
    170				esi_params[4] = arg4;
    171				esi_params[5] = arg5;
    172				esi_params[6] = arg6;
    173				esi_params[7] = arg7;
    174				ia64_save_scratch_fpregs(fr);
    175				spin_lock_irqsave(&sal_lock, flags);
    176				*isrvp = esi_call_phys(esi_proc, esi_params);
    177				spin_unlock_irqrestore(&sal_lock, flags);
    178				ia64_load_scratch_fpregs(fr);
    179				return 0;
    180			}
    181		}
    182		p += ESI_DESC_SIZE(*p);
    183	}
    184	return -1;
    185}
    186EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
    187
    188static void __exit esi_exit (void)
    189{
    190}
    191
    192module_init(esi_init);
    193module_exit(esi_exit);	/* makes module removable... */