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