Commit e8b767f5 authored by Linus Torvalds's avatar Linus Torvalds

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
parents a87a08e3 82017457
......@@ -1193,6 +1193,26 @@ E.g. ``os_close_file()`` is just a wrapper around ``close()``
which ensures that the userspace function close does not clash
with similarly named function(s) in the kernel part.
Using UML as a Test Platform
============================
UML is an excellent test platform for device driver development. As
with most things UML, "some user assembly may be required". It is
up to the user to build their emulation environment. UML at present
provides only the kernel infrastructure.
Part of this infrastructure is the ability to load and parse fdt
device tree blobs as used in Arm or Open Firmware platforms. These
are supplied as an optional extra argument to the kernel command
line::
dtb=filename
The device tree is loaded and parsed at boottime and is accessible by
drivers which query it. At this moment in time this facility is
intended solely for development purposes. UML's own devices do not
query the device tree.
Security Considerations
-----------------------
......
......@@ -20539,14 +20539,15 @@ F: Documentation/admin-guide/media/zr364xx*
F: drivers/media/usb/zr364xx/
USER-MODE LINUX (UML)
M: Jeff Dike <jdike@addtoit.com>
M: Richard Weinberger <richard@nod.at>
M: Anton Ivanov <anton.ivanov@cambridgegreys.com>
M: Johannes Berg <johannes@sipsolutions.net>
L: linux-um@lists.infradead.org
S: Maintained
W: http://user-mode-linux.sourceforge.net
Q: https://patchwork.ozlabs.org/project/linux-um/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux.git next
T: git git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux.git fixes
F: Documentation/virt/uml/
F: arch/um/
F: arch/x86/um/
......
......@@ -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)
......
......@@ -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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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 @@ static struct vector_queue *create_queue(
/*
* 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 @@ static int writev_tx(struct vector_private *vp, struct sk_buff *skb)
* 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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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
......@@ -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);
......
......@@ -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)
......
......@@ -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);
......
......@@ -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:
......
......@@ -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;
......
......@@ -10,13 +10,12 @@
#include <linux/msg.h>
#include <linux/shm.h>
typedef long syscall_handler_t(void);
typedef long syscall_handler_t(long, long, long, long, long, long);
extern syscall_handler_t *sys_call_table[];
#define EXECUTE_SYSCALL(syscall, regs) \
(((long (*)(long, long, long, long, long, long)) \
(*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
(((*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
UPT_SYSCALL_ARG2(&regs->regs), \
UPT_SYSCALL_ARG3(&regs->regs), \
UPT_SYSCALL_ARG4(&regs->regs), \
......
......@@ -12,7 +12,6 @@
#include <asm/prctl.h> /* XXX This should get the constants from libc */
#include <registers.h>
#include <os.h>
#include <registers.h>
long arch_prctl(struct task_struct *task, int option,
unsigned long __user *arg2)
......
......@@ -68,7 +68,7 @@ int logic_iomem_add_region(struct resource *resource,
}
EXPORT_SYMBOL(logic_iomem_add_region);
#ifndef CONFIG_LOGIC_IOMEM_FALLBACK
#ifndef CONFIG_INDIRECT_IOMEM_FALLBACK
static void __iomem *real_ioremap(phys_addr_t offset, size_t size)
{
WARN(1, "invalid ioremap(0x%llx, 0x%zx)\n",
......@@ -81,7 +81,7 @@ static void real_iounmap(volatile void __iomem *addr)
WARN(1, "invalid iounmap for addr 0x%llx\n",
(unsigned long long)(uintptr_t __force)addr);
}
#endif /* CONFIG_LOGIC_IOMEM_FALLBACK */
#endif /* CONFIG_INDIRECT_IOMEM_FALLBACK */
void __iomem *ioremap(phys_addr_t offset, size_t size)
{
......@@ -168,7 +168,7 @@ void iounmap(volatile void __iomem *addr)
}
EXPORT_SYMBOL(iounmap);
#ifndef CONFIG_LOGIC_IOMEM_FALLBACK
#ifndef CONFIG_INDIRECT_IOMEM_FALLBACK
#define MAKE_FALLBACK(op, sz) \
static u##sz real_raw_read ## op(const volatile void __iomem *addr) \
{ \
......@@ -213,7 +213,7 @@ static void real_memcpy_toio(volatile void __iomem *addr, const void *buffer,
WARN(1, "Invalid memcpy_toio at address 0x%llx\n",
(unsigned long long)(uintptr_t __force)addr);
}
#endif /* CONFIG_LOGIC_IOMEM_FALLBACK */
#endif /* CONFIG_INDIRECT_IOMEM_FALLBACK */
#define MAKE_OP(op, sz) \
u##sz __raw_read ## op(const volatile void __iomem *addr) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment