Skip to content

Commit f2772a0

Browse files
committed
Merge tag 'for-linus-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/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
2 parents fcd9814 + b482e48 commit f2772a0

File tree

15 files changed

+320
-142
lines changed

15 files changed

+320
-142
lines changed

arch/um/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,18 @@ config SECCOMP
184184

185185
If unsure, say Y.
186186

187+
config UML_TIME_TRAVEL_SUPPORT
188+
bool
189+
prompt "Support time-travel mode (e.g. for test execution)"
190+
help
191+
Enable this option to support time travel inside the UML instance.
192+
193+
After enabling this option, two modes are accessible at runtime
194+
(selected by the kernel command line), see the kernel's command-
195+
line help for more details.
196+
197+
It is safe to say Y, but you probably don't need this.
198+
187199
endmenu
188200

189201
source "arch/um/drivers/Kconfig"

arch/um/configs/i386_defconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ CONFIG_XTERM_CHAN=y
3636
CONFIG_CON_CHAN="pts"
3737
CONFIG_SSL_CHAN="pts"
3838
CONFIG_UML_SOUND=m
39-
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
4039
CONFIG_DEVTMPFS=y
4140
CONFIG_DEVTMPFS_MOUNT=y
4241
CONFIG_BLK_DEV_UBD=y

arch/um/configs/x86_64_defconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ CONFIG_XTERM_CHAN=y
3434
CONFIG_CON_CHAN="pts"
3535
CONFIG_SSL_CHAN="pts"
3636
CONFIG_UML_SOUND=m
37-
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
3837
CONFIG_DEVTMPFS=y
3938
CONFIG_DEVTMPFS_MOUNT=y
4039
CONFIG_BLK_DEV_UBD=y

arch/um/drivers/chan_kern.c

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,19 +171,55 @@ int enable_chan(struct line *line)
171171
return err;
172172
}
173173

174+
/* Items are added in IRQ context, when free_irq can't be called, and
175+
* removed in process context, when it can.
176+
* This handles interrupt sources which disappear, and which need to
177+
* be permanently disabled. This is discovered in IRQ context, but
178+
* the freeing of the IRQ must be done later.
179+
*/
180+
static DEFINE_SPINLOCK(irqs_to_free_lock);
181+
static LIST_HEAD(irqs_to_free);
182+
183+
void free_irqs(void)
184+
{
185+
struct chan *chan;
186+
LIST_HEAD(list);
187+
struct list_head *ele;
188+
unsigned long flags;
189+
190+
spin_lock_irqsave(&irqs_to_free_lock, flags);
191+
list_splice_init(&irqs_to_free, &list);
192+
spin_unlock_irqrestore(&irqs_to_free_lock, flags);
193+
194+
list_for_each(ele, &list) {
195+
chan = list_entry(ele, struct chan, free_list);
196+
197+
if (chan->input && chan->enabled)
198+
um_free_irq(chan->line->driver->read_irq, chan);
199+
if (chan->output && chan->enabled)
200+
um_free_irq(chan->line->driver->write_irq, chan);
201+
chan->enabled = 0;
202+
}
203+
}
204+
174205
static void close_one_chan(struct chan *chan, int delay_free_irq)
175206
{
207+
unsigned long flags;
208+
176209
if (!chan->opened)
177210
return;
178211

179-
/* we can safely call free now - it will be marked
180-
* as free and freed once the IRQ stopped processing
181-
*/
182-
if (chan->input && chan->enabled)
183-
um_free_irq(chan->line->driver->read_irq, chan);
184-
if (chan->output && chan->enabled)
185-
um_free_irq(chan->line->driver->write_irq, chan);
186-
chan->enabled = 0;
212+
if (delay_free_irq) {
213+
spin_lock_irqsave(&irqs_to_free_lock, flags);
214+
list_add(&chan->free_list, &irqs_to_free);
215+
spin_unlock_irqrestore(&irqs_to_free_lock, flags);
216+
} else {
217+
if (chan->input && chan->enabled)
218+
um_free_irq(chan->line->driver->read_irq, chan);
219+
if (chan->output && chan->enabled)
220+
um_free_irq(chan->line->driver->write_irq, chan);
221+
chan->enabled = 0;
222+
}
187223
if (chan->ops->close != NULL)
188224
(*chan->ops->close)(chan->fd, chan->data);
189225

arch/um/drivers/ssl.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include <linux/console.h>
1313
#include <asm/termbits.h>
1414
#include <asm/irq.h>
15-
#include "ssl.h"
1615
#include "chan.h"
1716
#include <init.h>
1817
#include <irq_user.h>

arch/um/drivers/ssl.h

Lines changed: 0 additions & 13 deletions
This file was deleted.

arch/um/include/asm/mmu_context.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
5252
* when the new ->mm is used for the first time.
5353
*/
5454
__switch_mm(&new->context.id);
55-
down_write(&new->mmap_sem);
55+
down_write_nested(&new->mmap_sem, 1);
5656
uml_setup_stubs(new);
5757
up_write(&new->mmap_sem);
5858
}

