Merge tag 'for-linus-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Sep 2019 18:07:02 +0000 (11:07 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Sep 2019 18:07:02 +0000 (11:07 -0700)
Pull UML updates from Richard Weinberger:

 - virtio support

 - fixes for our new time travel mode

 - various improvements to make lockdep and kasan work better

 - SPDX header updates

* tag 'for-linus-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: (25 commits)
  um: irq: Fix LAST_IRQ usage in init_IRQ()
  um: Add SPDX headers for files in arch/um/include
  um: Add SPDX headers for files in arch/um/os-Linux
  um: Add SPDX headers to files in arch/um/kernel/
  um: Add SPDX headers for files in arch/um/drivers
  um: virtio: Implement VHOST_USER_PROTOCOL_F_REPLY_ACK
  um: virtio: Implement VHOST_USER_PROTOCOL_F_SLAVE_REQ
  um: drivers: Add virtio vhost-user driver
  um: Use real DMA barriers
  um: Don't use generic barrier.h
  um: time-travel: Restrict time update in IRQ handler
  um: time-travel: Fix periodic timers
  um: Enable CONFIG_CONSTRUCTORS
  um: Place (soft)irq text with macros
  um: Fix VDSO compiler warning
  um: Implement TRACE_IRQFLAGS_SUPPORT
  um: Remove misleading #define ARCh_IRQ_ENABLED
  um: Avoid using uninitialized regs
  um: Remove sig_info[SIGALRM]
  um: Error handling fixes in vector drivers
  ...

154 files changed:
arch/um/drivers/Kconfig
arch/um/drivers/Makefile
arch/um/drivers/chan.h
arch/um/drivers/chan_kern.c
arch/um/drivers/chan_user.c
arch/um/drivers/chan_user.h
arch/um/drivers/cow_user.c
arch/um/drivers/daemon.h
arch/um/drivers/daemon_kern.c
arch/um/drivers/daemon_user.c
arch/um/drivers/fd.c
arch/um/drivers/harddog_user.c
arch/um/drivers/hostaudio_kern.c
arch/um/drivers/line.c
arch/um/drivers/line.h
arch/um/drivers/mconsole.h
arch/um/drivers/mconsole_kern.c
arch/um/drivers/mconsole_kern.h
arch/um/drivers/mconsole_user.c
arch/um/drivers/net_kern.c
arch/um/drivers/net_user.c
arch/um/drivers/null.c
arch/um/drivers/pcap_kern.c
arch/um/drivers/pcap_user.c
arch/um/drivers/pcap_user.h
arch/um/drivers/port.h
arch/um/drivers/port_kern.c
arch/um/drivers/port_user.c
arch/um/drivers/pty.c
arch/um/drivers/slip_kern.c
arch/um/drivers/slip_user.c
arch/um/drivers/slirp_kern.c
arch/um/drivers/slirp_user.c
arch/um/drivers/ssl.c
arch/um/drivers/stdio_console.c
arch/um/drivers/stdio_console.h
arch/um/drivers/tty.c
arch/um/drivers/ubd.h
arch/um/drivers/ubd_kern.c
arch/um/drivers/ubd_user.c
arch/um/drivers/umcast.h
arch/um/drivers/umcast_kern.c
arch/um/drivers/umcast_user.c
arch/um/drivers/vde.h
arch/um/drivers/vde_kern.c
arch/um/drivers/vde_user.c
arch/um/drivers/vector_kern.c
arch/um/drivers/vector_kern.h
arch/um/drivers/vector_transports.c
arch/um/drivers/vector_user.c
arch/um/drivers/vector_user.h
arch/um/drivers/vhost_user.h [new file with mode: 0644]
arch/um/drivers/virtio_uml.c [new file with mode: 0644]
arch/um/drivers/xterm.c
arch/um/drivers/xterm.h
arch/um/drivers/xterm_kern.c
arch/um/include/asm/Kbuild
arch/um/include/asm/common.lds.S
arch/um/include/asm/irq.h
arch/um/include/asm/irqflags.h
arch/um/include/asm/kmap_types.h
arch/um/include/asm/mmu.h
arch/um/include/asm/mmu_context.h
arch/um/include/asm/page.h
arch/um/include/asm/pgalloc.h
arch/um/include/asm/pgtable-2level.h
arch/um/include/asm/pgtable-3level.h
arch/um/include/asm/pgtable.h
arch/um/include/asm/processor-generic.h
arch/um/include/asm/ptrace-generic.h
arch/um/include/asm/thread_info.h
arch/um/include/asm/tlbflush.h
arch/um/include/asm/uaccess.h
arch/um/include/shared/arch.h
arch/um/include/shared/as-layout.h
arch/um/include/shared/elf_user.h
arch/um/include/shared/frame_kern.h
arch/um/include/shared/irq_kern.h
arch/um/include/shared/irq_user.h
arch/um/include/shared/kern.h
arch/um/include/shared/kern_util.h
arch/um/include/shared/longjmp.h
arch/um/include/shared/mem.h
arch/um/include/shared/net_kern.h
arch/um/include/shared/net_user.h
arch/um/include/shared/os.h
arch/um/include/shared/ptrace_user.h
arch/um/include/shared/registers.h
arch/um/include/shared/sigio.h
arch/um/include/shared/skas/mm_id.h
arch/um/include/shared/skas/skas.h
arch/um/include/shared/skas/stub-data.h
arch/um/include/shared/timer-internal.h
arch/um/include/shared/um_malloc.h
arch/um/include/shared/user.h
arch/um/kernel/Makefile
arch/um/kernel/config.c.in
arch/um/kernel/dyn.lds.S
arch/um/kernel/exec.c
arch/um/kernel/exitcode.c
arch/um/kernel/gmon_syms.c
arch/um/kernel/gprof_syms.c
arch/um/kernel/initrd.c
arch/um/kernel/irq.c
arch/um/kernel/ksyms.c
arch/um/kernel/mem.c
arch/um/kernel/physmem.c
arch/um/kernel/process.c
arch/um/kernel/ptrace.c
arch/um/kernel/reboot.c
arch/um/kernel/sigio.c
arch/um/kernel/signal.c
arch/um/kernel/skas/Makefile
arch/um/kernel/skas/clone.c
arch/um/kernel/skas/mmu.c
arch/um/kernel/skas/process.c
arch/um/kernel/skas/syscall.c
arch/um/kernel/skas/uaccess.c
arch/um/kernel/syscall.c
arch/um/kernel/time.c
arch/um/kernel/tlb.c
arch/um/kernel/trap.c
arch/um/kernel/um_arch.c
arch/um/kernel/umid.c
arch/um/kernel/uml.lds.S
arch/um/os-Linux/Makefile
arch/um/os-Linux/drivers/Makefile
arch/um/os-Linux/drivers/etap.h
arch/um/os-Linux/drivers/ethertap_kern.c
arch/um/os-Linux/drivers/ethertap_user.c
arch/um/os-Linux/drivers/tuntap.h
arch/um/os-Linux/drivers/tuntap_kern.c
arch/um/os-Linux/drivers/tuntap_user.c
arch/um/os-Linux/file.c
arch/um/os-Linux/helper.c
arch/um/os-Linux/irq.c
arch/um/os-Linux/main.c
arch/um/os-Linux/mem.c
arch/um/os-Linux/process.c
arch/um/os-Linux/registers.c
arch/um/os-Linux/sigio.c
arch/um/os-Linux/signal.c
arch/um/os-Linux/skas/Makefile
arch/um/os-Linux/skas/mem.c
arch/um/os-Linux/skas/process.c
arch/um/os-Linux/start_up.c
arch/um/os-Linux/time.c
arch/um/os-Linux/tty.c
arch/um/os-Linux/umid.c
arch/um/os-Linux/util.c
arch/x86/um/asm/barrier.h
arch/x86/um/vdso/um_vdso.c
init/Kconfig
kernel/gcov/Kconfig

index 2638e46f50ccdc26f6eb396363e8ff81209bf76c..fea5a0d522dcfaa6ec38f881545c6b77c062e3bf 100644 (file)
@@ -335,3 +335,10 @@ config UML_NET_SLIRP
          Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
 
 endmenu
+
+config VIRTIO_UML
+       tristate "UML driver for virtio devices"
+       select VIRTIO
+       help
+         This driver provides support for virtio based paravirtual device
+         drivers over vhost-user sockets.
index 693319839f69ec93083b03d3f267d92c85f7c4fb..a290821e355c276ab6b5f1531ece0ad8daec595c 100644 (file)
@@ -1,6 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
 # 
 # Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com)
-# Licensed under the GPL
 #
 
 # pcap is broken in 2.5 because kbuild doesn't allow pcap.a to be linked
@@ -61,6 +61,7 @@ obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
 obj-$(CONFIG_UML_WATCHDOG) += harddog.o
 obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
 obj-$(CONFIG_UML_RANDOM) += random.o
+obj-$(CONFIG_VIRTIO_UML) += virtio_uml.o
 
 # pcap_user.o must be added explicitly.
 USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o pcap_user.o vde_user.o vector_user.o
index c512b0306dd41beff8039787d1eca7b90546ed40..c37cc4f26f91c7e592978337352a1c8e60a4b7cf 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __CHAN_KERN_H__
index 749d2bf5959946c3b5133f8e395c25344e53ed26..62997055c45476074bd4ff683821daf286c8e46e 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
  */
 
 #include <linux/slab.h>
index 3fd7c3efdb18df6b0f8f1dfd68e3883052b329c1..4d80526a4236e69113c102dbcc95b9fe3195fa24 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
  */
 
 #include <stdlib.h>
index 03f1b565c5f9ac9028ed7b91444b89c1dde963f1..72222bb036f503aa6bbcaa95a96fb29d75a24826 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __CHAN_USER_H__
index 0ee9cc6cc4c79dfb4d78fd8fa15072294c62568f..74b0c2686c95e7b5fdd8c6c82ad17457e2c03433 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
  */
 
 /*
index c2dd1951559f3376f9db686b11b6d27c7888e14e..1509cc7eb907a87f3b601b6b83c8d6a2bf49ccd5 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __DAEMON_H__
index 7568cc2f3cd680ef79e3e8ad81e376ccb06ff7bb..fd2402669c49b60cad0f958374031817fc33f631 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Copyright (C) 2001 by various other people who didn't put their name here.
- * Licensed under the GPL.
  */
 
 #include <linux/init.h>
index 8813c10d0177504f35bfcf58e1b49cffa2a943c8..3695821d06a2d6027ecad25f79ee90f51bfcf60c 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 by various other people who didn't put their name here.
- * Licensed under the GPL.
  */
 
 #include <stdint.h>
index a13a427b996bad391eba6fcac6b60a0baa03a850..082d739dc052112fe487534dd1eee38913e23937 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index 3aa8b0d52a48245ce99ee0418b0bc357d2693753..070468d22e3943f4d047aa8917776ee7f87b43db 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index 7f9dbdbc4eb7468f3c0b7f5a21e47c668faac49c..bf75b1ceac47222477c524a01141b43cfd6393fc 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 Steve Schmidtke
- * Licensed under the GPL
  */
 
 #include <linux/fs.h>
index e0e63931fb2b46829e5a1b6ba8eada3a1c4c9e0b..4f2a4ac8a82bbe03f92ebfb338fc91df5d3c3aaf 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/irqreturn.h>
index 138a14526d9c5c140fe4c91caee9c528a63d5680..a151ff5155efe08a645079f146c7b34cc9e6ebb8 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __LINE_H__
index 44af7379ea19c3da2cc4eb261287d8cab3ddfa16..6356378304fd9d3b6a6008f72bdaf601fb8ae977 100644 (file)
@@ -1,7 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __MCONSOLE_H__
index ff3ab72fd90ff192504205535cc29422c902420c..0117489e9b30a8560d4bef26685f3732f2ffb8cf 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
  * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/console.h>
index 7a0c6a1ad1d4786c70980a2c1a558c4b1d491339..56d8d6a3ff76f6407f01872a5dbdb56bb78dff86 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __MCONSOLE_KERN_H__
index 99209826adb15daffcd8ed299e00b42ae8ea752d..e24298a734befd9023f534080bb23680b1f99c7d 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <errno.h>
index 6e5be5fb4143695379ae4fc218971d23446d0b2f..327b728f72445332bb26cb2e993548a900de2ada 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 by various other people who didn't put their name here.
- * Licensed under the GPL.
  */
 
 #include <linux/memblock.h>
index e9f8445861dc73639bb32742bb5f6fae327a8b4c..4c9576452ab05886ea49669f38994c69b0ed6986 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index 10495747ce8ed932c7b65066ccfe46120490b7fd..87087763a417f946e15fb33992ccb269db218d3e 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
  */
 
 #include <stddef.h>
index be0fb57bd1d7a61d3c34213edced786c357c4197..cfe4cb17694cc611fdb738b255421951945ad53f 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL.
  */
 
 #include <linux/init.h>
index c07b9c752c8647185ea2e98e65d3b61115b5773f..bbd20638788aff787964f56ac6862e771a80a79a 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL.
  */
 
 #include <errno.h>
index 1ca7c764cc638734e69bd5c507f9cda260ca75bc..216246f5f09bdbc5e06978e9f0db0d2d9a374b35 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #include <net_user.h>
index 372a80c0556a275cdf5454b638efa7057d80007d..9085b336e683c9514f4042e6d3a46644928b94e8 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __PORT_H__
index b0e9ff35daee29bd5f574a7c819940586598c05d..a47ca5376d9d232a9cf870e6ce9bfc6af5bcefe1 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
  */
 
 #include <linux/completion.h>
index 5f56d11b886fc2926ac412b0f3b292a1a88b2ec3..5b5b64cb1071335603feb1d57b6570d08ec04294 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index f1fcc2cedb5ef964bdf0a5b73a11d7fd4d2e3cd1..39c60068cfdf67ad4cc4509fd806be08e680591d 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index ed5249fc0574d18f9de12642c17be2eca38759f5..c58ccdcc16d67a6361601d4661f84a1c9d855189 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL.
  */
 
 #include <linux/if_arp.h>
index 0d6b66c64a813731c465c4e2ecaf33ffa97e327c..8016d32b68092d5046c396845c61eb222e22732c 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL.
  */
 
 #include <stdio.h>
index 4ef11ca7cacf8184d0baa2fb8947c1d966d8eaeb..2d9769237f08e885482ef007c455eb14618659c5 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL.
  */
 
 #include <linux/if_arp.h>
index 98b6a41a254e47d8c6226ab809e4198f88fe5f57..8f633e2e5f3d660eef36b343df6960e406b2d580 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL.
  */
 
 #include <unistd.h>
index 7ae407d5337e19738c34ff3c0e962f88bd7b3f3c..b213201b8a3bd1c73243fee994378e3dc38f28ba 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /* 
  * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #include <linux/fs.h>
index c90817b04da968a611ff22979068539911929648..0021d7ffb528c387d8378687a56e3508cf0615a4 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /* 
  * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #include <linux/posix_types.h>
index 6d8275f71fd40a0c752370ece8ae2c5548d4d110..3a409ec23d6308869d2d1559b07e2cce7f09fde7 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __STDIO_CONSOLE_H
index eaa201bca5ed85db9ad0486ae9495498bcfb676a..884a762d21c71d9addeb32afef72d5d86971abb2 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
  */
 
 #include <errno.h>
