xref: /linux/arch/um/kernel/skas/mmu.c (revision 542dc79f6ea601788704a79ff54283c2bea265e9)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
4  * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
5  */
6 
7 #include <linux/mm.h>
8 #include <linux/sched/signal.h>
9 #include <linux/slab.h>
10 
11 #include <asm/pgalloc.h>
12 #include <asm/sections.h>
13 #include <asm/mmu_context.h>
14 #include <as-layout.h>
15 #include <os.h>
16 #include <skas.h>
17 #include <stub-data.h>
18 
19 /* Ensure the stub_data struct covers the allocated area */
20 static_assert(sizeof(struct stub_data) == STUB_DATA_PAGES * UM_KERN_PAGE_SIZE);
21 
22 int init_new_context(struct task_struct *task, struct mm_struct *mm)
23 {
24  	struct mm_context *from_mm = NULL;
25 	struct mm_context *to_mm = &mm->context;
26 	unsigned long stack = 0;
27 	int ret = -ENOMEM;
28 
29 	stack = __get_free_pages(GFP_KERNEL | __GFP_ZERO, ilog2(STUB_DATA_PAGES));
30 	if (stack == 0)
31 		goto out;
32 
33 	to_mm->id.stack = stack;
34 	if (current->mm != NULL && current->mm != &init_mm)
35 		from_mm = &current->mm->context;
36 
37 	block_signals_trace();
38 	if (from_mm)
39 		to_mm->id.u.pid = copy_context_skas0(stack,
40 						     from_mm->id.u.pid);
41 	else to_mm->id.u.pid = start_userspace(stack);
42 	unblock_signals_trace();
43 
44 	if (to_mm->id.u.pid < 0) {
45 		ret = to_mm->id.u.pid;
46 		goto out_free;
47 	}
48 
49 	ret = init_new_ldt(to_mm, from_mm);
50 	if (ret < 0) {
51 		printk(KERN_ERR "init_new_context_skas - init_ldt"
52 		       " failed, errno = %d\n", ret);
53 		goto out_free;
54 	}
55 
56 	return 0;
57 
58  out_free:
59 	if (to_mm->id.stack != 0)
60 		free_pages(to_mm->id.stack, ilog2(STUB_DATA_PAGES));
61  out:
62 	return ret;
63 }
64 
65 void destroy_context(struct mm_struct *mm)
66 {
67 	struct mm_context *mmu = &mm->context;
68 
69 	/*
70 	 * If init_new_context wasn't called, this will be
71 	 * zero, resulting in a kill(0), which will result in the
72 	 * whole UML suddenly dying.  Also, cover negative and
73 	 * 1 cases, since they shouldn't happen either.
74 	 */
75 	if (mmu->id.u.pid < 2) {
76 		printk(KERN_ERR "corrupt mm_context - pid = %d\n",
77 		       mmu->id.u.pid);
78 		return;
79 	}
80 	os_kill_ptraced_process(mmu->id.u.pid, 1);
81 
82 	free_pages(mmu->id.stack, ilog2(STUB_DATA_PAGES));
83 	free_ldt(mmu);
84 }
85