Skip to content

Commit 4a22c4c

Browse files
jmberg-intelrichardweinberger
authored andcommitted
um: virt-pci: don't do DMA from stack
When enabling VMAP_STACK, SG helpers immediately complained that we were doing DMA from stack. Use per-CPU variables to avoid that. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Richard Weinberger <richard@nod.at>
1 parent 1568cb0 commit 4a22c4c

File tree

1 file changed

+78
-26
lines changed

1 file changed

+78
-26
lines changed

arch/um/drivers/virt-pci.c

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ static unsigned long um_pci_msi_used[BITS_TO_LONGS(MAX_MSI_VECTORS)];
5656

5757
#define UM_VIRT_PCI_MAXDELAY 40000
5858

59+
struct um_pci_message_buffer {
60+
struct virtio_pcidev_msg hdr;
61+
u8 data[8];
62+
};
63+
64+
static struct um_pci_message_buffer __percpu *um_pci_msg_bufs;
65+
5966
static int um_pci_send_cmd(struct um_pci_device *dev,
6067
struct virtio_pcidev_msg *cmd,
6168
unsigned int cmd_size,
@@ -68,11 +75,12 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
6875
[1] = extra ? &extra_sg : &in_sg,
6976
[2] = extra ? &in_sg : NULL,
7077
};
78+
struct um_pci_message_buffer *buf;
7179
int delay_count = 0;
7280
int ret, len;
7381
bool posted;
7482

75-
if (WARN_ON(cmd_size < sizeof(*cmd)))
83+
if (WARN_ON(cmd_size < sizeof(*cmd) || cmd_size > sizeof(*buf)))
7684
return -EINVAL;
7785

7886
switch (cmd->op) {
@@ -88,6 +96,9 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
8896
break;
8997
}
9098

99+
buf = get_cpu_var(um_pci_msg_bufs);
100+
memcpy(buf, cmd, cmd_size);
101+
91102
if (posted) {
92103
u8 *ncmd = kmalloc(cmd_size + extra_size, GFP_ATOMIC);
93104

@@ -102,7 +113,10 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
102113
} else {
103114
/* try without allocating memory */
104115
posted = false;
116+
cmd = (void *)buf;
105117
}
118+
} else {
119+
cmd = (void *)buf;
106120
}
107121

108122
sg_init_one(&out_sg, cmd, cmd_size);
@@ -118,11 +132,12 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
118132
posted ? cmd : HANDLE_NO_FREE(cmd),
119133
GFP_ATOMIC);
120134
if (ret)
121-
return ret;
135+
goto out;
122136

123137
if (posted) {
124138
virtqueue_kick(dev->cmd_vq);
125-
return 0;
139+
ret = 0;
140+
goto out;
126141
}
127142

128143
/* kick and poll for getting a response on the queue */
@@ -148,6 +163,8 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
148163
}
149164
clear_bit(UM_PCI_STAT_WAITING, &dev->status);
150165

166+
out:
167+
put_cpu_var(um_pci_msg_bufs);
151168
return ret;
152169
}
153170

@@ -161,12 +178,17 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
161178
.size = size,
162179
.addr = offset,
163180
};
164-
/* maximum size - we may only use parts of it */
165-
u8 data[8];
181+
/* buf->data is maximum size - we may only use parts of it */
182+
struct um_pci_message_buffer *buf;
183+
u8 *data;
184+
unsigned long ret = ~0ULL;
166185

167186
if (!dev)
168187
return ~0ULL;
169188

189+
buf = get_cpu_var(um_pci_msg_bufs);
190+
data = buf->data;
191+
170192
memset(data, 0xff, sizeof(data));
171193

172194
switch (size) {
@@ -179,27 +201,34 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
179201
break;
180202
default:
181203
WARN(1, "invalid config space read size %d\n", size);
182-
return ~0ULL;
204+
goto out;
183205
}
184206

185-
if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0,
186-
data, sizeof(data)))
187-
return ~0ULL;
207+
if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, 8))
208+
goto out;
188209

