summary refs log tree commit diff
path: root/arch/um
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-03-31 16:16:58 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-03-31 16:16:58 -0700
commite8b767f5e04097aaedcd6e06e2270f9fe5282696 (patch)
tree1d8ba4a3bf81ea9ca7a0a3506745eccc9d93b058 /arch/um
parenta87a08e3bf2decaed29c4dfde3916676f9b966a8 (diff)
parent82017457957a550d7d00dde419435dd74a890887 (diff)
downloadlinux-e8b767f5e04097aaedcd6e06e2270f9fe5282696.tar.gz
Merge tag 'for-linus-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
Pull UML updates from Richard Weinberger:

 - Devicetree support (for testing)

 - Various cleanups and fixes: UBD, port_user, uml_mconsole

 - Maintainer update

* tag 'for-linus-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
  um: run_helper: Write error message to kernel log on exec failure on host
  um: port_user: Improve error handling when port-helper is not found
  um: port_user: Allow setting path to port-helper using UML_PORT_HELPER envvar
  um: port_user: Search for in.telnetd in PATH
  um: clang: Strip out -mno-global-merge from USER_CFLAGS
  docs: UML: Mention telnetd for port channel
  um: Remove unused timeval_to_ns() function
  um: Fix uml_mconsole stop/go
  um: Cleanup syscall_handler_t definition/cast, fix warning
  uml: net: vector: fix const issue
  um: Fix WRITE_ZEROES in the UBD Driver
  um: Migrate vector drivers to NAPI
  um: Fix order of dtb unflatten/early init
  um: fix and optimize xor select template for CONFIG64 and timetravel mode
  um: Document dtb command line option
  lib/logic_iomem: correct fallback config references
  um: Remove duplicated include in syscalls_64.c
  MAINTAINERS: Update UserModeLinux entry
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Makefile4
-rw-r--r--arch/um/drivers/mconsole_kern.c3
-rw-r--r--arch/um/drivers/port_user.c18
-rw-r--r--arch/um/drivers/ubd_kern.c8
-rw-r--r--arch/um/drivers/vector_kern.c105
-rw-r--r--arch/um/drivers/vector_kern.h3
-rw-r--r--arch/um/drivers/vector_user.c2
-rw-r--r--arch/um/drivers/vector_user.h2
-rw-r--r--arch/um/include/asm/xor.h4
-rw-r--r--arch/um/include/shared/os.h1
-rw-r--r--arch/um/kernel/dtb.c2
-rw-r--r--arch/um/os-Linux/file.c9
-rw-r--r--arch/um/os-Linux/helper.c5
-rw-r--r--arch/um/os-Linux/time.c6
14 files changed, 102 insertions, 70 deletions
diff --git a/arch/um/Makefile b/arch/um/Makefile
index f2fe63bfd819..320b09cd513c 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -75,6 +75,10 @@ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
 		-D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
 		-idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__
 
+ifdef CONFIG_CC_IS_CLANG
+USER_CFLAGS := $(patsubst -mno-global-merge,,$(USER_CFLAGS))
+endif
+
 #This will adjust *FLAGS accordingly to the platform.
 include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS)
 
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 6ead1e240457..8ca67a692683 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -224,7 +224,7 @@ void mconsole_go(struct mc_request *req)
 
 void mconsole_stop(struct mc_request *req)
 {
-	deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
+	block_signals();
 	os_set_fd_block(req->originating_fd, 1);
 	mconsole_reply(req, "stopped", 0, 0);
 	for (;;) {
@@ -247,6 +247,7 @@ void mconsole_stop(struct mc_request *req)
 	}
 	os_set_fd_block(req->originating_fd, 0);
 	mconsole_reply(req, "", 0, 0);
+	unblock_signals();
 }
 
 static DEFINE_SPINLOCK(mc_devices_lock);
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 5b5b64cb1071..3c62ae81df62 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -5,6 +5,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <errno.h>
 #include <termios.h>
 #include <unistd.h>
