Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+124 -42
+1
arch/um/Kconfig
··· 24 24 select SET_FS 25 25 select TRACE_IRQFLAGS_SUPPORT 26 26 select TTY # Needed for line.c 27 + select HAVE_ARCH_VMAP_STACK 27 28 28 29 config MMU 29 30 bool
+80 -28
arch/um/drivers/virt-pci.c
··· 56 56 57 57 #define UM_VIRT_PCI_MAXDELAY 40000 58 58 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 + 59 66 static int um_pci_send_cmd(struct um_pci_device *dev, 60 67 struct virtio_pcidev_msg *cmd, 61 68 unsigned int cmd_size, ··· 75 68 [1] = extra ? &extra_sg : &in_sg, 76 69 [2] = extra ? &in_sg : NULL, 77 70 }; 71 + struct um_pci_message_buffer *buf; 78 72 int delay_count = 0; 79 73 int ret, len; 80 74 bool posted; 81 75 82 - if (WARN_ON(cmd_size < sizeof(*cmd))) 76 + if (WARN_ON(cmd_size < sizeof(*cmd) || cmd_size > sizeof(*buf))) 83 77 return -EINVAL; 84 78 85 79 switch (cmd->op) { ··· 96 88 break; 97 89 } 98 90 91 + buf = get_cpu_var(um_pci_msg_bufs); 92 + memcpy(buf, cmd, cmd_size); 93 + 99 94 if (posted) { 100 95 u8 *ncmd = kmalloc(cmd_size + extra_size, GFP_ATOMIC); 101 96 ··· 113 102 } else { 114 103 /* try without allocating memory */ 115 104 posted = false; 105 + cmd = (void *)buf; 116 106 } 107 + } else { 108 + cmd = (void *)buf; 117 109 } 118 110 119 111 sg_init_one(&out_sg, cmd, cmd_size); ··· 132 118 posted ? cmd : HANDLE_NO_FREE(cmd), 133 119 GFP_ATOMIC); 134 120 if (ret) 135 - return ret; 121 + goto out; 136 122 137 123 if (posted) { 138 124 virtqueue_kick(dev->cmd_vq); 139 - return 0; 125 + ret = 0; 126 + goto out; 140 127 } 141 128 142 129 /* kick and poll for getting a response on the queue */ ··· 163 148 } 164 149 clear_bit(UM_PCI_STAT_WAITING, &dev->status); 165 150 151 + out: 152 + put_cpu_var(um_pci_msg_bufs); 166 153 return ret; 167 154 } 168 155 ··· 178 161 .size = size, 179 162 .addr = offset, 180 163 }; 181 - /* maximum size - we may only use parts of it */ 182 - u8 data[8]; 164 + /* buf->data is maximum size - we may only use parts of it */ 165 + struct um_pci_message_buffer *buf; 166 + u8 *data; 167 + unsigned long ret = ~0ULL; 183 168 184 169 if (!dev) 185 170 return ~0ULL; 171 + 172 + buf = get_cpu_var(um_pci_msg_bufs); 173 + data = buf->data; 186 174 187 175 memset(data, 0xff, sizeof(data)); 188 176 ··· 201 179 break; 202 180 default: 203 181 WARN(1, "invalid config space read size %d\n", size); 204 - return ~0ULL; 182 + goto out; 205 183 } 206 184 207 - if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, 208 - data, sizeof(data))) 209 - return ~0ULL; 185 + if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, 8)) 186 + goto out; 210 187 211 188 switch (size) { 212 189 case 1: 213 - return data[0]; 190 + ret = data[0]; 191 + break; 214 192 case 2: 215 - return le16_to_cpup((void *)data); 193 + ret = le16_to_cpup((void *)data); 194 + break; 216 195 case 4: 217 - return le32_to_cpup((void *)data); 196 + ret = le32_to_cpup((void *)data); 197 + break; 218 198 #ifdef CONFIG_64BIT 219 199 case 8: 220 - return le64_to_cpup((void *)data); 200 + ret = le64_to_cpup((void *)data); 201 + break; 221 202 #endif 222 203 default: 223 - return ~0ULL; 204 + break; 224 205 } 206 + 207 + out: 208 + put_cpu_var(um_pci_msg_bufs); 209 + return ret; 225 210 } 226 211 227 212 static void um_pci_cfgspace_write(void *priv, unsigned int offset, int size, ··· 301 272 static unsigned long um_pci_bar_read(void *priv, unsigned int offset, 302 273 int size) 303 274 { 304 - /* maximum size - we may only use parts of it */ 305 - u8 data[8]; 275 + /* buf->data is maximum size - we may only use parts of it */ 276 + struct um_pci_message_buffer *buf; 277 + u8 *data; 278 + unsigned long ret = ~0ULL; 279 + 280 + buf = get_cpu_var(um_pci_msg_bufs); 281 + data = buf->data; 306 282 307 283 switch (size) { 308 284 case 1: ··· 319 285 break; 320 286 default: 321 287 WARN(1, "invalid config space read size %d\n", size); 322 - return ~0ULL; 288 + goto out; 323 289 } 324 290 325 291 um_pci_bar_copy_from(priv, data, offset, size); 326 292 327 293 switch (size) { 328 294 case 1: 329 - return data[0]; 295 + ret = data[0]; 296 + break; 330 297 case 2: 331 - return le16_to_cpup((void *)data); 298 + ret = le16_to_cpup((void *)data); 299 + break; 332 300 case 4: 333 - return le32_to_cpup((void *)data); 301 + ret = le32_to_cpup((void *)data); 302 + break; 334 303 #ifdef CONFIG_64BIT 335 304 case 8: 336 - return le64_to_cpup((void *)data); 305 + ret = le64_to_cpup((void *)data); 306 + break; 337 307 #endif 338 308 default: 339 - return ~0ULL; 309 + break; 340 310 } 311 + 312 + out: 313 + put_cpu_var(um_pci_msg_bufs); 314 + return ret; 341 315 } 342 316 343 317 static void um_pci_bar_copy_to(void *priv, unsigned int offset, ··· 852 810 return um_pci_fwnode; 853 811 } 854 812 855 - int um_pci_init(void) 813 + static int um_pci_init(void) 856 814 { 857 815 int err, i; 858 816 ··· 865 823 "No virtio device ID configured for PCI - no PCI support\n")) 866 824 return 0; 867 825 868 - bridge = pci_alloc_host_bridge(0); 869 - if (!bridge) 826 + um_pci_msg_bufs = alloc_percpu(struct um_pci_message_buffer); 827 + if (!um_pci_msg_bufs) 870 828 return -ENOMEM; 829 + 830 + bridge = pci_alloc_host_bridge(0); 831 + if (!bridge) { 832 + err = -ENOMEM; 833 + goto free; 834 + } 871 835 872 836 um_pci_fwnode = irq_domain_alloc_named_fwnode("um-pci"); 873 837 if (!um_pci_fwnode) { ··· 926 878 irq_domain_remove(um_pci_inner_domain); 927 879 if (um_pci_fwnode) 928 880 irq_domain_free_fwnode(um_pci_fwnode); 929 - pci_free_resource_list(&bridge->windows); 930 - pci_free_host_bridge(bridge); 881 + if (bridge) { 882 + pci_free_resource_list(&bridge->windows); 883 + pci_free_host_bridge(bridge); 884 + } 885 + free_percpu(um_pci_msg_bufs); 931 886 return err; 932 887 } 933 888 module_init(um_pci_init); 934 889 935 - void um_pci_exit(void) 890 + static void um_pci_exit(void) 936 891 { 937 892 unregister_virtio_driver(&um_pci_virtio_driver); 938 893 irq_domain_remove(um_pci_msi_domain); 939 894 irq_domain_remove(um_pci_inner_domain); 940 895 pci_free_resource_list(&bridge->windows); 941 896 pci_free_host_bridge(bridge); 897 + free_percpu(um_pci_msg_bufs); 942 898 } 943 899 module_exit(um_pci_exit);
+4 -1
arch/um/drivers/virtio_uml.c
··· 27 27 #include <linux/virtio_config.h> 28 28 #include <linux/virtio_ring.h> 29 29 #include <linux/time-internal.h> 30 + #include <linux/virtio-uml.h> 30 31 #include <shared/as-layout.h> 31 32 #include <irq_kern.h> 32 33 #include <init.h> ··· 1140 1139 rc = os_connect_socket(pdata->socket_path); 1141 1140 } while (rc == -EINTR); 1142 1141 if (rc < 0) 1143 - return rc; 1142 + goto error_free; 1144 1143 vu_dev->sock = rc; 1145 1144 1146 1145 spin_lock_init(&vu_dev->sock_lock); ··· 1161 1160 1162 1161 error_init: 1163 1162 os_close_file(vu_dev->sock); 1163 + error_free: 1164 + kfree(vu_dev); 1164 1165 return rc; 1165 1166 } 1166 1167
+1 -2
arch/um/kernel/skas/clone.c
··· 24 24 void __attribute__ ((__section__ (".__syscall_stub"))) 25 25 stub_clone_handler(void) 26 26 { 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(); 29 28 long err; 30 29 31 30 err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
+12
arch/x86/um/shared/sysdep/stub_32.h
··· 101 101 "memory"); 102 102 } 103 103 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 + } 104 116 #endif
+12
arch/x86/um/shared/sysdep/stub_64.h
··· 108 108 __syscall_clobber, "r10", "r8", "r9"); 109 109 } 110 110 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 + } 111 123 #endif
+1 -2
arch/x86/um/stub_segv.c
··· 11 11 void __attribute__ ((__section__ (".__syscall_stub"))) 12 12 stub_segv_handler(int sig, siginfo_t *info, void *p) 13 13 { 14 - int stack; 14 + struct faultinfo *f = get_stub_page(); 15 15 ucontext_t *uc = p; 16 - struct faultinfo *f = (void *)(((unsigned long)&stack) & ~(UM_KERN_PAGE_SIZE - 1)); 17 16 18 17 GET_FAULTINFO_FROM_MC(*f, &uc->uc_mcontext); 19 18 trap_myself();
+1
fs/hostfs/hostfs_kern.c
··· 381 381 static const struct file_operations hostfs_file_fops = { 382 382 .llseek = generic_file_llseek, 383 383 .splice_read = generic_file_splice_read, 384 + .splice_write = iter_file_splice_write, 384 385 .read_iter = generic_file_read_iter, 385 386 .write_iter = generic_file_write_iter, 386 387 .mmap = generic_file_mmap,
+3 -2
include/uapi/linux/virtio_pcidev.h
··· 9 9 10 10 /** 11 11 * enum virtio_pcidev_ops - virtual PCI device operations 12 + * @VIRTIO_PCIDEV_OP_RESERVED: reserved to catch errors 12 13 * @VIRTIO_PCIDEV_OP_CFG_READ: read config space, size is 1, 2, 4 or 8; 13 14 * the @data field should be filled in by the device (in little endian). 14 15 * @VIRTIO_PCIDEV_OP_CFG_WRITE: write config space, size is 1, 2, 4 or 8; 15 16 * 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; 17 18 * 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; 19 20 * the @data field contains the data to write (in little endian). 20 21 * @VIRTIO_PCIDEV_OP_MMIO_MEMSET: memset MMIO, size is variable but 21 22 * the @data field only has one byte (unlike @VIRTIO_PCIDEV_OP_MMIO_WRITE)
+9 -7
lib/logic_iomem.c
··· 6 6 #include <linux/types.h> 7 7 #include <linux/slab.h> 8 8 #include <linux/logic_iomem.h> 9 + #include <asm/io.h> 9 10 10 11 struct logic_iomem_region { 11 12 const struct resource *res; ··· 79 78 static void real_iounmap(void __iomem *addr) 80 79 { 81 80 WARN(1, "invalid iounmap for addr 0x%llx\n", 82 - (unsigned long long)addr); 81 + (unsigned long long __force)addr); 83 82 } 84 83 #endif /* CONFIG_LOGIC_IOMEM_FALLBACK */ 85 84 ··· 173 172 static u##sz real_raw_read ## op(const volatile void __iomem *addr) \ 174 173 { \ 175 174 WARN(1, "Invalid read" #op " at address %llx\n", \ 176 - (unsigned long long)addr); \ 175 + (unsigned long long __force)addr); \ 177 176 return (u ## sz)~0ULL; \ 178 177 } \ 179 178 \ 180 - void real_raw_write ## op(u ## sz val, volatile void __iomem *addr) \ 179 + static void real_raw_write ## op(u ## sz val, \ 180 + volatile void __iomem *addr) \ 181 181 { \ 182 182 WARN(1, "Invalid writeq" #op " of 0x%llx at address %llx\n", \ 183 - (unsigned long long)val, (unsigned long long)addr); \ 183 + (unsigned long long)val, (unsigned long long __force)addr);\ 184 184 } \ 185 185 186 186 MAKE_FALLBACK(b, 8); ··· 194 192 static void real_memset_io(volatile void __iomem *addr, int value, size_t size) 195 193 { 196 194 WARN(1, "Invalid memset_io at address 0x%llx\n", 197 - (unsigned long long)addr); 195 + (unsigned long long __force)addr); 198 196 } 199 197 200 198 static void real_memcpy_fromio(void *buffer, const volatile void __iomem *addr, 201 199 size_t size) 202 200 { 203 201 WARN(1, "Invalid memcpy_fromio at address 0x%llx\n", 204 - (unsigned long long)addr); 202 + (unsigned long long __force)addr); 205 203 206 204 memset(buffer, 0xff, size); 207 205 } ··· 210 208 size_t size) 211 209 { 212 210 WARN(1, "Invalid memcpy_toio at address 0x%llx\n", 213 - (unsigned long long)addr); 211 + (unsigned long long __force)addr); 214 212 } 215 213 #endif /* CONFIG_LOGIC_IOMEM_FALLBACK */ 216 214