index cc1cc85f5afc25ab5d0a53778856cb58b1c3f9a0..f016fe15499f544e0c762acdae726d76d98dbddf 100644 (file)
@@ -1,7 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
  * Copyright (C) 2001 RidgeRun, Inc (glonnon@ridgerun.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_UBD_USER_H
index 33c1cd6a12ac83fa9f901c98a5bbbca82932e905..612535cd97065beecb42bb59c4d2d4ca8252f6c4 100644 (file)
@@ -1,8 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2018 Cambridge Greys Ltd
  * Copyright (C) 2015-2016 Anton Ivanov (aivanov@brocade.com)
  * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 /* 2001-09-28...2002-04-17
index 6f744794d1416e795e5727065998f0b702c6343c..a1afe414ce481481adb956675783b78660a9ab46 100644 (file)
@@ -1,8 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2016 Anton Ivanov (aivanov@brocade.com)
  * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
- * Licensed under the GPL
  */
 
 #include <stddef.h>
index c190c64409119596b015cdf1208c6c251235c33d..fe39bee1e3bd60987851059c393af4bc460b65e3 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __DRIVERS_UMCAST_H
index f5ba6e377913b479a74bfb3bd433dd2f0146af92..595a54f2b9c6bccd38a3500411b1854ec4ad9726 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * user-mode-linux networking multicast transport
  * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org>
@@ -8,7 +9,6 @@
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 by various other people who didn't put their name here.
  *
- * Licensed under the GPL.
  */
 
 #include <linux/init.h>
index 6074184bb51b5eb13d74d13b32a92f1364031d39..b50b13cff04e61c03243f8be267392eb049c590c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * user-mode-linux networking multicast transport
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
@@ -8,7 +9,6 @@
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 by various other people who didn't put their name here.
  *
- * Licensed under the GPL.
  *
  */
 
index fc3a05902ba1e02d649acade926f1bc96b4ffe39..cab0379e6142cb08358e2a532203e3b5d47800a1 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
- * Licensed under the GPL.
  */
 
 #ifndef __UM_VDE_H__
index 6a365fadc7c4d90e73891b0db71cdc3b4bb49312..bc6f22cbfb35ed7a966f9614565f5e9570f008c7 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
- * Licensed under the GPL.
  *
  * Transport usage:
  *  ethN=vde,<vde_switch>,<mac addr>,<port>,<group>,<mode>,<description>
index 64cb630d11573df6fdb5c0e1379e1346475ce820..bc7dc4e1e486792c80e17bd99ac67a6f465f44d9 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2007 Luca Bigliardi (shammash@artha.org).
- * Licensed under the GPL.
  */
 
 #include <stddef.h>
index e190e4ca52e1fd11a199de61ea2d1244d8676b87..769ffbd9e9a61476262d5ceefc0de7716e9072d4 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2017 - Cambridge Greys Limited
  * Copyright (C) 2011 - 2014 Cisco Systems Inc
@@ -5,7 +6,6 @@
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 by various other people who didn't put their name here.
- * Licensed under the GPL.
  */
 
 #include <linux/version.h>
@@ -76,6 +76,7 @@ static void vector_eth_configure(int n, struct arglist *def);
 #define DEFAULT_VECTOR_SIZE 64
 #define TX_SMALL_PACKET 128
 #define MAX_IOV_SIZE (MAX_SKB_FRAGS + 1)
+#define MAX_ITERATIONS 64
 
 static const struct {
        const char string[ETH_GSTRING_LEN];
@@ -121,7 +122,8 @@ static int get_mtu(struct arglist *def)
 
        if (mtu != NULL) {
                if (kstrtoul(mtu, 10, &result) == 0)
-                       return result;
+                       if ((result < (1 << 16) - 1) && (result >= 576))
+                               return result;
        }
        return ETH_MAX_PACKET;
 }
@@ -186,6 +188,8 @@ static int get_transport_options(struct arglist *def)
 
 
        if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
+               return 0;
+       if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
                return (vec_rx | VECTOR_BPF);
        if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
                return (vec_rx | vec_tx | VECTOR_QDISC_BYPASS);
@@ -415,6 +419,7 @@ static int vector_send(struct vector_queue *qi)
                                        if (net_ratelimit())
                                                netdev_err(vp->dev, "sendmmsg err=%i\n",
                                                        result);
+                                       vp->in_error = true;
                                        result = send_len;
                                }
                                if (result > 0) {
@@ -842,6 +847,10 @@ static int vector_legacy_rx(struct vector_private *vp)
        }
 
        pkt_len = uml_vector_recvmsg(vp->fds->rx_fd, &hdr, 0);
+       if (pkt_len < 0) {
+               vp->in_error = true;
+               return pkt_len;
+       }
 
        if (skb != NULL) {
                if (pkt_len > vp->header_size) {
@@ -888,12 +897,16 @@ static int writev_tx(struct vector_private *vp, struct sk_buff *skb)
 
        if (iov_count < 1)
                goto drop;
+
        pkt_len = uml_vector_writev(
                vp->fds->tx_fd,
                (struct iovec *) &iov,
                iov_count
        );
 
+       if (pkt_len < 0)
+               goto drop;
+
        netif_trans_update(vp->dev);
        netif_wake_queue(vp->dev);
 
@@ -908,6 +921,8 @@ static int writev_tx(struct vector_private *vp, struct sk_buff *skb)
 drop:
        vp->dev->stats.tx_dropped++;
        consume_skb(skb);
+       if (pkt_len < 0)
+               vp->in_error = true;
        return pkt_len;
 }
 
@@ -936,6 +951,9 @@ static int vector_mmsg_rx(struct vector_private *vp)
        packet_count = uml_vector_recvmmsg(
                vp->fds->rx_fd, qi->mmsg_vector, qi->max_depth, 0);
 
+       if (packet_count < 0)
+               vp->in_error = true;
+
        if (packet_count <= 0)
                return packet_count;
 
@@ -1005,15 +1023,18 @@ static int vector_mmsg_rx(struct vector_private *vp)
 static void vector_rx(struct vector_private *vp)
 {
        int err;
+       int iter = 0;
 
        if ((vp->options & VECTOR_RX) > 0)
-               while ((err = vector_mmsg_rx(vp)) > 0)
-                       ;
+               while (((err = vector_mmsg_rx(vp)) > 0) && (iter < MAX_ITERATIONS))
+                       iter++;
        else
-               while ((err = vector_legacy_rx(vp)) > 0)
-                       ;
+               while (((err = vector_legacy_rx(vp)) > 0) && (iter < MAX_ITERATIONS))
+                       iter++;
        if ((err != 0) && net_ratelimit())
                netdev_err(vp->dev, "vector_rx: error(%d)\n", err);
+       if (iter == MAX_ITERATIONS)
+               netdev_err(vp->dev, "vector_rx: device stuck, remote end may have closed the connection\n");
 }
 
 static int vector_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -1021,6 +1042,13 @@ static int vector_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct vector_private *vp = netdev_priv(dev);
        int queue_depth = 0;
 
+       if (vp->in_error) {
+               deactivate_fd(vp->fds->rx_fd, vp->rx_irq);
+               if ((vp->fds->rx_fd != vp->fds->tx_fd) && (vp->tx_irq != 0))
+                       deactivate_fd(vp->fds->tx_fd, vp->tx_irq);
+               return NETDEV_TX_BUSY;
+       }
+
        if ((vp->options & VECTOR_TX) == 0) {
                writev_tx(vp, skb);
                return NETDEV_TX_OK;
@@ -1131,6 +1159,7 @@ static int vector_net_close(struct net_device *dev)
        vp->fds = NULL;
        spin_lock_irqsave(&vp->lock, flags);
        vp->opened = false;
+       vp->in_error = false;
        spin_unlock_irqrestore(&vp->lock, flags);
        return 0;
 }
@@ -1498,7 +1527,8 @@ static void vector_eth_configure(
                .transport_data         = NULL,
                .in_write_poll          = false,
                .coalesce               = 2,
-               .req_size               = get_req_size(def)
+               .req_size               = get_req_size(def),
+               .in_error               = false
                });
 
        dev->features = dev->hw_features = (NETIF_F_SG | NETIF_F_FRAGLIST);
index 0b0a767b90760a6f5d1298f13c618b1eefb6856e..4d292e6c07af32c5eb4bdfc403ef95ee1ea7674b 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2002 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_VECTOR_KERN_H
@@ -116,6 +116,7 @@ struct vector_private {
        bool rexmit_scheduled;
        bool opened;
        bool in_write_poll;
+       bool in_error;
 
        /* ethtool stats */
 
index 77e4ebc206ae1da08ac341010300ed8a0526b000..0794d23f07cbcca867f9f30b2fafc3a90b20d280 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2017 - Cambridge Greys Limited
  * Copyright (C) 2011 - 2014 Cisco Systems Inc
- * Licensed under the GPL.
  */
 
 #include <linux/etherdevice.h>
@@ -418,7 +418,7 @@ static int build_raw_transport_data(struct vector_private *vp)
        return 0;
 }
 
-static int build_tap_transport_data(struct vector_private *vp)
+static int build_hybrid_transport_data(struct vector_private *vp)
 {
        if (uml_raw_enable_vnet_headers(vp->fds->rx_fd)) {
                vp->form_header = &raw_form_header;
@@ -432,7 +432,7 @@ static int build_tap_transport_data(struct vector_private *vp)
                                NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
                netdev_info(
                        vp->dev,
-                       "tap/raw: using vnet headers for tso and tx/rx checksum"
+                       "tap/raw hybrid: using vnet headers for tso and tx/rx checksum"
                );
        } else {
                return 0; /* do not try to enable tap too if raw failed */
@@ -442,6 +442,38 @@ static int build_tap_transport_data(struct vector_private *vp)
        return -1;
 }
 
+static int build_tap_transport_data(struct vector_private *vp)
+{
+       /* "Pure" tap uses the same fd for rx and tx */
+       if (uml_tap_enable_vnet_headers(vp->fds->tx_fd)) {
+               vp->form_header = &raw_form_header;
+               vp->verify_header = &raw_verify_header;
+               vp->header_size = sizeof(struct virtio_net_hdr);
+               vp->rx_header_size = sizeof(struct virtio_net_hdr);
+               vp->dev->hw_features |=
+                       (NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
+               vp->dev->features |=
+                       (NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
+                               NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
+               netdev_info(
+                       vp->dev,
+                       "tap: using vnet headers for tso and tx/rx checksum"
+               );
+               return 0;
+       }
+       return -1;
+}
+
+
+static int build_bess_transport_data(struct vector_private *vp)
+{
+       vp->form_header = NULL;
+       vp->verify_header = NULL;
+       vp->header_size = 0;
+       vp->rx_header_size = 0;
+       return 0;
+}
+
 int build_transport_data(struct vector_private *vp)
 {
        char *transport = uml_vector_fetch_arg(vp->parsed, "transport");
@@ -454,6 +486,10 @@ int build_transport_data(struct vector_private *vp)
                return build_raw_transport_data(vp);
        if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
                return build_tap_transport_data(vp);
+       if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
+               return build_hybrid_transport_data(vp);
+       if (strncmp(transport, TRANS_BESS, TRANS_BESS_LEN) == 0)
+               return build_bess_transport_data(vp);
        return 0;
 }
 
index b3f7b3ca896dd268391e139731cd2823efdf3488..e2c969b9f7eed5f84656c790ba58e51db79e2c32 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
@@ -17,6 +17,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <net/ethernet.h>
 #include <netinet/ip.h>
 #include <netinet/ether.h>
@@ -33,7 +34,8 @@
 
 #define ID_GRE 0
 #define ID_L2TPV3 1
-#define ID_MAX 1
+#define ID_BESS 2
+#define ID_MAX 2
 
 #define TOKEN_IFNAME "ifname"
 
 #define VNET_HDR_FAIL "could not enable vnet headers on fd %d"
 #define TUN_GET_F_FAIL "tapraw: TUNGETFEATURES failed: %s"
 #define L2TPV3_BIND_FAIL "l2tpv3_open : could not bind socket err=%i"
+#define UNIX_BIND_FAIL "unix_open : could not bind socket err=%i"
 #define BPF_ATTACH_FAIL "Failed to attach filter size %d to %d, err %d\n"
 
+#define MAX_UN_LEN 107
+
 /* This is very ugly and brute force lookup, but it is done
  * only once at initialization so not worth doing hashes or
  * anything more intelligent
@@ -114,12 +119,76 @@ cleanup:
 
 #define PATH_NET_TUN "/dev/net/tun"
 
-static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
+
+static int create_tap_fd(char *iface)
 {
        struct ifreq ifr;
        int fd = -1;
-       struct sockaddr_ll sock;
        int err = -ENOMEM, offload;
+
+       fd = open(PATH_NET_TUN, O_RDWR);
+       if (fd < 0) {
+               printk(UM_KERN_ERR "uml_tap: failed to open tun device\n");
+               goto tap_fd_cleanup;
+       }
+       memset(&ifr, 0, sizeof(ifr));
+       ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
+       strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
+
+       err = ioctl(fd, TUNSETIFF, (void *) &ifr);
+       if (err != 0) {
+               printk(UM_KERN_ERR "uml_tap: failed to select tap interface\n");
+               goto tap_fd_cleanup;
+       }
+
+       offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
+       ioctl(fd, TUNSETOFFLOAD, offload);
+       return fd;
+tap_fd_cleanup:
+       if (fd >= 0)
+               os_close_file(fd);
+       return err;
+}
+
+static int create_raw_fd(char *iface, int flags, int proto)
+{
+       struct ifreq ifr;
+       int fd = -1;
+       struct sockaddr_ll sock;
+       int err = -ENOMEM;
+
+       fd = socket(AF_PACKET, SOCK_RAW, flags);
+       if (fd == -1) {
+               err = -errno;
+               goto raw_fd_cleanup;
+       }
+       memset(&ifr, 0, sizeof(ifr));
+       strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
+       if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
+               err = -errno;
+               goto raw_fd_cleanup;
+       }
+
+       sock.sll_family = AF_PACKET;
+       sock.sll_protocol = htons(proto);
+       sock.sll_ifindex = ifr.ifr_ifindex;
+
+       if (bind(fd,
+               (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
+               err = -errno;
+               goto raw_fd_cleanup;
+       }
+       return fd;
+raw_fd_cleanup:
+       printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
+       if (fd >= 0)
+               os_close_file(fd);
+       return err;
+}
+
+static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
+{
+       int fd = -1;
        char *iface;
        struct vector_fds *result = NULL;
 
@@ -141,117 +210,167 @@ static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
 
        /* TAP */
 
-       fd = open(PATH_NET_TUN, O_RDWR);
+       fd = create_tap_fd(iface);
        if (fd < 0) {
-               printk(UM_KERN_ERR "uml_tap: failed to open tun device\n");
+               printk(UM_KERN_ERR "uml_tap: failed to create tun interface\n");
                goto tap_cleanup;
        }
        result->tx_fd = fd;
-       memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
-       strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
+       result->rx_fd = fd;
+       return result;
+tap_cleanup:
+       printk(UM_KERN_ERR "user_init_tap: init failed, error %d", fd);
+       if (result != NULL)
+               kfree(result);
+       return NULL;
+}
 
-       err = ioctl(fd, TUNSETIFF, (void *) &ifr);
-       if (err != 0) {
-               printk(UM_KERN_ERR "uml_tap: failed to select tap interface\n");
-               goto tap_cleanup;
+static struct vector_fds *user_init_hybrid_fds(struct arglist *ifspec)
+{
+       char *iface;
+       struct vector_fds *result = NULL;
+
+       iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
+       if (iface == NULL) {
+               printk(UM_KERN_ERR "uml_tap: failed to parse interface spec\n");
+               goto hybrid_cleanup;
        }
 
-       offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
-       ioctl(fd, TUNSETOFFLOAD, offload);
+       result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
+       if (result == NULL) {
+               printk(UM_KERN_ERR "uml_tap: failed to allocate file descriptors\n");
+               goto hybrid_cleanup;
+       }
+       result->rx_fd = -1;
+       result->tx_fd = -1;
+       result->remote_addr = NULL;
+       result->remote_addr_size = 0;
+
+       /* TAP */
+
+       result->tx_fd = create_tap_fd(iface);
+       if (result->tx_fd < 0) {
+               printk(UM_KERN_ERR "uml_tap: failed to create tun interface: %i\n", result->tx_fd);
+               goto hybrid_cleanup;
+       }
 
        /* RAW */
 
-       fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
-       if (fd == -1) {
+       result->rx_fd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL);
+       if (result->rx_fd == -1) {
                printk(UM_KERN_ERR
-                       "uml_tap: failed to create socket: %i\n", -errno);
-               goto tap_cleanup;
+                       "uml_tap: failed to create paired raw socket: %i\n", result->rx_fd);
+               goto hybrid_cleanup;
        }
-       result->rx_fd = fd;
-       memset(&ifr, 0, sizeof(ifr));
-       strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
-       if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
-               printk(UM_KERN_ERR
-                       "uml_tap: failed to set interface: %i\n", -errno);
-               goto tap_cleanup;
+       return result;
+hybrid_cleanup:
+       printk(UM_KERN_ERR "user_init_hybrid: init failed");
+       if (result != NULL)
+               kfree(result);
+       return NULL;
+}
+
+static struct vector_fds *user_init_unix_fds(struct arglist *ifspec, int id)
+{
+       int fd = -1;
+       int socktype;
+       char *src, *dst;
+       struct vector_fds *result = NULL;
+       struct sockaddr_un *local_addr = NULL, *remote_addr = NULL;
+
+       src = uml_vector_fetch_arg(ifspec, "src");
+       dst = uml_vector_fetch_arg(ifspec, "dst");
+       result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
+       if (result == NULL) {
+               printk(UM_KERN_ERR "unix open:cannot allocate remote addr");
+               goto unix_cleanup;
+       }
+       remote_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
+       if (remote_addr == NULL) {
+               printk(UM_KERN_ERR "unix open:cannot allocate remote addr");
+               goto unix_cleanup;
        }
 
-       sock.sll_family = AF_PACKET;
-       sock.sll_protocol = htons(ETH_P_ALL);
-       sock.sll_ifindex = ifr.ifr_ifindex;
+       switch (id) {
+       case ID_BESS:
+               socktype = SOCK_SEQPACKET;
+               if ((src != NULL) && (strlen(src) <= MAX_UN_LEN)) {
+                       local_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
+                       if (local_addr == NULL) {
+                               printk(UM_KERN_ERR "bess open:cannot allocate local addr");
+                               goto unix_cleanup;
+                       }
+                       local_addr->sun_family = AF_UNIX;
+                       memcpy(local_addr->sun_path, src, strlen(src) + 1);
+               }
+               if ((dst == NULL) || (strlen(dst) > MAX_UN_LEN))
+                       goto unix_cleanup;
+               remote_addr->sun_family = AF_UNIX;
+               memcpy(remote_addr->sun_path, dst, strlen(dst) + 1);
+               break;
+       default:
+               printk(KERN_ERR "Unsupported unix socket type\n");
+               return NULL;
+       }
 
-       if (bind(fd,
-               (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
+       fd = socket(AF_UNIX, socktype, 0);
+       if (fd == -1) {
                printk(UM_KERN_ERR
-                       "user_init_tap: failed to bind raw pair, err %d\n",
-                               -errno);
-               goto tap_cleanup;
+                       "unix open: could not open socket, error = %d",
+                       -errno
+               );
+               goto unix_cleanup;
        }
+       if (local_addr != NULL) {
+               if (bind(fd, (struct sockaddr *) local_addr, sizeof(struct sockaddr_un))) {
+                       printk(UM_KERN_ERR UNIX_BIND_FAIL, errno);
+                       goto unix_cleanup;
+               }
+       }
+       switch (id) {
+       case ID_BESS:
+               if (connect(fd, remote_addr, sizeof(struct sockaddr_un)) < 0) {
+                       printk(UM_KERN_ERR "bess open:cannot connect to %s %i", remote_addr->sun_path, -errno);
+                       goto unix_cleanup;
+               }
+               break;
+       }
+       result->rx_fd = fd;
+       result->tx_fd = fd;
+       result->remote_addr_size = sizeof(struct sockaddr_un);
+       result->remote_addr = remote_addr;
        return result;
-tap_cleanup:
-       printk(UM_KERN_ERR "user_init_tap: init failed, error %d", err);
-       if (result != NULL) {
-               if (result->rx_fd >= 0)
-                       os_close_file(result->rx_fd);
-               if (result->tx_fd >= 0)
-                       os_close_file(result->tx_fd);
+unix_cleanup:
+       if (fd >= 0)
+               os_close_file(fd);
+       if (remote_addr != NULL)
+               kfree(remote_addr);
+       if (result != NULL)
                kfree(result);
-       }
        return NULL;
 }
 
-
 static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
 {
-       struct ifreq ifr;
        int rxfd = -1, txfd = -1;
-       struct sockaddr_ll sock;
        int err = -ENOMEM;
        char *iface;
        struct vector_fds *result = NULL;
 
        iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
        if (iface == NULL)
-               goto cleanup;
+               goto raw_cleanup;
 
-       rxfd = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL);
+       rxfd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL);
        if (rxfd == -1) {
                err = -errno;
-               goto cleanup;
+               goto raw_cleanup;
        }
-       txfd = socket(AF_PACKET, SOCK_RAW, 0); /* Turn off RX on this fd */
+       txfd = create_raw_fd(iface, 0, ETH_P_IP); /* Turn off RX on this fd */
        if (txfd == -1) {
                err = -errno;
-               goto cleanup;
+               goto raw_cleanup;
        }
-       memset(&ifr, 0, sizeof(ifr));
-       strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1);
-       if (ioctl(rxfd, SIOCGIFINDEX, (void *) &ifr) < 0) {
-               err = -errno;
-               goto cleanup;
-       }
-
-       sock.sll_family = AF_PACKET;
-       sock.sll_protocol = htons(ETH_P_ALL);
-       sock.sll_ifindex = ifr.ifr_ifindex;
-
-       if (bind(rxfd,
-               (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
-               err = -errno;
-               goto cleanup;
-       }
-
-       sock.sll_family = AF_PACKET;
-       sock.sll_protocol = htons(ETH_P_IP);
-       sock.sll_ifindex = ifr.ifr_ifindex;
-
-       if (bind(txfd,
-               (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
-               err = -errno;
-               goto cleanup;
-       }
-
        result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
        if (result != NULL) {
                result->rx_fd = rxfd;
@@ -260,13 +379,10 @@ static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
                result->remote_addr_size = 0;
        }
        return result;
-cleanup:
+raw_cleanup:
        printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
-       if (rxfd >= 0)
-               os_close_file(rxfd);
-       if (txfd >= 0)
-               os_close_file(txfd);
-       kfree(result);
+       if (result != NULL)
+               kfree(result);
        return NULL;
 }
 
@@ -456,12 +572,16 @@ struct vector_fds *uml_vector_user_open(
        }
        if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
                return user_init_raw_fds(parsed);
+       if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
+               return user_init_hybrid_fds(parsed);
        if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
                return user_init_tap_fds(parsed);
        if (strncmp(transport, TRANS_GRE, TRANS_GRE_LEN) == 0)
                return user_init_socket_fds(parsed, ID_GRE);
        if (strncmp(transport, TRANS_L2TPV3, TRANS_L2TPV3_LEN) == 0)
                return user_init_socket_fds(parsed, ID_L2TPV3);
+       if (strncmp(transport, TRANS_BESS, TRANS_BESS_LEN) == 0)
+               return user_init_unix_fds(parsed, ID_BESS);
        return NULL;
 }
 
@@ -482,8 +602,9 @@ int uml_vector_sendmsg(int fd, void *hdr, int flags)
 int uml_vector_recvmsg(int fd, void *hdr, int flags)
 {
        int n;
+       struct msghdr *msg = (struct msghdr *) hdr;
 
-       CATCH_EINTR(n = recvmsg(fd, (struct msghdr *) hdr,  flags));
+       CATCH_EINTR(n = readv(fd, msg->msg_iov, msg->msg_iovlen));
        if ((n < 0) && (errno == EAGAIN))
                return 0;
        if (n >= 0)
@@ -497,7 +618,7 @@ int uml_vector_writev(int fd, void *hdr, int iovcount)
        int n;
 
        CATCH_EINTR(n = writev(fd, (struct iovec *) hdr,  iovcount));
-       if ((n < 0) && (errno == EAGAIN))
+       if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS)))
                return 0;
        if (n >= 0)
                return n;
@@ -514,7 +635,7 @@ int uml_vector_sendmmsg(
        int n;
 
        CATCH_EINTR(n = sendmmsg(fd, (struct mmsghdr *) msgvec, vlen, flags));
-       if ((n < 0) && (errno == EAGAIN))
+       if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS)))
                return 0;
        if (n >= 0)
                return n;
index d7cbff73b7ff2ffad826be45aeba724b67a0eb58..649ec250268beb1d0ba49f9c114273fc2c8955be 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2002 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_VECTOR_USER_H
 #define TRANS_TAP "tap"
 #define TRANS_TAP_LEN strlen(TRANS_TAP)
 
-
 #define TRANS_GRE "gre"
 #define TRANS_GRE_LEN strlen(TRANS_RAW)
 
 #define TRANS_L2TPV3 "l2tpv3"
 #define TRANS_L2TPV3_LEN strlen(TRANS_L2TPV3)
 
+#define TRANS_HYBRID "hybrid"
+#define TRANS_HYBRID_LEN strlen(TRANS_HYBRID)
+
+#define TRANS_BESS "bess"
+#define TRANS_BESS_LEN strlen(TRANS_BESS)
+
 #ifndef IPPROTO_GRE
 #define IPPROTO_GRE 0x2F
 #endif