@@ -167,14 +168,29 @@ static void port_pre_exec(void *arg)
 int port_connection(int fd, int *socket, int *pid_out)
 {
 	int new, err;
-	char *argv[] = { "/usr/sbin/in.telnetd", "-L",
+	char *env;
+	char *argv[] = { "in.telnetd", "-L",
 			 OS_LIB_PATH "/uml/port-helper", NULL };
 	struct port_pre_exec_data data;
 
+	if ((env = getenv("UML_PORT_HELPER")))
+		argv[2] = env;
+
 	new = accept(fd, NULL, 0);
 	if (new < 0)
 		return -errno;
 
+	err = os_access(argv[2], X_OK);
+	if (err < 0) {
+		printk(UM_KERN_ERR "port_connection : error accessing port-helper "
+		       "executable at %s: %s\n", argv[2], strerror(-err));
+		if (env == NULL)
+			printk(UM_KERN_ERR "Set UML_PORT_HELPER environment "
+				"variable to path to uml-utilities port-helper "
+				"binary\n");
+		goto out_close;
+	}
+
 	err = os_pipe(socket, 0, 0);
 	if (err < 0)
 		goto out_close;
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 69d2d0049a61..b03269faef71 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1526,13 +1526,19 @@ static void do_io(struct io_thread_req *req, struct io_desc *desc)
 			}
 			break;
 		case REQ_OP_DISCARD:
-		case REQ_OP_WRITE_ZEROES:
 			n = os_falloc_punch(req->fds[bit], off, len);
 			if (n) {
 				req->error = map_error(-n);
 				return;
 			}
 			break;
+		case REQ_OP_WRITE_ZEROES:
+			n = os_falloc_zeroes(req->fds[bit], off, len);
+			if (n) {
+				req->error = map_error(-n);
+				return;
+			}
+			break;
 		default:
 			WARN_ON_ONCE(1);
 			req->error = BLK_STS_NOTSUPP;
diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 4fc1a5d70dcf..1d6f6a66766c 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -67,6 +67,7 @@ static LIST_HEAD(vector_devices);
 static int driver_registered;
 
 static void vector_eth_configure(int n, struct arglist *def);
+static int vector_mmsg_rx(struct vector_private *vp, int budget);
 
 /* Argument accessors to set variables (and/or set default values)
  * mtu, buffer sizing, default headroom, etc
@@ -77,7 +78,6 @@ 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];
@@ -458,7 +458,6 @@ static int vector_send(struct vector_queue *qi)
 					vp->estats.tx_queue_running_average =
 						(vp->estats.tx_queue_running_average + result) >> 1;
 				}
-				netif_trans_update(qi->dev);
 				netif_wake_queue(qi->dev);
 				/* if TX is busy, break out of the send loop,
 				 *  poll write IRQ will reschedule xmit for us
@@ -470,8 +469,6 @@ static int vector_send(struct vector_queue *qi)
 			}
 		}
 		spin_unlock(&qi->head_lock);
-	} else {
-		tasklet_schedule(&vp->tx_poll);
 	}
 	return queue_depth;
 }
@@ -608,7 +605,7 @@ out_fail:
 
 /*
  * We do not use the RX queue as a proper wraparound queue for now
- * This is not necessary because the consumption via netif_rx()
+ * This is not necessary because the consumption via napi_gro_receive()
  * happens in-line. While we can try using the return code of
  * netif_rx() for flow control there are no drivers doing this today.
  * For this RX specific use we ignore the tail/head locks and
@@ -896,7 +893,7 @@ static int vector_legacy_rx(struct vector_private *vp)
 			skb->protocol = eth_type_trans(skb, skb->dev);
 			vp->dev->stats.rx_bytes += skb->len;
 			vp->dev->stats.rx_packets++;
-			netif_rx(skb);
+			napi_gro_receive(&vp->napi, skb);
 		} else {
 			dev_kfree_skb_irq(skb);
 		}
@@ -955,7 +952,7 @@ drop:
  * mmsg vector matched to an skb vector which we prepared earlier.
  */
 
-static int vector_mmsg_rx(struct vector_private *vp)
+static int vector_mmsg_rx(struct vector_private *vp, int budget)
 {
 	int packet_count, i;
 	struct vector_queue *qi = vp->rx_queue;
@@ -972,6 +969,9 @@ static int vector_mmsg_rx(struct vector_private *vp)
 
 	/* Fire the Lazy Gun - get as many packets as we can in one go. */
 
+	if (budget > qi->max_depth)
+		budget = qi->max_depth;
+
 	packet_count = uml_vector_recvmmsg(
 		vp->fds->rx_fd, qi->mmsg_vector, qi->max_depth, 0);
 
@@ -1021,7 +1021,7 @@ static int vector_mmsg_rx(struct vector_private *vp)
 			 */
 			vp->dev->stats.rx_bytes += skb->len;
 			vp->dev->stats.rx_packets++;
-			netif_rx(skb);
+			napi_gro_receive(&vp->napi, skb);
 		} else {
 			/* Overlay header too short to do anything - discard.
 			 * We can actually keep this skb and reuse it,
@@ -1044,23 +1044,6 @@ static int vector_mmsg_rx(struct vector_private *vp)
 	return packet_count;
 }
 
-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) && (iter < MAX_ITERATIONS))
-			iter++;
-	else
-		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)
 {
 	struct vector_private *vp = netdev_priv(dev);
@@ -1085,25 +1068,15 @@ static int vector_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	netdev_sent_queue(vp->dev, skb->len);
 	queue_depth = vector_enqueue(vp->tx_queue, skb);
 
-	/* if the device queue is full, stop the upper layers and
-	 * flush it.
-	 */
-
-	if (queue_depth >= vp->tx_queue->max_depth - 1) {
-		vp->estats.tx_kicks++;
-		netif_stop_queue(dev);
-		vector_send(vp->tx_queue);
-		return NETDEV_TX_OK;
-	}
-	if (netdev_xmit_more()) {
+	if (queue_depth < vp->tx_queue->max_depth && netdev_xmit_more()) {
 		mod_timer(&vp->tl, vp->coalesce);
 		return NETDEV_TX_OK;
+	} else {
+		queue_depth = vector_send(vp->tx_queue);
+		if (queue_depth > 0)
+			napi_schedule(&vp->napi);
 	}
-	if (skb->len < TX_SMALL_PACKET) {
-		vp->estats.tx_kicks++;
-		vector_send(vp->tx_queue);
-	} else
-		tasklet_schedule(&vp->tx_poll);
+
 	return NETDEV_TX_OK;
 }
 
@@ -1114,7 +1087,7 @@ static irqreturn_t vector_rx_interrupt(int irq, void *dev_id)
 
 	if (!netif_running(dev))
 		return IRQ_NONE;
-	vector_rx(vp);
+	napi_schedule(&vp->napi);
 	return IRQ_HANDLED;
 
 }
@@ -1133,8 +1106,7 @@ static irqreturn_t vector_tx_interrupt(int irq, void *dev_id)
 	 * tweaking the IRQ mask less costly
 	 */
 
-	if (vp->in_write_poll)
-		tasklet_schedule(&vp->tx_poll);
+	napi_schedule(&vp->napi);
 	return IRQ_HANDLED;
 
 }
