Skip to content

Commit fb5539b

Browse files
committed
cache: Provide an alternative cache API
SyncDCache/InvalidDCache are annoying to use because of their provided range being inclusive at both ends, it's too easy to accidentally affect an extra cache line at the end. This provides a new cache API and implements the older ones using it.
1 parent 66d9a3e commit fb5539b

File tree

2 files changed

+133
-47
lines changed

2 files changed

+133
-47
lines changed

ee/kernel/include/cache.h

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#ifndef CACHE_H_
2+
#define CACHE_H_
3+
4+
#define CACHE_LINE_SIZE 0x40
5+
#define CACHE_LINE_MASK (~(CACHE_LINE_SIZE - 1))
6+
7+
#define OP_IHIN 0x0b /* Instruction cache: Hit INvalidate. */
8+
#define OP_DXWBIN 0x14 /* Data cache: indeX WriteBack INvalidate. */
9+
#define OP_DXIN 0x16 /* Data cache: indeX INvalidate. */
10+
#define OP_DHWBIN 0x18 /* Data cache: Hit WriteBack INvalidate. */
11+
#define OP_DHIN 0x1a /* Data cache: Hit INvalidate. */
12+
13+
#define DCACHE_OP_LINE(op, line) \
14+
__asm__ volatile( \
15+
".set push \n" \
16+
".set noreorder \n" \
17+
"sync.l \n" \
18+
"cache %0, 0(%1) \n" \
19+
"sync.l \n" \
20+
".set pop \n" \
21+
: \
22+
: "i"(op), "r"(line));
23+
24+
#define ICACHE_OP_LINE(op, line) \
25+
__asm__ volatile( \
26+
".set push \n" \
27+
".set noreorder \n" \
28+
"sync.p \n" \
29+
"cache %0, 0(%1) \n" \
30+
"sync.p \n" \
31+
".set pop \n" \
32+
: \
33+
: "i"(op), "r"(line));
34+
35+
/* Single line operations */
36+
static inline void dcache_writeback_line(unsigned addr)
37+
{
38+
DCACHE_OP_LINE(OP_DHWBIN, addr);
39+
}
40+
41+
static inline void dcache_invalid_line(unsigned addr)
42+
{
43+
DCACHE_OP_LINE(OP_DHIN, addr);
44+
}
45+
46+
static inline void icache_invalid_line(unsigned addr)
47+
{
48+
ICACHE_OP_LINE(OP_IHIN, addr);
49+
}
50+
51+
/*
52+
* The standard SyncDCache/InvalidDCache functions have a slightly awkward
53+
* API in that the range is inclusive of both the start and end, requiring
54+
* you to remember to substract from the end to avoid affecting unrelated
55+
* cache lines.
56+
*
57+
*
58+
* These functions are exclusive of the end and can therefore be used
59+
* with sizeof in less error-prone way.
60+
* e.g. dcache_writeback_range(&mystruct, &mystruct + sizeof(mystruct));
61+
*/
62+
63+
/*
64+
* Write back data cache lines corresponding to range [start, end)
65+
*/
66+
static inline void dcache_writeback_range(unsigned start, unsigned end)
67+
{
68+
start = start & CACHE_LINE_MASK;
69+
end = (end - 1) & CACHE_LINE_MASK;
70+
71+
while (1) {
72+
dcache_writeback_line(start);
73+
if (start == end) {
74+
break;
75+
}
76+
start += CACHE_LINE_SIZE;
77+
}
78+
}
79+
80+
/*
81+
* Invalidate data cache lines corresponding to range [start, end)
82+
*/
83+
static inline void dcache_invalid_range(unsigned start, unsigned end)
84+
{
85+
start = start & CACHE_LINE_MASK;
86+
end = (end - 1) & CACHE_LINE_MASK;
87+
88+
while (1) {
89+
dcache_invalid_line(start);
90+
if (start == end) {
91+
break;
92+
}
93+
start += CACHE_LINE_SIZE;
94+
}
95+
}
96+
97+
/*
98+
* Invalidate instruction cache lines corresponding to range [start, end)
99+
* This also automatically invalidates the relevant BTAC entries.
100+
*/
101+
static inline void icache_invalid_range(unsigned start, unsigned end)
102+
{
103+
start = start & CACHE_LINE_MASK;
104+
end = (end - 1) & CACHE_LINE_MASK;
105+
106+
while (1) {
107+
icache_invalid_line(start);
108+
if (start == end) {
109+
break;
110+
}
111+
start += CACHE_LINE_SIZE;
112+
}
113+
}
114+
115+
116+
#endif // CACHE_H_