diff --git a/arch/um/drivers/vhost_user.h b/arch/um/drivers/vhost_user.h
new file mode 100644 (file)
index 0000000..45ff5ea
--- /dev/null
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Vhost-user protocol */
+
+#ifndef __VHOST_USER_H__
+#define __VHOST_USER_H__
+
+/* Message flags */
+#define VHOST_USER_FLAG_REPLY          BIT(2)
+#define VHOST_USER_FLAG_NEED_REPLY     BIT(3)
+/* Feature bits */
+#define VHOST_USER_F_PROTOCOL_FEATURES 30
+/* Protocol feature bits */
+#define VHOST_USER_PROTOCOL_F_REPLY_ACK                3
+#define VHOST_USER_PROTOCOL_F_SLAVE_REQ                5
+#define VHOST_USER_PROTOCOL_F_CONFIG           9
+/* Vring state index masks */
+#define VHOST_USER_VRING_INDEX_MASK    0xff
+#define VHOST_USER_VRING_POLL_MASK     BIT(8)
+
+/* Supported version */
+#define VHOST_USER_VERSION             1
+/* Supported transport features */
+#define VHOST_USER_SUPPORTED_F         BIT_ULL(VHOST_USER_F_PROTOCOL_FEATURES)
+/* Supported protocol features */
+#define VHOST_USER_SUPPORTED_PROTOCOL_F        (BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
+                                        BIT_ULL(VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \
+                                        BIT_ULL(VHOST_USER_PROTOCOL_F_CONFIG))
+
+enum vhost_user_request {
+       VHOST_USER_GET_FEATURES = 1,
+       VHOST_USER_SET_FEATURES = 2,
+       VHOST_USER_SET_OWNER = 3,
+       VHOST_USER_RESET_OWNER = 4,
+       VHOST_USER_SET_MEM_TABLE = 5,
+       VHOST_USER_SET_LOG_BASE = 6,
+       VHOST_USER_SET_LOG_FD = 7,
+       VHOST_USER_SET_VRING_NUM = 8,
+       VHOST_USER_SET_VRING_ADDR = 9,
+       VHOST_USER_SET_VRING_BASE = 10,
+       VHOST_USER_GET_VRING_BASE = 11,
+       VHOST_USER_SET_VRING_KICK = 12,
+       VHOST_USER_SET_VRING_CALL = 13,
+       VHOST_USER_SET_VRING_ERR = 14,
+       VHOST_USER_GET_PROTOCOL_FEATURES = 15,
+       VHOST_USER_SET_PROTOCOL_FEATURES = 16,
+       VHOST_USER_GET_QUEUE_NUM = 17,
+       VHOST_USER_SET_VRING_ENABLE = 18,
+       VHOST_USER_SEND_RARP = 19,
+       VHOST_USER_NET_SEND_MTU = 20,
+       VHOST_USER_SET_SLAVE_REQ_FD = 21,
+       VHOST_USER_IOTLB_MSG = 22,
+       VHOST_USER_SET_VRING_ENDIAN = 23,
+       VHOST_USER_GET_CONFIG = 24,
+       VHOST_USER_SET_CONFIG = 25,
+};
+
+enum vhost_user_slave_request {
+       VHOST_USER_SLAVE_IOTLB_MSG = 1,
+       VHOST_USER_SLAVE_CONFIG_CHANGE_MSG = 2,
+       VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG = 3,
+};
+
+struct vhost_user_header {
+       /*
+        * Use enum vhost_user_request for outgoing messages,
+        * uses enum vhost_user_slave_request for incoming ones.
+        */
+       u32 request;
+       u32 flags;
+       u32 size;
+} __packed;
+
+struct vhost_user_config {
+       u32 offset;
+       u32 size;
+       u32 flags;
+       u8 payload[0]; /* Variable length */
+} __packed;
+
+struct vhost_user_vring_state {
+       u32 index;
+       u32 num;
+} __packed;
+
+struct vhost_user_vring_addr {
+       u32 index;
+       u32 flags;
+       u64 desc, used, avail, log;
+} __packed;
+
+struct vhost_user_mem_region {
+       u64 guest_addr;
+       u64 size;
+       u64 user_addr;
+       u64 mmap_offset;
+} __packed;
+
+struct vhost_user_mem_regions {
+       u32 num;
+       u32 padding;
+       struct vhost_user_mem_region regions[2]; /* Currently supporting 2 */
+} __packed;
+
+union vhost_user_payload {
+       u64 integer;
+       struct vhost_user_config config;
+       struct vhost_user_vring_state vring_state;
+       struct vhost_user_vring_addr vring_addr;
+       struct vhost_user_mem_regions mem_regions;
+};
+
+struct vhost_user_msg {
+       struct vhost_user_header header;
+       union vhost_user_payload payload;
+} __packed;
+
+#endif
diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
new file mode 100644 (file)
index 0000000..fc8c52c
--- /dev/null
@@ -0,0 +1,1177 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Virtio vhost-user driver
+ *
+ * Copyright(c) 2019 Intel Corporation
+ *
+ * This module allows virtio devices to be used over a vhost-user socket.
+ *
+ * Guest devices can be instantiated by kernel module or command line
+ * parameters. One device will be created for each parameter. Syntax:
+ *
+ *             [virtio_uml.]device=<socket>:<virtio_id>[:<platform_id>]
+ * where:
+ *             <socket>        := vhost-user socket path to connect
+ *             <virtio_id>     := virtio device id (as in virtio_ids.h)
+ *             <platform_id>   := (optional) platform device id
+ *
+ * example:
+ *             virtio_uml.device=/var/uml.socket:1
+ *
+ * Based on Virtio MMIO driver by Pawel Moll, copyright 2011-2014, ARM Ltd.
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/virtio.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+#include <shared/as-layout.h>
+#include <irq_kern.h>
+#include <init.h>
+#include <os.h>
+#include "vhost_user.h"
+
+/* Workaround due to a conflict between irq_user.h and irqreturn.h */
+#ifdef IRQ_NONE
+#undef IRQ_NONE
+#endif
+
+#define MAX_SUPPORTED_QUEUE_SIZE       256
+
+#define to_virtio_uml_device(_vdev) \
+       container_of(_vdev, struct virtio_uml_device, vdev)
+
+struct virtio_uml_device {
+       struct virtio_device vdev;
+       struct platform_device *pdev;
+
+       int sock, req_fd;
+       u64 features;
+       u64 protocol_features;
+       u8 status;
+};
+
+struct virtio_uml_vq_info {
+       int kick_fd, call_fd;
+       char name[32];
+};
+
+extern unsigned long long physmem_size, highmem;
+
+#define vu_err(vu_dev, ...)    dev_err(&(vu_dev)->pdev->dev, __VA_ARGS__)
+
+/* Vhost-user protocol */
+
+static int full_sendmsg_fds(int fd, const void *buf, unsigned int len,
+                           const int *fds, unsigned int fds_num)
+{
+       int rc;
+
+       do {
+               rc = os_sendmsg_fds(fd, buf, len, fds, fds_num);
+               if (rc > 0) {
+                       buf += rc;
+                       len -= rc;
+                       fds = NULL;
+                       fds_num = 0;
+               }
+       } while (len && (rc >= 0 || rc == -EINTR));
+
+       if (rc < 0)
+               return rc;
+       return 0;
+}
+
+static int full_read(int fd, void *buf, int len)
+{
+       int rc;
+
+       do {
+               rc = os_read_file(fd, buf, len);
+               if (rc > 0) {
+                       buf += rc;
+                       len -= rc;
+               }
+       } while (len && (rc > 0 || rc == -EINTR));
+
+       if (rc < 0)
+               return rc;
+       if (rc == 0)
+               return -ECONNRESET;
+       return 0;
+}
+
+static int vhost_user_recv_header(int fd, struct vhost_user_msg *msg)
+{
+       return full_read(fd, msg, sizeof(msg->header));
+}
+
+static int vhost_user_recv(int fd, struct vhost_user_msg *msg,
+                          size_t max_payload_size)
+{
+       size_t size;
+       int rc = vhost_user_recv_header(fd, msg);
+
+       if (rc)
+               return rc;
+       size = msg->header.size;
+       if (size > max_payload_size)
+               return -EPROTO;
+       return full_read(fd, &msg->payload, size);
+}
+
+static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev,
+                               struct vhost_user_msg *msg,
+                               size_t max_payload_size)
+{
+       int rc = vhost_user_recv(vu_dev->sock, msg, max_payload_size);
+
+       if (rc)
+               return rc;
+
+       if (msg->header.flags != (VHOST_USER_FLAG_REPLY | VHOST_USER_VERSION))
+               return -EPROTO;
+
+       return 0;
+}
+
+static int vhost_user_recv_u64(struct virtio_uml_device *vu_dev,
+                              u64 *value)
+{
+       struct vhost_user_msg msg;
+       int rc = vhost_user_recv_resp(vu_dev, &msg,
+                                     sizeof(msg.payload.integer));
+
+       if (rc)
+               return rc;
+       if (msg.header.size != sizeof(msg.payload.integer))
+               return -EPROTO;
+       *value = msg.payload.integer;
+       return 0;
+}
+
+static int vhost_user_recv_req(struct virtio_uml_device *vu_dev,
+                              struct vhost_user_msg *msg,
+                              size_t max_payload_size)
+{
+       int rc = vhost_user_recv(vu_dev->req_fd, msg, max_payload_size);
+
+       if (rc)
+               return rc;
+
+       if ((msg->header.flags & ~VHOST_USER_FLAG_NEED_REPLY) !=
+                       VHOST_USER_VERSION)
+               return -EPROTO;
+
+       return 0;
+}
+
+static int vhost_user_send(struct virtio_uml_device *vu_dev,
+                          bool need_response, struct vhost_user_msg *msg,
+                          int *fds, size_t num_fds)
+{
+       size_t size = sizeof(msg->header) + msg->header.size;
+       bool request_ack;
+       int rc;
+
+       msg->header.flags |= VHOST_USER_VERSION;
+
+       /*
+        * The need_response flag indicates that we already need a response,
+        * e.g. to read the features. In these cases, don't request an ACK as
+        * it is meaningless. Also request an ACK only if supported.
+        */
+       request_ack = !need_response;
+       if (!(vu_dev->protocol_features &
+                       BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK)))
+               request_ack = false;
+
+       if (request_ack)
+               msg->header.flags |= VHOST_USER_FLAG_NEED_REPLY;
+
+       rc = full_sendmsg_fds(vu_dev->sock, msg, size, fds, num_fds);
+       if (rc < 0)
+               return rc;
+
+       if (request_ack) {
+               uint64_t status;
+
+               rc = vhost_user_recv_u64(vu_dev, &status);
+               if (rc)
+                       return rc;
+
+               if (status) {
+                       vu_err(vu_dev, "slave reports error: %llu\n", status);
+                       return -EIO;
+               }
+       }
+
+       return 0;
+}
+
+static int vhost_user_send_no_payload(struct virtio_uml_device *vu_dev,
+                                     bool need_response, u32 request)
+{
+       struct vhost_user_msg msg = {
+               .header.request = request,
+       };
+
+       return vhost_user_send(vu_dev, need_response, &msg, NULL, 0);
+}
+
+static int vhost_user_send_no_payload_fd(struct virtio_uml_device *vu_dev,
+                                        u32 request, int fd)
+{
+       struct vhost_user_msg msg = {
+               .header.request = request,
+       };
+
+       return vhost_user_send(vu_dev, false, &msg, &fd, 1);
+}
+
+static int vhost_user_send_u64(struct virtio_uml_device *vu_dev,
+                              u32 request, u64 value)
+{
+       struct vhost_user_msg msg = {
+               .header.request = request,
+               .header.size = sizeof(msg.payload.integer),
+               .payload.integer = value,
+       };
+
+       return vhost_user_send(vu_dev, false, &msg, NULL, 0);
+}
+
+static int vhost_user_set_owner(struct virtio_uml_device *vu_dev)
+{
+       return vhost_user_send_no_payload(vu_dev, false, VHOST_USER_SET_OWNER);
+}
+
+static int vhost_user_get_features(struct virtio_uml_device *vu_dev,
+                                  u64 *features)
+{
+       int rc = vhost_user_send_no_payload(vu_dev, true,
+                                           VHOST_USER_GET_FEATURES);
+
+       if (rc)
+               return rc;
+       return vhost_user_recv_u64(vu_dev, features);
+}
+
+static int vhost_user_set_features(struct virtio_uml_device *vu_dev,
+                                  u64 features)
+{
+       return vhost_user_send_u64(vu_dev, VHOST_USER_SET_FEATURES, features);
+}
+
+static int vhost_user_get_protocol_features(struct virtio_uml_device *vu_dev,
+                                           u64 *protocol_features)
+{
+       int rc = vhost_user_send_no_payload(vu_dev, true,
+                       VHOST_USER_GET_PROTOCOL_FEATURES);
+
+       if (rc)
+               return rc;
+       return vhost_user_recv_u64(vu_dev, protocol_features);
+}
+
+static int vhost_user_set_protocol_features(struct virtio_uml_device *vu_dev,
+                                           u64 protocol_features)
+{
+       return vhost_user_send_u64(vu_dev, VHOST_USER_SET_PROTOCOL_FEATURES,
+                                  protocol_features);
+}
+
+static void vhost_user_reply(struct virtio_uml_device *vu_dev,
+                            struct vhost_user_msg *msg, int response)
+{
+       struct vhost_user_msg reply = {
+               .payload.integer = response,
+       };
+       size_t size = sizeof(reply.header) + sizeof(reply.payload.integer);
+       int rc;
+
+       reply.header = msg->header;
+       reply.header.flags &= ~VHOST_USER_FLAG_NEED_REPLY;
+       reply.header.flags |= VHOST_USER_FLAG_REPLY;
+       reply.header.size = sizeof(reply.payload.integer);
+
+       rc = full_sendmsg_fds(vu_dev->req_fd, &reply, size, NULL, 0);
+
+       if (rc)
+               vu_err(vu_dev,
+                      "sending reply to slave request failed: %d (size %zu)\n",
+                      rc, size);
+}
+
+static irqreturn_t vu_req_interrupt(int irq, void *data)
+{
+       struct virtio_uml_device *vu_dev = data;
+       int response = 1;
+       struct {
+               struct vhost_user_msg msg;
+               u8 extra_payload[512];
+       } msg;
+       int rc;
+
+       rc = vhost_user_recv_req(vu_dev, &msg.msg,
+                                sizeof(msg.msg.payload) +
+                                sizeof(msg.extra_payload));
+
+       if (rc)
+               return IRQ_NONE;
+
+       switch (msg.msg.header.request) {
+       case VHOST_USER_SLAVE_CONFIG_CHANGE_MSG:
+               virtio_config_changed(&vu_dev->vdev);
+               response = 0;
+               break;
+       case VHOST_USER_SLAVE_IOTLB_MSG:
+               /* not supported - VIRTIO_F_IOMMU_PLATFORM */
+       case VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG:
+               /* not supported - VHOST_USER_PROTOCOL_F_HOST_NOTIFIER */
+       default:
+               vu_err(vu_dev, "unexpected slave request %d\n",
+                      msg.msg.header.request);
+       }
+
+       if (msg.msg.header.flags & VHOST_USER_FLAG_NEED_REPLY)
+               vhost_user_reply(vu_dev, &msg.msg, response);
+
+       return IRQ_HANDLED;
+}
+
+static int vhost_user_init_slave_req(struct virtio_uml_device *vu_dev)
+{
+       int rc, req_fds[2];
+
+       /* Use a pipe for slave req fd, SIGIO is not supported for eventfd */
+       rc = os_pipe(req_fds, true, true);
+       if (rc < 0)
+               return rc;
+       vu_dev->req_fd = req_fds[0];
+
+       rc = um_request_irq(VIRTIO_IRQ, vu_dev->req_fd, IRQ_READ,
+                           vu_req_interrupt, IRQF_SHARED,
+                           vu_dev->pdev->name, vu_dev);
+       if (rc)
+               goto err_close;
+
+       rc = vhost_user_send_no_payload_fd(vu_dev, VHOST_USER_SET_SLAVE_REQ_FD,
+                                          req_fds[1]);
+       if (rc)
+               goto err_free_irq;
+
+       goto out;
+
+err_free_irq:
+       um_free_irq(VIRTIO_IRQ, vu_dev);
+err_close:
+       os_close_file(req_fds[0]);
+out:
+       /* Close unused write end of request fds */
+       os_close_file(req_fds[1]);
+       return rc;
+}
+
+static int vhost_user_init(struct virtio_uml_device *vu_dev)
+{
+       int rc = vhost_user_set_owner(vu_dev);
+
+       if (rc)
+               return rc;
+       rc = vhost_user_get_features(vu_dev, &vu_dev->features);
+       if (rc)
+               return rc;
+
+       if (vu_dev->features & BIT_ULL(VHOST_USER_F_PROTOCOL_FEATURES)) {
+               rc = vhost_user_get_protocol_features(vu_dev,
+                               &vu_dev->protocol_features);
+               if (rc)
+                       return rc;
+               vu_dev->protocol_features &= VHOST_USER_SUPPORTED_PROTOCOL_F;
+               rc = vhost_user_set_protocol_features(vu_dev,
+                               vu_dev->protocol_features);
+               if (rc)
+                       return rc;
+       }
+
+       if (vu_dev->protocol_features &
+                       BIT_ULL(VHOST_USER_PROTOCOL_F_SLAVE_REQ)) {
+               rc = vhost_user_init_slave_req(vu_dev);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
+
+static void vhost_user_get_config(struct virtio_uml_device *vu_dev,
+                                 u32 offset, void *buf, u32 len)
+{
+       u32 cfg_size = offset + len;
+       struct vhost_user_msg *msg;
+       size_t payload_size = sizeof(msg->payload.config) + cfg_size;
+       size_t msg_size = sizeof(msg->header) + payload_size;
+       int rc;
+
+       if (!(vu_dev->protocol_features &
+             BIT_ULL(VHOST_USER_PROTOCOL_F_CONFIG)))
+               return;
+
+       msg = kzalloc(msg_size, GFP_KERNEL);
+       if (!msg)
+               return;
+       msg->header.request = VHOST_USER_GET_CONFIG;
+       msg->header.size = payload_size;
+       msg->payload.config.offset = 0;
+       msg->payload.config.size = cfg_size;
+
+       rc = vhost_user_send(vu_dev, true, msg, NULL, 0);
+       if (rc) {
+               vu_err(vu_dev, "sending VHOST_USER_GET_CONFIG failed: %d\n",
+                      rc);
+               goto free;
+       }
+
+       rc = vhost_user_recv_resp(vu_dev, msg, msg_size);
+       if (rc) {
+               vu_err(vu_dev,
+                      "receiving VHOST_USER_GET_CONFIG response failed: %d\n",
+                      rc);
+               goto free;
+       }
+
+       if (msg->header.size != payload_size ||
+           msg->payload.config.size != cfg_size) {
+               rc = -EPROTO;
+               vu_err(vu_dev,
+                      "Invalid VHOST_USER_GET_CONFIG sizes (payload %d expected %zu, config %u expected %u)\n",
+                      msg->header.size, payload_size,
+                      msg->payload.config.size, cfg_size);
+               goto free;
+       }
+       memcpy(buf, msg->payload.config.payload + offset, len);
+
+free:
+       kfree(msg);
+}
+
+static void vhost_user_set_config(struct virtio_uml_device *vu_dev,
+                                 u32 offset, const void *buf, u32 len)
+{
+       struct vhost_user_msg *msg;
+       size_t payload_size = sizeof(msg->payload.config) + len;
+       size_t msg_size = sizeof(msg->header) + payload_size;
+       int rc;
+
+       if (!(vu_dev->protocol_features &
+             BIT_ULL(VHOST_USER_PROTOCOL_F_CONFIG)))
+               return;
+
+       msg = kzalloc(msg_size, GFP_KERNEL);
+       if (!msg)
+               return;
+       msg->header.request = VHOST_USER_SET_CONFIG;
+       msg->header.size = payload_size;
+       msg->payload.config.offset = offset;
+       msg->payload.config.size = len;
+       memcpy(msg->payload.config.payload, buf, len);
+
+       rc = vhost_user_send(vu_dev, false, msg, NULL, 0);
+       if (rc)
+               vu_err(vu_dev, "sending VHOST_USER_SET_CONFIG failed: %d\n",
+                      rc);
+
+       kfree(msg);
+}
+
+static int vhost_user_init_mem_region(u64 addr, u64 size, int *fd_out,
+                                     struct vhost_user_mem_region *region_out)
+{
+       unsigned long long mem_offset;
+       int rc = phys_mapping(addr, &mem_offset);
+
+       if (WARN(rc < 0, "phys_mapping of 0x%llx returned %d\n", addr, rc))
+               return -EFAULT;
+       *fd_out = rc;
+       region_out->guest_addr = addr;
+       region_out->user_addr = addr;
+       region_out->size = size;
+       region_out->mmap_offset = mem_offset;
+
+       /* Ensure mapping is valid for the entire region */
+       rc = phys_mapping(addr + size - 1, &mem_offset);
+       if (WARN(rc != *fd_out, "phys_mapping of 0x%llx failed: %d != %d\n",
+                addr + size - 1, rc, *fd_out))
+               return -EFAULT;
+       return 0;
+}
+
+static int vhost_user_set_mem_table(struct virtio_uml_device *vu_dev)
+{
+       struct vhost_user_msg msg = {
+               .header.request = VHOST_USER_SET_MEM_TABLE,
+               .header.size = sizeof(msg.payload.mem_regions),
+               .payload.mem_regions.num = 1,
+       };
+       unsigned long reserved = uml_reserved - uml_physmem;
+       int fds[2];
+       int rc;
+
+       /*
+        * This is a bit tricky, see also the comment with setup_physmem().
+        *
+        * Essentially, setup_physmem() uses a file to mmap() our physmem,
+        * but the code and data we *already* have is omitted. To us, this
+        * is no difference, since they both become part of our address
+        * space and memory consumption. To somebody looking in from the
+        * outside, however, it is different because the part of our memory
+        * consumption that's already part of the binary (code/data) is not
+        * mapped from the file, so it's not visible to another mmap from
+        * the file descriptor.
+        *
+        * Thus, don't advertise this space to the vhost-user slave. This
+        * means that the slave will likely abort or similar when we give
+        * it an address from the hidden range, since it's not marked as
+        * a valid address, but at least that way we detect the issue and
+        * don't just have the slave read an all-zeroes buffer from the
+        * shared memory file, or write something there that we can never
+        * see (depending on the direction of the virtqueue traffic.)
+        *
+        * Since we usually don't want to use .text for virtio buffers,
+        * this effectively means that you cannot use
+        *  1) global variables, which are in the .bss and not in the shm
+        *     file-backed memory
+        *  2) the stack in some processes, depending on where they have
+        *     their stack (or maybe only no interrupt stack?)
+        *
+        * The stack is already not typically valid for DMA, so this isn't
+        * much of a restriction, but global variables might be encountered.
+        *
+        * It might be possible to fix it by copying around the data that's
+        * between bss_start and where we map the file now, but it's not
+        * something that you typically encounter with virtio drivers, so
+        * it didn't seem worthwhile.
+        */
+       rc = vhost_user_init_mem_region(reserved, physmem_size - reserved,
+                                       &fds[0],
+                                       &msg.payload.mem_regions.regions[0]);
+
+       if (rc < 0)
+               return rc;
+       if (highmem) {
+               msg.payload.mem_regions.num++;
+               rc = vhost_user_init_mem_region(__pa(end_iomem), highmem,
+                               &fds[1], &msg.payload.mem_regions.regions[1]);
+               if (rc < 0)
+                       return rc;
+       }
+
+       return vhost_user_send(vu_dev, false, &msg, fds,
+                              msg.payload.mem_regions.num);
+}
+
+static int vhost_user_set_vring_state(struct virtio_uml_device *vu_dev,
+                                     u32 request, u32 index, u32 num)
+{
+       struct vhost_user_msg msg = {
+               .header.request = request,
+               .header.size = sizeof(msg.payload.vring_state),
+               .payload.vring_state.index = index,
+               .payload.vring_state.num = num,
+       };
+
+       return vhost_user_send(vu_dev, false, &msg, NULL, 0);
+}
+
+static int vhost_user_set_vring_num(struct virtio_uml_device *vu_dev,
+                                   u32 index, u32 num)
+{
+       return vhost_user_set_vring_state(vu_dev, VHOST_USER_SET_VRING_NUM,
+                                         index, num);
+}
+
+static int vhost_user_set_vring_base(struct virtio_uml_device *vu_dev,
+                                    u32 index, u32 offset)
+{
+       return vhost_user_set_vring_state(vu_dev, VHOST_USER_SET_VRING_BASE,
+                                         index, offset);
+}
+
+static int vhost_user_set_vring_addr(struct virtio_uml_device *vu_dev,
+                                    u32 index, u64 desc, u64 used, u64 avail,
+                                    u64 log)
+{
+       struct vhost_user_msg msg = {
+               .header.request = VHOST_USER_SET_VRING_ADDR,
+               .header.size = sizeof(msg.payload.vring_addr),
+               .payload.vring_addr.index = index,
+               .payload.vring_addr.desc = desc,
+               .payload.vring_addr.used = used,
+               .payload.vring_addr.avail = avail,
+               .payload.vring_addr.log = log,
+       };
+
+       return vhost_user_send(vu_dev, false, &msg, NULL, 0);
+}
+
+static int vhost_user_set_vring_fd(struct virtio_uml_device *vu_dev,
+                                  u32 request, int index, int fd)
+{
+       struct vhost_user_msg msg = {
+               .header.request = request,
+               .header.size = sizeof(msg.payload.integer),
+               .payload.integer = index,
+       };
+
+       if (index & ~VHOST_USER_VRING_INDEX_MASK)
+               return -EINVAL;
+       if (fd < 0) {
+               msg.payload.integer |= VHOST_USER_VRING_POLL_MASK;
+               return vhost_user_send(vu_dev, false, &msg, NULL, 0);
+       }
+       return vhost_user_send(vu_dev, false, &msg, &fd, 1);
+}
+
+static int vhost_user_set_vring_call(struct virtio_uml_device *vu_dev,
+                                    int index, int fd)
+{
+       return vhost_user_set_vring_fd(vu_dev, VHOST_USER_SET_VRING_CALL,
+                                      index, fd);
+}
+
+static int vhost_user_set_vring_kick(struct virtio_uml_device *vu_dev,
+                                    int index, int fd)
+{
+       return vhost_user_set_vring_fd(vu_dev, VHOST_USER_SET_VRING_KICK,
+                                      index, fd);
+}
+
+static int vhost_user_set_vring_enable(struct virtio_uml_device *vu_dev,
+                                      u32 index, bool enable)
+{
+       if (!(vu_dev->features & BIT_ULL(VHOST_USER_F_PROTOCOL_FEATURES)))
+               return 0;
+
+       return vhost_user_set_vring_state(vu_dev, VHOST_USER_SET_VRING_ENABLE,
+                                         index, enable);
+}
+
+
+/* Virtio interface */
+
+static bool vu_notify(struct virtqueue *vq)
+{
+       struct virtio_uml_vq_info *info = vq->priv;
+       const uint64_t n = 1;
+       int rc;
+
+       do {
+               rc = os_write_file(info->kick_fd, &n, sizeof(n));
+       } while (rc == -EINTR);
+       return !WARN(rc != sizeof(n), "write returned %d\n", rc);
+}
+
+static irqreturn_t vu_interrupt(int irq, void *opaque)
+{
+       struct virtqueue *vq = opaque;
+       struct virtio_uml_vq_info *info = vq->priv;
+       uint64_t n;
+       int rc;
+       irqreturn_t ret = IRQ_NONE;
+
+       do {
+               rc = os_read_file(info->call_fd, &n, sizeof(n));
+               if (rc == sizeof(n))
+                       ret |= vring_interrupt(irq, vq);
+       } while (rc == sizeof(n) || rc == -EINTR);
+       WARN(rc != -EAGAIN, "read returned %d\n", rc);
+       return ret;
+}
+
+
+static void vu_get(struct virtio_device *vdev, unsigned offset,
+                  void *buf, unsigned len)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+
+       vhost_user_get_config(vu_dev, offset, buf, len);
+}
+
+static void vu_set(struct virtio_device *vdev, unsigned offset,
+                  const void *buf, unsigned len)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+
+       vhost_user_set_config(vu_dev, offset, buf, len);
+}
+
+static u8 vu_get_status(struct virtio_device *vdev)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+
+       return vu_dev->status;
+}
+
+static void vu_set_status(struct virtio_device *vdev, u8 status)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+
+       vu_dev->status = status;
+}
+
+static void vu_reset(struct virtio_device *vdev)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+
+       vu_dev->status = 0;
+}
+
+static void vu_del_vq(struct virtqueue *vq)
+{
+       struct virtio_uml_vq_info *info = vq->priv;
+
+       um_free_irq(VIRTIO_IRQ, vq);
+
+       os_close_file(info->call_fd);
+       os_close_file(info->kick_fd);
+
+       vring_del_virtqueue(vq);
+       kfree(info);
+}
+
+static void vu_del_vqs(struct virtio_device *vdev)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+       struct virtqueue *vq, *n;
+       u64 features;
+
+       /* Note: reverse order as a workaround to a decoding bug in snabb */
+       list_for_each_entry_reverse(vq, &vdev->vqs, list)
+               WARN_ON(vhost_user_set_vring_enable(vu_dev, vq->index, false));
+
+       /* Ensure previous messages have been processed */
+       WARN_ON(vhost_user_get_features(vu_dev, &features));
+
+       list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+               vu_del_vq(vq);
+}
+
+static int vu_setup_vq_call_fd(struct virtio_uml_device *vu_dev,
+                              struct virtqueue *vq)
+{
+       struct virtio_uml_vq_info *info = vq->priv;
+       int call_fds[2];
+       int rc;
+
+       /* Use a pipe for call fd, since SIGIO is not supported for eventfd */
+       rc = os_pipe(call_fds, true, true);
+       if (rc < 0)
+               return rc;
+
+       info->call_fd = call_fds[0];
+       rc = um_request_irq(VIRTIO_IRQ, info->call_fd, IRQ_READ,
+                           vu_interrupt, IRQF_SHARED, info->name, vq);
+       if (rc)
+               goto close_both;
+
+       rc = vhost_user_set_vring_call(vu_dev, vq->index, call_fds[1]);
+       if (rc)
+               goto release_irq;
+
+       goto out;
+
+release_irq:
+       um_free_irq(VIRTIO_IRQ, vq);
+close_both:
+       os_close_file(call_fds[0]);
+out:
+       /* Close (unused) write end of call fds */
+       os_close_file(call_fds[1]);
+
+       return rc;
+}
+
+static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
+                                    unsigned index, vq_callback_t *callback,
+                                    const char *name, bool ctx)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+       struct platform_device *pdev = vu_dev->pdev;
+       struct virtio_uml_vq_info *info;
+       struct virtqueue *vq;
+       int num = MAX_SUPPORTED_QUEUE_SIZE;
+       int rc;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               rc = -ENOMEM;
+               goto error_kzalloc;
+       }
+       snprintf(info->name, sizeof(info->name), "%s.%d-%s", pdev->name,
+                pdev->id, name);
+
+       vq = vring_create_virtqueue(index, num, PAGE_SIZE, vdev, true, true,
+                                   ctx, vu_notify, callback, info->name);
+       if (!vq) {
+               rc = -ENOMEM;
+               goto error_create;
+       }
+       vq->priv = info;
+       num = virtqueue_get_vring_size(vq);
+
+       rc = os_eventfd(0, 0);
+       if (rc < 0)
+               goto error_kick;
+       info->kick_fd = rc;
+
+       rc = vu_setup_vq_call_fd(vu_dev, vq);
+       if (rc)
+               goto error_call;
+
+       rc = vhost_user_set_vring_num(vu_dev, index, num);
+       if (rc)
+               goto error_setup;
+
+       rc = vhost_user_set_vring_base(vu_dev, index, 0);
+       if (rc)
+               goto error_setup;
+
+       rc = vhost_user_set_vring_addr(vu_dev, index,
+                                      virtqueue_get_desc_addr(vq),
+                                      virtqueue_get_used_addr(vq),
+                                      virtqueue_get_avail_addr(vq),
+                                      (u64) -1);
+       if (rc)
+               goto error_setup;
+
+       return vq;
+
+error_setup:
+       um_free_irq(VIRTIO_IRQ, vq);
+       os_close_file(info->call_fd);
+error_call:
+       os_close_file(info->kick_fd);
+error_kick:
+       vring_del_virtqueue(vq);
+error_create:
+       kfree(info);
+error_kzalloc:
+       return ERR_PTR(rc);
+}
+
+static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+                      struct virtqueue *vqs[], vq_callback_t *callbacks[],
+                      const char * const names[], const bool *ctx,
+                      struct irq_affinity *desc)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+       int i, queue_idx = 0, rc;
+       struct virtqueue *vq;
+
+       rc = vhost_user_set_mem_table(vu_dev);
+       if (rc)
+               return rc;
+
+       for (i = 0; i < nvqs; ++i) {
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = vu_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
+                                    ctx ? ctx[i] : false);
+               if (IS_ERR(vqs[i])) {
+                       rc = PTR_ERR(vqs[i]);
+                       goto error_setup;
+               }
+       }
+
+       list_for_each_entry(vq, &vdev->vqs, list) {
+               struct virtio_uml_vq_info *info = vq->priv;
+
+               rc = vhost_user_set_vring_kick(vu_dev, vq->index,
+                                              info->kick_fd);
+               if (rc)
+                       goto error_setup;
+
+               rc = vhost_user_set_vring_enable(vu_dev, vq->index, true);
+               if (rc)
+                       goto error_setup;
+       }
+
+       return 0;
+
+error_setup:
+       vu_del_vqs(vdev);
+       return rc;
+}
+
+static u64 vu_get_features(struct virtio_device *vdev)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+
+       return vu_dev->features;
+}
+
+static int vu_finalize_features(struct virtio_device *vdev)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+       u64 supported = vdev->features & VHOST_USER_SUPPORTED_F;
+
+       vring_transport_features(vdev);
+       vu_dev->features = vdev->features | supported;
+
+       return vhost_user_set_features(vu_dev, vu_dev->features);
+}
+
+static const char *vu_bus_name(struct virtio_device *vdev)
+{
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+
+       return vu_dev->pdev->name;
+}
+
+static const struct virtio_config_ops virtio_uml_config_ops = {
+       .get = vu_get,
+       .set = vu_set,
+       .get_status = vu_get_status,
+       .set_status = vu_set_status,
+       .reset = vu_reset,
+       .find_vqs = vu_find_vqs,
+       .del_vqs = vu_del_vqs,
+       .get_features = vu_get_features,
+       .finalize_features = vu_finalize_features,
+       .bus_name = vu_bus_name,
+};
+
+static void virtio_uml_release_dev(struct device *d)
+{
+       struct virtio_device *vdev =
+                       container_of(d, struct virtio_device, dev);
+       struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
+
+       /* might not have been opened due to not negotiating the feature */
+       if (vu_dev->req_fd >= 0) {
+               um_free_irq(VIRTIO_IRQ, vu_dev);
+               os_close_file(vu_dev->req_fd);
+       }
+
+       os_close_file(vu_dev->sock);
+}
+
+/* Platform device */
+
+struct virtio_uml_platform_data {
+       u32 virtio_device_id;
+       const char *socket_path;
+};
+
+static int virtio_uml_probe(struct platform_device *pdev)
+{
+       struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
+       struct virtio_uml_device *vu_dev;
+       int rc;
+
+       if (!pdata)
+               return -EINVAL;
+
+       vu_dev = devm_kzalloc(&pdev->dev, sizeof(*vu_dev), GFP_KERNEL);
+       if (!vu_dev)
+               return -ENOMEM;
+
+       vu_dev->vdev.dev.parent = &pdev->dev;
+       vu_dev->vdev.dev.release = virtio_uml_release_dev;
+       vu_dev->vdev.config = &virtio_uml_config_ops;
+       vu_dev->vdev.id.device = pdata->virtio_device_id;
+       vu_dev->vdev.id.vendor = VIRTIO_DEV_ANY_ID;
+       vu_dev->pdev = pdev;
+       vu_dev->req_fd = -1;
+
+       do {
+               rc = os_connect_socket(pdata->socket_path);
+       } while (rc == -EINTR);
+       if (rc < 0)
+               return rc;
+       vu_dev->sock = rc;
+
+       rc = vhost_user_init(vu_dev);
+       if (rc)
+               goto error_init;
+
+       platform_set_drvdata(pdev, vu_dev);
+
+       rc = register_virtio_device(&vu_dev->vdev);
+       if (rc)
+               put_device(&vu_dev->vdev.dev);
+       return rc;
+
+error_init:
+       os_close_file(vu_dev->sock);
+       return rc;
+}
+
+static int virtio_uml_remove(struct platform_device *pdev)
+{
+       struct virtio_uml_device *vu_dev = platform_get_drvdata(pdev);
+
+       unregister_virtio_device(&vu_dev->vdev);
+       return 0;
+}
+
+/* Command line device list */
+
+static void vu_cmdline_release_dev(struct device *d)
+{
+}
+
+static struct device vu_cmdline_parent = {
+       .init_name = "virtio-uml-cmdline",
+       .release = vu_cmdline_release_dev,
+};
+
+static bool vu_cmdline_parent_registered;
+static int vu_cmdline_id;
+
+static int vu_cmdline_set(const char *device, const struct kernel_param *kp)
+{
+       const char *ids = strchr(device, ':');
+       unsigned int virtio_device_id;
+       int processed, consumed, err;
+       char *socket_path;
+       struct virtio_uml_platform_data pdata;
+       struct platform_device *pdev;
+
+       if (!ids || ids == device)
+               return -EINVAL;
+
+       processed = sscanf(ids, ":%u%n:%d%n",
+                          &virtio_device_id, &consumed,
+                          &vu_cmdline_id, &consumed);
+
+       if (processed < 1 || ids[consumed])
+               return -EINVAL;
+
+       if (!vu_cmdline_parent_registered) {
+               err = device_register(&vu_cmdline_parent);
+               if (err) {
+                       pr_err("Failed to register parent device!\n");
+                       put_device(&vu_cmdline_parent);
+                       return err;
+               }
+               vu_cmdline_parent_registered = true;
+       }
+
+       socket_path = kmemdup_nul(device, ids - device, GFP_KERNEL);
+       if (!socket_path)
+               return -ENOMEM;
+
+       pdata.virtio_device_id = (u32) virtio_device_id;
+       pdata.socket_path = socket_path;
+
+       pr_info("Registering device virtio-uml.%d id=%d at %s\n",
+               vu_cmdline_id, virtio_device_id, socket_path);
+
+       pdev = platform_device_register_data(&vu_cmdline_parent, "virtio-uml",
+                                            vu_cmdline_id++, &pdata,
+                                            sizeof(pdata));
+       err = PTR_ERR_OR_ZERO(pdev);
+       if (err)
+               goto free;
+       return 0;
+
+free:
+       kfree(socket_path);
+       return err;
+}
+
+static int vu_cmdline_get_device(struct device *dev, void *data)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
+       char *buffer = data;
+       unsigned int len = strlen(buffer);
+
+       snprintf(buffer + len, PAGE_SIZE - len, "%s:%d:%d\n",
+                pdata->socket_path, pdata->virtio_device_id, pdev->id);
+       return 0;
+}
+
+static int vu_cmdline_get(char *buffer, const struct kernel_param *kp)
+{
+       buffer[0] = '\0';
+       if (vu_cmdline_parent_registered)
+               device_for_each_child(&vu_cmdline_parent, buffer,
+                                     vu_cmdline_get_device);
+       return strlen(buffer) + 1;
+}
+
+static const struct kernel_param_ops vu_cmdline_param_ops = {
+       .set = vu_cmdline_set,
+       .get = vu_cmdline_get,
+};
+
+device_param_cb(device, &vu_cmdline_param_ops, NULL, S_IRUSR);
+__uml_help(vu_cmdline_param_ops,
+"virtio_uml.device=<socket>:<virtio_id>[:<platform_id>]\n"
+"    Configure a virtio device over a vhost-user socket.\n"
+"    See virtio_ids.h for a list of possible virtio device id values.\n"
+"    Optionally use a specific platform_device id.\n\n"
+);
+
+
+static int vu_unregister_cmdline_device(struct device *dev, void *data)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
+
+       kfree(pdata->socket_path);
+       platform_device_unregister(pdev);
+       return 0;
+}
+
+static void vu_unregister_cmdline_devices(void)
+{
+       if (vu_cmdline_parent_registered) {
+               device_for_each_child(&vu_cmdline_parent, NULL,
+                                     vu_unregister_cmdline_device);
+               device_unregister(&vu_cmdline_parent);
+               vu_cmdline_parent_registered = false;
+       }
+}
+
+/* Platform driver */
+
+static const struct of_device_id virtio_uml_match[] = {
+       { .compatible = "virtio,uml", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, virtio_uml_match);
+
+static struct platform_driver virtio_uml_driver = {
+       .probe = virtio_uml_probe,
+       .remove = virtio_uml_remove,
+       .driver = {
+               .name = "virtio-uml",
+               .of_match_table = virtio_uml_match,
+       },
+};
+
+static int __init virtio_uml_init(void)
+{
+       return platform_driver_register(&virtio_uml_driver);
+}
+
+static void __exit virtio_uml_exit(void)
+{
+       platform_driver_unregister(&virtio_uml_driver);
+       vu_unregister_cmdline_devices();
+}
+
+module_init(virtio_uml_init);
+module_exit(virtio_uml_exit);
+__uml_exitcall(virtio_uml_exit);
+
+MODULE_DESCRIPTION("UML driver for vhost-user virtio devices");
+MODULE_LICENSE("GPL");
index 20e30be44795b2d957402601180dc1684363ae91..fc7f1e74670325a803e2078f839c6f62dbfcc4ec 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stddef.h>
index 56b9c4aba423b0b57b64d049d85cb43260f67e5a..5968da3a6aba992b1846375da35bf6e54ced4bec 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __XTERM_H__
index e8f9957bfbf6bad39a17812298a194f4f39b882e..d64ef6d0d4631f4c1358b77c0c2e29546c49e87d 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /* 
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/slab.h>
index b352ed09260ec6626f0535e0b3383816492ce166..398006d27e40c420c1b7203ce1d8e643bf9c1a68 100644 (file)
@@ -1,5 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-generic-y += barrier.h
 generic-y += bpf_perf_event.h
 generic-y += bug.h
 generic-y += compat.h
index 4049f2c463876205ccd9ff965e03fa111df6489e..d7086b985f27882cbe7b60defc0b7eff168e9f45 100644 (file)
@@ -83,8 +83,8 @@
        __preinit_array_end = .;
   }
   .init_array : {
+        /* dummy - we call this ourselves */
        __init_array_start = .;
-       *(.init_array)
        __init_array_end = .;
   }
   .fini_array : {
index 49ed3e35b35adb1a5b679cfcbfe4f72d2cb97d09..42c6205e2dc43d725af10a5e0d90614aaaea62d7 100644 (file)
 #define TELNETD_IRQ            12
 #define XTERM_IRQ              13
 #define RANDOM_IRQ             14
+#define VIRTIO_IRQ             15
 
 #ifdef CONFIG_UML_NET_VECTOR
 
-#define VECTOR_BASE_IRQ                15
+#define VECTOR_BASE_IRQ                (VIRTIO_IRQ + 1)
 #define VECTOR_IRQ_SPACE       8
 
-#define LAST_IRQ (VECTOR_IRQ_SPACE + VECTOR_BASE_IRQ)
+#define LAST_IRQ (VECTOR_IRQ_SPACE + VECTOR_BASE_IRQ - 1)
 
 #else
 
-#define LAST_IRQ RANDOM_IRQ
+#define LAST_IRQ VIRTIO_IRQ
 
 #endif
 
index cbc6c0013a644521cd1b8c099626f1a1c9284f94..0642ad9035d14bf34c672eb2f4850ca7807cc5ed 100644 (file)
@@ -32,7 +32,6 @@ static inline void arch_local_irq_disable(void)
 }
 
 #define ARCH_IRQ_DISABLED      0
