Skip to content

Commit

Permalink
riscv: abstract out CSR names for supervisor vs machine mode
Browse files Browse the repository at this point in the history
Many of the privileged CSRs exist in a supervisor and machine version
that are used very similarly.  Provide versions of the CSR names and
fields that map to either the S-mode or M-mode variant depending on
a new CONFIG_RISCV_M_MODE kconfig symbol.

Contains contributions from Damien Le Moal <Damien.LeMoal@wdc.com>
and Paul Walmsley <paul.walmsley@sifive.com>.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Thomas Gleixner <tglx@linutronix.de> # for drivers/clocksource, drivers/irqchip
[paul.walmsley@sifive.com: updated to apply]
Signed-off-by: Paul Walmsley <paul.walmsley@sifive.com>
  • Loading branch information
Christoph Hellwig authored and Paul Walmsley committed Nov 5, 2019
1 parent 0c3ac28 commit a4c3733
Show file tree
Hide file tree
Showing 21 changed files with 199 additions and 135 deletions.
4 changes: 4 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ config ARCH_MMAP_RND_BITS_MAX
default 24 if 64BIT # SV39 based
default 17

# set if we run in machine mode, cleared if we run in supervisor mode
config RISCV_M_MODE
bool

config MMU
def_bool y

Expand Down
72 changes: 62 additions & 10 deletions arch/riscv/include/asm/csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@

/* Status register flags */
#define SR_SIE _AC(0x00000002, UL) /* Supervisor Interrupt Enable */
#define SR_MIE _AC(0x00000008, UL) /* Machine Interrupt Enable */
#define SR_SPIE _AC(0x00000020, UL) /* Previous Supervisor IE */
#define SR_MPIE _AC(0x00000080, UL) /* Previous Machine IE */
#define SR_SPP _AC(0x00000100, UL) /* Previously Supervisor */
#define SR_MPP _AC(0x00001800, UL) /* Previously Machine */
#define SR_SUM _AC(0x00040000, UL) /* Supervisor User Memory Access */

#define SR_FS _AC(0x00006000, UL) /* Floating-point Status */
Expand Down Expand Up @@ -44,9 +47,10 @@
#define SATP_MODE SATP_MODE_39
#endif

/* SCAUSE */
#define SCAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1))
/* Exception cause high bit - is an interrupt if set */
#define CAUSE_IRQ_FLAG (_AC(1, UL) << (__riscv_xlen - 1))

/* Interrupt causes (minus the high bit) */
#define IRQ_U_SOFT 0
#define IRQ_S_SOFT 1
#define IRQ_M_SOFT 3
Expand All @@ -57,6 +61,7 @@
#define IRQ_S_EXT 9
#define IRQ_M_EXT 11

/* Exception causes */
#define EXC_INST_MISALIGNED 0
#define EXC_INST_ACCESS 1
#define EXC_BREAKPOINT 3
Expand All @@ -67,14 +72,14 @@
#define EXC_LOAD_PAGE_FAULT 13
#define EXC_STORE_PAGE_FAULT 15

/* SIE (Interrupt Enable) and SIP (Interrupt Pending) flags */
#define SIE_SSIE (_AC(0x1, UL) << IRQ_S_SOFT)
#define SIE_STIE (_AC(0x1, UL) << IRQ_S_TIMER)
#define SIE_SEIE (_AC(0x1, UL) << IRQ_S_EXT)

/* symbolic CSR names: */
#define CSR_CYCLE 0xc00
#define CSR_TIME 0xc01
#define CSR_INSTRET 0xc02
#define CSR_CYCLEH 0xc80
#define CSR_TIMEH 0xc81
#define CSR_INSTRETH 0xc82

#define CSR_SSTATUS 0x100
#define CSR_SIE 0x104
#define CSR_STVEC 0x105
Expand All @@ -85,9 +90,56 @@
#define CSR_STVAL 0x143
#define CSR_SIP 0x144
#define CSR_SATP 0x180
#define CSR_CYCLEH 0xc80
#define CSR_TIMEH 0xc81
#define CSR_INSTRETH 0xc82

