summaryrefslogtreecommitdiff
path: root/include/sbi/sbi_scratch.h
blob: 40a3bc93c6dd4870503430555cca8ea558b26d70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2019 Western Digital Corporation or its affiliates.
 *
 * Authors:
 *   Anup Patel <anup.patel@wdc.com>
 */

#ifndef __SBI_SCRATCH_H__
#define __SBI_SCRATCH_H__

#include <sbi/riscv_asm.h>

/* clang-format off */

/** Offset of fw_start member in sbi_scratch */
#define SBI_SCRATCH_FW_START_OFFSET		(0 * __SIZEOF_POINTER__)
/** Offset of fw_size member in sbi_scratch */
#define SBI_SCRATCH_FW_SIZE_OFFSET		(1 * __SIZEOF_POINTER__)
/** Offset of next_arg1 member in sbi_scratch */
#define SBI_SCRATCH_NEXT_ARG1_OFFSET		(2 * __SIZEOF_POINTER__)
/** Offset of next_addr member in sbi_scratch */
#define SBI_SCRATCH_NEXT_ADDR_OFFSET		(3 * __SIZEOF_POINTER__)
/** Offset of next_mode member in sbi_scratch */
#define SBI_SCRATCH_NEXT_MODE_OFFSET		(4 * __SIZEOF_POINTER__)
/** Offset of warmboot_addr member in sbi_scratch */
#define SBI_SCRATCH_WARMBOOT_ADDR_OFFSET	(5 * __SIZEOF_POINTER__)
/** Offset of platform_addr member in sbi_scratch */
#define SBI_SCRATCH_PLATFORM_ADDR_OFFSET	(6 * __SIZEOF_POINTER__)
/** Offset of hartid_to_scratch member in sbi_scratch */
#define SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET	(7 * __SIZEOF_POINTER__)
/** Offset of trap_exit member in sbi_scratch */
#define SBI_SCRATCH_TRAP_EXIT_OFFSET		(8 * __SIZEOF_POINTER__)
/** Offset of tmp0 member in sbi_scratch */
#define SBI_SCRATCH_TMP0_OFFSET			(9 * __SIZEOF_POINTER__)
/** Offset of options member in sbi_scratch */
#define SBI_SCRATCH_OPTIONS_OFFSET		(10 * __SIZEOF_POINTER__)
/** Offset of extra space in sbi_scratch */
#define SBI_SCRATCH_EXTRA_SPACE_OFFSET		(11 * __SIZEOF_POINTER__)
/** Maximum size of sbi_scratch (4KB) */
#define SBI_SCRATCH_SIZE			(0x1000)

/* clang-format on */

#ifndef __ASSEMBLER__

#include <sbi/sbi_types.h>

/** Representation of per-HART scratch space */
struct sbi_scratch {
	/** Start (or base) address of firmware linked to OpenSBI library */
	unsigned long fw_start;
	/** Size (in bytes) of firmware linked to OpenSBI library */
	unsigned long fw_size;
	/** Arg1 (or 'a1' register) of next booting stage for this HART */
	unsigned long next_arg1;
	/** Address of next booting stage for this HART */
	unsigned long next_addr;
	/** Privilege mode of next booting stage for this HART */
	unsigned long next_mode;
	/** Warm boot entry point address for this HART */
	unsigned long warmboot_addr;
	/** Address of sbi_platform */
	unsigned long platform_addr;
	/** Address of HART ID to sbi_scratch conversion function */
	unsigned long hartid_to_scratch;
	/** Address of trap exit function */
	unsigned long trap_exit;
	/** Temporary storage */
	unsigned long tmp0;
	/** Options for OpenSBI library */
	unsigned long options;
};

/**
 * Prevent modification of struct sbi_scratch from affecting
 * SBI_SCRATCH_xxx_OFFSET
 */
_Static_assert(
	offsetof(struct sbi_scratch, fw_start)
		== SBI_SCRATCH_FW_START_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_FW_START_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, fw_size)
		== SBI_SCRATCH_FW_SIZE_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_FW_SIZE_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, next_arg1)
		== SBI_SCRATCH_NEXT_ARG1_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_NEXT_ARG1_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, next_addr)
		== SBI_SCRATCH_NEXT_ADDR_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_NEXT_ADDR_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, next_mode)
		== SBI_SCRATCH_NEXT_MODE_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_NEXT_MODE_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, warmboot_addr)
		== SBI_SCRATCH_WARMBOOT_ADDR_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_WARMBOOT_ADDR_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, platform_addr)
		== SBI_SCRATCH_PLATFORM_ADDR_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_PLATFORM_ADDR_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, hartid_to_scratch)
		== SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, trap_exit)
		== SBI_SCRATCH_TRAP_EXIT_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_TRAP_EXIT_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, tmp0)
		== SBI_SCRATCH_TMP0_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_TMP0_OFFSET");
_Static_assert(
	offsetof(struct sbi_scratch, options)
		== SBI_SCRATCH_OPTIONS_OFFSET,
	"struct sbi_scratch definition has changed, please redefine "
	"SBI_SCRATCH_OPTIONS_OFFSET");

/** Possible options for OpenSBI library */
enum sbi_scratch_options {
	/** Disable prints during boot */
	SBI_SCRATCH_NO_BOOT_PRINTS = (1 << 0),
	/** Enable runtime debug prints */
	SBI_SCRATCH_DEBUG_PRINTS = (1 << 1),
};

/** Get pointer to sbi_scratch for current HART */
#define sbi_scratch_thishart_ptr() \
	((struct sbi_scratch *)csr_read(CSR_MSCRATCH))

/** Get Arg1 of next booting stage for current HART */
#define sbi_scratch_thishart_arg1_ptr() \
	((void *)(sbi_scratch_thishart_ptr()->next_arg1))

/** Initialize scratch table and allocator */
int sbi_scratch_init(struct sbi_scratch *scratch);

/**
 * Allocate from extra space in sbi_scratch
 *
 * @return zero on failure and non-zero (>= SBI_SCRATCH_EXTRA_SPACE_OFFSET)
 * on success
 */
unsigned long sbi_scratch_alloc_offset(unsigned long size);

/** Free-up extra space in sbi_scratch */
void sbi_scratch_free_offset(unsigned long offset);

/** Get pointer from offset in sbi_scratch */
#define sbi_scratch_offset_ptr(scratch, offset)	(void *)((char *)(scratch) + (offset))

/** Get pointer from offset in sbi_scratch for current HART */
#define sbi_scratch_thishart_offset_ptr(offset)	\
	(void *)((char *)sbi_scratch_thishart_ptr() + (offset))

/** HART id to scratch table */
extern struct sbi_scratch *hartid_to_scratch_table[];

/** Get sbi_scratch from HART id */
#define sbi_hartid_to_scratch(__hartid) \
	hartid_to_scratch_table[__hartid]

/** Last HART id having a sbi_scratch pointer */
extern u32 last_hartid_having_scratch;

/** Get last HART id having a sbi_scratch pointer */
#define sbi_scratch_last_hartid()	last_hartid_having_scratch

#endif

#endif