@@ -1161,7 +1133,8 @@ static int vector_net_close(struct net_device *dev)
 		um_free_irq(vp->tx_irq, dev);
 		vp->tx_irq = 0;
 	}
-	tasklet_kill(&vp->tx_poll);
+	napi_disable(&vp->napi);
+	netif_napi_del(&vp->napi);
 	if (vp->fds->rx_fd > 0) {
 		if (vp->bpf)
 			uml_vector_detach_bpf(vp->fds->rx_fd, vp->bpf);
@@ -1193,15 +1166,32 @@ static int vector_net_close(struct net_device *dev)
 	return 0;
 }
 
-/* TX tasklet */
-
-static void vector_tx_poll(struct tasklet_struct *t)
+static int vector_poll(struct napi_struct *napi, int budget)
 {
-	struct vector_private *vp = from_tasklet(vp, t, tx_poll);
+	struct vector_private *vp = container_of(napi, struct vector_private, napi);
+	int work_done = 0;
+	int err;
+	bool tx_enqueued = false;
 
-	vp->estats.tx_kicks++;
-	vector_send(vp->tx_queue);
+	if ((vp->options & VECTOR_TX) != 0)
+		tx_enqueued = (vector_send(vp->tx_queue) > 0);
+	if ((vp->options & VECTOR_RX) > 0)
+		err = vector_mmsg_rx(vp, budget);
+	else {
+		err = vector_legacy_rx(vp);
+		if (err > 0)
+			err = 1;
+	}
+	if (err > 0)
+		work_done += err;
+
+	if (tx_enqueued || err > 0)
+		napi_schedule(napi);
+	if (work_done < budget)
+		napi_complete_done(napi, work_done);
+	return work_done;
 }
