Skip to content

Commit d6c338a

Browse files
committed
Merge tag 'for-linus-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
Pull UML updates from Richard Weinberger: - Support for VMAP_STACK - Support for splice_write in hostfs - Fixes for virt-pci - Fixes for virtio_uml - Various fixes * tag 'for-linus-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: um: fix stub location calculation um: virt-pci: fix uapi documentation um: enable VMAP_STACK um: virt-pci: don't do DMA from stack hostfs: support splice_write um: virtio_uml: fix memory leak on init failures um: virtio_uml: include linux/virtio-uml.h lib/logic_iomem: fix sparse warnings um: make PCI emulation driver init/exit static
2 parents 35776f1 + adf9ae0 commit d6c338a

File tree

10 files changed

+124
-42
lines changed

10 files changed

+124
-42
lines changed

arch/um/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ config UML
2424
select SET_FS
2525
select TRACE_IRQFLAGS_SUPPORT
2626
select TTY # Needed for line.c
27+
select HAVE_ARCH_VMAP_STACK
2728

2829
config MMU
2930
bool

arch/um/drivers/virt-pci.c

Lines changed: 80 additions & 28 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,
@@ -810,7 +852,7 @@ void *pci_root_bus_fwnode(struct pci_bus *bus)
810852
return um_pci_fwnode;
811853
}
812854

813-
int um_pci_init(void)
855+
static int um_pci_init(void)
814856
{
815857
int err, i;
816858

@@ -823,10 +865,16 @@ 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,18 +926,22 @@ 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);
886937

887-
void um_pci_exit(void)
938+
static void um_pci_exit(void)
888939
{
889940
unregister_virtio_driver(&um_pci_virtio_driver);
890941
irq_domain_remove(um_pci_msi_domain);
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);

arch/um/drivers/virtio_uml.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/virtio_config.h>
2828
#include <linux/virtio_ring.h>
2929
#include <linux/time-internal.h>
30+
#include <linux/virtio-uml.h>
3031
#include <shared/as-layout.h>
3132
#include <irq_kern.h>
3233
#include <init.h>
@@ -1139,7 +1140,7 @@ static int virtio_uml_probe(struct platform_device *pdev)
11391140
rc = os_connect_socket(pdata->socket_path);
11401141
} while (rc == -EINTR);
11411142
if (rc < 0)
1142-
return rc;
1143+
goto error_free;
11431144
vu_dev->sock = rc;
11441145

11451146
spin_lock_init(&vu_dev->sock_lock);
@@ -1160,6 +1161,8 @@ static int virtio_uml_probe(struct platform_device *pdev)
11601161

11611162
error_init:
11621163
os_close_file(vu_dev->sock);
1164+
error_free:
1165+
kfree(vu_dev);
11631166
return rc;
11641167
}
11651168

arch/um/kernel/skas/clone.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
void __attribute__ ((__section__ (".__syscall_stub")))
2525
stub_clone_handler(void)
2626
{
27-
int stack;
28-
struct stub_data *data = (void *) ((unsigned long)&stack & ~(UM_KERN_PAGE_SIZE - 1));
27+
struct stub_data *data = get_stub_page();
2928
long err;
3029

3130
err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,

arch/x86/um/shared/sysdep/stub_32.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,16 @@ static inline void remap_stack_and_trap(void)
101101
"memory");
102102
}
103103

104+
static __always_inline void *get_stub_page(void)
105+
{
106+
unsigned long ret;
107+
108+
asm volatile (
109+
"movl %%esp,%0 ;"
110+
"andl %1,%0"
111+
: "=a" (ret)
112+
: "g" (~(UM_KERN_PAGE_SIZE - 1)));
113+
114+
return (void *)ret;
115+
}
104116
#endif

arch/x86/um/shared/sysdep/stub_64.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,16 @@ static inline void remap_stack_and_trap(void)
108108
__syscall_clobber, "r10", "r8", "r9");
109109
}
110110

111+
static __always_inline void *get_stub_page(void)
112+
{
113+
unsigned long ret;
114+
115+
asm volatile (
116+
"movq %%rsp,%0 ;"
117+
"andq %1,%0"
118+
: "=a" (ret)
119+
: "g" (~(UM_KERN_PAGE_SIZE - 1)));
120+
121+
return (void *)ret;
122+
}
111123
#endif

arch/x86/um/stub_segv.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
void __attribute__ ((__section__ (".__syscall_stub")))
1212
stub_segv_handler(int sig, siginfo_t *info, void *p)
1313
{
14-
int stack;
14+
struct faultinfo *f = get_stub_page();
1515
ucontext_t *uc = p;
16-
struct faultinfo *f = (void *)(((unsigned long)&stack) & ~(UM_KERN_PAGE_SIZE - 1));
1716

1817
GET_FAULTINFO_FROM_MC(*f, &uc->uc_mcontext);
1918
trap_myself();

fs/hostfs/hostfs_kern.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ static int hostfs_fsync(struct file *file, loff_t start, loff_t end,
381381
static const struct file_operations hostfs_file_fops = {
382382
.llseek = generic_file_llseek,
383383
.splice_read = generic_file_splice_read,
384+
.splice_write = iter_file_splice_write,
384385
.read_iter = generic_file_read_iter,
385386
.write_iter = generic_file_write_iter,
386387
.mmap = generic_file_mmap,

include/uapi/linux/virtio_pcidev.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99

1010
/**
1111
* enum virtio_pcidev_ops - virtual PCI device operations
12+
* @VIRTIO_PCIDEV_OP_RESERVED: reserved to catch errors
1213
* @VIRTIO_PCIDEV_OP_CFG_READ: read config space, size is 1, 2, 4 or 8;
1314
* the @data field should be filled in by the device (in little endian).
1415
* @VIRTIO_PCIDEV_OP_CFG_WRITE: write config space, size is 1, 2, 4 or 8;
1516
* the @data field contains the data to write (in little endian).
16-
* @VIRTIO_PCIDEV_OP_BAR_READ: read BAR mem/pio, size can be variable;
17+
* @VIRTIO_PCIDEV_OP_MMIO_READ: read BAR mem/pio, size can be variable;
1718
* the @data field should be filled in by the device (in little endian).
18-
* @VIRTIO_PCIDEV_OP_BAR_WRITE: write BAR mem/pio, size can be variable;
19+
* @VIRTIO_PCIDEV_OP_MMIO_WRITE: write BAR mem/pio, size can be variable;
1920
* the @data field contains the data to write (in little endian).
2021
* @VIRTIO_PCIDEV_OP_MMIO_MEMSET: memset MMIO, size is variable but
2122
* the @data field only has one byte (unlike @VIRTIO_PCIDEV_OP_MMIO_WRITE)

0 commit comments

Comments
 (0)