summaryrefslogtreecommitdiffstats
path: root/src/ssx/ppc405/ppc405_cache_core.c
blob: a03f5e2d5dc75d6ed87cd7f9c3cb2845f88cf69e (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
// $Id: ppc405_cache_core.c,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_cache_core.c,v $
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2013
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------

/// \file ppc405_cache_core.c
/// \brief Core cache management routines required of any PPC405 configuration
/// of SSX that interacts with DMA devices using cacheable memory. 
///
///  The entry points in this file are considered 'core' routines that will
///  always be present at runtime in any SSX application.
///
///  \todo The compiler generates wierd assembly language for these cache
///  management APIs - probably due to the "volatile" asm - it may be best to
///  recode them directly in assembler.

#include "ssx.h"

/// Invalidate a range of addresses from the D-cache
///
/// \param p A pointer to the memory area to be invalidated.
///
/// \param bytes The size (in bytes) of the area to invalidate.
///
/// The dcache_invalidate() API is used to invalidate an arbitrary range of
/// memory in the cache. Note that invalidation is a destructive operation
/// that may cause the loss of information.  This API will invalidate all
/// cache lines from the line containing the address \a p, to the line
/// containing the address \a p + \a size - 1.  (If \a size == 0 this call is
/// a NOP.) It is the caller's responsibility to insure that no useful data is
/// inadverdently invalidated.  D-cache invalidation is more-or-less a no-op
/// for data either not in the cache or marked as non-cacheable.
///
/// This API always issues a sync() after the invalidation, even in the event
/// of \a size == 0.
///
/// \note For invalidating small blocks of data where some alignmment
/// constraints are known it may be more efficient to use
/// dcache_invalidate_line() rather than this API.

void
dcache_invalidate(void *p, size_t bytes)
{
    size_t lines;

    if (bytes != 0) {
        lines = 1;
        bytes -=  
            MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)),
                bytes);
        lines += bytes / CACHE_LINE_SIZE;
        if (!cache_aligned(bytes)) {
            lines++;
        }
        while (lines--) {
            dcbi(p);
            p += CACHE_LINE_SIZE;
        }
    }
    sync();
}
         

/// Flush and invalidate a range of addresses from the D-cache
///
/// \param p A pointer to a memory area to be invalidated.
///
/// \param bytes The size (in bytes) of the area to invalidate.
///
/// The dcache_flush() API is used to flush and invalidate an arbitrary range
/// of memory from the D-cache. Note that flushing is not a destructive
/// operation in the sense that no information is lost.  This API will flush
/// and invalidate all cache lines from the line containing the address \a p,
/// to the line containing the address \a p + \a size - 1.  (If \a size == 0
/// this call is a NOP.)  D-cache flush is more-or-less a no-op for data
/// either not in the cache or marked as non-cacheable.
///
/// This API always issues a sync() after the flush, even in the event of \a
/// size == 0.
///
/// \note For flushing small blocks of data where some alignmment constraints
/// are known it may be more efficient to use dcache_flush_line() rather than
/// this API.


void
dcache_flush(void *p, size_t bytes)
{
    size_t lines;

    if (bytes != 0) {
        lines = 1;
        bytes -=  
            MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)),
                bytes);
        lines += bytes / CACHE_LINE_SIZE;
        if (!cache_aligned(bytes)) {
            lines++;
        }
        while (lines--) {
            dcbf(p);
            p += CACHE_LINE_SIZE;
        }
    }
    sync();
}
         
        

        


OpenPOWER on IntegriCloud