-#define ARCh_IRQ_ENABLED       (SIGIO|SIGVTALRM)
 
 #include <asm-generic/irqflags.h>
 
index 2e0a6b1d83000a15cf4695608e1733ed5f538dcc..b0bd12de1d23cf47b8ae33c20990d0bcc7037ce6 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_KMAP_TYPES_H
index da705448590f2fea52f4f44c913ac1bad54bb123..5b072aba5b658f95ab8b0248f569d1fd1f2cee5b 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __ARCH_UM_MMU_H
index 00cefd33afdd379c5cc727da32ef6bcac26ea265..5aee0626e39042aee45122542120786a25bd725d 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_MMU_CONTEXT_H
index f878bec23576c54c619b633ce0c81508519ddb56..95af12e82a328448ce122a4eb81996d26bd1cb02 100644 (file)
@@ -1,7 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
  * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
  */
 
 #ifndef __UM_PAGE_H
index d7b282e9c4d51deae49b5a71d3af9b15a5c4958b..023599c3fa5122c6fdf2db7e4d3852dfcead0c29 100644 (file)
@@ -1,8 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Copyright 2003 PathScale, Inc.
  * Derived from include/asm-i386/pgalloc.h and include/asm-i386/pgtable.h
- * Licensed under the GPL
  */
 
 #ifndef __UM_PGALLOC_H
