1/*
2 * Copyright 2018, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
8 * See "LICENSE_GPLv2.txt" for details.
9 *
10 * @TAG(DATA61_GPL)
11 */
12
13/*
14 *
15 * Copyright 2016, 2017 Hesham Almatary, Data61/CSIRO <hesham.almatary@data61.csiro.au>
16 * Copyright 2015, 2016 Hesham Almatary <heshamelmatary@gmail.com>
17 */
18
19#ifndef __ARCH_MACHINE_H
20#define __ARCH_MACHINE_H
21
22#ifndef __ASSEMBLER__
23#include <arch/types.h>
24#include <arch/object/structures.h>
25#include <arch/machine/hardware.h>
26#include <arch/encoding.h>
27#include <arch/model/statedata.h>
28#include <arch/sbi.h>
29
30static inline void sfence(void)
31{
32    asm volatile ("sfence.vma" ::: "memory");
33}
34
35static inline void hwASIDFlush(asid_t asid)
36{
37    asm volatile ("sfence.vma x0, %0" :: "r" (asid): "memory");
38}
39
40word_t PURE getRestartPC(tcb_t *thread);
41void setNextPC(tcb_t *thread, word_t v);
42
43/* Cleaning memory before user-level access */
44static inline void clearMemory(void* ptr, unsigned int bits)
45{
46    memzero(ptr, BIT(bits));
47}
48
49static inline void write_sptbr(word_t value)
50{
51    asm volatile("csrw sptbr, %0" :: "rK"(value));
52}
53
54static inline void write_stvec(word_t value)
55{
56    asm volatile("csrw stvec, %0" :: "rK"(value));
57}
58
59static inline word_t read_sbadaddr(void)
60{
61    word_t temp;
62    asm volatile("csrr %0, sbadaddr" : "=r"(temp));
63    return temp;
64}
65
66static inline word_t read_scause(void)
67{
68    word_t temp;
69    asm volatile("csrr %0, scause" : "=r"(temp));
70    return temp;
71}
72
73static inline word_t read_sepc(void)
74{
75    word_t temp;
76    asm volatile("csrr %0, sepc" : "=r"(temp));
77    return temp;
78}
79
80static inline word_t read_sstatus(void)
81{
82    word_t temp;
83    asm volatile("csrr %0, sstatus" : "=r"(temp));
84    return temp;
85}
86
87static inline void set_sie_mask(word_t mask_high)
88{
89    word_t temp;
90    asm volatile("csrrs %0, sie, %1" : "=r"(temp) : "rK"(mask_high));
91}
92
93static inline void clear_sie_mask(word_t mask_low)
94{
95    word_t temp;
96    asm volatile("csrrc %0, sie, %1" : "=r"(temp) : "rK"(mask_low));
97}
98
99static inline void clear_sip_mask(word_t mask_low)
100{
101    word_t temp;
102    asm volatile("csrrc %0, sip, %1" : "=r"(temp) : "rK"(mask_low));
103}
104
105#if CONFIG_PT_LEVELS == 2
106#define SATP_MODE SPTBR_MODE_SV32
107#elif CONFIG_PT_LEVELS == 3
108#define SATP_MODE SPTBR_MODE_SV39
109#elif CONFIG_PT_LEVELS == 4
110#define SATP_MODE SPTBR_MODE_SV48
111#else
112#error "Unsupported PT levels"
113#endif
114static inline void setVSpaceRoot(paddr_t addr, asid_t asid)
115{
116    satp_t satp = satp_new(SATP_MODE,              /* mode */
117                           asid,                         /* asid */
118                           addr >> seL4_PageBits); /* PPN */
119
120    /* Current toolchain still uses sptbr register name although it got renamed in priv-1.10.
121     * This will most likely need to change with newer toolchains
122     */
123    write_sptbr(satp.words[0]);
124
125    /* Order read/write operations */
126    sfence();
127}
128
129static inline void Arch_finaliseInterrupt(void)
130{
131}
132
133#endif // __ASSEMBLER__
134#endif
135
136