1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2014 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "mmu/mmu_fmt.h"
25 
26 NvU64
mmuFmtAllPageSizes(const MMU_FMT_LEVEL * pLevel)27 mmuFmtAllPageSizes(const MMU_FMT_LEVEL *pLevel)
28 {
29     NvU32 i;
30     NvU64 mask = 0;
31     if (pLevel->bPageTable)
32     {
33         mask |= mmuFmtLevelPageSize(pLevel);
34     }
35     for (i = 0; i < pLevel->numSubLevels; ++i)
36     {
37         mask |= mmuFmtAllPageSizes(pLevel->subLevels + i);
38     }
39     return mask;
40 }
41 
42 NvU64
mmuFmtAllLevelCoverages(const MMU_FMT_LEVEL * pLevel)43 mmuFmtAllLevelCoverages(const MMU_FMT_LEVEL *pLevel)
44 {
45     NvU32 i;
46     NvU64 mask = mmuFmtLevelPageSize(pLevel);
47     for (i = 0; i < pLevel->numSubLevels; ++i)
48     {
49         mask |= mmuFmtAllLevelCoverages(pLevel->subLevels + i);
50     }
51     return mask;
52 }
53 
54 const MMU_FMT_LEVEL *
mmuFmtFindLevelWithPageShift(const MMU_FMT_LEVEL * pLevel,const NvU64 pageShift)55 mmuFmtFindLevelWithPageShift
56 (
57     const MMU_FMT_LEVEL *pLevel,
58     const NvU64          pageShift
59 )
60 {
61     NvU32 i;
62     if (pLevel->virtAddrBitLo == pageShift)
63     {
64         return pLevel;
65     }
66     for (i = 0; i < pLevel->numSubLevels; ++i)
67     {
68         const MMU_FMT_LEVEL *pRes =
69             mmuFmtFindLevelWithPageShift(pLevel->subLevels + i, pageShift);
70         if (NULL != pRes)
71         {
72             return pRes;
73         }
74     }
75     return NULL;
76 }
77 
78 const MMU_FMT_LEVEL *
mmuFmtFindLevelParent(const MMU_FMT_LEVEL * pRoot,const MMU_FMT_LEVEL * pLevel,NvU32 * pSubLevel)79 mmuFmtFindLevelParent
80 (
81     const MMU_FMT_LEVEL *pRoot,
82     const MMU_FMT_LEVEL *pLevel,
83     NvU32               *pSubLevel
84 )
85 {
86     NvU32 i;
87     for (i = 0; i < pRoot->numSubLevels; ++i)
88     {
89         const MMU_FMT_LEVEL *pRes;
90         if ((pRoot->subLevels + i) == pLevel)
91         {
92             if (NULL != pSubLevel)
93             {
94                 *pSubLevel = i;
95             }
96             pRes = pRoot;
97         }
98         else
99         {
100             pRes = mmuFmtFindLevelParent(pRoot->subLevels + i, pLevel, pSubLevel);
101         }
102         if (NULL != pRes)
103         {
104             return pRes;
105         }
106     }
107     return NULL;
108 }
109 
110 const MMU_FMT_LEVEL *
mmuFmtGetNextLevel(const MMU_FMT_LEVEL * pLevelFmt,const MMU_FMT_LEVEL * pTargetFmt)111 mmuFmtGetNextLevel
112 (
113     const MMU_FMT_LEVEL *pLevelFmt,
114     const MMU_FMT_LEVEL *pTargetFmt
115 )
116 {
117     if (pLevelFmt != pTargetFmt)
118     {
119         NvU32 subLevel = 0;
120         if (1 == pLevelFmt->numSubLevels)
121         {
122             return pLevelFmt->subLevels;
123         }
124         for (subLevel = 0; subLevel < pLevelFmt->numSubLevels; ++subLevel)
125         {
126             const MMU_FMT_LEVEL *pSubLevelFmt = pLevelFmt->subLevels + subLevel;
127             if (pSubLevelFmt == pTargetFmt)
128             {
129                 return pSubLevelFmt;
130             }
131         }
132     }
133     return NULL;
134 }
135 
136 const char*
mmuFmtConvertLevelIdToSuffix(const MMU_FMT_LEVEL * pLevelFmt)137 mmuFmtConvertLevelIdToSuffix
138 (
139     const MMU_FMT_LEVEL *pLevelFmt
140 )
141 {
142     switch (pLevelFmt->pageLevelIdTag)
143     {
144         case MMU_FMT_PT_SURF_ID_PD0:
145             return "_pd0";
146         case MMU_FMT_PT_SURF_ID_PD1:
147             return "_pd1";
148         case MMU_FMT_PT_SURF_ID_PD2:
149             return "_pd2";
150         case MMU_FMT_PT_SURF_ID_PD3:
151             return "_pd3";
152         case MMU_FMT_PT_SURF_ID_PD4:
153             return "_pd4";
154         case MMU_FMT_PT_SURF_ID_PT_4K:
155             return "_pt_4k";
156         case MMU_FMT_PT_SURF_ID_PT_BIG:
157             return "_pt_big";
158         default:
159             return NULL;
160     }
161 }
162 
163