lib: sbi: Print scratch size and usage at boot time
[platform/kernel/opensbi.git] / include / sbi / sbi_scratch.h
1 /*
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2019 Western Digital Corporation or its affiliates.
5  *
6  * Authors:
7  *   Anup Patel <anup.patel@wdc.com>
8  */
9
10 #ifndef __SBI_SCRATCH_H__
11 #define __SBI_SCRATCH_H__
12
13 #include <sbi/riscv_asm.h>
14
15 /* clang-format off */
16
17 /** Offset of fw_start member in sbi_scratch */
18 #define SBI_SCRATCH_FW_START_OFFSET             (0 * __SIZEOF_POINTER__)
19 /** Offset of fw_size member in sbi_scratch */
20 #define SBI_SCRATCH_FW_SIZE_OFFSET              (1 * __SIZEOF_POINTER__)
21 /** Offset (in sbi_scratch) of the R/W Offset */
22 #define SBI_SCRATCH_FW_RW_OFFSET                (2 * __SIZEOF_POINTER__)
23 /** Offset of fw_heap_offset member in sbi_scratch */
24 #define SBI_SCRATCH_FW_HEAP_OFFSET              (3 * __SIZEOF_POINTER__)
25 /** Offset of fw_heap_size_offset member in sbi_scratch */
26 #define SBI_SCRATCH_FW_HEAP_SIZE_OFFSET         (4 * __SIZEOF_POINTER__)
27 /** Offset of next_arg1 member in sbi_scratch */
28 #define SBI_SCRATCH_NEXT_ARG1_OFFSET            (5 * __SIZEOF_POINTER__)
29 /** Offset of next_addr member in sbi_scratch */
30 #define SBI_SCRATCH_NEXT_ADDR_OFFSET            (6 * __SIZEOF_POINTER__)
31 /** Offset of next_mode member in sbi_scratch */
32 #define SBI_SCRATCH_NEXT_MODE_OFFSET            (7 * __SIZEOF_POINTER__)
33 /** Offset of warmboot_addr member in sbi_scratch */
34 #define SBI_SCRATCH_WARMBOOT_ADDR_OFFSET        (8 * __SIZEOF_POINTER__)
35 /** Offset of platform_addr member in sbi_scratch */
36 #define SBI_SCRATCH_PLATFORM_ADDR_OFFSET        (9 * __SIZEOF_POINTER__)
37 /** Offset of hartid_to_scratch member in sbi_scratch */
38 #define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET    (10 * __SIZEOF_POINTER__)
39 /** Offset of trap_exit member in sbi_scratch */
40 #define SBI_SCRATCH_TRAP_EXIT_OFFSET            (11 * __SIZEOF_POINTER__)
41 /** Offset of tmp0 member in sbi_scratch */
42 #define SBI_SCRATCH_TMP0_OFFSET                 (12 * __SIZEOF_POINTER__)
43 /** Offset of options member in sbi_scratch */
44 #define SBI_SCRATCH_OPTIONS_OFFSET              (13 * __SIZEOF_POINTER__)
45 /** Offset of extra space in sbi_scratch */
46 #define SBI_SCRATCH_EXTRA_SPACE_OFFSET          (14 * __SIZEOF_POINTER__)
47 /** Maximum size of sbi_scratch (4KB) */
48 #define SBI_SCRATCH_SIZE                        (0x1000)
49
50 /* clang-format on */
51
52 #ifndef __ASSEMBLER__
53
54 #include <sbi/sbi_types.h>
55
56 /** Representation of per-HART scratch space */
57 struct sbi_scratch {
58         /** Start (or base) address of firmware linked to OpenSBI library */
59         unsigned long fw_start;
60         /** Size (in bytes) of firmware linked to OpenSBI library */
61         unsigned long fw_size;
62         /** Offset (in bytes) of the R/W section */
63         unsigned long fw_rw_offset;
64         /** Offset (in bytes) of the heap area */
65         unsigned long fw_heap_offset;
66         /** Size (in bytes) of the heap area */
67         unsigned long fw_heap_size;
68         /** Arg1 (or 'a1' register) of next booting stage for this HART */
69         unsigned long next_arg1;
70         /** Address of next booting stage for this HART */
71         unsigned long next_addr;
72         /** Privilege mode of next booting stage for this HART */
73         unsigned long next_mode;
74         /** Warm boot entry point address for this HART */
75         unsigned long warmboot_addr;
76         /** Address of sbi_platform */
77         unsigned long platform_addr;
78         /** Address of HART ID to sbi_scratch conversion function */
79         unsigned long hartid_to_scratch;
80         /** Address of trap exit function */
81         unsigned long trap_exit;
82         /** Temporary storage */
83         unsigned long tmp0;
84         /** Options for OpenSBI library */
85         unsigned long options;
86 };
87
88 /**
89  * Prevent modification of struct sbi_scratch from affecting
90  * SBI_SCRATCH_xxx_OFFSET
91  */
92 _Static_assert(
93         offsetof(struct sbi_scratch, fw_start)
94                 == SBI_SCRATCH_FW_START_OFFSET,
95         "struct sbi_scratch definition has changed, please redefine "
96         "SBI_SCRATCH_FW_START_OFFSET");
97 _Static_assert(
98         offsetof(struct sbi_scratch, fw_size)
99                 == SBI_SCRATCH_FW_SIZE_OFFSET,
100         "struct sbi_scratch definition has changed, please redefine "
101         "SBI_SCRATCH_FW_SIZE_OFFSET");
102 _Static_assert(
103         offsetof(struct sbi_scratch, next_arg1)
104                 == SBI_SCRATCH_NEXT_ARG1_OFFSET,
105         "struct sbi_scratch definition has changed, please redefine "
106         "SBI_SCRATCH_NEXT_ARG1_OFFSET");
107 _Static_assert(
108         offsetof(struct sbi_scratch, next_addr)
109                 == SBI_SCRATCH_NEXT_ADDR_OFFSET,
110         "struct sbi_scratch definition has changed, please redefine "
111         "SBI_SCRATCH_NEXT_ADDR_OFFSET");
112 _Static_assert(
113         offsetof(struct sbi_scratch, next_mode)
114                 == SBI_SCRATCH_NEXT_MODE_OFFSET,
115         "struct sbi_scratch definition has changed, please redefine "
116         "SBI_SCRATCH_NEXT_MODE_OFFSET");
117 _Static_assert(
118         offsetof(struct sbi_scratch, warmboot_addr)
119                 == SBI_SCRATCH_WARMBOOT_ADDR_OFFSET,
120         "struct sbi_scratch definition has changed, please redefine "
121         "SBI_SCRATCH_WARMBOOT_ADDR_OFFSET");
122 _Static_assert(
123         offsetof(struct sbi_scratch, platform_addr)
124                 == SBI_SCRATCH_PLATFORM_ADDR_OFFSET,
125         "struct sbi_scratch definition has changed, please redefine "
126         "SBI_SCRATCH_PLATFORM_ADDR_OFFSET");
127 _Static_assert(
128         offsetof(struct sbi_scratch, hartid_to_scratch)
129                 == SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET,
130         "struct sbi_scratch definition has changed, please redefine "
131         "SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET");
132 _Static_assert(
133         offsetof(struct sbi_scratch, trap_exit)
134                 == SBI_SCRATCH_TRAP_EXIT_OFFSET,
135         "struct sbi_scratch definition has changed, please redefine "
136         "SBI_SCRATCH_TRAP_EXIT_OFFSET");
137 _Static_assert(
138         offsetof(struct sbi_scratch, tmp0)
139                 == SBI_SCRATCH_TMP0_OFFSET,
140         "struct sbi_scratch definition has changed, please redefine "
141         "SBI_SCRATCH_TMP0_OFFSET");
142 _Static_assert(
143         offsetof(struct sbi_scratch, options)
144                 == SBI_SCRATCH_OPTIONS_OFFSET,
145         "struct sbi_scratch definition has changed, please redefine "
146         "SBI_SCRATCH_OPTIONS_OFFSET");
147
148 /** Possible options for OpenSBI library */
149 enum sbi_scratch_options {
150         /** Disable prints during boot */
151         SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0),
152         /** Enable runtime debug prints */
153         SBI_SCRATCH_DEBUG_PRINTS = (1 << 1),
154 };
155
156 /** Get pointer to sbi_scratch for current HART */
157 #define sbi_scratch_thishart_ptr() \
158         ((struct sbi_scratch *)csr_read(CSR_MSCRATCH))
159
160 /** Get Arg1 of next booting stage for current HART */
161 #define sbi_scratch_thishart_arg1_ptr() \
162         ((void *)(sbi_scratch_thishart_ptr()->next_arg1))
163
164 /** Initialize scratch table and allocator */
165 int sbi_scratch_init(struct sbi_scratch *scratch);
166
167 /**
168  * Allocate from extra space in sbi_scratch
169  *
170  * @return zero on failure and non-zero (>= SBI_SCRATCH_EXTRA_SPACE_OFFSET)
171  * on success
172  */
173 unsigned long sbi_scratch_alloc_offset(unsigned long size);
174
175 /** Free-up extra space in sbi_scratch */
176 void sbi_scratch_free_offset(unsigned long offset);
177
178 /** Amount (in bytes) of used space in in sbi_scratch */
179 unsigned long sbi_scratch_used_space(void);
180
181 /** Get pointer from offset in sbi_scratch */
182 #define sbi_scratch_offset_ptr(scratch, offset) (void *)((char *)(scratch) + (offset))
183
184 /** Get pointer from offset in sbi_scratch for current HART */
185 #define sbi_scratch_thishart_offset_ptr(offset) \
186         (void *)((char *)sbi_scratch_thishart_ptr() + (offset))
187
188 /** Allocate offset for a data type in sbi_scratch */
189 #define sbi_scratch_alloc_type_offset(__type)                           \
190         sbi_scratch_alloc_offset(sizeof(__type))
191
192 /** Read a data type from sbi_scratch at given offset */
193 #define sbi_scratch_read_type(__scratch, __type, __offset)              \
194 ({                                                                      \
195         *((__type *)sbi_scratch_offset_ptr((__scratch), (__offset)));   \
196 })
197
198 /** Write a data type to sbi_scratch at given offset */
199 #define sbi_scratch_write_type(__scratch, __type, __offset, __ptr)      \
200 do {                                                                    \
201         *((__type *)sbi_scratch_offset_ptr((__scratch), (__offset)))    \
202                                         = (__type)(__ptr);              \
203 } while (0)
204
205 /** HART id to scratch table */
206 extern struct sbi_scratch *hartid_to_scratch_table[];
207
208 /** Get sbi_scratch from HART id */
209 #define sbi_hartid_to_scratch(__hartid) \
210         hartid_to_scratch_table[__hartid]
211
212 /** Last HART id having a sbi_scratch pointer */
213 extern u32 last_hartid_having_scratch;
214
215 /** Get last HART id having a sbi_scratch pointer */
216 #define sbi_scratch_last_hartid()       last_hartid_having_scratch
217
218 #endif
219
220 #endif