Commit 5c2ffce1 authored by Anton Ivanov's avatar Anton Ivanov Committed by Richard Weinberger

um: Revert to using stack for pt_regs in signal handling

Reverts commit b6024b21 and
adjusts default stack sizing to cope with larger size of
floating point save registers on the newer Intel CPUs.

b6024b21 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: default avatarAnton Ivanov <anton.ivanov@cambridgegreys.com>
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent 37624b58
...@@ -142,13 +142,17 @@ config MAGIC_SYSRQ ...@@ -142,13 +142,17 @@ config MAGIC_SYSRQ
config KERNEL_STACK_ORDER config KERNEL_STACK_ORDER
int "Kernel stack size order" int "Kernel stack size order"
default 1 if 64BIT default 2 if 64BIT
range 1 10 if 64BIT range 2 10 if 64BIT
default 0 if !64BIT default 1 if !64BIT
help help
This option determines the size of UML kernel stacks. They will This option determines the size of UML kernel stacks. They will
be 1 << order pages. The default is OK unless you're running Valgrind be 1 << order pages. The default is OK unless you're running Valgrind
on UML, in which case, set this to 3. on UML, in which case, set this to 3.
It is possible to reduce the stack to 1 for 64BIT and 0 for 32BIT on
older (pre-2017) CPUs. It is not recommended on newer CPUs due to the
increase in the size of the state which needs to be saved when handling
signals.
config MMAPPER config MMAPPER
tristate "iomem emulation driver" tristate "iomem emulation driver"
......
...@@ -31,29 +31,23 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = { ...@@ -31,29 +31,23 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc) static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
{ {
struct uml_pt_regs *r; struct uml_pt_regs r;
int save_errno = errno; int save_errno = errno;
r = uml_kmalloc(sizeof(struct uml_pt_regs), UM_GFP_ATOMIC); r.is_user = 0;
if (!r)
panic("out of memory");
r->is_user = 0;
if (sig == SIGSEGV) { if (sig == SIGSEGV) {
/* For segfaults, we want the data from the sigcontext. */ /* For segfaults, we want the data from the sigcontext. */
get_regs_from_mc(r, mc); get_regs_from_mc(&r, mc);
GET_FAULTINFO_FROM_MC(r->faultinfo, mc); GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
} }
/* enable signals if sig isn't IRQ signal */ /* enable signals if sig isn't IRQ signal */
if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM)) if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM))
unblock_signals(); unblock_signals();
(*sig_info[sig])(sig, si, r); (*sig_info[sig])(sig, si, &r);
errno = save_errno; errno = save_errno;
free(r);
} }
/* /*
...@@ -91,17 +85,11 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc) ...@@ -91,17 +85,11 @@ void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
static void timer_real_alarm_handler(mcontext_t *mc) static void timer_real_alarm_handler(mcontext_t *mc)
{ {
struct uml_pt_regs *regs; struct uml_pt_regs regs;
regs = uml_kmalloc(sizeof(struct uml_pt_regs), UM_GFP_ATOMIC);
if (!regs)
panic("out of memory");
if (mc != NULL) if (mc != NULL)
get_regs_from_mc(regs, mc); get_regs_from_mc(&regs, mc);
timer_handler(SIGALRM, NULL, regs); timer_handler(SIGALRM, NULL, &regs);
free(regs);
} }
void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment