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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
|
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
/* $Source: src/ssx/ppc405/ppc405_cache_init.S $ */
/* */
/* OpenPOWER OnChipController Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2014,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
/* You may obtain a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
/* implied. See the License for the specific language governing */
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
/// \file ppc405_cache_init.S
/// \brief PPC405-specific procedures required for cache initialization
///
/// The routines in this file are not part of SSX per se, but are included
/// with SSX because they are used during initialialization and boot.
///
/// These are 'initialization' routines used by the SSX bootloader and other
/// application initialization code and may not be needed after
/// boot/initialization of the SSX application.
///
/// See the documents './doc/PowerPC 405-S Core Errata' and './doc/PowerPC
/// 405-S Core Errata Impact on PGP OCC Firmware' for information on the
/// CPU_xxx errata.
.nolist
#include "ssx.h"
#include "ppc405_context.h"
.list
/// \fn void icache_invalidate_all()
/// \brief Invalidate the entire I-Cache
///
/// In the PPC405 a single instruction invalidates the entire I-Cache,
/// therefore this routine need not be executed from a critical section.
///
///
/// This API always issues an isync() after the invalidation.
#ifdef DOXYGEN_ONLY
void icache_invalidate_all();
#endif
/// \cond
.global_function icache_invalidate_all
icache_invalidate_all:
_ssx_critical_section_enter SSX_SUPERCRITICAL, %r5, %r6
# Workaround for CPU_121: The iccci instruction may errantly
# cause a Data TLB exception. Workaround avoids this erratum by
# temporarily disabling data address translation.
mfmsr %r3
andi. %r4, %r3, 0xffef
mtmsr %r4
isync
## On the 405, iccci invalidates the entire I-Cache.
iccci %r0,%r0
# Restore MSR/DR bit
mtmsr %r3
isync
_ssx_critical_section_exit %r5
blr
.epilogue icache_invalidate_all
/// \endcond
/// \fn void dcache_invalidate_all()
/// \brief Invalidate the entire D-Cache
///
/// This API operates in an SSX_SUPERCRITICAL critical section. This API always
/// issues a sync() after the invalidation.
#ifdef DOXYGEN_ONLY
void dcache_invalidate_all();
#endif
/// \cond
.global_function dcache_invalidate_all
dcache_invalidate_all:
_ssx_critical_section_enter SSX_SUPERCRITICAL, %r5, %r6
## We loop through addresses 0 ... (DCACHE_SIZE / DCACHE_WAYS) - 1
## invalidating the D-Cache. The dccci instruction on the 405
## invalidates both ways.
li %r3, 0
_liwa %r4, (DCACHE_LINES / DCACHE_WAYS)
mtctr %r4
1:
dccci %r0, %r3
addi %r3, %r3, CACHE_LINE_SIZE
bdnz 1b
sync
_ssx_critical_section_exit %r5
blr
.epilogue dcache_invalidate_all
/// \endcond
#ifndef USE_GENERIC_DCACHE_FLUSH_ALL
#define USE_GENERIC_DCACHE_FLUSH_ALL 1
#endif
/// \fn void dcache_flush_all()
/// \brief Flush the entire D-Cache (Generic)
///
/// This API is necessary whenever it is required to change data cacheability
/// after boot. The D-cache is scanned, and any lines present in the cache are
/// flushed. This API operates in an SSX_SUPERCRITICAL critical section. This
/// API always issues a sync() after the flush.
///
/// This is a generic implementation that should work on all PPC405
/// systems. If something is known about the memory configuration then SSX
/// ports can implement better/more efficient flush-all algorithms.
///
/// This API runs with data translation disabled. This is necessary for
/// correctness, and also obviates the need to check whether a cache entry is
/// valid before flushing the entry.
///
/// This API is currently a NOP in Simics simulations which complain that the
/// dcread instruction is implemented as a NOP.
#ifdef DOXYGEN_ONLY
void dcache_flush_all();
#endif
/// \cond
#if USE_GENERIC_DCACHE_FLUSH_ALL
.global_function dcache_flush_all
dcache_flush_all:
#if !SIMICS_ENVIRONMENT
## %r3 used as temp throughout
## %r4 holds the original MSR throughout
## %r8 used as a temp throughout
## %r9 used as a temp throughout
_ssx_critical_section_enter SSX_SUPERCRITICAL, %r4, %r3
mfmsr %r3
_clrbit %r3, %r3, MSR_DR_BIT
mtmsr %r3
isync
## %r5 counts the congruence class address
## CTR counts the number of congruence classes
li %r5, 0
_liwa %r9, (DCACHE_LINES / DCACHE_WAYS)
mtctr %r9
## %r6 has the CCR0 value for reading DCACHE tag on way A
## %r7 has the CCR0 value for reading DCACHE tag on way B
## %r8 has the cache tag mask
mfccr0 %r6
_liwa %r9, 0x00000011
andc %r6, %r6, %r9 # Clear DCREAD control bits
ori %r6, %r6, 0x0010
ori %r7, %r6, 0x0001
_liwa %r8, DCACHE_TAG_MASK # Cache tag mask
dflush_loop:
## Way A
mtccr0 %r6 # Set CCR0 for DCREAD
dcread %r9, %r0, %r5
and %r9, %r9, %r8 # Mask out cache tag
or %r9, %r9, %r5 # OR in the congruence class address
dcbf %r0, %r9 # Flush the line
## Way B
mtccr0 %r7 # Set CCR0 for DCREAD
dcread %r9, %r0, %r5
and %r9, %r9, %r8 # Mask out cache tag
or %r9, %r9, %r5 # OR in the congruence class address
dcbf %r0, %r9 # Flush the line
addi %r5, %r5, CACHE_LINE_SIZE
bdnz dflush_loop
## Restore the MSR and return
_ssx_critical_section_exit %r4
#endif // SIMICS_ENVIRONMENT
blr
.epilogue dcache_flush_all
#endif // USE_GENERIC_DCACHE_FLUSH_ALL
/// \endcond
/// \fn int ppc405_ccr0_modify(uint32_t bits_to_clear, uint32_t bits_to_set)
/// \brief A special code sequence to modify the Cache Control Register 0 (CCR0)
///
/// \param bits_to_clear A positive mask of bits in CCR0 that will be cleared
/// by this call.
///
/// \param bits_to_set A positive mask of bits in CCR0 that will be set by
/// this call.
///
/// The code that implements this procedure \e must be in I-cacheable memory.
///
/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors
///
/// \retval 0 Successful completion.
///
/// \retval -SSX_ILLEGAL_CONTEXT_PPC405_CACHE The code implementing the API
/// is not cacheable.
///
#ifdef DOXYGEN_ONLY
int ppc405_ccr0_modify(uint32_t bits_to_clear, uint32_t bits_to_set);
#endif
/// \cond
## The implementation is based on an example from the 405GP manual.
.global_function ppc405_ccr0_modify
ppc405_ccr0_modify:
## %r3 is parameter bits_to_clear
## %r4 is parameter bits_to_set
## %r5 will hold the original MSR
## %r6 will hold the address of the update code.
## %r7, %r8, %r9 are used for computation.
## Disable external and critical interrupts
mfmsr %r5
_liwa %r6, (MSR_CE | MSR_EE)
andc %r6, %r5, %r6
mtmsr %r6 # Interrupts disabled
sync
.if SSX_ERROR_CHECK_API
## Check for cacheability of the code sequence
_liw %r6, ccr0_modify_doit
extrwi %r7, %r6, 5, 0 # Upper 5 bits are address range
mficcr %r8
_liwa %r9, 0x80000000
srw %r9, %r9, %r7 # %r9 holds bit to check in %r8
and. %r9, %r9, %r8
bne ccr0_modify_continue
## Whoops! Code not cacheable; restore MSR and return error code.
.if SSX_ERROR_PANIC
_ssx_panic SSX_ILLEGAL_CONTEXT_PPC405_CACHE
.else
_liwa %r3, -SSX_ILLEGAL_CONTEXT_PPC405_CACHE
mtmsr %r5
isync
.endif
blr
.endif
## Touch the code sequence into the I-Cache and do it.
ccr0_modify_continue:
icbt %r0, %r6
isync # Erratum CPU_208
b ccr0_modify_doit
## The ICBT is repeated to insure that the code is really in
## the cache. The bits are cleared, set, updated and we exit.
.cache_align # Must be cache-line aligned
ccr0_modify_doit:
icbt %r0, %r6
isync
mfccr0 %r7
andc %r7, %r7, %r3 # Clear some bits
or %r7, %r7, %r4 # Set some bits
mtccr0 %r7
isync
## Restore MSR and return 0.
li %r3, 0
mtmsr %r5
isync
blr
.epilogue ppc405_ccr0_modify
/// \endcond
|