summaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorAnton Ivanov <anton.ivanov@cambridgegreys.com>2019-01-04 10:38:21 -0500
committerRichard Weinberger <richard@nod.at>2019-05-07 17:18:28 -0400
commit5c2ffce1e9496477720966e70d79f2da3e4b84e6 (patch)
tree12e77ce3c8debd687029236435ea5f3f7fbfdf70 /arch/um
parent37624b58542fb9f2d9a70e6ea006ef8a5f66c30b (diff)
um: Revert to using stack for pt_regs in signal handling
Reverts commit b6024b21fec8367ef961a771cc9dde31f1831965 and adjusts default stack sizing to cope with larger size of floating point save registers on the newer Intel CPUs. b6024b21fec8367ef961a771cc9dde31f1831965 replaced storing the register state on the stack with kmalloc-ed storage. That has a number of issues and a panic if that fails. 1. kmalloc/ATOMIC can fail. There was a latent hard crash in all interrupt and fault handling as a result. 2. kmalloc in the interrupt path introduces a considerable performance penalty for networking ~ 14% on iperf. This commit restores uml to a stable state until a better solution is found. Signed-off-by: Anton Ivanov <anton.ivanov@cambridgegreys.com> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/Kconfig10
-rw-r--r--arch/um/os-Linux/signal.c28
2 files changed, 15 insertions, 23 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index ec9711d068b7..41913504a56e 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -142,13 +142,17 @@ config MAGIC_SYSRQ
142 142
143config KERNEL_STACK_ORDER 143config KERNEL_STACK_ORDER
144 int "Kernel stack size order" 144 int "Kernel stack size order"
145 default 1 if 64BIT 145 default 2 if 64BIT
146 range 1 10 if 64BIT 146 range 2 10 if 64BIT
147 default 0 if !64BIT 147 default 1 if !64BIT
148 help 148 help
149 This option determines the size of UML kernel stacks. They will 149 This option determines the size of UML kernel stacks. They will
150 be 1 << order pages. The default is OK unless you're running Valgrind 150 be 1 << order pages. The default is OK unless you're running Valgrind
151 on UML, in which case, set this to 3. 151 on UML, in which case, set this to 3.
152 It is possible to reduce the stack to 1 for 64BIT and 0 for 32BIT on
153 older (pre-2017) CPUs. It is not recommended on newer CPUs due to the
154 increase in the size of the state which needs to be saved when handling
155 signals.
152 156
153config MMAPPER 157config MMAPPER
154 tristate "iomem emulation driver" 158 tristate "iomem emulation driver"
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index bf0acb8aad8b..75b10235d369 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -31,29 +31,23 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
31 31
32static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc) 32static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
33{ 33{
34 struct uml_pt_regs *r; 34 struct uml_pt_regs r;
35 int save_errno = errno; 35 int save_errno = errno;
36 36
37 r = uml_kmalloc(sizeof(struct uml_pt_regs), UM_GFP_ATOMIC); 37 r.is_user = 0;
38 if (!r)
39 panic("out of memory");
40
41 r->is_user = 0;
42 if (sig == SIGSEGV) { 38 if (sig == SIGSEGV) {
43 /* For segfaults, we want the data from the sigcontext. */ 39 /* For segfaults, we want the data from the sigcontext. */
44 get_regs_from_mc(r, mc); 40 get_regs_from_mc(&r, mc);
45 GET_FAULTINFO_FROM_MC(r->faultinfo, mc); 41 GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
46 } 42 }
47 43
48 /* enable signals if sig isn't IRQ signal */ 44 /* enable signals if sig isn't IRQ signal */
49 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM)) 45 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM))
50 unblock_signals(); 46 unblock_signals();
51 47
52 (*sig_info[sig])(sig, si, r); 48 (*sig_info[sig])(sig, si, &r);
53 49
54 errno = save_errno; 50 errno = save_errno;
55
56 free(r);
57} 51}
58 52
59/* 53/*
@@ -91,17 +85,11 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
91 85
92static void timer_real_alarm_handler(mcontext_t *mc) 86static void timer_real_alarm_handler(mcontext_t *mc)
93{ 87{
94 struct uml_pt_regs *regs; 88 struct uml_pt_regs regs;
95
96 regs = uml_kmalloc(sizeof(struct uml_pt_regs), UM_GFP_ATOMIC);
97 if (!regs)
98 panic("out of memory");
99 89
100 if (mc != NULL) 90 if (mc != NULL)
101 get_regs_from_mc(regs, mc); 91 get_regs_from_mc(&regs, mc);
102 timer_handler(SIGALRM, NULL, regs); 92 timer_handler(SIGALRM, NULL, &regs);
103
104 free(regs);
105} 93}
106 94
107void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) 95void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)