1 Upstream-Status: Backport
3 Signed-off-by: Kai Kang <kai.kang@windriver.com>
5 From 7611dae8a69f0f1775ba1a9a942961c2aa10d88e Mon Sep 17 00:00:00 2001
6 From: Jan Beulich <jbeulich@suse.com>
7 Date: Tue, 2 Jun 2015 15:07:00 +0000
8 Subject: xen: don't allow guest to control MSI mask register
9 Bug-Debian: http://bugs.debian.org/787547
11 It's being used by the hypervisor. For now simply mimic a device not
12 capable of masking, and fully emulate any accesses a guest may issue
13 nevertheless as simple reads/writes without side effects.
17 Signed-off-by: Jan Beulich <jbeulich@suse.com>
18 Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
21 hw/xen/xen_pt_config_init.c | 98 ++++++++++++++++++++++++++++++++++++++++-----
22 include/hw/pci/pci_regs.h | 2 +
23 3 files changed, 90 insertions(+), 14 deletions(-)
25 diff --git a/hw/pci/msi.c b/hw/pci/msi.c
26 index c111dba..f9c0484 100644
30 #include "hw/pci/msi.h"
31 #include "qemu/range.h"
33 -/* Eventually those constants should go to Linux pci_regs.h */
34 -#define PCI_MSI_PENDING_32 0x10
35 -#define PCI_MSI_PENDING_64 0x14
37 /* PCI_MSI_ADDRESS_LO */
38 #define PCI_MSI_ADDRESS_LO_MASK (~0x3)
40 diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c
41 index dae0519..68b8f22 100644
42 --- a/hw/xen/xen_pt_config_init.c
43 +++ b/hw/xen/xen_pt_config_init.c
44 @@ -1016,13 +1016,9 @@ static XenPTRegInfo xen_pt_emu_reg_pm[] = {
48 -static bool xen_pt_msgdata_check_type(uint32_t offset, uint16_t flags)
50 - /* check the offset whether matches the type or not */
51 - bool is_32 = (offset == PCI_MSI_DATA_32) && !(flags & PCI_MSI_FLAGS_64BIT);
52 - bool is_64 = (offset == PCI_MSI_DATA_64) && (flags & PCI_MSI_FLAGS_64BIT);
53 - return is_32 || is_64;
55 +#define xen_pt_msi_check_type(offset, flags, what) \
56 + ((offset) == ((flags) & PCI_MSI_FLAGS_64BIT ? \
57 + PCI_MSI_##what##_64 : PCI_MSI_##what##_32))
59 /* Message Control register */
60 static int xen_pt_msgctrl_reg_init(XenPCIPassthroughState *s,
61 @@ -1134,7 +1130,45 @@ static int xen_pt_msgdata_reg_init(XenPCIPassthroughState *s,
62 uint32_t offset = reg->offset;
64 /* check the offset whether matches the type or not */
65 - if (xen_pt_msgdata_check_type(offset, flags)) {
66 + if (xen_pt_msi_check_type(offset, flags, DATA)) {
67 + *data = reg->init_val;
69 + *data = XEN_PT_INVALID_REG;
74 +/* this function will be called twice (for 32 bit and 64 bit type) */
75 +/* initialize Mask register */
76 +static int xen_pt_mask_reg_init(XenPCIPassthroughState *s,
77 + XenPTRegInfo *reg, uint32_t real_offset,
80 + uint32_t flags = s->msi->flags;
82 + /* check the offset whether matches the type or not */
83 + if (!(flags & PCI_MSI_FLAGS_MASKBIT)) {
84 + *data = XEN_PT_INVALID_REG;
85 + } else if (xen_pt_msi_check_type(reg->offset, flags, MASK)) {
86 + *data = reg->init_val;
88 + *data = XEN_PT_INVALID_REG;
93 +/* this function will be called twice (for 32 bit and 64 bit type) */
94 +/* initialize Pending register */
95 +static int xen_pt_pending_reg_init(XenPCIPassthroughState *s,
96 + XenPTRegInfo *reg, uint32_t real_offset,
99 + uint32_t flags = s->msi->flags;
101 + /* check the offset whether matches the type or not */
102 + if (!(flags & PCI_MSI_FLAGS_MASKBIT)) {
103 + *data = XEN_PT_INVALID_REG;
104 + } else if (xen_pt_msi_check_type(reg->offset, flags, PENDING)) {
105 *data = reg->init_val;
107 *data = XEN_PT_INVALID_REG;
108 @@ -1222,7 +1256,7 @@ static int xen_pt_msgdata_reg_write(XenPCIPassthroughState *s,
109 uint32_t offset = reg->offset;
111 /* check the offset whether matches the type or not */
112 - if (!xen_pt_msgdata_check_type(offset, msi->flags)) {
113 + if (!xen_pt_msi_check_type(offset, msi->flags, DATA)) {
114 /* exit I/O emulator */
115 XEN_PT_ERR(&s->dev, "the offset does not match the 32/64 bit type!\n");
117 @@ -1267,7 +1301,7 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] = {
121 - .emu_mask = 0x007F,
122 + .emu_mask = 0x017F,
123 .init = xen_pt_msgctrl_reg_init,
124 .u.w.read = xen_pt_word_reg_read,
125 .u.w.write = xen_pt_msgctrl_reg_write,
126 @@ -1316,6 +1350,50 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] = {
127 .u.w.read = xen_pt_word_reg_read,
128 .u.w.write = xen_pt_msgdata_reg_write,
130 + /* Mask reg (if PCI_MSI_FLAGS_MASKBIT set, for 32-bit devices) */
132 + .offset = PCI_MSI_MASK_32,
134 + .init_val = 0x00000000,
135 + .ro_mask = 0xFFFFFFFF,
136 + .emu_mask = 0xFFFFFFFF,
137 + .init = xen_pt_mask_reg_init,
138 + .u.dw.read = xen_pt_long_reg_read,
139 + .u.dw.write = xen_pt_long_reg_write,
141 + /* Mask reg (if PCI_MSI_FLAGS_MASKBIT set, for 64-bit devices) */
143 + .offset = PCI_MSI_MASK_64,
145 + .init_val = 0x00000000,
146 + .ro_mask = 0xFFFFFFFF,
147 + .emu_mask = 0xFFFFFFFF,
148 + .init = xen_pt_mask_reg_init,
149 + .u.dw.read = xen_pt_long_reg_read,
150 + .u.dw.write = xen_pt_long_reg_write,
152 + /* Pending reg (if PCI_MSI_FLAGS_MASKBIT set, for 32-bit devices) */
154 + .offset = PCI_MSI_MASK_32 + 4,
156 + .init_val = 0x00000000,
157 + .ro_mask = 0xFFFFFFFF,
158 + .emu_mask = 0x00000000,
159 + .init = xen_pt_pending_reg_init,
160 + .u.dw.read = xen_pt_long_reg_read,
161 + .u.dw.write = xen_pt_long_reg_write,
163 + /* Pending reg (if PCI_MSI_FLAGS_MASKBIT set, for 64-bit devices) */
165 + .offset = PCI_MSI_MASK_64 + 4,
167 + .init_val = 0x00000000,
168 + .ro_mask = 0xFFFFFFFF,
169 + .emu_mask = 0x00000000,
170 + .init = xen_pt_pending_reg_init,
171 + .u.dw.read = xen_pt_long_reg_read,
172 + .u.dw.write = xen_pt_long_reg_write,
177 diff --git a/include/hw/pci/pci_regs.h b/include/hw/pci/pci_regs.h
178 index 56a404b..57e8c80 100644
179 --- a/include/hw/pci/pci_regs.h
180 +++ b/include/hw/pci/pci_regs.h
182 #define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
183 #define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
184 #define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */
185 +#define PCI_MSI_PENDING_32 16 /* Pending bits register for 32-bit devices */
186 #define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
187 #define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */
188 +#define PCI_MSI_PENDING_64 20 /* Pending bits register for 32-bit devices */
190 /* MSI-X registers */
191 #define PCI_MSIX_FLAGS 2