Skip to content

Commit 3c83170

Browse files
benzeajmberg-intel
authored andcommitted
um: Delay flushing syscalls until the thread is restarted
As running the syscalls is expensive due to context switches, we should do so as late as possible in case more syscalls need to be queued later on. This will also benefit a later move to a SECCOMP enabled userspace as in that case the need for extra context switches is removed entirely. Signed-off-by: Benjamin Berg <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Johannes Berg <[email protected]>
1 parent a5d2cfe commit 3c83170

File tree

7 files changed

+49
-42
lines changed

7 files changed

+49
-42
lines changed

arch/um/include/shared/os.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ extern void get_host_cpu_features(
195195
/* mem.c */
196196
extern int create_mem_file(unsigned long long len);
197197

198+
/* tlb.c */
199+
extern void report_enomem(void);
200+
198201
/* process.c */
199202
extern unsigned long os_process_pc(int pid);
200203
extern int os_process_parent(int pid);
@@ -274,6 +277,7 @@ extern long long os_nsecs(void);
274277
/* skas/mem.c */
275278
int syscall_stub_flush(struct mm_id *mm_idp);
276279
struct stub_syscall *syscall_stub_alloc(struct mm_id *mm_idp);
280+
void syscall_stub_dump_error(struct mm_id *mm_idp);
277281

278282
void map(struct mm_id *mm_idp, unsigned long virt,
279283
unsigned long len, int prot, int phys_fd,

arch/um/include/shared/skas/mm_id.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ struct mm_id {
1212
int pid;
1313
} u;
1414
unsigned long stack;
15-
int kill;
1615
int syscall_data_len;
1716
};
1817

arch/um/include/shared/skas/skas.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ extern void new_thread_handler(void);
1515
extern void handle_syscall(struct uml_pt_regs *regs);
1616
extern long execute_syscall_skas(void *r);
1717
extern unsigned long current_stub_stack(void);
18+
extern struct mm_id *current_mm_id(void);
1819

1920
#endif

arch/um/kernel/skas/process.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,11 @@ unsigned long current_stub_stack(void)
5050

5151
return current->mm->context.id.stack;
5252
}
53+
54+
struct mm_id *current_mm_id(void)
55+
{
56+
if (current->mm == NULL)
57+
return NULL;
58+
59+
return &current->mm->context.id;
60+
}

arch/um/kernel/tlb.c

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ struct host_vm_change {
5353
.index = 0, \
5454
.force = force })
5555

56-
static void report_enomem(void)
56+
void report_enomem(void)
5757
{
5858
printk(KERN_ERR "UML ran out of memory on the host side! "
5959
"This can happen due to a memory limitation or "
@@ -338,15 +338,6 @@ static void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
338338

339339
if (!ret)
340340
ret = do_ops(&hvc, hvc.index, 1);
341-
342-
/* This is not an else because ret is modified above */
343-
if (ret) {
344-
struct mm_id *mm_idp = &current->mm->context.id;
345-
346-
printk(KERN_ERR "fix_range_common: failed, killing current "
347-
"process: %d\n", task_tgid_vnr(current));
348-
mm_idp->kill = 1;
349-
}
350341
}
351342

352343
static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
@@ -461,7 +452,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
461452
pmd_t *pmd;
462453
pte_t *pte;
463454
struct mm_struct *mm = vma->vm_mm;
464-
int r, w, x, prot, err = 0;
455+
int r, w, x, prot;
465456
struct mm_id *mm_id;
466457

467458
address &= PAGE_MASK;
@@ -509,14 +500,6 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
509500
} else if (pte_newprot(*pte))
510501
protect(mm_id, address, PAGE_SIZE, prot);
511502

512-
err = syscall_stub_flush(mm_id);
513-
if (err) {
514-
if (err == -ENOMEM)
515-
report_enomem();
516-
517-
goto kill;
518-
}
519-
520503
*pte = pte_mkuptodate(*pte);
521504

522505
return;

arch/um/os-Linux/skas/mem.c

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,29 @@
2222