#define CSR_MSTATUS 0x300
#define CSR_MIE 0x304
#define CSR_MTVEC 0x305
#define CSR_MSCRATCH 0x340
#define CSR_MEPC 0x341
#define CSR_MCAUSE 0x342
#define CSR_MTVAL 0x343
#define CSR_MIP 0x344

#ifdef CONFIG_RISCV_M_MODE
# define CSR_STATUS CSR_MSTATUS
# define CSR_IE CSR_MIE
# define CSR_TVEC CSR_MTVEC
# define CSR_SCRATCH CSR_MSCRATCH
# define CSR_EPC CSR_MEPC
# define CSR_CAUSE CSR_MCAUSE
# define CSR_TVAL CSR_MTVAL
# define CSR_IP CSR_MIP

# define SR_IE SR_MIE
# define SR_PIE SR_MPIE
# define SR_PP SR_MPP

# define IRQ_SOFT IRQ_M_SOFT
# define IRQ_TIMER IRQ_M_TIMER
# define IRQ_EXT IRQ_M_EXT
#else /* CONFIG_RISCV_M_MODE */
# define CSR_STATUS CSR_SSTATUS
# define CSR_IE CSR_SIE
# define CSR_TVEC CSR_STVEC
# define CSR_SCRATCH CSR_SSCRATCH
# define CSR_EPC CSR_SEPC
# define CSR_CAUSE CSR_SCAUSE
# define CSR_TVAL CSR_STVAL
# define CSR_IP CSR_SIP

# define SR_IE SR_SIE
# define SR_PIE SR_SPIE
# define SR_PP SR_SPP

# define IRQ_SOFT IRQ_S_SOFT
# define IRQ_TIMER IRQ_S_TIMER
# define IRQ_EXT IRQ_S_EXT
#endif /* CONFIG_RISCV_M_MODE */

/* IE/IP (Supervisor/Machine Interrupt Enable/Pending) flags */
#define IE_SIE (_AC(0x1, UL) << IRQ_SOFT)
#define IE_TIE (_AC(0x1, UL) << IRQ_TIMER)
#define IE_EIE (_AC(0x1, UL) << IRQ_EXT)

#ifndef __ASSEMBLY__

Expand Down
12 changes: 6 additions & 6 deletions arch/riscv/include/asm/irqflags.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,31 @@
/* read interrupt enabled status */
static inline unsigned long arch_local_save_flags(void)
{
return csr_read(CSR_SSTATUS);
return csr_read(CSR_STATUS);
}

/* unconditionally enable interrupts */
static inline void arch_local_irq_enable(void)
{
csr_set(CSR_SSTATUS, SR_SIE);
csr_set(CSR_STATUS, SR_IE);
}

/* unconditionally disable interrupts */
static inline void arch_local_irq_disable(void)
{
csr_clear(CSR_SSTATUS, SR_SIE);
csr_clear(CSR_STATUS, SR_IE);
}

/* get status and disable interrupts */
static inline unsigned long arch_local_irq_save(void)
{
return csr_read_clear(CSR_SSTATUS, SR_SIE);
return csr_read_clear(CSR_STATUS, SR_IE);
}

/* test flags */
static inline int arch_irqs_disabled_flags(unsigned long flags)
{
return !(flags & SR_SIE);
return !(flags & SR_IE);
}

/* test hardware interrupt enable bit */
Expand All @@ -49,7 +49,7 @@ static inline int arch_irqs_disabled(void)
/* set interrupt enabled status */
static inline void arch_local_irq_restore(unsigned long flags)
{
csr_set(CSR_SSTATUS, flags & SR_SIE);
csr_set(CSR_STATUS, flags & SR_IE);
}

