Skip to content

Commit 7db91e5

Browse files
RISC-V: Task implementation
This patch contains the implementation of tasks on RISC-V, most of which is involved in task switching. Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 2129a23 commit 7db91e5

File tree

9 files changed

+1243
-0
lines changed

9 files changed

+1243
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include <generated/asm-offsets.h>

arch/riscv/include/asm/current.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Based on arm/arm64/include/asm/current.h
3+
*
4+
* Copyright (C) 2016 ARM
5+
* Copyright (C) 2017 SiFive
6+
*
7+
* This program is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU General Public License
9+
* as published by the Free Software Foundation, version 2.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*/
16+
17+
18+
#ifndef __ASM_CURRENT_H
19+
#define __ASM_CURRENT_H
20+
21+
#include <linux/bug.h>
22+
#include <linux/compiler.h>
23+
24+
#ifndef __ASSEMBLY__
25+
26+
struct task_struct;
27+
28+
/*
29+
* This only works because "struct thread_info" is at offset 0 from "struct
30+
* task_struct". This constraint seems to be necessary on other architectures
31+
* as well, but __switch_to enforces it. We can't check TASK_TI here because
32+
* <asm/asm-offsets.h> includes this, and I can't get the definition of "struct
33+
* task_struct" here due to some header ordering problems.
34+
*/
35+
static __always_inline struct task_struct *get_current(void)
36+
{
37+
register struct task_struct *tp __asm__("tp");
38+
return tp;
39+
}
40+
41+
#define current get_current()
42+
43+
#endif /* __ASSEMBLY__ */
44+
45+
#endif /* __ASM_CURRENT_H */

arch/riscv/include/asm/kprobes.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copied from arch/arm64/include/asm/kprobes.h
3+
*
4+
* Copyright (C) 2013 Linaro Limited
5+
* Copyright (C) 2017 SiFive
6+
*
7+
* This program is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License version 2 as
9+
* published by the Free Software Foundation.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* General Public License for more details.
15+
*/
16+
17+
#ifndef _RISCV_KPROBES_H
18+
#define _RISCV_KPROBES_H
19+
20+
#include <asm-generic/kprobes.h>
21+
22+
#endif /* _RISCV_KPROBES_H */

arch/riscv/include/asm/processor.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (C) 2012 Regents of the University of California
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, version 2.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*/
13+
14+
#ifndef _ASM_RISCV_PROCESSOR_H
15+
#define _ASM_RISCV_PROCESSOR_H
16+
17+
#include <linux/const.h>
18+
19+
#include <asm/ptrace.h>
20+
21+
/*
22+
* This decides where the kernel will search for a free chunk of vm
23+
* space during mmap's.
24+
*/
25+
#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE >> 1)
26+
27+
#define STACK_TOP TASK_SIZE
28+
#define STACK_TOP_MAX STACK_TOP
29+
#define STACK_ALIGN 16
30+
31+
#ifndef __ASSEMBLY__
32+
33+
struct task_struct;
34+
struct pt_regs;
35+
36+
/*
37+
* Default implementation of macro that returns current
38+
* instruction pointer ("program counter").
39+
*/
40+
#define current_text_addr() ({ __label__ _l; _l: &&_l; })
41+
42+
/* CPU-specific state of a task */
43+
struct thread_struct {
44+
/* Callee-saved registers */
45+
unsigned long ra;
46+
unsigned long sp; /* Kernel mode stack */
47+
unsigned long s[12]; /* s[0]: frame pointer */
48+
struct __riscv_d_ext_state fstate;
49+
};
50+
51+
#define INIT_THREAD { \
52+
.sp = sizeof(init_stack) + (long)&init_stack, \
53+
}
54+
55+
#define task_pt_regs(tsk) \
56+
((struct pt_regs *)(task_stack_page(tsk) + THREAD_SIZE \
57+
- ALIGN(sizeof(struct pt_regs), STACK_ALIGN)))
58+
59+
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->sepc)
60+
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp)
61+
62+
63+
/* Do necessary setup to start up a newly executed thread. */
64+
extern void start_thread(struct pt_regs *regs,
65+
unsigned long pc, unsigned long sp);
66+
67+
/* Free all resources held by a thread. */
68+
static inline void release_thread(struct task_struct *dead_task)
69+
{
70+
}
71+
72+
extern unsigned long get_wchan(struct task_struct *p);
73+
74+
75+
static inline void cpu_relax(void)
76+
{
77+
#ifdef __riscv_muldiv
78+
int dummy;
79+
/* In lieu of a halt instruction, induce a long-latency stall. */
80+
__asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy));
81+
#endif
82+
barrier();
83+
}
84+
85+
static inline void wait_for_interrupt(void)
86+
{
87+
__asm__ __volatile__ ("wfi");
88+
}
89+
90+
struct device_node;
91+
extern int riscv_of_processor_hart(struct device_node *node);
92+
93+
extern void riscv_fill_hwcap(void);
94+
95+
#endif /* __ASSEMBLY__ */
96+
97+
#endif /* _ASM_RISCV_PROCESSOR_H */

arch/riscv/include/asm/switch_to.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (C) 2012 Regents of the University of California
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation, version 2.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU General Public License for more details.
12+
*/
13+
14+
#ifndef _ASM_RISCV_SWITCH_TO_H
15+
#define _ASM_RISCV_SWITCH_TO_H
16+
17+
#include <asm/processor.h>
18+
#include <asm/ptrace.h>
19+
#include <asm/csr.h>
20+
21+
extern void __fstate_save(struct task_struct *save_to);
22+
extern void __fstate_restore(struct task_struct *restore_from);
23+
24+
static inline void __fstate_clean(struct pt_regs *regs)
25+
{
26+
regs->sstatus |= (regs->sstatus & ~(SR_FS)) | SR_FS_CLEAN;
27+
}
28+
29+
static inline void fstate_save(struct task_struct *task,
30+
struct pt_regs *regs)
31+
{
32+
if ((regs->sstatus & SR_FS) == SR_FS_DIRTY) {
33+
__fstate_save(task);
34+
__fstate_clean(regs);
35+
}
36+
}
37+
38+
static inline void fstate_restore(struct task_struct *task,
39+
struct pt_regs *regs)
40+
{
41+
if ((regs->sstatus & SR_FS) != SR_FS_OFF) {
42+
__fstate_restore(task);
43+
__fstate_clean(regs);
44+
}
45+
}
46+
47+
static inline void __switch_to_aux(struct task_struct *prev,
48+
struct task_struct *next)
49+
{
50+
struct pt_regs *regs;
51+
52+
regs = task_pt_regs(prev);
53+
if (unlikely(regs->sstatus & SR_SD))
54+
fstate_save(prev, regs);
55+
fstate_restore(next, task_pt_regs(next));
56+
}
57+
58+
extern struct task_struct *__switch_to(struct task_struct *,
59+
struct task_struct *);
60+
61+
#define switch_to(prev, next, last) \
62+
do { \
63+
struct task_struct *__prev = (prev); \
64+
struct task_struct *__next = (next); \
65+
__switch_to_aux(__prev, __next); \
66+
((last) = __switch_to(__prev, __next)); \
67+
} while (0)
68+
69+
#endif /* _ASM_RISCV_SWITCH_TO_H */
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (C) 2009 Chen Liqin <[email protected]>
3+
* Copyright (C) 2012 Regents of the University of California
4+
* Copyright (C) 2017 SiFive
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU General Public License
8+
* as published by the Free Software Foundation, version 2.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*/
15+
16+
#ifndef _ASM_RISCV_THREAD_INFO_H
17+
#define _ASM_RISCV_THREAD_INFO_H
18+
19+
#include <asm/page.h>
20+
#include <linux/const.h>
21+
22+
/* thread information allocation */
23+
#define THREAD_SIZE_ORDER (1)
24+
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
25+
26+
#ifndef __ASSEMBLY__
27+
28+
#include <asm/processor.h>
29+
#include <asm/csr.h>
30+
31+
typedef unsigned long mm_segment_t;
32+
33+
/*
34+
* low level task data that entry.S needs immediate access to
35+
* - this struct should fit entirely inside of one cache line
36+
* - if the members of this struct changes, the assembly constants
37+
* in asm-offsets.c must be updated accordingly
38+
* - thread_info is included in task_struct at an offset of 0. This means that
39+
* tp points to both thread_info and task_struct.
40+
*/
41+
struct thread_info {
42+
unsigned long flags; /* low level flags */
43+
int preempt_count; /* 0=>preemptible, <0=>BUG */
44+
mm_segment_t addr_limit;
45+
/*
46+
* These stack pointers are overwritten on every system call or
47+
* exception. SP is also saved to the stack it can be recovered when
48+
* overwritten.
49+
*/
50+
long kernel_sp; /* Kernel stack pointer */
51+
long user_sp; /* User stack pointer */
52+
int cpu;
53+
};
54+
55+
/*
56+
* macros/functions for gaining access to the thread information structure
57+
*
58+
* preempt_count needs to be 1 initially, until the scheduler is functional.
59+
*/
60+
#define INIT_THREAD_INFO(tsk) \
61+
{ \
62+
.flags = 0, \
63+
.preempt_count = INIT_PREEMPT_COUNT, \
64+
.addr_limit = KERNEL_DS, \
65+
}
66+
67+
#define init_stack (init_thread_union.stack)
68+
69+
#endif /* !__ASSEMBLY__ */
70+
71+
/*
72+
* thread information flags
73+
* - these are process state flags that various assembly files may need to
74+
* access
75+
* - pending work-to-be-done flags are in lowest half-word
76+
* - other flags in upper half-word(s)
77+
*/
78+
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
79+
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
80+
#define TIF_SIGPENDING 2 /* signal pending */
81+
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
82+
#define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */
83+
#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
84+
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
85+
86+
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
87+
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
88+
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
89+
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
90+
91+
#define _TIF_WORK_MASK \
92+
(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED)
93+
94+
#endif /* _ASM_RISCV_THREAD_INFO_H */

0 commit comments

Comments
 (0)