index 179c0ea87a0c3b48e93821d2d1158259c0454b1b..32b3d26a71097a48daa3a7f2b9e7df213df008a0 100644 (file)
@@ -1,8 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Copyright 2003 PathScale, Inc.
  * Derived from include/asm-i386/pgtable.h
- * Licensed under the GPL
  */
 
 #ifndef __UM_PGTABLE_2LEVEL_H
index c4d876dfb9acd14bc11ff6b4230bbff5bbe070fe..9812269fefc9f1d07773b3d4014a619ae2392599 100644 (file)
@@ -1,7 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright 2003 PathScale Inc
  * Derived from include/asm-i386/pgtable.h
- * Licensed under the GPL
  */
 
 #ifndef __UM_PGTABLE_3LEVEL_H
index b377df76cc281da4d734d88478f703a05718c40d..e4d3ed980d822c61ee1b7d7f0c2ed247f1b9e785 100644 (file)
@@ -1,8 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Copyright 2003 PathScale, Inc.
  * Derived from include/asm-i386/pgtable.h
- * Licensed under the GPL
  */
 
 #ifndef __UM_PGTABLE_H
index b58b746d3f2ca90b594be73388576aee9f20788f..afd9b267cf81311c9c9af0cb56be0398ad187e49 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_PROCESSOR_GENERIC_H
index 5ab20620fc977e7b1be8b2f5359c7012c89b8225..81c647ef9c6c8df98ae917178318a61647d9391e 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_PTRACE_GENERIC_H
index 4eecd960ee8c17586742b1b11745b056c122167e..4c19ce4c49f18dbc7011e249d056342e3b31c5c9 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_THREAD_INFO_H
index 614f2c0911781aebf9a62d3912272f4b640f99d1..a5bda890390db5f7219336c26017dff1c5543f92 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_TLBFLUSH_H
index cc00fc50768f7d8a10e6037aac6ed01a1d506e56..fe66d659acad06f635a4c5868d8870df94964fe8 100644 (file)
@@ -1,7 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Copyright (C) 2015 Richard Weinberger (richard@nod.at)
- * Licensed under the GPL
  */
 
 #ifndef __UM_UACCESS_H
index 4f46abda060d17ef2621a001b4be6101ea0b20bc..880ee42a3329e3355beff5103077a5b9fc31d471 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __ARCH_H__
index ca1843e1df157b9c40c53cb5a58f50d1f9166c64..5f286ef2721b8f214f67c5514b0e6907cc65485a 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __START_H__
index 53516b6372721395aa179194e8149a5bbd05428b..fd461ee40c0551d5f00d587e78955ad90ea1e59a 100644 (file)
@@ -1,7 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
  * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
- * Licensed under the GPL
  */
 
 #ifndef __ELF_USER_H__
index a5cde5c433b4285d61faa6f01099045f93f421da..ed952ac661caaae971b5d6175e3ec327a5414a9f 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __FRAME_KERN_H_
index e05bd667de152e06038daec8dd86dda7075ed7bb..7cd1a10c6244ceb2b78d26b87ea1224c1631f14f 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __IRQ_KERN_H__
index e7242a0ae48972edf4a05b2d4f265ac5e437e9e2..107751dce1533326939b0a5c30cf45439473dd37 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __IRQ_USER_H__
index 6cd01240bbf098a6e55536c45dc11f1714ad8392..3a9c75a8413c8bec52fe9720b540e5a8d5c9e848 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __KERN_H__
index 35ab97e4bb9b5f79aae8fefacf046e1cca541d24..ccafb62e8ccec32e39c27c617ad64132e145bbcd 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __KERN_UTIL_H__
index b3315c1f198bede97a50bd8d9c9743d261710cd7..85a1cc290ecb93a5dcd4d4f4e037992f697121d5 100644 (file)
@@ -18,7 +18,7 @@ extern void longjmp(jmp_buf, int);
        enable = get_signals(); \
        n = setjmp(*buf); \
        if(n != 0) \
-               set_signals(enable); \
+               set_signals_trace(enable); \
        n; })
 
 #endif
index 5cd40e99e8d5c925ba0f7a983972f5153462a571..4862c91d4213c4f6d1c1e9430ca902e080aae0a2 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __MEM_H__
index 40442b98b17351356b835207376303d1c3be2379..a87be13c5b877dd70c29bd170f900ce698ed0cdf 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2002 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_NET_KERN_H
index 3dabbe128e40b0186538f9b4389a1311f2b738f2..1b0531769a5ebb52b4bfe8d9731f586077aca244 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_NET_USER_H__
index 4a62ac4251a53d4797cf8600c9c18aab6e602992..506bcd1bca68512225405f2aa01e54f5f81a5bc9 100644 (file)
@@ -1,8 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __OS_H__
@@ -36,6 +36,8 @@
 #define OS_LIB_PATH    "/usr/lib/"
 #endif
 
