1//++
2// Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
3// This program and the accompanying materials
4// are licensed and made available under the terms and conditions of the BSD License
5// which accompanies this distribution.  The full text of the license may be found at
6// http://opensource.org/licenses/bsd-license.php.
7//
8// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10//
11//  Module Name:
12//    InternalFlushCacheRange.s
13//
14//  Abstract:
15//    Assemble routine to flush cache lines
16//
17// Revision History:
18//
19//--
20.file  "IpfCpuCache.s"
21
22#include <IpfMacro.i>
23
24//
25//  Internal worker function to invalidate a range of instruction cache lines
26//  in the cache coherency domain of the calling CPU.
27//
28//  Internal worker function to invalidate the instruction cache lines specified
29//  by Address and Length. If Address is not aligned on a cache line boundary,
30//  then entire instruction cache line containing Address is invalidated. If
31//  Address + Length is not aligned on a cache line boundary, then the entire
32//  instruction cache line containing Address + Length -1 is invalidated. This
33//  function may choose to invalidate the entire instruction cache if that is more
34//  efficient than invalidating the specified range. If Length is 0, the no instruction
35//  cache lines are invalidated. Address is returned.
36//  This function is only available on IPF.
37//
38//  @param  Address The base address of the instruction cache lines to
39//                  invalidate. If the CPU is in a physical addressing mode, then
40//                  Address is a physical address. If the CPU is in a virtual
41//                  addressing mode, then Address is a virtual address.
42//
43//  @param  Length  The number of bytes to invalidate from the instruction cache.
44//
45//  @return Address
46//
47//  VOID *
48//  EFIAPI
49//  InternalFlushCacheRange (
50//    IN      VOID                      *Address,
51//    IN      UINTN                     Length
52//    );
53//
54PROCEDURE_ENTRY (InternalFlushCacheRange)
55
56      NESTED_SETUP (5,8,0,0)
57
58      mov         loc2 = ar.lc
59
60      mov         loc3 = in0                  // Start address.
61      mov         loc4 = in1;;                // Length in bytes.
62
63      cmp.eq  p6,p7 = loc4, r0;;               // If Length is zero then don't flush any cache
64      (p6)  br.spnt.many DoneFlushingC;;
65
66      add         loc4 = loc4,loc3
67      mov         loc5 = 1;;
68      sub         loc4 = loc4, loc5 ;; // the End address to flush
69
70      dep         loc3 = r0,loc3,0,5
71      dep         loc4 = r0,loc4,0,5;;
72      shr         loc3 = loc3,5
73      shr         loc4 = loc4,5;;    // 32 byte cache line
74
75      sub         loc4 = loc4,loc3;; // total flush count, It should be add 1 but
76                                     // the br.cloop will first execute one time
77      mov         loc3 = in0
78      mov         loc5 = 32
79      mov         ar.lc = loc4;;
80
81StillFlushingC:
82      fc          loc3;;
83      sync.i;;
84      srlz.i;;
85      add         loc3 = loc5,loc3;;
86      br.cloop.sptk.few StillFlushingC;;
87
88DoneFlushingC:
89      mov         ar.lc = loc2
90      mov          r8   = in0       // return *Address
91      NESTED_RETURN
92
93PROCEDURE_EXIT (InternalFlushCacheRange)
94
95