Commit 12cc5240 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'uml-for-linus-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux

Pull UML updates from Richard Weinberger:

 - Removal of dead code (TT mode leftovers, etc)

 - Fixes for the network vector driver

 - Fixes for time-travel mode

* tag 'uml-for-linus-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/uml/linux:
  um: fix time-travel syscall scheduling hack
  um: Remove outdated asm/sysrq.h header
  um: Remove the declaration of user_thread function
  um: Remove the call to SUBARCH_EXECVE1 macro
  um: Remove unused mm_fd field from mm_id
  um: Remove unused fields from thread_struct
  um: Remove the redundant newpage check in update_pte_range
  um: Remove unused kpte_clear_flush macro
  um: Remove obsoleted declaration for execute_syscall_skas
  user_mode_linux_howto_v2: add VDE vector support in doc
  vector_user: add VDE support
  um: remove ARCH_NO_PREEMPT_DYNAMIC
  um: vector: Fix NAPI budget handling
  um: vector: Replace locks guarding queue depth with atomics
  um: remove variable stack array in os_rcv_fd_msg()
parents 0c33037c 381d2f95
......@@ -217,6 +217,8 @@ remote UML and other VM instances.
+-----------+--------+------------------------------------+------------+
| fd | vector | dependent on fd type | varies |
+-----------+--------+------------------------------------+------------+
| vde | vector | dep. on VDE VPN: Virt.Net Locator | varies |
+-----------+--------+------------------------------------+------------+
| tuntap | legacy | none | ~ 500Mbit |
+-----------+--------+------------------------------------+------------+
| daemon | legacy | none | ~ 450Mbit |
......@@ -573,6 +575,41 @@ https://github.com/NetSys/bess/wiki/Built-In-Modules-and-Ports
BESS transport does not require any special privileges.
VDE vector transport
--------------------
Virtual Distributed Ethernet (VDE) is a project whose main goal is to provide a
highly flexible support for virtual networking.
http://wiki.virtualsquare.org/#/tutorials/vdebasics
Common usages of VDE include fast prototyping and teaching.
Examples:
``vecX:transport=vde,vnl=tap://tap0``
use tap0
``vecX:transport=vde,vnl=slirp://``
use slirp
``vec0:transport=vde,vnl=vde:///tmp/switch``
connect to a vde switch
``vecX:transport=\"vde,vnl=cmd://ssh remote.host //tmp/sshlirp\"``
connect to a remote slirp (instant VPN: convert ssh to VPN, it uses sshlirp)
https://github.com/virtualsquare/sshlirp
``vec0:transport=vde,vnl=vxvde://234.0.0.1``
connect to a local area cloud (all the UML nodes using the same
multicast address running on hosts in the same multicast domain (LAN)
will be automagically connected together to a virtual LAN.
Configuring Legacy transports
=============================
......
......@@ -11,7 +11,6 @@ config UML
select ARCH_HAS_KCOV
select ARCH_HAS_STRNCPY_FROM_USER
select ARCH_HAS_STRNLEN_USER
select ARCH_NO_PREEMPT_DYNAMIC
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_KASAN if X86_64
select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
......
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include <linux/ctype.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <asm/atomic.h>
#include "vector_user.h"
......@@ -44,7 +45,8 @@ struct vector_queue {
struct net_device *dev;
spinlock_t head_lock;
spinlock_t tail_lock;
int queue_depth, head, tail, max_depth, max_iov_frags;
atomic_t queue_depth;
int head, tail, max_depth, max_iov_frags;
short options;
};
......
......@@ -46,6 +46,9 @@
#define TRANS_FD "fd"
#define TRANS_FD_LEN strlen(TRANS_FD)
#define TRANS_VDE "vde"
#define TRANS_VDE_LEN strlen(TRANS_VDE)
#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"
......@@ -434,6 +437,84 @@ static struct vector_fds *user_init_fd_fds(struct arglist *ifspec)
return NULL;
}
/* enough char to store an int type */
#define ENOUGH(type) ((CHAR_BIT * sizeof(type) - 1) / 3 + 2)
#define ENOUGH_OCTAL(type) ((CHAR_BIT * sizeof(type) + 2) / 3)
/* vde_plug --descr xx --port2 xx --mod2 xx --group2 xx seqpacket://NN vnl (NULL) */
#define VDE_MAX_ARGC 12
#define VDE_SEQPACKET_HEAD "seqpacket://"
#define VDE_SEQPACKET_HEAD_LEN (sizeof(VDE_SEQPACKET_HEAD) - 1)
#define VDE_DEFAULT_DESCRIPTION "UML"
static struct vector_fds *user_init_vde_fds(struct arglist *ifspec)
{
char seqpacketvnl[VDE_SEQPACKET_HEAD_LEN + ENOUGH(int) + 1];
char *argv[VDE_MAX_ARGC] = {"vde_plug"};
int argc = 1;
int rv;
int sv[2];
struct vector_fds *result = NULL;
char *vnl = uml_vector_fetch_arg(ifspec,"vnl");
char *descr = uml_vector_fetch_arg(ifspec,"descr");
char *port = uml_vector_fetch_arg(ifspec,"port");
char *mode = uml_vector_fetch_arg(ifspec,"mode");
char *group = uml_vector_fetch_arg(ifspec,"group");
if (descr == NULL) descr = VDE_DEFAULT_DESCRIPTION;
argv[argc++] = "--descr";
argv[argc++] = descr;
if (port != NULL) {
argv[argc++] = "--port2";
argv[argc++] = port;
}
if (mode != NULL) {
argv[argc++] = "--mod2";
argv[argc++] = mode;
}
if (group != NULL) {
argv[argc++] = "--group2";
argv[argc++] = group;
}
argv[argc++] = seqpacketvnl;
argv[argc++] = vnl;
argv[argc++] = NULL;
rv = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sv);
if (rv < 0) {
printk(UM_KERN_ERR "vde: seqpacket socketpair err %d", -errno);
return NULL;
}
rv = os_set_exec_close(sv[0]);
if (rv < 0) {
printk(UM_KERN_ERR "vde: seqpacket socketpair cloexec err %d", -errno);
goto vde_cleanup_sv;
}
snprintf(seqpacketvnl, sizeof(seqpacketvnl), VDE_SEQPACKET_HEAD "%d", sv[1]);
run_helper(NULL, NULL, argv);
close(sv[1]);
result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
if (result == NULL) {
printk(UM_KERN_ERR "fd open: allocation failed");
goto vde_cleanup;
}
result->rx_fd = sv[0];
result->tx_fd = sv[0];
result->remote_addr_size = 0;
result->remote_addr = NULL;
return result;
vde_cleanup_sv:
close(sv[1]);
vde_cleanup:
close(sv[0]);
return NULL;
}
static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
{
int rxfd = -1, txfd = -1;
......@@ -673,6 +754,8 @@ struct vector_fds *uml_vector_user_open(
return user_init_unix_fds(parsed, ID_BESS);
if (strncmp(transport, TRANS_FD, TRANS_FD_LEN) == 0)
return user_init_fd_fds(parsed);
if (strncmp(transport, TRANS_VDE, TRANS_VDE_LEN) == 0)
return user_init_vde_fds(parsed);
return NULL;
}
......
......@@ -359,11 +359,4 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
return pte;
}
/* Clear a kernel PTE and flush it from the TLB */
#define kpte_clear_flush(ptep, vaddr) \
do { \
pte_clear(&init_mm, (vaddr), (ptep)); \
__flush_tlb_one((vaddr)); \
} while (0)
#endif
......@@ -28,20 +28,10 @@ struct thread_struct {
struct arch_thread arch;
jmp_buf switch_buf;
struct {
int op;
union {
struct {
int pid;
} fork, exec;
struct {
int (*proc)(void *);
void *arg;
} thread;
struct {
void (*proc)(void *);
void *arg;
} cb;
} u;
struct {
int (*proc)(void *);
void *arg;
} thread;
} request;
};
......@@ -51,7 +41,7 @@ struct thread_struct {
.fault_addr = NULL, \
.prev_sched = NULL, \
.arch = INIT_ARCH_THREAD, \
.request = { 0 } \
.request = { } \
}
/*
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __UM_SYSRQ_H
#define __UM_SYSRQ_H
struct task_struct;
extern void show_trace(struct task_struct* task, unsigned long *stack);
#endif
......@@ -7,10 +7,7 @@
#define __MM_ID_H
struct mm_id {
union {
int mm_fd;
int pid;
} u;
int pid;
unsigned long stack;
int syscall_data_len;
};
......
......@@ -10,10 +10,8 @@
extern int userspace_pid[];
extern int user_thread(unsigned long stack, int flags);
extern void new_thread_handler(void);
extern void handle_syscall(struct uml_pt_regs *regs);
extern long execute_syscall_skas(void *r);
extern unsigned long current_stub_stack(void);
extern struct mm_id *current_mm_id(void);
extern void current_mm_sync(void);
......
......@@ -35,8 +35,5 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp;
clear_thread_flag(TIF_SINGLESTEP);
#ifdef SUBARCH_EXECVE1
SUBARCH_EXECVE1(regs->regs);
#endif
}
EXPORT_SYMBOL(start_thread);
......@@ -109,8 +109,8 @@ void new_thread_handler(void)
schedule_tail(current->thread.prev_sched);
current->thread.prev_sched = NULL;
fn = current->thread.request.u.thread.proc;
arg = current->thread.request.u.thread.arg;
fn = current->thread.request.thread.proc;
arg = current->thread.request.thread.arg;
/*
* callback returns only if the kernel thread execs a process
......@@ -158,8 +158,8 @@ int copy_thread(struct task_struct * p, const struct kernel_clone_args *args)
arch_copy_thread(&current->thread.arch, &p->thread.arch);
} else {
get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
p->thread.request.u.thread.proc = args->fn;
p->thread.request.u.thread.arg = args->fn_arg;
p->thread.request.thread.proc = args->fn;
p->thread.request.thread.arg = args->fn_arg;
handler = new_thread_handler;
}
......
......@@ -29,7 +29,7 @@ static void kill_off_processes(void)
t = find_lock_task_mm(p);
if (!t)
continue;
pid = t->mm->context.id.u.pid;
pid = t->mm->context.id.pid;
task_unlock(t);
os_kill_ptraced_process(pid, 1);
}
......
......@@ -32,11 +32,11 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
new_id->stack = stack;
block_signals_trace();
new_id->u.pid = start_userspace(stack);
new_id->pid = start_userspace(stack);
unblock_signals_trace();
if (new_id->u.pid < 0) {
ret = new_id->u.pid;
if (new_id->pid < 0) {
ret = new_id->pid;
goto out_free;
}
......@@ -83,12 +83,12 @@ void destroy_context(struct mm_struct *mm)
* whole UML suddenly dying. Also, cover negative and
* 1 cases, since they shouldn't happen either.
*/
if (mmu->id.u.pid < 2) {
if (mmu->id.pid < 2) {
printk(KERN_ERR "corrupt mm_context - pid = %d\n",
mmu->id.u.pid);
mmu->id.pid);
return;
}
os_kill_ptraced_process(mmu->id.u.pid, 1);
os_kill_ptraced_process(mmu->id.pid, 1);
free_pages(mmu->id.stack, ilog2(STUB_DATA_PAGES));
}
......@@ -39,8 +39,8 @@ int __init start_uml(void)
init_new_thread_signals();
init_task.thread.request.u.thread.proc = start_kernel_proc;
init_task.thread.request.u.thread.arg = NULL;
init_task.thread.request.thread.proc = start_kernel_proc;
init_task.thread.request.thread.arg = NULL;
return start_idle_thread(task_stack_page(&init_task),
&init_task.thread.switch_buf);
}
......
......@@ -12,23 +12,13 @@
#include <sysdep/syscalls.h>
#include <linux/time-internal.h>
#include <asm/unistd.h>
#include <asm/delay.h>
void handle_syscall(struct uml_pt_regs *r)
{
struct pt_regs *regs = container_of(r, struct pt_regs, regs);
int syscall;
/*
* If we have infinite CPU resources, then make every syscall also a
* preemption point, since we don't have any other preemption in this
* case, and kernel threads would basically never run until userspace
* went to sleep, even if said userspace interacts with the kernel in
* various ways.
*/
if (time_travel_mode == TT_MODE_INFCPU ||
time_travel_mode == TT_MODE_EXTERNAL)
schedule();
/* Initialize the syscall number and default return value. */
UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp);
PT_REGS_SET_SYSCALL_RETURN(regs, -ENOSYS);
......@@ -41,9 +31,25 @@ void handle_syscall(struct uml_pt_regs *r)
goto out;
syscall = UPT_SYSCALL_NR(r);
if (syscall >= 0 && syscall < __NR_syscalls)
PT_REGS_SET_SYSCALL_RETURN(regs,
EXECUTE_SYSCALL(syscall, regs));
if (syscall >= 0 && syscall < __NR_syscalls) {
unsigned long ret = EXECUTE_SYSCALL(syscall, regs);
PT_REGS_SET_SYSCALL_RETURN(regs, ret);
/*
* An error value here can be some form of -ERESTARTSYS
* and then we'd just loop. Make any error syscalls take
* some time, so that it won't just loop if something is
* not ready, and hopefully other things will make some
* progress.
*/
if (IS_ERR_VALUE(ret) &&
(time_travel_mode == TT_MODE_INFCPU ||
time_travel_mode == TT_MODE_EXTERNAL)) {
um_udelay(1);
schedule();
}
}
out:
syscall_trace_leave(regs);
......
......@@ -11,7 +11,6 @@
#include <linux/sched/debug.h>
#include <linux/sched/task_stack.h>
#include <asm/sysrq.h>
#include <asm/stacktrace.h>
#include <os.h>
......
......@@ -839,7 +839,7 @@ static irqreturn_t um_timer(int irq, void *dev)
if (get_current()->mm != NULL)
{
/* userspace - relay signal, results in correct userspace timers */
os_alarm_process(get_current()->mm->context.id.u.pid);
os_alarm_process(get_current()->mm->context.id.pid);
}
(*timer_clockevent.event_handler)(&timer_clockevent);
......
......@@ -82,16 +82,12 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
(x ? UM_PROT_EXEC : 0));
if (pte_newpage(*pte)) {
if (pte_present(*pte)) {
if (pte_newpage(*pte)) {
__u64 offset;
unsigned long phys =
pte_val(*pte) & PAGE_MASK;
int fd = phys_mapping(phys, &offset);
ret = ops->mmap(ops->mm_idp, addr,
PAGE_SIZE, prot, fd,
offset);
}
__u64 offset;
unsigned long phys = pte_val(*pte) & PAGE_MASK;
int fd = phys_mapping(phys, &offset);
ret = ops->mmap(ops->mm_idp, addr, PAGE_SIZE,
prot, fd, offset);
} else
ret = ops->unmap(ops->mm_idp, addr, PAGE_SIZE);
} else if (pte_newprot(*pte))
......
......@@ -528,7 +528,8 @@ int os_shutdown_socket(int fd, int r, int w)
ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds,
void *data, size_t data_len)
{
char buf[CMSG_SPACE(sizeof(*fds) * n_fds)];
#define MAX_RCV_FDS 2
char buf[CMSG_SPACE(sizeof(*fds) * MAX_RCV_FDS)];
struct cmsghdr *cmsg;
struct iovec iov = {
.iov_base = data,
......@@ -538,10 +539,13 @@ ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds,
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = buf,
.msg_controllen = sizeof(buf),
.msg_controllen = CMSG_SPACE(sizeof(*fds) * n_fds),
};
int n;
if (n_fds > MAX_RCV_FDS)
return -EINVAL;
n = recvmsg(fd, &msg, 0);
if (n < 0)
return -errno;
......
......@@ -78,7 +78,7 @@ static inline long do_syscall_stub(struct mm_id *mm_idp)
{
struct stub_data *proc_data = (void *)mm_idp->stack;
int n, i;
int err, pid = mm_idp->u.pid;
int err, pid = mm_idp->pid;
n = ptrace_setregs(pid, syscall_regs);
if (n < 0) {
......
......@@ -588,5 +588,5 @@ void reboot_skas(void)
void __switch_mm(struct mm_id *mm_idp)
{
userspace_pid[0] = mm_idp->u.pid;
userspace_pid[0] = mm_idp->pid;
}
......@@ -9,7 +9,6 @@
#include <linux/sched/debug.h>
#include <linux/kallsyms.h>
#include <asm/ptrace.h>
#include <asm/sysrq.h>
/* This is declared by <linux/sched.h> */
void show_regs(struct pt_regs *regs)
......
......@@ -12,7 +12,6 @@
#include <linux/utsname.h>
#include <asm/current.h>
#include <asm/ptrace.h>
#include <asm/sysrq.h>
void show_regs(struct pt_regs *regs)
{
......
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