+#define OS_SENDMSG_MAX_FDS 8
+
 /*
  * types taken from stat_file() in hostfs_user.c
  * (if they are wrong here, they are wrong there...).
@@ -176,6 +178,9 @@ extern unsigned os_major(unsigned long long dev);
 extern unsigned os_minor(unsigned long long dev);
 extern unsigned long long os_makedev(unsigned major, unsigned minor);
 extern int os_falloc_punch(int fd, unsigned long long offset, int count);
+extern int os_eventfd(unsigned int initval, int flags);
+extern int os_sendmsg_fds(int fd, const void *buf, unsigned int len,
+                         const int *fds, unsigned int fds_num);
 
 /* start_up.c */
 extern void os_early_checks(void);
@@ -232,6 +237,7 @@ extern void block_signals(void);
 extern void unblock_signals(void);
 extern int get_signals(void);
 extern int set_signals(int enable);
+extern int set_signals_trace(int enable);
 extern int os_is_signal_stack(void);
 extern void deliver_alarm(void);
 
@@ -317,4 +323,10 @@ extern unsigned long os_get_top_address(void);
 
 long syscall(long number, ...);
 
+/* irqflags tracing */
+extern void block_signals_trace(void);
+extern void unblock_signals_trace(void);
+extern void um_trace_signals_on(void);
+extern void um_trace_signals_off(void);
+
 #endif
index 56b2f284b108e91f1e70b8573fffe37176a1a4e1..95455e8996e7252fc44cd2a3576809efb5d209e2 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __PTRACE_USER_H__
index a74449b5b0e314a13eac6b2e51ce9ee2f398b5ff..0c50fa6e8a55b7330f43027c4dea3170e5173d72 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2004 PathScale, Inc
- * Licensed under the GPL
  */
 
 #ifndef __REGISTERS_H
index 434f1a9ae4b354621f01d82eb3965cc8645af989..8fe8f57c05de8a99442934f2816a2686021400e5 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __SIGIO_H__
index 48dd0989ddaa6e8dca1050c079254af46fa3bb3f..4337b4ced095413a83b5b918d611970cb2b2ae35 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __MM_ID_H
index 911f3c45ad1f89bd6686443a87a57c4bcaa882f3..c93d2cbc8f326c825b6162fc5715c7b48a374f3a 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __SKAS_H
index 13f404e1262bd96a61a3bd452d014abf1b44a095..6b01d97a938677f945325e729e911108d2c3311f 100644 (file)
@@ -1,8 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
 
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2005 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #ifndef __STUB_DATA_H
index 9991ec2371e44e21626df7b587f486c18dc4641d..2d2d13c9b46f96246bd06be19a85a610196cc756 100644 (file)
@@ -1,7 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2012 - 2014 Cisco Systems
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __TIMER_INTERNAL_H__
@@ -43,6 +43,11 @@ static inline void time_travel_set_timer_expiry(unsigned long long expiry)
 {
        time_travel_timer_expiry = expiry;
 }
+
+static inline void time_travel_set_timer_interval(unsigned long long interval)
+{
+       time_travel_timer_interval = interval;
+}
 #else
 #define time_travel_mode TT_MODE_OFF
 #define time_travel_time 0
@@ -61,6 +66,10 @@ static inline void time_travel_set_timer_expiry(unsigned long long expiry)
 {
 }
 
+static inline void time_travel_set_timer_interval(unsigned long long interval)
+{
+}
+
 #define time_travel_timer_mode TT_TMR_DISABLED
 #endif
 
index 6395fef6b69b443fcea86e5ddd64dc3a9820d7e0..13da93284c2c7f35cef859c3c79647a58315acd5 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
- * Licensed under the GPL
  */
 
 #ifndef __UM_MALLOC_H__
index 4cff19f6207ac2cafd8d0821baff32f7a94602a1..e793e4212f0a5f80eca76d55dea6cb2f4b94809a 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __USER_H__
index 2f36d515762ecbcaf9507f00b08fa6b955b919f9..5aa882011e041c8f32a6fcfd44e762ad2061730b 100644 (file)
@@ -1,6 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux,intel}.com)
-# Licensed under the GPL
 #
 
 # Don't instrument UML-specific code; without this, we may crash when
@@ -13,7 +13,6 @@ CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START)          \
                         -DELF_FORMAT=$(LDS_ELF_FORMAT) \
                        $(LDS_EXTRA)
 extra-y := vmlinux.lds
-clean-files :=
 
 obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
        physmem.o process.o ptrace.o reboot.o sigio.o \
index 972bf1659564fc640fe630771dc2d82e6af315b5..3ece3c3b31cc16636e84adee6e3efaa3ded91900 100644 (file)
@@ -1,6 +1,6 @@
-/* 
+// SPDX-License-Identifier: GPL-2.0
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index 5568cf88237118dfa6d754926eb6f3128fefbc18..c69d69ee96bebae0c8125dbd2cd9b468398e2710 100644 (file)
@@ -70,6 +70,8 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
+    IRQENTRY_TEXT
+    SOFTIRQENTRY_TEXT
     *(.fixup)
     *(.stub .text.* .gnu.linkonce.t.*)
     /* .gnu.warning sections are handled specially by elf32.em.  */
@@ -101,7 +103,6 @@ SECTIONS
      be empty, which isn't pretty.  */
   . = ALIGN(32 / 8);
   .preinit_array     : { *(.preinit_array) }
-  .init_array     : { *(.init_array) }
   .fini_array     : { *(.fini_array) }
   .data           : {
     INIT_TASK_DATA(KERNEL_STACK_SIZE)
index 783b9247161f3bfa2e684170864345d7e07909cd..e8fd5d540b05de9107320adbd5d670b923f7e6a8 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/stddef.h>
index 546302e3b7fbf0db7fef2faf9e5b77695f312c3e..369fd844e195416a8415fe55cf56404386b53aeb 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/ctype.h>
index f138a4a0db990fc681bec3554b2790578bff9358..9361a8eb9bf1a34af462a3207ab38a5151d59ddd 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/module.h>
index 74ddb44288a30caba1bc0f4a49aa9d402d5850ea..84d536908775794c715d379b852ad5af6698c1fb 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /* 
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/module.h>
index 1dcd310cb34d04417e2696d1bcecf54a3e6031d4..c1981ffb717994787507d6f03e5c97f13ac472db 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/init.h>
index efde1f16c60362b51c43cae660ffdce278e5f47f..3577118bb4a5876e66f33da5b2bf47fc7b6404f9 100644 (file)
@@ -1,8 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2017 - Cambridge Greys Ltd
  * Copyright (C) 2011 - 2014 Cisco Systems Inc
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
  *     Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
  */
@@ -480,7 +480,7 @@ void __init init_IRQ(void)
        irq_set_chip_and_handler(TIMER_IRQ, &SIGVTALRM_irq_type, handle_edge_irq);
 
 
-       for (i = 1; i < LAST_IRQ; i++)
+       for (i = 1; i <= LAST_IRQ; i++)
                irq_set_chip_and_handler(i, &normal_irq_type, handle_edge_irq);
        /* Initialize EPOLL Loop */
        os_setup_epoll();
index 232b22307fdd39dfe1d97f8e749afe97389ac8b6..8ade54a86a7ef5896b3ae3c3f5718ecd9d0286fb 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /* 
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/module.h>
@@ -38,6 +38,8 @@ EXPORT_SYMBOL(run_helper);
 EXPORT_SYMBOL(os_major);
 EXPORT_SYMBOL(os_minor);
 EXPORT_SYMBOL(os_makedev);
+EXPORT_SYMBOL(os_eventfd);
+EXPORT_SYMBOL(os_sendmsg_fds);
 
 EXPORT_SYMBOL(add_sigio_fd);
 EXPORT_SYMBOL(ignore_sigio_fd);
index de58e976b9bcfccd8a1dcf8caf92ad294a07346b..417ff647fb37741a878238a90d22bcb21896aea6 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/stddef.h>
@@ -31,6 +31,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 /* Initialized at boot time, and readonly after that */
 unsigned long long highmem;
+EXPORT_SYMBOL(highmem);
 int kmalloc_ok = 0;
 
 /* Used during early boot */
index 5bf56af4d5b9522f2b1284236a516a39dcd37581..e7c7b53a1435bacc8a118cfc2f7d1499534ed501 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/module.h>
@@ -143,6 +143,7 @@ int phys_mapping(unsigned long phys, unsigned long long *offset_out)
 
        return fd;
 }
+EXPORT_SYMBOL(phys_mapping);
 
 static int __init uml_mem_setup(char *line, int *add)
 {
index 6bede7888fc202f1a268ffcab0f763219a9fba5d..263a8f06913341d1b0a9d013d89f12971e928391 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Copyright 2003 PathScale, Inc.
- * Licensed under the GPL
  */
 
 #include <linux/stddef.h>
@@ -210,15 +210,23 @@ static void time_travel_sleep(unsigned long long duration)
        if (time_travel_mode != TT_MODE_INFCPU)
                os_timer_disable();
 
-       if (time_travel_timer_mode != TT_TMR_DISABLED ||
+       while (time_travel_timer_mode == TT_TMR_PERIODIC &&
+              time_travel_timer_expiry < time_travel_time)
+               time_travel_set_timer_expiry(time_travel_timer_expiry +
+                                            time_travel_timer_interval);
+
+       if (time_travel_timer_mode != TT_TMR_DISABLED &&
            time_travel_timer_expiry < next) {
                if (time_travel_timer_mode == TT_TMR_ONESHOT)
                        time_travel_set_timer_mode(TT_TMR_DISABLED);
                /*
-                * time_travel_time will be adjusted in the timer
-                * IRQ handler so it works even when the signal
-                * comes from the OS timer
+                * In basic mode, time_travel_time will be adjusted in
+                * the timer IRQ handler so it works even when the signal
+                * comes from the OS timer, see there.
                 */
+               if (time_travel_mode != TT_MODE_BASIC)
+                       time_travel_set_time(time_travel_timer_expiry);
+
                deliver_alarm();
        } else {
                time_travel_set_time(next);
index da1e96b1ec3e27ac550d64f33a6214685e08b6f8..b425f47bddbb3f22465efe4534d1fb5104d75ee8 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/audit.h>
index 71f3e9217cf2a7ac0e39619fd7b8c9178e00b5e9..48c0610d506e0c6f636cb8aa54df0f3b381edc0e 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /* 
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/sched/signal.h>
index 3fb6a4041ed6ba4d5791fcddcff08a79cc0ad6cf..10c99e058fcae02df23d5c5f3896e17bbffcbf5f 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
- * Licensed under the GPL
  */
 
 #include <linux/interrupt.h>
index 57acbd67d85dbd4051cd3c534ceff2a300ce9906..3d57c71c532e47a41654d1a2974824f52f4d3ddf 100644 (file)
@@ -1,20 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/module.h>
 #include <linux/ptrace.h>
 #include <linux/sched.h>
+#include <linux/ftrace.h>
 #include <asm/siginfo.h>
 #include <asm/signal.h>
 #include <asm/unistd.h>
 #include <frame_kern.h>
 #include <kern_util.h>
+#include <os.h>
 
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
 
+void block_signals_trace(void)
+{
+       block_signals();
+       if (current_thread_info())
+               trace_hardirqs_off();
+}
+
+void unblock_signals_trace(void)
+{
+       if (current_thread_info())
+               trace_hardirqs_on();
+       unblock_signals();
+}
+
+void um_trace_signals_on(void)
+{
+       if (current_thread_info())
+               trace_hardirqs_on();
+}
+
+void um_trace_signals_off(void)
+{
+       if (current_thread_info())
+               trace_hardirqs_off();
+}
+
 /*
  * OK, we're invoking a handler
  */
index 5bd3edfcfedfda9dbbc6ab86f622142b6533ecb4..f3d494a4fd9ba2a627a6109b692d2e8f423de2a1 100644 (file)
@@ -1,6 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-# Licensed under the GPL
 #
 
 obj-y := clone.o mmu.o process.o syscall.o uaccess.o
index 0f25d41b1031b828912bc9bfaa650096e9985f68..bfb70c456b302ad8a19cde1869768e8c208573bf 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <signal.h>
index 29e7f5f9f18852df86d8c04f2c2cec619ee7da78..b5e3d91fc9c28385023d47519ccc25333de3405a 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/mm.h>
@@ -63,12 +63,12 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
        if (current->mm != NULL && current->mm != &init_mm)
                from_mm = &current->mm->context;
 
-       block_signals();
+       block_signals_trace();
        if (from_mm)
                to_mm->id.u.pid = copy_context_skas0(stack,
                                                     from_mm->id.u.pid);
        else to_mm->id.u.pid = start_userspace(stack);
-       unblock_signals();
+       unblock_signals_trace();
 
        if (to_mm->id.u.pid < 0) {
                ret = to_mm->id.u.pid;
index d4dbf08722d68c6da4cae14a02b3a6372603c8bb..f2ac134c97529c53e2404119c60d02325bda1e3b 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/init.h>
@@ -19,7 +19,7 @@ static int __init start_kernel_proc(void *unused)
 {
        int pid;
 
-       block_signals();
+       block_signals_trace();
        pid = os_getpid();
 
        cpu_tasks[0].pid = pid;
index 44bb107850753378247d67f573d14f39bdb048c9..f574b1856bc6daf46b691f68a08c8720970dde55 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/kernel.h>
index bd3cb694322cb124ee976984232099563a6b0594..3236052f20e67bc09732ac4eed0907ef59921329 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/err.h>
index 35f7047bdebcadb0e692a6d53f3391b5cab2d013..eed54c53fbbb954456879d48b4f20b0afc33258d 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/file.h>
index 234757233355fb1278bac9f98dca9c0bc637ea46..94ea87bd231cb0916b756ac88724a28921b3eff0 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2012-2014 Cisco Systems
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/clockchips.h>
@@ -39,7 +39,15 @@ void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
 {
        unsigned long flags;
 
-       if (time_travel_mode != TT_MODE_OFF)
+       /*
+        * In basic time-travel mode we still get real interrupts
+        * (signals) but since we don't read time from the OS, we
+        * must update the simulated time here to the expiry when
+        * we get a signal.
+        * This is not the case in inf-cpu mode, since there we
+        * never get any real signals from the OS.
+        */
+       if (time_travel_mode == TT_MODE_BASIC)
                time_travel_set_time(time_travel_timer_expiry);
 
        local_irq_save(flags);
@@ -65,6 +73,7 @@ static int itimer_set_periodic(struct clock_event_device *evt)
        if (time_travel_mode != TT_MODE_OFF) {
                time_travel_set_timer_mode(TT_TMR_PERIODIC);
                time_travel_set_timer_expiry(time_travel_time + interval);
+               time_travel_set_timer_interval(interval);
        }
 
        if (time_travel_mode != TT_MODE_INFCPU)
index 45f739bf302f7e622330aa52b734288014b8085e..b7eaf655635cda7f42d4dd9582892a7cc0daa941 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/mm.h>
index 58fe36856182f5cc128d97c11dd84ec2923cf428..e62296c66c95b2e91796ddbc82e967149725bc67 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/mm.h>
index a818ccef30ca2a4a3685c4bc1d89d58ea4922236..0f40eccbd7590850d0dd4bb58e82b6900c9a844d 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/delay.h>
@@ -113,6 +113,7 @@ static int have_root __initdata = 0;
 
 /* Set in uml_mem_setup and modified in linux_main */
 long long physmem_size = 32 * 1024 * 1024;
+EXPORT_SYMBOL(physmem_size);
 
 static const char *usage_string =
 "User Mode Linux v%s\n"
index 10bf4aca529f8940f29e80f0e270491d7bb768e6..8031a038eb5889b35da5582ceceba7688c13f1c9 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <asm/errno.h>
index 36b07ec09742ae088c55affb18874c1ef0f09c6b..9f21443be2c9e73f2fe0fbd089fc927760709d7e 100644 (file)
@@ -31,6 +31,8 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
+    IRQENTRY_TEXT
+    SOFTIRQENTRY_TEXT
     *(.fixup)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
index 455b500afe97b93dacfa3e8fbbef26d1274a9525..839915b8c31c954febc858532a52c98138b024d2 100644 (file)
@@ -1,6 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
 # 
 # Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
-# Licensed under the GPL
 #
 
 # Don't instrument UML-specific code
index 6c546dc9222bb8d3bc15e9afeec488c41a1f3991..d79e75f1b69a2892f4cdf393f38a0b9abb1056a3 100644 (file)
@@ -1,6 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
 # 
 # Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
-# Licensed under the GPL
 #
 
 ethertap-objs := ethertap_kern.o ethertap_user.o
index 54183a679fdd52092306edbe1d8fe064b0d0d6e9..a475259f90e1eb4c5ca0d347e84288000080768c 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __DRIVERS_ETAP_H
index f424600a583f9afa3b42cc0ab2d0ecac16d4dbc5..3182e759d8de62a0c1a29309a4b53707763f5ff8 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Copyright (C) 2001 by various other people who didn't put their name here.
- * Licensed under the GPL.
  */
 
 #include <linux/init.h>
index 6d4918246ffebf21775887f1f1747bd591ba3011..9483021d86dd1b0b1c661a92a2a456e03e908ed8 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
  * James Leu (jleu@mindspring.net).
  * Copyright (C) 2001 by various other people who didn't put their name here.
- * Licensed under the GPL.
  */
 
 #include <stdio.h>
index 7367354ac8df6e548cb1b94eab806e0b8263c452..e364e42abfc55ab6ccf6294e7801e35c1ef98b5a 100644 (file)
@@ -1,6 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /* 
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #ifndef __UM_TUNTAP_H
index d9d56e5810fe179f5f606b36a1d0c9c76a7d5b89..adcb6717be6f463dd745b1754d9335456a7d165a 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <linux/netdevice.h>
index db24ce0d09a6443fc18e7d1a69acc7971ecd11d9..53eb3d508645d72c5b9b5eae9c02d5156a66dd4c 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /* 
  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index f25b110d4e7012712aa358e4d7c744311b6e0ede..5133e3afb96f707f3e71814fb64046e47a2d8bd5 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
@@ -15,6 +15,7 @@
 #include <sys/sysmacros.h>
 #include <sys/un.h>
 #include <sys/types.h>
+#include <sys/eventfd.h>
 #include <os.h>
 
 static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
@@ -620,3 +621,46 @@ int os_falloc_punch(int fd, unsigned long long offset, int len)
        return n;
 }
 
+int os_eventfd(unsigned int initval, int flags)
+{
+       int fd = eventfd(initval, flags);
+
+       if (fd < 0)
+               return -errno;
+       return fd;
+}
+
+int os_sendmsg_fds(int fd, const void *buf, unsigned int len, const int *fds,
+                  unsigned int fds_num)
+{
+       struct iovec iov = {
+               .iov_base = (void *) buf,
+               .iov_len = len,
+       };
+       union {
+               char control[CMSG_SPACE(sizeof(*fds) * OS_SENDMSG_MAX_FDS)];
+               struct cmsghdr align;
+       } u;
+       unsigned int fds_size = sizeof(*fds) * fds_num;
+       struct msghdr msg = {
+               .msg_iov = &iov,
+               .msg_iovlen = 1,
+               .msg_control = u.control,
+               .msg_controllen = CMSG_SPACE(fds_size),
+       };
+       struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+       int err;
+
+       if (fds_num > OS_SENDMSG_MAX_FDS)
+               return -EINVAL;
+       memset(u.control, 0, sizeof(u.control));
+       cmsg->cmsg_level = SOL_SOCKET;
+       cmsg->cmsg_type = SCM_RIGHTS;
+       cmsg->cmsg_len = CMSG_LEN(fds_size);
+       memcpy(CMSG_DATA(cmsg), fds, fds_size);
+       err = sendmsg(fd, &msg, 0);
+
+       if (err < 0)
+               return -errno;
+       return err;
+}
index 3f02d42328127bc6c41b786fd9b10145256cd57f..9fa6e4187d4fb4bcd0d116169a0527c73d020e92 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdlib.h>
index 365823010346a7567c63cde69009488d5d61d54d..d508310ee5e1eda2fa1c37a36a4f0b9585cb410c 100644 (file)
@@ -1,8 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2017 - Cambridge Greys Ltd
  * Copyright (C) 2011 - 2014 Cisco Systems Inc
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdlib.h>
index f1fee2b9123942c117ac1d498027da2f33f004b9..8014dfac644dc50a8f89f4ef7b36b80a3494f648 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
@@ -170,7 +170,7 @@ int __init main(int argc, char **argv, char **envp)
         * that they won't be delivered after the exec, when
         * they are definitely not expected.
         */
-       unblock_signals();
+       unblock_signals_trace();
 
        os_info("\n");
        /* Reboot */
index e162a95ad7ddb46a10ee2b58a0a4e92c7cadac48..3c1b77474d2d1eeb0b1b36c89547d126d1a6e931 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index b3e0d40932e1128031dc192dca7e220891de0c84..e52dd37ddadccc5f07eebea20705db23d6f65ada 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index 2ff8d4fe83c4fd2d202ab5a6e45028f844978d83..2d9270508e1565620e418f0134bf7573474351eb 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2004 PathScale, Inc
  * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <errno.h>
index 46e762f926eb9def51ad29fbc8dc6ac17f7bc485..75558080d0bf58e6640b0c1fcf1913651631a91d 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <unistd.h>
@@ -132,7 +132,7 @@ static void update_thread(void)
        int n;
        char c;
 
-       flags = set_signals(0);
+       flags = set_signals_trace(0);
        CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
        if (n != sizeof(c)) {
                printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
@@ -147,7 +147,7 @@ static void update_thread(void)
                goto fail;
        }
 
-       set_signals(flags);
+       set_signals_trace(flags);
        return;
  fail:
        /* Critical section start */
@@ -161,7 +161,7 @@ static void update_thread(void)
        close(write_sigio_fds[0]);
        close(write_sigio_fds[1]);
        /* Critical section end */
-       set_signals(flags);
+       set_signals_trace(flags);
 }
 
 int add_sigio_fd(int fd)
index 75b10235d3691b45adf78b0e9cf5077903bf0825..b58bc68cbe649606108aad440925cce7f0a372f6 100644 (file)
@@ -1,15 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2004 PathScale, Inc
  * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdlib.h>
 #include <stdarg.h>
 #include <errno.h>
 #include <signal.h>
+#include <string.h>
 #include <strings.h>
 #include <as-layout.h>
 #include <kern_util.h>
@@ -26,7 +27,6 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
        [SIGBUS]        = bus_handler,
        [SIGSEGV]       = segv_handler,
        [SIGIO]         = sigio_handler,
-       [SIGALRM]       = timer_handler
 };
 
 static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
@@ -42,8 +42,8 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
        }
 
        /* enable signals if sig isn't IRQ signal */
-       if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM))
-               unblock_signals();
+       if ((sig != SIGIO) && (sig != SIGWINCH))
+               unblock_signals_trace();
 
        (*sig_info[sig])(sig, si, &r);
 
@@ -76,11 +76,11 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
                return;
        }
 
-       block_signals();
+       block_signals_trace();
 
        sig_handler_common(sig, si, mc);
 
-       set_signals(enabled);
+       set_signals_trace(enabled);
 }
 
 static void timer_real_alarm_handler(mcontext_t *mc)
@@ -89,6 +89,8 @@ static void timer_real_alarm_handler(mcontext_t *mc)
 
        if (mc != NULL)
                get_regs_from_mc(&regs, mc);
+       else
+               memset(&regs, 0, sizeof(regs));
        timer_handler(SIGALRM, NULL, &regs);
 }
 
@@ -102,7 +104,7 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
                return;
        }
 
-       block_signals();
+       block_signals_trace();
 
        signals_active |= SIGALRM_MASK;
 
@@ -110,7 +112,7 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
 
        signals_active &= ~SIGALRM_MASK;
 
-       set_signals(enabled);
+       set_signals_trace(enabled);
 }
 
 void deliver_alarm(void) {
@@ -251,6 +253,8 @@ void unblock_signals(void)
        if (signals_enabled == 1)
                return;
 
+       signals_enabled = 1;
+
        /*
         * We loop because the IRQ handler returns with interrupts off.  So,
         * interrupts may have arrived and we need to re-enable them and
@@ -260,12 +264,9 @@ void unblock_signals(void)
                /*
                 * Save and reset save_pending after enabling signals.  This
                 * way, signals_pending won't be changed while we're reading it.
-                */
-               signals_enabled = 1;
-
-               /*
+                *
                 * Setting signals_enabled and reading signals_pending must
-                * happen in this order.
+                * happen in this order, so have the barrier here.
                 */
                barrier();
 
@@ -278,10 +279,13 @@ void unblock_signals(void)
                /*
                 * We have pending interrupts, so disable signals, as the
                 * handlers expect them off when they are called.  They will
-                * be enabled again above.
+                * be enabled again above. We need to trace this, as we're
+                * expected to be enabling interrupts already, but any more
+                * tracing that happens inside the handlers we call for the
+                * pending signals will mess up the tracing state.
                 */
-
                signals_enabled = 0;
+               um_trace_signals_off();
 
                /*
                 * Deal with SIGIO first because the alarm handler might
@@ -304,6 +308,9 @@ void unblock_signals(void)
                if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
                        return;
 
+               /* Re-enable signals and trace that we're doing so. */
+               um_trace_signals_on();
+               signals_enabled = 1;
        }
 }
 
@@ -326,6 +333,21 @@ int set_signals(int enable)
        return ret;
 }
 
+int set_signals_trace(int enable)
+{
+       int ret;
+       if (signals_enabled == enable)
+               return enable;
+
+       ret = signals_enabled;
+       if (enable)
+               unblock_signals_trace();
+       else
+               block_signals_trace();
+
+       return ret;
+}
+
 int os_is_signal_stack(void)
 {
        stack_t ss;
index d2ea3409e072e9818c3f643aa4b312caf351861d..c4566e78881509e71603b6249253785785d31e1a 100644 (file)
@@ -1,6 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
-# Licensed under the GPL
 #
 
 obj-y := mem.o process.o
index 35015e3e1e878eb83e27400f1dbe569383f28d7a..c546d16f8dfe67bea7ce06f77a9a90e8a3c5e828 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stddef.h>
index df4a985716eba7047cb0873fcea7fb61a57d7a80..4fb877b99ddedc6b4132bf3938bd80a1e2b285b6 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdlib.h>
@@ -425,9 +425,9 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
                        case SIGBUS:
                        case SIGFPE:
                        case SIGWINCH:
-                               block_signals();
+                               block_signals_trace();
                                (*sig_info[sig])(sig, (struct siginfo *)&si, regs);
-                               unblock_signals();
+                               unblock_signals_trace();
                                break;
                        default:
                                printk(UM_KERN_ERR "userspace - child stopped "
@@ -625,10 +625,10 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
        cb_arg = arg;
        cb_back = &here;
 
-       block_signals();
+       block_signals_trace();
        if (UML_SETJMP(&here) == 0)
                UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
-       unblock_signals();
+       unblock_signals_trace();
 
        cb_proc = NULL;
        cb_arg = NULL;
@@ -637,13 +637,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 
 void halt_skas(void)
 {
-       block_signals();
+       block_signals_trace();
        UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
 }
 
 void reboot_skas(void)
 {
-       block_signals();
+       block_signals_trace();
        UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
 }
 
index 82bf5f8442ba4ec963f27a2ab2ad310682c87032..f79dc338279e65e09653e23c1ac7169bf26076ff 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index 6d94ff52362c62cf4d6de3dbb1f309cc62bd7a77..432f8e1f55c2f892ac1a9fe66263aa30638d22e8 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2015 Anton Ivanov (aivanov@{brocade.com,kot-begemot.co.uk})
  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
  * Copyright (C) 2012-2014 Cisco Systems
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stddef.h>
index 721d8afa329b17e5547a59885aec1a054b5e8ab5..f784db83e026311678db5e1fe3da57dd111883d3 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdlib.h>
index e261656fe9d7a9a1a8e19f8975a543a4825dfdbf..44def53a11cd627b00dc5701076b9cb5541ce227 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index 8cc8b2617a670cc3f6ba475c07c21e62f2f37bd4..ecf2f390fad215a0c908812f3222b8bd893c41b4 100644 (file)
@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
- * Licensed under the GPL
  */
 
 #include <stdio.h>
index f31e5d9031617b21df04416feef5aff3f85e9b59..165be7f9a96447bc87138e0e4392d7b33f4868d8 100644 (file)
@@ -2,14 +2,7 @@
 #ifndef _ASM_UM_BARRIER_H_
 #define _ASM_UM_BARRIER_H_
 
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeatures.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
+#include <asm/alternative.h>
 
 /*
  * Force strict CPU ordering.
@@ -30,9 +23,6 @@
 
 #endif /* CONFIG_X86_32 */
 
-#define dma_rmb()      barrier()
-#define dma_wmb()      barrier()
-
 #include <asm-generic/barrier.h>
 
 #endif
index ac9c02b9d92c896ad021c548ff241bdb5b230e2b..891868756a51fed9f22c7f3ddfdc38c8ef4503d4 100644 (file)
@@ -47,7 +47,7 @@ time_t __vdso_time(time_t *t)
 
        return secs;
 }
-int time(time_t *t) __attribute__((weak, alias("__vdso_time")));
+time_t time(time_t *t) __attribute__((weak, alias("__vdso_time")));
 
 long
 __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
index 7020238fd2638d02b6de04f3bf61335a5ef2086d..058ba4e7425007269772195bdfca82e24a1f70cf 100644 (file)
@@ -54,7 +54,6 @@ config CC_DISABLE_WARN_MAYBE_UNINITIALIZED
 
 config CONSTRUCTORS
        bool
-       depends on !UML
 
 config IRQ_WORK
        bool
index 3941a9c48f833b3c9de3ee594a9ff5051d69fc5b..060e8e726755f02ddd18572f6e1279678d184510 100644 (file)
@@ -4,7 +4,7 @@ menu "GCOV-based kernel profiling"
 config GCOV_KERNEL
        bool "Enable gcov-based kernel profiling"
        depends on DEBUG_FS
-       select CONSTRUCTORS if !UML
+       select CONSTRUCTORS
        default n
        ---help---
        This option enables gcov-based code profiling (e.g. for code coverage