2323
extern char __syscall_stub_start[];
2424

25+
void syscall_stub_dump_error(struct mm_id *mm_idp)
26+
{
27+
struct stub_data *proc_data = (void *)mm_idp->stack;
28+
struct stub_syscall *sc;
29+
30+
if (proc_data->syscall_data_len < 0 ||
31+
proc_data->syscall_data_len >= ARRAY_SIZE(proc_data->syscall_data))
32+
panic("Syscall data was corrupted by stub (len is: %d, expected maximum: %d)!",
33+
proc_data->syscall_data_len,
34+
mm_idp->syscall_data_len);
35+
36+
sc = &proc_data->syscall_data[proc_data->syscall_data_len];
37+
38+
printk(UM_KERN_ERR "%s : length = %d, last offset = %d",
39+
__func__, mm_idp->syscall_data_len,
40+
proc_data->syscall_data_len);
41+
printk(UM_KERN_ERR "%s : stub syscall type %d failed, return value = 0x%lx\n",
42+
__func__, sc->syscall, proc_data->err);
43+
44+
print_hex_dump(UM_KERN_ERR, " syscall data: ", 0,
45+
16, 4, sc, sizeof(*sc), 0);
46+
}
47+
2548
static inline unsigned long *check_init_stack(struct mm_id * mm_idp,
2649
unsigned long *stack)
2750
{
@@ -82,26 +105,9 @@ static inline long do_syscall_stub(struct mm_id *mm_idp)
82105
* otherwise it will be zero (but we do not need to rely on that).
83106
*/
84107
if (proc_data->err < 0) {
85-
struct stub_syscall *sc;
86-
87-
if (proc_data->syscall_data_len < 0 ||
88-
proc_data->syscall_data_len >= ARRAY_SIZE(proc_data->syscall_data))
89-
panic("Syscall data was corrupted by stub (len is: %d, expected maximum: %d)!",
90-
proc_data->syscall_data_len,
91-
mm_idp->syscall_data_len);
92-
93-
sc = &proc_data->syscall_data[proc_data->syscall_data_len];
94-
95-
printk(UM_KERN_ERR "%s : length = %d, last offset = %d",
96-
__func__, mm_idp->syscall_data_len,
97-
proc_data->syscall_data_len);
98-
printk(UM_KERN_ERR "%s : stub syscall type %d failed, return value = 0x%lx\n",
99-
__func__, sc->syscall, proc_data->err);
100-
101-
print_hex_dump(UM_KERN_ERR,
102-
" syscall data: ", 0,
103-
16, 4, sc, sizeof(*sc), 0);
108+
syscall_stub_dump_error(mm_idp);
104109

110+
/* Store error code in case someone tries to add more syscalls */
105111
mm_idp->syscall_data_len = proc_data->err;
106112
} else {
107113
mm_idp->syscall_data_len = 0;

arch/um/os-Linux/skas/process.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,6 @@ static int userspace_tramp(void *stack)
254254
}
255255

256256
int userspace_pid[NR_CPUS];
257-
int kill_userspace_mm[NR_CPUS];
258257

259258
/**
260259
* start_userspace() - prepare a new userspace process
@@ -348,8 +347,16 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
348347
while (1) {
349348
time_travel_print_bc_msg();
350349

351-
if (kill_userspace_mm[0])
350+
/* Flush out any pending syscalls */
351+
err = syscall_stub_flush(current_mm_id());
352+
if (err) {
353+
if (err == -ENOMEM)
354+
report_enomem();
355+
356+
printk(UM_KERN_ERR "%s - Error flushing stub syscalls: %d",
357+
__func__, -err);
352358
fatal_sigsegv();
359+
}
353360

354361
/*
355362
* This can legitimately fail if the process loads a
@@ -580,5 +587,4 @@ void reboot_skas(void)
580587
void __switch_mm(struct mm_id *mm_idp)
581588
{
582589
userspace_pid[0] = mm_idp->u.pid;
583-
kill_userspace_mm[0] = mm_idp->kill;
584590
}

0 commit comments

Comments
 (0)