Skip to content

Commit 2f681ba

Browse files
benzeajmberg-intel
authored andcommitted
um: move thread info into task
This selects the THREAD_INFO_IN_TASK option for UM and changes the way that the current task is discovered. This is trivial though, as UML already tracks the current task in cpu_tasks[] and this can be used to retrieve it. Also remove the signal handler code that copies the thread information into the IRQ stack. It is obsolete now, which also means that the mentioned race condition cannot happen anymore. Signed-off-by: Benjamin Berg <[email protected]> Reviewed-by: Hajime Tazaki <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Johannes Berg <[email protected]>
1 parent 0f659ff commit 2f681ba

File tree

12 files changed

+34
-183
lines changed

12 files changed

+34
-183
lines changed

arch/um/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ config UML
3434
select HAVE_RUST
3535
select ARCH_HAS_UBSAN
3636
select HAVE_ARCH_TRACEHOOK
37+
select THREAD_INFO_IN_TASK
3738

3839
config MMU
3940
bool

arch/um/include/asm/Kbuild

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# SPDX-License-Identifier: GPL-2.0
22
generic-y += bug.h
33
generic-y += compat.h
4-
generic-y += current.h
54
generic-y += device.h
65
generic-y += dma-mapping.h
76
generic-y += emergency-restart.h

arch/um/include/asm/current.h

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __ASM_CURRENT_H
3+
#define __ASM_CURRENT_H
4+
5+
#include <linux/compiler.h>
6+
#include <linux/threads.h>
7+
8+
#ifndef __ASSEMBLY__
9+
10+
struct task_struct;
11+
extern struct task_struct *cpu_tasks[NR_CPUS];
12+
13+
static __always_inline struct task_struct *get_current(void)
14+
{
15+
return cpu_tasks[0];
16+
}
17+
18+
19+
#define current get_current()
20+
21+
#endif /* __ASSEMBLY__ */
22+
23+
#endif /* __ASM_CURRENT_H */

arch/um/include/asm/thread_info.h

-16
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,17 @@
1717
#include <sysdep/ptrace_user.h>
1818

1919
struct thread_info {
20-
struct task_struct *task; /* main task structure */
2120
unsigned long flags; /* low level flags */
2221
__u32 cpu; /* current CPU */
2322
int preempt_count; /* 0 => preemptable,
2423
<0 => BUG */
25-
struct thread_info *real_thread; /* Points to non-IRQ stack */
2624
};
2725

2826
#define INIT_THREAD_INFO(tsk) \
2927
{ \
30-
.task = &tsk, \
3128
.flags = 0, \
3229
.cpu = 0, \
3330
.preempt_count = INIT_PREEMPT_COUNT, \
34-
.real_thread = NULL, \
35-
}
36-
37-
/* how to get the thread information struct from C */
38-
static inline struct thread_info *current_thread_info(void)
39-
{
40-
struct thread_info *ti;
41-
unsigned long mask = THREAD_SIZE - 1;
42-
void *p;
43-
44-
asm volatile ("" : "=r" (p) : "0" (&ti));
45-
ti = (struct thread_info *) (((unsigned long)p) & ~mask);
46-
return ti;
4731
}
4832

4933
#endif

arch/um/include/shared/as-layout.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,8 @@
3030

3131
#include <sysdep/ptrace.h>
3232

33-
struct cpu_task {
34-
void *task;
35-
};
36-
37-
extern struct cpu_task cpu_tasks[];
33+
struct task_struct;
34+
extern struct task_struct *cpu_tasks[];
3835

3936
extern unsigned long long physmem_size;
4037

arch/um/kernel/dyn.lds.S

-2
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,6 @@ SECTIONS
116116
.fini_array : { *(.fini_array) }
117117
.data : {
118118
INIT_TASK_DATA(KERNEL_STACK_SIZE)
119-
. = ALIGN(KERNEL_STACK_SIZE);
120-
*(.data..init_irqstack)
121119
DATA_DATA
122120
*(.data.* .gnu.linkonce.d.*)
123121
SORT(CONSTRUCTORS)

arch/um/kernel/irq.c

-112
Original file line numberDiff line numberDiff line change
@@ -674,115 +674,3 @@ void __init init_IRQ(void)
674674
/* Initialize EPOLL Loop */
675675
os_setup_epoll();
676676
}
677-
678-
/*
679-
* IRQ stack entry and exit:
680-
*
681-
* Unlike i386, UML doesn't receive IRQs on the normal kernel stack
682-
* and switch over to the IRQ stack after some preparation. We use
683-
* sigaltstack to receive signals on a separate stack from the start.
684-
* These two functions make sure the rest of the kernel won't be too
685-
* upset by being on a different stack. The IRQ stack has a
686-
* thread_info structure at the bottom so that current et al continue
687-
* to work.
688-
*
689-
* to_irq_stack copies the current task's thread_info to the IRQ stack
690-
* thread_info and sets the tasks's stack to point to the IRQ stack.
691-
*
692-
* from_irq_stack copies the thread_info struct back (flags may have
693-
* been modified) and resets the task's stack pointer.
694-
*
695-
* Tricky bits -
696-
*
697-
* What happens when two signals race each other? UML doesn't block
698-
* signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal
699-
* could arrive while a previous one is still setting up the
700-
* thread_info.
701-
*
702-
* There are three cases -
703-
* The first interrupt on the stack - sets up the thread_info and
704-
* handles the interrupt
705-
* A nested interrupt interrupting the copying of the thread_info -
706-
* can't handle the interrupt, as the stack is in an unknown state
707-
* A nested interrupt not interrupting the copying of the
708-
* thread_info - doesn't do any setup, just handles the interrupt
709-
*
710-
* The first job is to figure out whether we interrupted stack setup.
711-
* This is done by xchging the signal mask with thread_info->pending.
712-
* If the value that comes back is zero, then there is no setup in
713-
* progress, and the interrupt can be handled. If the value is
714-
* non-zero, then there is stack setup in progress. In order to have
715-
* the interrupt handled, we leave our signal in the mask, and it will
716-
* be handled by the upper handler after it has set up the stack.
717-
*
718-
* Next is to figure out whether we are the outer handler or a nested
719-
* one. As part of setting up the stack, thread_info->real_thread is
720-
* set to non-NULL (and is reset to NULL on exit). This is the
721-
* nesting indicator. If it is non-NULL, then the stack is already
722-
* set up and the handler can run.
723-
*/
724-
725-
static unsigned long pending_mask;
726-
727-
unsigned long to_irq_stack(unsigned long *mask_out)
728-
{
729-
struct thread_info *ti;
730-
unsigned long mask, old;
731-
int nested;
732-
733-
mask = xchg(&pending_mask, *mask_out);
734-
if (mask != 0) {
735-
/*
736-
* If any interrupts come in at this point, we want to
737-
* make sure that their bits aren't lost by our
738-
* putting our bit in. So, this loop accumulates bits
739-
* until xchg returns the same value that we put in.
740-
* When that happens, there were no new interrupts,
741-
* and pending_mask contains a bit for each interrupt
742-
* that came in.
743-
*/
744-
old = *mask_out;
745-
do {
746-
old |= mask;
747-
mask = xchg(&pending_mask, old);
748-
} while (mask != old);
749-
return 1;
750-
}
751-
752-
ti = current_thread_info();
753-
nested = (ti->real_thread != NULL);
754-
if (!nested) {
755-
struct task_struct *task;
756-
struct thread_info *tti;
757-
758-
task = cpu_tasks[ti->cpu].task;
759-
tti = task_thread_info(task);
760-
761-
*ti = *tti;
762-
ti->real_thread = tti;
763-
task->stack = ti;
764-
}
765-
766-
mask = xchg(&pending_mask, 0);
767-
*mask_out |= mask | nested;
768-
return 0;
769-
}
770-
771-
unsigned long from_irq_stack(int nested)
772-
{
773-
struct thread_info *ti, *to;
774-
unsigned long mask;
775-
776-
ti = current_thread_info();
777-
778-
pending_mask = 1;
779-
780-
to = ti->real_thread;
781-
current->stack = to;
782-
ti->real_thread = NULL;
783-
*to = *ti;
784-
785-
mask = xchg(&pending_mask, 0);
786-
return mask & ~1;
787-
}
788-

arch/um/kernel/process.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
* cares about its entry, so it's OK if another processor is modifying its
4444
* entry.
4545
*/
46-
struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { NULL } };
46+
struct task_struct *cpu_tasks[NR_CPUS];
47+
EXPORT_SYMBOL(cpu_tasks);
4748

4849
void free_stack(unsigned long stack, int order)
4950
{
@@ -64,7 +65,7 @@ unsigned long alloc_stack(int order, int atomic)
6465

6566
static inline void set_current(struct task_struct *task)
6667
{
67-
cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) { task });
68+
cpu_tasks[task_thread_info(task)->cpu] = task;
6869
}
6970

7071
struct task_struct *__switch_to(struct task_struct *from, struct task_struct *to)

arch/um/kernel/skas/process.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@ static int __init start_kernel_proc(void *unused)
2222
{
2323
block_signals_trace();
2424

25-
cpu_tasks[0].task = current;
26-
2725
start_kernel();
2826
return 0;
2927
}
3028

3129
extern int userspace_pid[];
3230

33-
extern char cpu0_irqstack[];
31+
static char cpu0_irqstack[THREAD_SIZE] __aligned(THREAD_SIZE);
3432

3533
int __init start_uml(void)
3634
{

arch/um/kernel/um_arch.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ struct cpuinfo_um boot_cpu_data = {
6565

6666
EXPORT_SYMBOL(boot_cpu_data);
6767

68-
union thread_union cpu0_irqstack
69-
__section(".data..init_irqstack") =
70-
{ .thread_info = INIT_THREAD_INFO(init_task) };
7168

7269
/* Changed in setup_arch, which is called in early boot */
7370
static char host_info[(__NEW_UTS_LEN + 1) * 5];
@@ -244,6 +241,8 @@ static struct notifier_block panic_exit_notifier = {
244241

245242
void uml_finishsetup(void)
246243
{
244+
cpu_tasks[0] = &init_task;
245+
247246
atomic_notifier_chain_register(&panic_notifier_list,
248247
&panic_exit_notifier);
249248

@@ -418,7 +417,7 @@ void __init setup_arch(char **cmdline_p)
418417
{
419418
u8 rng_seed[32];
420419

421-
stack_protections((unsigned long) &init_thread_info);
420+
stack_protections((unsigned long) init_task.stack);
422421
setup_physmem(uml_physmem, uml_reserved, physmem_size);
423422
mem_total_pages(physmem_size, iomem_size);
424423
uml_dtb_init();

arch/um/kernel/uml.lds.S

-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ SECTIONS
7777
.data :
7878
{
7979
INIT_TASK_DATA(KERNEL_STACK_SIZE)
80-
. = ALIGN(KERNEL_STACK_SIZE);
81-
*(.data..init_irqstack)
8280
DATA_DATA
8381
*(.gnu.linkonce.d*)
8482
CONSTRUCTORS

arch/um/os-Linux/signal.c

+1-36
Original file line numberDiff line numberDiff line change
@@ -190,43 +190,8 @@ static void hard_handler(int sig, siginfo_t *si, void *p)
190190
{
191191
ucontext_t *uc = p;
192192
mcontext_t *mc = &uc->uc_mcontext;
193-
unsigned long pending = 1UL << sig;
194193

195-
do {
196-
int nested, bail;
197-
198-
/*
199-
* pending comes back with one bit set for each
200-
* interrupt that arrived while setting up the stack,
201-
* plus a bit for this interrupt, plus the zero bit is
202-
* set if this is a nested interrupt.
203-
* If bail is true, then we interrupted another
204-
* handler setting up the stack. In this case, we
205-
* have to return, and the upper handler will deal
206-
* with this interrupt.
207-
*/
208-
bail = to_irq_stack(&pending);
209-
if (bail)
210-
return;
211-
212-
nested = pending & 1;
213-
pending &= ~1;
214-
215-
while ((sig = ffs(pending)) != 0){
216-
sig--;
217-
pending &= ~(1 << sig);
218-
(*handlers[sig])(sig, (struct siginfo *)si, mc);
219-
}
220-
221-
/*
222-
* Again, pending comes back with a mask of signals
223-
* that arrived while tearing down the stack. If this
224-
* is non-zero, we just go back, set up the stack
225-
* again, and handle the new interrupts.
226-
*/
227-
if (!nested)
228-
pending = from_irq_stack(nested);
229-
} while (pending);
194+
(*handlers[sig])(sig, (struct siginfo *)si, mc);
230195
}
231196

232197
void set_handler(int sig)

0 commit comments

Comments
 (0)