1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/******************************************************************************
* ioport_emulate.c
*
* Handle I/O port access quirks of various platforms.
*/
#include <xen/init.h>
#include <xen/sched.h>
#include <xen/dmi.h>
unsigned int (*__read_mostly ioemul_handle_quirk)(
uint8_t opcode, char *io_emul_stub, struct cpu_user_regs *regs);
static unsigned int cf_check ioemul_handle_proliant_quirk(
u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs)
{
static const char stub[] = {
0x9c, /* pushf */
0xfa, /* cli */
0xee, /* out %al, %dx */
0xec, /* 1: in %dx, %al */
0xa8, 0x80, /* test $0x80, %al */
0x75, 0xfb, /* jnz 1b */
0x9d, /* popf */
};
uint16_t port = regs->dx;
uint8_t value = regs->al;
if ( (opcode != 0xee) || (port != 0xcd4) || !(value & 0x80) )
return 0;
memcpy(io_emul_stub, stub, sizeof(stub));
BUILD_BUG_ON(IOEMUL_QUIRK_STUB_BYTES < sizeof(stub));
return sizeof(stub);
}
/* This table is the set of system-specific I/O emulation hooks. */
static const struct dmi_system_id __initconstrel ioport_quirks_tbl[] = {
/*
* I/O emulation hook for certain HP ProLiant servers with
* 'special' SMM goodness.
*/
{
.ident = "HP ProLiant DL3xx",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL3"),
},
},
{
.ident = "HP ProLiant DL5xx",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL5"),
},
},
{
.ident = "HP ProLiant DL7xx",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL7"),
},
},
{
.ident = "HP ProLiant ML3xx",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML3"),
},
},
{
.ident = "HP ProLiant ML5xx",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML5"),
},
},
{
.ident = "HP ProLiant BL2xx",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL2"),
},
},
{
.ident = "HP ProLiant BL4xx",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL4"),
},
},
{
.ident = "HP ProLiant BL6xx",
.matches = {
DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL6"),
},
},
{ }
};
static int __init cf_check ioport_quirks_init(void)
{
if ( dmi_check_system(ioport_quirks_tbl) )
ioemul_handle_quirk = ioemul_handle_proliant_quirk;
return 0;
}
__initcall(ioport_quirks_init);
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
|