189210
switch (size) {
190211
case 1:
191-
return data[0];
212+
ret = data[0];
213+
break;
192214
case 2:
193-
return le16_to_cpup((void *)data);
215+
ret = le16_to_cpup((void *)data);
216+
break;
194217
case 4:
195-
return le32_to_cpup((void *)data);
218+
ret = le32_to_cpup((void *)data);
219+
break;
196220
#ifdef CONFIG_64BIT
197221
case 8:
198-
return le64_to_cpup((void *)data);
222+
ret = le64_to_cpup((void *)data);
223+
break;
199224
#endif
200225
default:
201-
return ~0ULL;
226+
break;
202227
}
228+
229+
out:
230+
put_cpu_var(um_pci_msg_bufs);
231+
return ret;
203232
}
204233

205234
static void um_pci_cfgspace_write(void *priv, unsigned int offset, int size,
@@ -272,8 +301,13 @@ static void um_pci_bar_copy_from(void *priv, void *buffer,
272301
static unsigned long um_pci_bar_read(void *priv, unsigned int offset,
273302
int size)
274303
{
275-
/* maximum size - we may only use parts of it */
276-
u8 data[8];
304+
/* buf->data is maximum size - we may only use parts of it */
305+
struct um_pci_message_buffer *buf;
306+
u8 *data;
307+
unsigned long ret = ~0ULL;
308+
309+
buf = get_cpu_var(um_pci_msg_bufs);
310+
data = buf->data;
277311

278312
switch (size) {
279313
case 1:
@@ -285,25 +319,33 @@ static unsigned long um_pci_bar_read(void *priv, unsigned int offset,
285319
break;
286320
default:
287321
WARN(1, "invalid config space read size %d\n", size);
288-
return ~0ULL;
322+
goto out;
289323
}
290324

291325
um_pci_bar_copy_from(priv, data, offset, size);
292326

293327
switch (size) {
294328
case 1:
295-
return data[0];
329+
ret = data[0];
330+
break;
296331
case 2:
297-
return le16_to_cpup((void *)data);
332+
ret = le16_to_cpup((void *)data);
333+
break;
298334
case 4:
299-
return le32_to_cpup((void *)data);
335+
ret = le32_to_cpup((void *)data);
336+
break;
300337
#ifdef CONFIG_64BIT
301338
case 8:
302-
return le64_to_cpup((void *)data);
339+
ret = le64_to_cpup((void *)data);
340+
break;
303341
#endif
304342
default:
305-
return ~0ULL;
343+
break;
306344
}
345+
346+
out:
347+
put_cpu_var(um_pci_msg_bufs);
348+
return ret;
307349
}
308350

309351
static void um_pci_bar_copy_to(void *priv, unsigned int offset,
@@ -823,10 +865,16 @@ static int um_pci_init(void)
823865
"No virtio device ID configured for PCI - no PCI support\n"))
824866
return 0;
825867

826-
bridge = pci_alloc_host_bridge(0);
827-
if (!bridge)
868+
um_pci_msg_bufs = alloc_percpu(struct um_pci_message_buffer);
869+
if (!um_pci_msg_bufs)
828870
return -ENOMEM;
829871

872+
bridge = pci_alloc_host_bridge(0);
873+
if (!bridge) {
874+
err = -ENOMEM;
875+
goto free;
876+
}
877+
830878
um_pci_fwnode = irq_domain_alloc_named_fwnode("um-pci");
831879
if (!um_pci_fwnode) {
832880
err = -ENOMEM;
@@ -878,8 +926,11 @@ static int um_pci_init(void)
878926
irq_domain_remove(um_pci_inner_domain);
879927
if (um_pci_fwnode)
880928
irq_domain_free_fwnode(um_pci_fwnode);
881-
pci_free_resource_list(&bridge->windows);
882-
pci_free_host_bridge(bridge);
929+
if (bridge) {
930+
pci_free_resource_list(&bridge->windows);
931+
pci_free_host_bridge(bridge);
932+
}
933+
free_percpu(um_pci_msg_bufs);
883934
return err;
884935
}
885936
module_init(um_pci_init);
@@ -891,5 +942,6 @@ static void um_pci_exit(void)
891942
irq_domain_remove(um_pci_inner_domain);
892943
pci_free_resource_list(&bridge->windows);
893944
pci_free_host_bridge(bridge);
945+
free_percpu(um_pci_msg_bufs);
894946
}
895947
module_exit(um_pci_exit);

0 commit comments

Comments
 (0)