]> code.ossystems Code Review - openembedded-core.git/blob
252bf0223caaf8acc7c20af79088481548d62af3
[openembedded-core.git] /
1 Upstream-Status: Backport
2
3 Signed-off-by: Kai Kang <kai.kang@windriver.com>
4
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
10
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.
14
15 This is XSA-129.
16
17 Signed-off-by: Jan Beulich <jbeulich@suse.com>
18 Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
19 ---
20  hw/pci/msi.c                |  4 --
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(-)
24
25 diff --git a/hw/pci/msi.c b/hw/pci/msi.c
26 index c111dba..f9c0484 100644
27 --- a/hw/pci/msi.c
28 +++ b/hw/pci/msi.c
29 @@ -21,10 +21,6 @@
30  #include "hw/pci/msi.h"
31  #include "qemu/range.h"
32  
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
36 -
37  /* PCI_MSI_ADDRESS_LO */
38  #define PCI_MSI_ADDRESS_LO_MASK         (~0x3)
39  
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[] = {
45   */
46  
47  /* Helper */
48 -static bool xen_pt_msgdata_check_type(uint32_t offset, uint16_t flags)
49 -{
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;
54 -}
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))
58  
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;
63  
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;
68 +    } else {
69 +        *data = XEN_PT_INVALID_REG;
70 +    }
71 +    return 0;
72 +}
73 +
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,
78 +                                uint32_t *data)
79 +{
80 +    uint32_t flags = s->msi->flags;
81 +
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;
87 +    } else {
88 +        *data = XEN_PT_INVALID_REG;
89 +    }
90 +    return 0;
91 +}
92 +
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,
97 +                                   uint32_t *data)
98 +{
99 +    uint32_t flags = s->msi->flags;
100 +
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;
106      } else {
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;
110  
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");
116          return -1;
117 @@ -1267,7 +1301,7 @@ static XenPTRegInfo xen_pt_emu_reg_msi[] = {
118          .size       = 2,
119          .init_val   = 0x0000,
120          .ro_mask    = 0xFF8E,
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,
129      },
130 +    /* Mask reg (if PCI_MSI_FLAGS_MASKBIT set, for 32-bit devices) */
131 +    {
132 +        .offset     = PCI_MSI_MASK_32,
133 +        .size       = 4,
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,
140 +    },
141 +    /* Mask reg (if PCI_MSI_FLAGS_MASKBIT set, for 64-bit devices) */
142 +    {
143 +        .offset     = PCI_MSI_MASK_64,
144 +        .size       = 4,
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,
151 +    },
152 +    /* Pending reg (if PCI_MSI_FLAGS_MASKBIT set, for 32-bit devices) */
153 +    {
154 +        .offset     = PCI_MSI_MASK_32 + 4,
155 +        .size       = 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,
162 +    },
163 +    /* Pending reg (if PCI_MSI_FLAGS_MASKBIT set, for 64-bit devices) */
164 +    {
165 +        .offset     = PCI_MSI_MASK_64 + 4,
166 +        .size       = 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,
173 +    },
174      {
175          .size = 0,
176      },
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
181 @@ -298,8 +298,10 @@
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 */
189  
190  /* MSI-X registers */
191  #define PCI_MSIX_FLAGS         2
192 -- 
193 2.1.4
194