Skip to content

Commit

Permalink
Merge tag 'for-linus-5.3-rc1' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/rw/uml

Pull UML updates from Richard Weinberger:

 - A new timer mode, time travel, for testing with UML

 - Many bugixes/improvements for the serial line driver

 - Various bugfixes

* tag 'for-linus-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
  um: fix build without CONFIG_UML_TIME_TRAVEL_SUPPORT
  um: Fix kcov crash during startup
  um: configs: Remove useless UEVENT_HELPER_PATH
  um: Support time travel mode
  um: Pass nsecs to os timer functions
  um: Remove drivers/ssl.h
  um: Don't garbage collect in deactivate_all_fds()
  um: Silence lockdep complaint about mmap_sem
  um: Remove locking in deactivate_all_fds()
  um: Timer code cleanup
  um: fix os_timer_one_shot()
  um: Fix IRQ controller regression on console read
  • Loading branch information
torvalds committed Jul 15, 2019
2 parents fcd9814 + b482e48 commit f2772a0
Show file tree
Hide file tree
Showing 15 changed files with 320 additions and 142 deletions.
12 changes: 12 additions & 0 deletions arch/um/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,18 @@ config SECCOMP

If unsure, say Y.

config UML_TIME_TRAVEL_SUPPORT
bool
prompt "Support time-travel mode (e.g. for test execution)"
help
Enable this option to support time travel inside the UML instance.

After enabling this option, two modes are accessible at runtime
(selected by the kernel command line), see the kernel's command-
line help for more details.

It is safe to say Y, but you probably don't need this.

endmenu

source "arch/um/drivers/Kconfig"
1 change: 0 additions & 1 deletion arch/um/configs/i386_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ CONFIG_XTERM_CHAN=y
CONFIG_CON_CHAN="pts"
CONFIG_SSL_CHAN="pts"
CONFIG_UML_SOUND=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_UBD=y
Expand Down
1 change: 0 additions & 1 deletion arch/um/configs/x86_64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ CONFIG_XTERM_CHAN=y
CONFIG_CON_CHAN="pts"
CONFIG_SSL_CHAN="pts"
CONFIG_UML_SOUND=m
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_UBD=y
Expand Down
52 changes: 44 additions & 8 deletions arch/um/drivers/chan_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,19 +171,55 @@ int enable_chan(struct line *line)
return err;
}

/* Items are added in IRQ context, when free_irq can't be called, and
* removed in process context, when it can.
* This handles interrupt sources which disappear, and which need to
* be permanently disabled. This is discovered in IRQ context, but
* the freeing of the IRQ must be done later.
*/
static DEFINE_SPINLOCK(irqs_to_free_lock);
static LIST_HEAD(irqs_to_free);

void free_irqs(void)
{
struct chan *chan;
LIST_HEAD(list);
struct list_head *ele;
unsigned long flags;

spin_lock_irqsave(&irqs_to_free_lock, flags);
list_splice_init(&irqs_to_free, &list);
spin_unlock_irqrestore(&irqs_to_free_lock, flags);

list_for_each(ele, &list) {
chan = list_entry(ele, struct chan, free_list);

if (chan->input && chan->enabled)
um_free_irq(chan->line->driver->read_irq, chan);
if (chan->output && chan->enabled)
um_free_irq(chan->line->driver->write_irq, chan);
chan->enabled = 0;
}
}

static void close_one_chan(struct chan *chan, int delay_free_irq)
{
unsigned long flags;

if (!chan->opened)
return;

/* we can safely call free now - it will be marked
* as free and freed once the IRQ stopped processing
*/
if (chan->input && chan->enabled)
um_free_irq(chan->line->driver->read_irq, chan);
if (chan->output && chan->enabled)
um_free_irq(chan->line->driver->write_irq, chan);
chan->enabled = 0;
if (delay_free_irq) {
spin_lock_irqsave(&irqs_to_free_lock, flags);
list_add(&chan->free_list, &irqs_to_free);
spin_unlock_irqrestore(&irqs_to_free_lock, flags);
} else {
if (chan->input && chan->enabled)
um_free_irq(chan->line->driver->read_irq, chan);
if (chan->output && chan->enabled)
um_free_irq(chan->line->driver->write_irq, chan);
chan->enabled = 0;
}
if (chan->ops->close != NULL)
(*chan->ops->close)(chan->fd, chan->data);

Expand Down
1 change: 0 additions & 1 deletion arch/um/drivers/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include <linux/console.h>
#include <asm/termbits.h>
#include <asm/irq.h>
#include "ssl.h"
#include "chan.h"
#include <init.h>
#include <irq_user.h>
Expand Down
13 changes: 0 additions & 13 deletions arch/um/drivers/ssl.h

This file was deleted.

2 changes: 1 addition & 1 deletion arch/um/include/asm/mmu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
* when the new ->mm is used for the first time.
*/
__switch_mm(&new->context.id);
down_write(&new->mmap_sem);
down_write_nested(&new->mmap_sem, 1);
uml_setup_stubs(new);
up_write(&new->mmap_sem);
}
Expand Down
10 changes: 4 additions & 6 deletions arch/um/include/shared/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,13 @@ extern void os_warn(const char *fmt, ...)

/* time.c */
extern void os_idle_sleep(unsigned long long nsecs);
extern int os_timer_create(void* timer);
extern int os_timer_set_interval(void* timer, void* its);
extern int os_timer_one_shot(int ticks);
extern long long os_timer_disable(void);
extern long os_timer_remain(void* timer);
extern int os_timer_create(void);
extern int os_timer_set_interval(unsigned long long nsecs);
extern int os_timer_one_shot(unsigned long long nsecs);
extern void os_timer_disable(void);
extern void uml_idle_timer(void);
extern long long os_persistent_clock_emulation(void);
extern long long os_nsecs(void);
extern long long os_vnsecs(void);

/* skas/mem.c */
extern long run_syscall_stub(struct mm_id * mm_idp,
Expand Down
48 changes: 48 additions & 0 deletions arch/um/include/shared/timer-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,52 @@
#define TIMER_MULTIPLIER 256
#define TIMER_MIN_DELTA 500

enum time_travel_mode {
TT_MODE_OFF,
TT_MODE_BASIC,
TT_MODE_INFCPU,
};

enum time_travel_timer_mode {
TT_TMR_DISABLED,
TT_TMR_ONESHOT,
TT_TMR_PERIODIC,
};

#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
extern enum time_travel_mode time_travel_mode;
extern unsigned long long time_travel_time;
extern enum time_travel_timer_mode time_travel_timer_mode;
extern unsigned long long time_travel_timer_expiry;
extern unsigned long long time_travel_timer_interval;

static inline void time_travel_set_time(unsigned long long ns)
{
time_travel_time = ns;
}

static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
unsigned long long expiry)
{
time_travel_timer_mode = mode;
time_travel_timer_expiry = expiry;
}
#else
#define time_travel_mode TT_MODE_OFF
#define time_travel_time 0
#define time_travel_timer_expiry 0
#define time_travel_timer_interval 0

static inline void time_travel_set_time(unsigned long long ns)
{
}

static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
unsigned long long expiry)
{
}

#define time_travel_timer_mode TT_TMR_DISABLED
#endif

#endif
9 changes: 5 additions & 4 deletions arch/um/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <irq_user.h>


extern void free_irqs(void);

/* When epoll triggers we do not know why it did so
* we can also have different IRQs for read and write.
* This is why we keep a small irq_fd array for each fd -
Expand Down Expand Up @@ -100,6 +102,8 @@ void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
}
}
}

free_irqs();
}

static int assign_epoll_events_to_irq(struct irq_entry *irq_entry)
Expand Down Expand Up @@ -380,10 +384,8 @@ EXPORT_SYMBOL(deactivate_fd);
*/
int deactivate_all_fds(void)
{
unsigned long flags;
struct irq_entry *to_free;

spin_lock_irqsave(&irq_lock, flags);
/* Stop IO. The IRQ loop has no lock so this is our
* only way of making sure we are safe to dispose
* of all IRQ handlers
Expand All @@ -399,8 +401,7 @@ int deactivate_all_fds(void)
);
to_free = to_free->next;
}
garbage_collect_irq_entries();
spin_unlock_irqrestore(&irq_lock, flags);
/* don't garbage collect - we can no longer call kfree() here */
os_close_epoll_fd();
return 0;
}
Expand Down
42 changes: 41 additions & 1 deletion arch/um/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,50 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
kmalloc_ok = save_kmalloc_ok;
}

static void time_travel_sleep(unsigned long long duration)
{
unsigned long long next = time_travel_time + duration;

if (time_travel_mode != TT_MODE_INFCPU)
os_timer_disable();

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(TT_TMR_DISABLED, 0);
/*
* time_travel_time will be adjusted in the timer
* IRQ handler so it works even when the signal
* comes from the OS timer
*/
deliver_alarm();
} else {
time_travel_set_time(next);
}

if (time_travel_mode != TT_MODE_INFCPU) {
if (time_travel_timer_mode == TT_TMR_PERIODIC)
os_timer_set_interval(time_travel_timer_interval);
else if (time_travel_timer_mode == TT_TMR_ONESHOT)
os_timer_one_shot(time_travel_timer_expiry - next);
}
}

static void um_idle_sleep(void)
{
unsigned long long duration = UM_NSEC_PER_SEC;

if (time_travel_mode != TT_MODE_OFF) {
time_travel_sleep(duration);
} else {
os_idle_sleep(duration);
}
}

void arch_cpu_idle(void)
{
cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
os_idle_sleep(UM_NSEC_PER_SEC);
um_idle_sleep();
local_irq_enable();
}

Expand Down
2 changes: 2 additions & 0 deletions arch/um/kernel/skas/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ obj-y := clone.o mmu.o process.o syscall.o uaccess.o
CFLAGS_clone.o := $(CFLAGS_NO_HARDENING)
UNPROFILE_OBJS := clone.o

KCOV_INSTRUMENT := n

include arch/um/scripts/Makefile.rules
11 changes: 11 additions & 0 deletions arch/um/kernel/skas/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,23 @@
#include <sysdep/ptrace.h>
#include <sysdep/ptrace_user.h>
#include <sysdep/syscalls.h>
#include <shared/timer-internal.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)
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);
Expand Down
Loading

0 comments on commit f2772a0

Please sign in to comment.