#endif /* _ASM_RISCV_IRQFLAGS_H */
2 changes: 1 addition & 1 deletion arch/riscv/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct thread_struct {
((struct pt_regs *)(task_stack_page(tsk) + THREAD_SIZE \
- ALIGN(sizeof(struct pt_regs), STACK_ALIGN)))

#define KSTK_EIP(tsk) (task_pt_regs(tsk)->sepc)
#define KSTK_EIP(tsk) (task_pt_regs(tsk)->epc)
#define KSTK_ESP(tsk) (task_pt_regs(tsk)->sp)


Expand Down
16 changes: 8 additions & 8 deletions arch/riscv/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#ifndef __ASSEMBLY__

struct pt_regs {
unsigned long sepc;
unsigned long epc;
unsigned long ra;
unsigned long sp;
unsigned long gp;
Expand Down Expand Up @@ -44,10 +44,10 @@ struct pt_regs {
unsigned long t4;
unsigned long t5;
unsigned long t6;
/* Supervisor CSRs */
unsigned long sstatus;
unsigned long sbadaddr;
unsigned long scause;
/* Supervisor/Machine CSRs */
unsigned long status;
unsigned long badaddr;
unsigned long cause;
/* a0 value before the syscall */
unsigned long orig_a0;
};
Expand All @@ -58,18 +58,18 @@ struct pt_regs {
#define REG_FMT "%08lx"
#endif

#define user_mode(regs) (((regs)->sstatus & SR_SPP) == 0)
#define user_mode(regs) (((regs)->status & SR_PP) == 0)


/* Helpers for working with the instruction pointer */
static inline unsigned long instruction_pointer(struct pt_regs *regs)
{
return regs->sepc;
return regs->epc;
}
static inline void instruction_pointer_set(struct pt_regs *regs,
unsigned long val)
{
regs->sepc = val;
regs->epc = val;
}

#define profile_pc(regs) instruction_pointer(regs)
Expand Down
10 changes: 5 additions & 5 deletions arch/riscv/include/asm/switch_to.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ extern void __fstate_restore(struct task_struct *restore_from);

static inline void __fstate_clean(struct pt_regs *regs)
{
regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_CLEAN;
regs->status = (regs->status & ~SR_FS) | SR_FS_CLEAN;
}

static inline void fstate_off(struct task_struct *task,
struct pt_regs *regs)
{
regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_OFF;
regs->status = (regs->status & ~SR_FS) | SR_FS_OFF;
}

static inline void fstate_save(struct task_struct *task,
struct pt_regs *regs)
{
if ((regs->sstatus & SR_FS) == SR_FS_DIRTY) {
if ((regs->status & SR_FS) == SR_FS_DIRTY) {
__fstate_save(task);
__fstate_clean(regs);
}
Expand All @@ -38,7 +38,7 @@ static inline void fstate_save(struct task_struct *task,
static inline void fstate_restore(struct task_struct *task,
struct pt_regs *regs)
{
if ((regs->sstatus & SR_FS) != SR_FS_OFF) {
if ((regs->status & SR_FS) != SR_FS_OFF) {
__fstate_restore(task);
__fstate_clean(regs);
}
Expand All @@ -50,7 +50,7 @@ static inline void __switch_to_aux(struct task_struct *prev,
struct pt_regs *regs;

regs = task_pt_regs(prev);
if (unlikely(regs->sstatus & SR_SD))
if (unlikely(regs->status & SR_SD))
fstate_save(prev, regs);
fstate_restore(next, task_pt_regs(next));
}
Expand Down
8 changes: 4 additions & 4 deletions arch/riscv/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void asm_offsets(void)
OFFSET(TASK_THREAD_FCSR, task_struct, thread.fstate.fcsr);

DEFINE(PT_SIZE, sizeof(struct pt_regs));
OFFSET(PT_SEPC, pt_regs, sepc);
OFFSET(PT_EPC, pt_regs, epc);
OFFSET(PT_RA, pt_regs, ra);
OFFSET(PT_FP, pt_regs, s0);
OFFSET(PT_S0, pt_regs, s0);
Expand Down Expand Up @@ -105,9 +105,9 @@ void asm_offsets(void)
OFFSET(PT_T6, pt_regs, t6);
OFFSET(PT_GP, pt_regs, gp);
OFFSET(PT_ORIG_A0, pt_regs, orig_a0);
OFFSET(PT_SSTATUS, pt_regs, sstatus);
OFFSET(PT_SBADADDR, pt_regs, sbadaddr);
OFFSET(PT_SCAUSE, pt_regs, scause);
OFFSET(PT_STATUS, pt_regs, status);
OFFSET(PT_BADADDR, pt_regs, badaddr);
OFFSET(PT_CAUSE, pt_regs, cause);

/*
* THREAD_{F,X}* might be larger than a S-type offset can handle, but
Expand Down
Loading

0 comments on commit a4c3733

Please sign in to comment.