arch/um/include/shared/os.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,15 +250,13 @@ extern void os_warn(const char *fmt, ...)
250250

251251
/* time.c */
252252
extern void os_idle_sleep(unsigned long long nsecs);
253-
extern int os_timer_create(void* timer);
254-
extern int os_timer_set_interval(void* timer, void* its);
255-
extern int os_timer_one_shot(int ticks);
256-
extern long long os_timer_disable(void);
257-
extern long os_timer_remain(void* timer);
253+
extern int os_timer_create(void);
254+
extern int os_timer_set_interval(unsigned long long nsecs);
255+
extern int os_timer_one_shot(unsigned long long nsecs);
256+
extern void os_timer_disable(void);
258257
extern void uml_idle_timer(void);
259258
extern long long os_persistent_clock_emulation(void);
260259
extern long long os_nsecs(void);
261-
extern long long os_vnsecs(void);
262260

263261
/* skas/mem.c */
264262
extern long run_syscall_stub(struct mm_id * mm_idp,

arch/um/include/shared/timer-internal.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,52 @@
1010
#define TIMER_MULTIPLIER 256
1111
#define TIMER_MIN_DELTA 500
1212

13+
enum time_travel_mode {
14+
TT_MODE_OFF,
15+
TT_MODE_BASIC,
16+
TT_MODE_INFCPU,
17+
};
18+
19+
enum time_travel_timer_mode {
20+
TT_TMR_DISABLED,
21+
TT_TMR_ONESHOT,
22+
TT_TMR_PERIODIC,
23+
};
24+
25+
#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
26+
extern enum time_travel_mode time_travel_mode;
27+
extern unsigned long long time_travel_time;
28+
extern enum time_travel_timer_mode time_travel_timer_mode;
29+
extern unsigned long long time_travel_timer_expiry;
30+
extern unsigned long long time_travel_timer_interval;
31+
32+
static inline void time_travel_set_time(unsigned long long ns)
33+
{
34+
time_travel_time = ns;
35+
}
36+
37+
static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
38+
unsigned long long expiry)
39+
{
40+
time_travel_timer_mode = mode;
41+
time_travel_timer_expiry = expiry;
42+
}
43+
#else
44+
#define time_travel_mode TT_MODE_OFF
45+
#define time_travel_time 0
46+
#define time_travel_timer_expiry 0
47+
#define time_travel_timer_interval 0
48+
49+
static inline void time_travel_set_time(unsigned long long ns)
50+
{
51+
}
52+
53+
static inline void time_travel_set_timer(enum time_travel_timer_mode mode,
54+
unsigned long long expiry)
55+
{
56+
}
57+
58+
#define time_travel_timer_mode TT_TMR_DISABLED
59+
#endif
60+
1361
#endif

arch/um/kernel/irq.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include <irq_user.h>
2222

2323