+
 static void vector_reset_tx(struct work_struct *work)
 {
 	struct vector_private *vp =
@@ -1265,6 +1255,9 @@ static int vector_net_open(struct net_device *dev)
 			goto out_close;
 	}
 
+	netif_napi_add(vp->dev, &vp->napi, vector_poll, get_depth(vp->parsed));
+	napi_enable(&vp->napi);
+
 	/* READ IRQ */
 	err = um_request_irq(
 		irq_rr + VECTOR_BASE_IRQ, vp->fds->rx_fd,
@@ -1306,15 +1299,15 @@ static int vector_net_open(struct net_device *dev)
 		uml_vector_attach_bpf(vp->fds->rx_fd, vp->bpf);
 
 	netif_start_queue(dev);
+	vector_reset_stats(vp);
 
 	/* clear buffer - it can happen that the host side of the interface
 	 * is full when we get here. In this case, new data is never queued,
 	 * SIGIOs never arrive, and the net never works.
 	 */
 
-	vector_rx(vp);
+	napi_schedule(&vp->napi);
 
-	vector_reset_stats(vp);
 	vdevice = find_device(vp->unit);
 	vdevice->opened = 1;
 
@@ -1543,15 +1536,16 @@ static const struct net_device_ops vector_netdev_ops = {
 #endif
 };
 
-
 static void vector_timer_expire(struct timer_list *t)
 {
 	struct vector_private *vp = from_timer(vp, t, tl);
 
 	vp->estats.tx_kicks++;
-	vector_send(vp->tx_queue);
+	napi_schedule(&vp->napi);
 }
 
+
+
 static void vector_eth_configure(
 		int n,
 		struct arglist *def
@@ -1634,7 +1628,6 @@ static void vector_eth_configure(
 	});
 
 	dev->features = dev->hw_features = (NETIF_F_SG | NETIF_F_FRAGLIST);
-	tasklet_setup(&vp->tx_poll, vector_tx_poll);
 	INIT_WORK(&vp->reset_tx, vector_reset_tx);
 
 	timer_setup(&vp->tl, vector_timer_expire, 0);
diff --git a/arch/um/drivers/vector_kern.h b/arch/um/drivers/vector_kern.h
index 8fff93a75a92..2a1fa8e0f3e1 100644
--- a/arch/um/drivers/vector_kern.h
+++ b/arch/um/drivers/vector_kern.h
@@ -14,6 +14,7 @@
 #include <linux/ctype.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
+
 #include "vector_user.h"
 
 /* Queue structure specially adapted for multiple enqueue/dequeue
@@ -72,6 +73,7 @@ struct vector_private {
 	struct list_head list;
 	spinlock_t lock;
 	struct net_device *dev;
+	struct napi_struct		napi	____cacheline_aligned;
 
 	int unit;
 
@@ -115,7 +117,6 @@ struct vector_private {
 
 	spinlock_t stats_lock;
 
-	struct tasklet_struct tx_poll;
 	bool rexmit_scheduled;
 	bool opened;
 	bool in_write_poll;
diff --git a/arch/um/drivers/vector_user.c b/arch/um/drivers/vector_user.c
index e4ffeb9a1fa4..c650e428432b 100644
--- a/arch/um/drivers/vector_user.c
+++ b/arch/um/drivers/vector_user.c
@@ -771,7 +771,7 @@ int uml_vector_detach_bpf(int fd, void *bpf)
 		printk(KERN_ERR BPF_DETACH_FAIL, prog->len, prog->filter, fd, -errno);
 	return err;
 }
-void *uml_vector_default_bpf(void *mac)
+void *uml_vector_default_bpf(const void *mac)
 {
 	struct sock_filter *bpf;
 	uint32_t *mac1 = (uint32_t *)(mac + 2);
diff --git a/arch/um/drivers/vector_user.h b/arch/um/drivers/vector_user.h
index d29d5fdd98fa..3a73d17a0161 100644
--- a/arch/um/drivers/vector_user.h
+++ b/arch/um/drivers/vector_user.h
@@ -97,7 +97,7 @@ extern int uml_vector_recvmmsg(
 	unsigned int vlen,
 	unsigned int flags
 );
-extern void *uml_vector_default_bpf(void *mac);
+extern void *uml_vector_default_bpf(const void *mac);
 extern void *uml_vector_user_bpf(char *filename);
 extern int uml_vector_attach_bpf(int fd, void *bpf);
 extern int uml_vector_detach_bpf(int fd, void *bpf);
diff --git a/arch/um/include/asm/xor.h b/arch/um/include/asm/xor.h
index f512704a9ec7..22b39de73c24 100644
--- a/arch/um/include/asm/xor.h
+++ b/arch/um/include/asm/xor.h
@@ -4,8 +4,10 @@
 
 #ifdef CONFIG_64BIT
 #undef CONFIG_X86_32
+#define TT_CPU_INF_XOR_DEFAULT (AVX_SELECT(&xor_block_sse_pf64))
 #else
 #define CONFIG_X86_32 1
+#define TT_CPU_INF_XOR_DEFAULT (AVX_SELECT(&xor_block_8regs))
 #endif
 
 #include <asm/cpufeature.h>
@@ -16,7 +18,7 @@
 #undef XOR_SELECT_TEMPLATE
 /* pick an arbitrary one - measuring isn't possible with inf-cpu */
 #define XOR_SELECT_TEMPLATE(x)	\
-	(time_travel_mode == TT_MODE_INFCPU ? &xor_block_8regs : NULL)
+	(time_travel_mode == TT_MODE_INFCPU ? TT_CPU_INF_XOR_DEFAULT : x))
 #endif
 
 #endif
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 00214059d9ec..fafde1d5416e 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -168,6 +168,7 @@ 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_falloc_zeroes(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);
diff --git a/arch/um/kernel/dtb.c b/arch/um/kernel/dtb.c
index ca69d72025f3..484141b06938 100644
--- a/arch/um/kernel/dtb.c
+++ b/arch/um/kernel/dtb.c
@@ -25,8 +25,8 @@ void uml_dtb_init(void)
 		return;
 	}
 