ee/kernel/src/cache.c

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,48 @@
1-
#include "kernel.h"
2-
3-
#define LINE_SIZE 0x40
4-
#define LINE_MASK (~(LINE_SIZE - 1))
5-
6-
#define DXWBIN 0x14 /* Data cache: indeX WriteBack INvalidate. */
7-
#define DXIN 0x16 /* Data cache: indeX INvalidate. */
8-
#define DHWBIN 0x18 /* Data cache: Hit WriteBack INvalidate. */
9-
#define DHIN 0x1a /* Data cache: Hit INvalidate. */
10-
11-
#define DCACHE_OP_LINE(op, line) \
12-
__asm__ volatile( \
13-
".set push \n" \
14-
".set noreorder \n" \
15-
"sync.l \n" \
16-
"cache %0, 0(%1) \n" \
17-
"sync.l \n" \
18-
".set pop \n" \
19-
: \
20-
: "i"(op), "r"(start));
21-
22-
23-
static inline void _SyncDCache(u32 start, u32 end)
24-
{
25-
while (1) {
26-
DCACHE_OP_LINE(DHWBIN, start);
27-
if (start == end) {
28-
break;
29-
}
30-
start += LINE_SIZE;
31-
}
32-
}
1+
#include "cache.h"
332

34-
static inline void _InvalidDCache(u32 start, u32 end)
35-
{
36-
while (1) {
37-
DCACHE_OP_LINE(DHIN, start);
38-
if (start == end) {
39-
break;
40-
}
41-
start += LINE_SIZE;
42-
}
43-
}
3+
#include "kernel.h"
444

5+
/*
6+
* Write back data cache lines corresponding to range [start, end)
7+
*/
458
#ifdef F_sceSifWriteBackDCache
469
void sceSifWriteBackDCache(void *ptr, int size)
4710
{
48-
_SyncDCache((u32)ptr & LINE_MASK, ((u32)(ptr) + size - 1) & LINE_MASK);
11+
dcache_writeback_range((u32)ptr, (u32)ptr + size);
4912
}
5013
#endif
5114

15+
/*
16+
* These functions affect range [start, end]
17+
* (Inclusive on both sides)
18+
*
19+
* e.g. SyncDCache(0x0, 0x40) would affect two cache lines.
20+
*/
21+
5222
#ifdef F_SyncDCache
5323
void SyncDCache(void *start, void *end)
5424
{
55-
_SyncDCache((u32)start & LINE_MASK, (u32)end & LINE_MASK);
25+
dcache_writeback_range((u32)start, (u32)end + 1);
5626
}
5727
#endif
5828

5929
#ifdef F_iSyncDCache
6030
void iSyncDCache(void *start, void *end)
6131
{
62-
_SyncDCache((u32)start & LINE_MASK, (u32)end & LINE_MASK);
32+
dcache_writeback_range((u32)start, (u32)end + 1);
6333
}
6434
#endif
6535

6636
#ifdef F_InvalidDCache
6737
void InvalidDCache(void *start, void *end)
6838
{
69-
_InvalidDCache((u32)start & LINE_MASK, (u32)end & LINE_MASK);
39+
dcache_invalid_range((u32)start, (u32)end + 1);
7040
}
7141
#endif
7242

7343
#ifdef F_iInvalidDCache
7444
void iInvalidDCache(void *start, void *end)
7545
{
76-
_InvalidDCache((u32)start & LINE_MASK, (u32)end & LINE_MASK);
46+
dcache_invalid_range((u32)start, (u32)end + 1);
7747
}
7848
#endif

0 commit comments

Comments
 (0)