24+
extern void free_irqs(void);
25+
2426
/* When epoll triggers we do not know why it did so
2527
* we can also have different IRQs for read and write.
2628
* This is why we keep a small irq_fd array for each fd -
@@ -100,6 +102,8 @@ void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
100102
}
101103
}
102104
}
105+
106+
free_irqs();
103107
}
104108

105109
static int assign_epoll_events_to_irq(struct irq_entry *irq_entry)
@@ -380,10 +384,8 @@ EXPORT_SYMBOL(deactivate_fd);
380384
*/
381385
int deactivate_all_fds(void)
382386
{
383-
unsigned long flags;
384387
struct irq_entry *to_free;
385388

386-
spin_lock_irqsave(&irq_lock, flags);
387389
/* Stop IO. The IRQ loop has no lock so this is our
388390
* only way of making sure we are safe to dispose
389391
* of all IRQ handlers
@@ -399,8 +401,7 @@ int deactivate_all_fds(void)
399401
);
400402
to_free = to_free->next;
401403
}
402-
garbage_collect_irq_entries();
403-
spin_unlock_irqrestore(&irq_lock, flags);
404+
/* don't garbage collect - we can no longer call kfree() here */
404405
os_close_epoll_fd();
405406
return 0;
406407
}

arch/um/kernel/process.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,50 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
203203
kmalloc_ok = save_kmalloc_ok;
204204
}
205205

206+
static void time_travel_sleep(unsigned long long duration)
207+
{
208+
unsigned long long next = time_travel_time + duration;
209+
210+
if (time_travel_mode != TT_MODE_INFCPU)
211+
os_timer_disable();
212+
213+
if (time_travel_timer_mode != TT_TMR_DISABLED ||
214+
time_travel_timer_expiry < next) {
215+
if (time_travel_timer_mode == TT_TMR_ONESHOT)
216+
time_travel_set_timer(TT_TMR_DISABLED, 0);
217+
/*
218+
* time_travel_time will be adjusted in the timer
219+
* IRQ handler so it works even when the signal
220+
* comes from the OS timer
221+
*/
222+
deliver_alarm();
223+
} else {
224+
time_travel_set_time(next);
225+
}
226+
227+
if (time_travel_mode != TT_MODE_INFCPU) {
228+
if (time_travel_timer_mode == TT_TMR_PERIODIC)
229+
os_timer_set_interval(time_travel_timer_interval);
230+
else if (time_travel_timer_mode == TT_TMR_ONESHOT)
231+
os_timer_one_shot(time_travel_timer_expiry - next);
232+
}
233+
}
234+
235+
static void um_idle_sleep(void)
236+
{
237+
unsigned long long duration = UM_NSEC_PER_SEC;
238+
239+
if (time_travel_mode != TT_MODE_OFF) {
240+
time_travel_sleep(duration);
241+
} else {
242+
os_idle_sleep(duration);
243+
}
244+
}
245+
206246
void arch_cpu_idle(void)
207247
{
208248
cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
209-
os_idle_sleep(UM_NSEC_PER_SEC);
249+
um_idle_sleep();
210250
local_irq_enable();
211251
}
212252

arch/um/kernel/skas/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ obj-y := clone.o mmu.o process.o syscall.o uaccess.o
1212
CFLAGS_clone.o := $(CFLAGS_NO_HARDENING)
1313
UNPROFILE_OBJS := clone.o
1414

15+
KCOV_INSTRUMENT := n
16+
1517
include arch/um/scripts/Makefile.rules

arch/um/kernel/skas/syscall.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,23 @@
1010
#include <sysdep/ptrace.h>
1111
#include <sysdep/ptrace_user.h>
1212
#include <sysdep/syscalls.h>
13+
#include <shared/timer-internal.h>
1314

1415
void handle_syscall(struct uml_pt_regs *r)
1516
{
1617
struct pt_regs *regs = container_of(r, struct pt_regs, regs);
1718
int syscall;
1819

20+
/*
21+
* If we have infinite CPU resources, then make every syscall also a
22+
* preemption point, since we don't have any other preemption in this
23+
* case, and kernel threads would basically never run until userspace
24+
* went to sleep, even if said userspace interacts with the kernel in
25+
* various ways.
26+
*/
27+
if (time_travel_mode == TT_MODE_INFCPU)
28+
schedule();
29+
1930
/* Initialize the syscall number and default return value. */
2031
UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp);
2132
PT_REGS_SET_SYSCALL_RETURN(regs, -ENOSYS);

0 commit comments

Comments
 (0)