-	unflatten_device_tree();
 	early_init_fdt_scan_reserved_mem();
+	unflatten_device_tree();
 }
 
 static int __init uml_dtb_setup(char *line, int *add)
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index e4421dbc4c36..fc4450db59bd 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -625,6 +625,15 @@ int os_falloc_punch(int fd, unsigned long long offset, int len)
 	return n;
 }
 
+int os_falloc_zeroes(int fd, unsigned long long offset, int len)
+{
+	int n = fallocate(fd, FALLOC_FL_ZERO_RANGE|FALLOC_FL_KEEP_SIZE, offset, len);
+
+	if (n < 0)
+		return -errno;
+	return n;
+}
+
 int os_eventfd(unsigned int initval, int flags)
 {
 	int fd = eventfd(initval, flags);
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 32e88baf18dd..b459745f52e2 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -4,6 +4,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <errno.h>
 #include <sched.h>
@@ -99,6 +100,10 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
 		CATCH_EINTR(waitpid(pid, NULL, __WALL));
 	}
 
+	if (ret < 0)
+		printk(UM_KERN_ERR "run_helper : failed to exec %s on host: %s\n",
+		       argv[0], strerror(-ret));
+
 out_free2:
 	kfree(data.buf);
 out_close:
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 6c5041c5560b..4d5591d96d8c 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -18,12 +18,6 @@
 
 static timer_t event_high_res_timer = 0;
 
-static inline long long timeval_to_ns(const struct timeval *tv)
-{
-	return ((long long) tv->tv_sec * UM_NSEC_PER_SEC) +
-		tv->tv_usec * UM_NSEC_PER_USEC;
-}
-
 static inline long long timespec_to_ns(const struct timespec *ts)
 {
 	return ((long long) ts->tv_sec * UM_NSEC_PER_SEC) + ts->tv_nsec;