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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
xen: don't allow guest to control MSI mask register
It's being used by the hypervisor. For now simply mimic a device not
capable of masking, and fully emulate any accesses a guest may issue
nevertheless as simple reads/writes without side effects.
This is XSA-129.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -147,6 +147,10 @@ static uint32_t pt_msgaddr64_reg_init(st
struct pt_reg_info_tbl *reg, uint32_t real_offset);
static uint32_t pt_msgdata_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_mask_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_pending_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset);
static uint32_t pt_msixctrl_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset);
static uint32_t pt_header_type_reg_init(struct pt_dev *ptdev,
@@ -644,7 +648,7 @@ static struct pt_reg_info_tbl pt_emu_reg
.size = 2,
.init_val = 0x0000,
.ro_mask = 0xFF8E,
- .emu_mask = 0x007F,
+ .emu_mask = 0x017F,
.init = pt_msgctrl_reg_init,
.u.w.read = pt_word_reg_read,
.u.w.write = pt_msgctrl_reg_write,
@@ -698,6 +702,50 @@ static struct pt_reg_info_tbl pt_emu_reg
.u.w.write = pt_msgdata_reg_write,
.u.w.restore = NULL,
},
+ /* Mask reg (if PCI_MSI_FLAGS_MASK_BIT set, for 32-bit devices) */
+ {
+ .offset = PCI_MSI_MASK_32,
+ .size = 4,
+ .init_val = 0x00000000,
+ .ro_mask = 0xFFFFFFFF,
+ .emu_mask = 0xFFFFFFFF,
+ .init = pt_mask_reg_init,
+ .u.dw.read = pt_long_reg_read,
+ .u.dw.write = pt_long_reg_write,
+ },
+ /* Mask reg (if PCI_MSI_FLAGS_MASK_BIT set, for 64-bit devices) */
+ {
+ .offset = PCI_MSI_MASK_64,
+ .size = 4,
+ .init_val = 0x00000000,
+ .ro_mask = 0xFFFFFFFF,
+ .emu_mask = 0xFFFFFFFF,
+ .init = pt_mask_reg_init,
+ .u.dw.read = pt_long_reg_read,
+ .u.dw.write = pt_long_reg_write,
+ },
+ /* Pending reg (if PCI_MSI_FLAGS_MASK_BIT set, for 32-bit devices) */
+ {
+ .offset = PCI_MSI_MASK_32 + 4,
+ .size = 4,
+ .init_val = 0x00000000,
+ .ro_mask = 0xFFFFFFFF,
+ .emu_mask = 0x00000000,
+ .init = pt_pending_reg_init,
+ .u.dw.read = pt_long_reg_read,
+ .u.dw.write = pt_long_reg_write,
+ },
+ /* Pending reg (if PCI_MSI_FLAGS_MASK_BIT set, for 64-bit devices) */
+ {
+ .offset = PCI_MSI_MASK_64 + 4,
+ .size = 4,
+ .init_val = 0x00000000,
+ .ro_mask = 0xFFFFFFFF,
+ .emu_mask = 0x00000000,
+ .init = pt_pending_reg_init,
+ .u.dw.read = pt_long_reg_read,
+ .u.dw.write = pt_long_reg_write,
+ },
{
.size = 0,
},
@@ -3023,6 +3071,42 @@ static uint32_t pt_msgdata_reg_init(stru
return PT_INVALID_REG;
}
+/* this function will be called twice (for 32 bit and 64 bit type) */
+/* initialize Mask register */
+static uint32_t pt_mask_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+ uint32_t flags = ptdev->msi->flags;
+ uint32_t offset = reg->offset;
+
+ if (!(flags & PCI_MSI_FLAGS_MASK_BIT))
+ return PT_INVALID_REG;
+
+ if (offset == (flags & PCI_MSI_FLAGS_64BIT ?
+ PCI_MSI_MASK_64 : PCI_MSI_MASK_32))
+ return reg->init_val;
+
+ return PT_INVALID_REG;
+}
+
+/* this function will be called twice (for 32 bit and 64 bit type) */
+/* initialize Pending register */
+static uint32_t pt_pending_reg_init(struct pt_dev *ptdev,
+ struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+ uint32_t flags = ptdev->msi->flags;
+ uint32_t offset = reg->offset;
+
+ if (!(flags & PCI_MSI_FLAGS_MASK_BIT))
+ return PT_INVALID_REG;
+
+ if (offset == (flags & PCI_MSI_FLAGS_64BIT ?
+ PCI_MSI_MASK_64 + 4 : PCI_MSI_MASK_32 + 4))
+ return reg->init_val;
+
+ return PT_INVALID_REG;
+}
+
/* initialize Message Control register for MSI-X */
static uint32_t pt_msixctrl_reg_init(struct pt_dev *ptdev,
struct pt_reg_info_tbl *reg, uint32_t real_offset)
--- a/hw/pass-through.h
+++ b/hw/pass-through.h
@@ -84,6 +84,12 @@
#define PCI_MSI_FLAGS_MASK_BIT 0x0100
#endif
+#ifndef PCI_MSI_MASK_32
+/* interrupt masking register */
+#define PCI_MSI_MASK_32 12
+#define PCI_MSI_MASK_64 16
+#endif
+
#ifndef PCI_EXP_TYPE_PCIE_BRIDGE
/* PCI/PCI-X to PCIE Bridge */
#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8
|