Skip to content

Commit 58c34fd

Browse files
Enhance PageTable testing
- and mock PageTables with entries access - new test checking correct entries filling Change-Id: I4ad70aac2915f0ff2611c65a8480dadcf87c0b8d
1 parent be4c2cc commit 58c34fd

File tree

5 files changed

+169
-77
lines changed

5 files changed

+169
-77
lines changed

runtime/memory_manager/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ set(RUNTIME_SRCS_MEMORY_MANAGER
3939
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_agnostic_memory_manager_allocate_in_device_pool.cpp
4040
${CMAKE_CURRENT_SOURCE_DIR}/page_table.cpp
4141
${CMAKE_CURRENT_SOURCE_DIR}/page_table.h
42+
${CMAKE_CURRENT_SOURCE_DIR}/page_table.inl
4243
${CMAKE_CURRENT_SOURCE_DIR}/residency.h
4344
${CMAKE_CURRENT_SOURCE_DIR}/residency.cpp
4445
${CMAKE_CURRENT_SOURCE_DIR}/residency_container.h

runtime/memory_manager/page_table.cpp

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,13 @@
2121
*/
2222

2323
#include "runtime/memory_manager/page_table.h"
24-
25-
#include <inttypes.h>
26-
#include <iostream>
24+
#include "runtime/memory_manager/page_table.inl"
2725

2826
namespace OCLRT {
2927

3028
const uint32_t PTE::initialPage = 1;
3129
std::atomic<uint32_t> PTE::nextPage(PTE::initialPage);
3230

33-
template <>
34-
uintptr_t PageTable<void, 0, 9>::map(uintptr_t vm, size_t size) {
35-
return 0;
36-
}
37-
38-
template <>
39-
size_t PageTable<void, 0, 9>::getBits() {
40-
return 9;
41-
}
42-
4331
uintptr_t PTE::map(uintptr_t vm, size_t size) {
4432
const size_t shift = 12;
4533
const uint32_t mask = (1 << bits) - 1;
@@ -57,30 +45,6 @@ uintptr_t PTE::map(uintptr_t vm, size_t size) {
5745
return (res & ~0x1) + (vm & (pageSize - 1));
5846
}
5947

60-
template <class T, uint32_t level, uint32_t bits>
61-
uintptr_t PageTable<T, level, bits>::map(uintptr_t vm, size_t size) {
62-
const size_t shift = T::getBits() + 12;
63-
const uintptr_t mask = (1 << bits) - 1;
64-
size_t indexStart = (vm >> shift) & mask;
65-
size_t indexEnd = ((vm + size - 1) >> shift) & mask;
66-
uintptr_t res = -1;
67-
uintptr_t vmMask = (uintptr_t(-1) >> (sizeof(void *) * 8 - shift - bits));
68-
auto maskedVm = vm & vmMask;
69-
70-
for (size_t index = indexStart; index <= indexEnd; index++) {
71-
uintptr_t vmStart = (uintptr_t(1) << shift) * index;
72-
vmStart = std::max(vmStart, maskedVm);
73-
uintptr_t vmEnd = (uintptr_t(1) << shift) * (index + 1) - 1;
74-
vmEnd = std::min(vmEnd, maskedVm + size - 1);
75-
76-
if (entries[index] == nullptr) {
77-
entries[index] = new T;
78-
}
79-
res = std::min((entries[index])->map(vmStart, vmEnd - vmStart + 1), res);
80-
}
81-
return res;
82-
}
83-
8448
void PTE::pageWalk(uintptr_t vm, size_t size, size_t offset, PageWalker &pageWalker) {
8549
static const uint32_t bits = 9;
8650
const size_t shift = 12;
@@ -106,44 +70,6 @@ void PTE::pageWalk(uintptr_t vm, size_t size, size_t offset, PageWalker &pageWal
10670
}
10771
}
10872

109-
template <>
110-
void PageTable<void, 0, 9>::pageWalk(uintptr_t vm, size_t size, size_t offset, PageWalker &pageWalker) {
111-
}
112-
113-
template <class T, uint32_t level, uint32_t bits>
114-
void PageTable<T, level, bits>::pageWalk(uintptr_t vm, size_t size, size_t offset, PageWalker &pageWalker) {
115-
const size_t shift = T::getBits() + 12;
116-
const uintptr_t mask = (1 << bits) - 1;
117-
size_t indexStart = (vm >> shift) & mask;
118-
size_t indexEnd = ((vm + size - 1) >> shift) & mask;
119-
uintptr_t vmMask = (uintptr_t(-1) >> (sizeof(void *) * 8 - shift - bits));
120-
auto maskedVm = vm & vmMask;
121-
122-
for (size_t index = indexStart; index <= indexEnd; index++) {
123-
uintptr_t vmStart = (uintptr_t(1) << shift) * index;
124-
vmStart = std::max(vmStart, maskedVm);
125-
uintptr_t vmEnd = (uintptr_t(1) << shift) * (index + 1) - 1;
126-
vmEnd = std::min(vmEnd, maskedVm + size - 1);
127-
128-
if (entries[index] == nullptr) {
129-
entries[index] = new T;
130-
}
131-
entries[index]->pageWalk(vmStart, vmEnd - vmStart + 1, offset, pageWalker);
132-
133-
offset += (vmEnd - vmStart + 1);
134-
}
135-
}
136-
137-
template <>
138-
PageTable<void, 0, 9>::~PageTable() {
139-
}
140-
141-
template <class T, uint32_t level, uint32_t bits>
142-
PageTable<T, level, bits>::~PageTable() {
143-
for (auto &e : entries)
144-
delete e;
145-
}
146-
14773
template class PageTable<class PDP, 3, 9>;
14874
template class PageTable<class PDE, 2, 2>;
14975
} // namespace OCLRT

runtime/memory_manager/page_table.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323
#pragma once
2424
#include "runtime/helpers/basic_math.h"
2525

26-
#include <functional>
27-
#include <atomic>
2826
#include <array>
27+
#include <atomic>
28+
#include <cinttypes>
29+
#include <functional>
2930
#include <memory>
3031
#include <vector>
3132

runtime/memory_manager/page_table.inl

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2018, Intel Corporation
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a
5+
* copy of this software and associated documentation files (the "Software"),
6+
* to deal in the Software without restriction, including without limitation
7+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
* and/or sell copies of the Software, and to permit persons to whom the
9+
* Software is furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included
12+
* in all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18+
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19+
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20+
* OTHER DEALINGS IN THE SOFTWARE.
21+
*/
22+
23+
namespace OCLRT {
24+
25+
template <>
26+
inline uintptr_t PageTable<void, 0, 9>::map(uintptr_t vm, size_t size) {
27+
return 0;
28+
}
29+
30+
template <>
31+
inline size_t PageTable<void, 0, 9>::getBits() {
32+
return 9;
33+
}
34+
35+
template <>
36+
inline void PageTable<void, 0, 9>::pageWalk(uintptr_t vm, size_t size, size_t offset, PageWalker &pageWalker) {
37+
}
38+
39+
template <>
40+
inline PageTable<void, 0, 9>::~PageTable() {
41+
}
42+
43+
template <class T, uint32_t level, uint32_t bits>
44+
inline uintptr_t PageTable<T, level, bits>::map(uintptr_t vm, size_t size) {
45+
const size_t shift = T::getBits() + 12;
46+
const uintptr_t mask = (1 << bits) - 1;
47+
size_t indexStart = (vm >> shift) & mask;
48+
size_t indexEnd = ((vm + size - 1) >> shift) & mask;
49+
uintptr_t res = -1;
50+
uintptr_t vmMask = (uintptr_t(-1) >> (sizeof(void *) * 8 - shift - bits));
51+
auto maskedVm = vm & vmMask;
52+
53+
for (size_t index = indexStart; index <= indexEnd; index++) {
54+
uintptr_t vmStart = (uintptr_t(1) << shift) * index;
55+
vmStart = std::max(vmStart, maskedVm);
56+
uintptr_t vmEnd = (uintptr_t(1) << shift) * (index + 1) - 1;
57+
vmEnd = std::min(vmEnd, maskedVm + size - 1);
58+
59+
if (entries[index] == nullptr) {
60+
entries[index] = new T;
61+
}
62+
res = std::min((entries[index])->map(vmStart, vmEnd - vmStart + 1), res);
63+
}
64+
return res;
65+
}
66+
67+
template <class T, uint32_t level, uint32_t bits>
68+
inline void PageTable<T, level, bits>::pageWalk(uintptr_t vm, size_t size, size_t offset, PageWalker &pageWalker) {
69+
const size_t shift = T::getBits() + 12;
70+
const uintptr_t mask = (1 << bits) - 1;
71+
size_t indexStart = (vm >> shift) & mask;
72+
size_t indexEnd = ((vm + size - 1) >> shift) & mask;
73+
uintptr_t vmMask = (uintptr_t(-1) >> (sizeof(void *) * 8 - shift - bits));
74+
auto maskedVm = vm & vmMask;
75+
76+
for (size_t index = indexStart; index <= indexEnd; index++) {
77+
uintptr_t vmStart = (uintptr_t(1) << shift) * index;
78+
vmStart = std::max(vmStart, maskedVm);
79+
uintptr_t vmEnd = (uintptr_t(1) << shift) * (index + 1) - 1;
80+
vmEnd = std::min(vmEnd, maskedVm + size - 1);
81+
82+
if (entries[index] == nullptr) {
83+
entries[index] = new T;
84+
}
85+
entries[index]->pageWalk(vmStart, vmEnd - vmStart + 1, offset, pageWalker);
86+
87+
offset += (vmEnd - vmStart + 1);
88+
}
89+
}
90+
91+
template <class T, uint32_t level, uint32_t bits>
92+
inline PageTable<T, level, bits>::~PageTable() {
93+
for (auto &e : entries)
94+
delete e;
95+
}
96+
97+
} // namespace OCLRT

unit_tests/memory_manager/page_table_tests.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "runtime/helpers/selectors.h"
2424
#include "runtime/memory_manager/page_table.h"
25+
#include "runtime/memory_manager/page_table.inl"
2526
#include "test.h"
2627
#include "gtest/gtest.h"
2728
#include "unit_tests/helpers/memory_management.h"
@@ -58,6 +59,40 @@ TEST_F(PTETest, physicalAddressesInAUBCantStartAt0) {
5859
EXPECT_NE(0u, physAddress);
5960
}
6061

62+
template <class T, uint32_t level, uint32_t bits = 9>
63+
class MockPageTable : public PageTable<T, level, bits> {
64+
public:
65+
using PageTable<T, level, bits>::PageTable;
66+
using PageTable<T, level, bits>::entries;
67+
};
68+
69+
class MockPTE : public PTE {
70+
public:
71+
using PTE::entries;
72+
73+
uintptr_t map(uintptr_t vm, size_t size) override {
74+
return PTE::map(vm, size);
75+
}
76+
void pageWalk(uintptr_t vm, size_t size, size_t offset, PageWalker &pageWalker) override {
77+
return PTE::pageWalk(vm, size, offset, pageWalker);
78+
}
79+
};
80+
81+
class MockPDE : public MockPageTable<MockPTE, 1> {
82+
public:
83+
using MockPageTable<MockPTE, 1>::entries;
84+
};
85+
86+
class MockPDP : public MockPageTable<MockPDE, 2> {
87+
public:
88+
using MockPageTable<MockPDE, 2>::entries;
89+
};
90+
91+
class MockPML4 : public MockPageTable<MockPDP, 3> {
92+
public:
93+
using MockPageTable<MockPDP, 3>::entries;
94+
};
95+
6196
class PPGTTPageTable : public TypeSelector<PML4, PDPE, sizeof(void *) == 8>::type {
6297
public:
6398
const size_t ppgttEntries = IntSelector<512u, 4u, sizeof(void *) == 8>::value;
@@ -128,6 +163,38 @@ TEST_F(PageTableTests48, DISABLED_mapSizeZero) {
128163
std::cerr << phys1 << std::endl;
129164
}
130165

166+
TEST_F(PageTableTests48, givenReservedPhysicalAddressWhenPageWalkIsCalledThenPageTablesAreFilledWithProperAddresses) {
167+
if (is64Bit) {
168+
std::unique_ptr<MockPML4> pageTable(std::make_unique<MockPML4>());
169+
170+
int shiftPML4 = is64Bit ? (9 + 9 + 9 + 12) : 0;
171+
int shiftPDP = is64Bit ? (9 + 9 + 12) : 0;
172+
173+
uintptr_t gpuVa = (uintptr_t(0x1) << (shiftPML4)) | (uintptr_t(0x1) << (shiftPDP)) | (uintptr_t(0x1) << (9 + 12)) | 0x100;
174+
175+
size_t size = 10 * pageSize;
176+
177+
size_t walked = 0u;
178+
auto address = this->getNextPage() * pageSize;
179+
180+
PageWalker walker = [&](uint64_t physAddress, size_t size, size_t offset) {
181+
walked += size;
182+
};
183+
pageTable->pageWalk(gpuVa, size, 0, walker);
184+
185+
EXPECT_EQ(size, walked);
186+
187+
ASSERT_NE(nullptr, pageTable->entries[1]);
188+
ASSERT_NE(nullptr, pageTable->entries[1]->entries[1]);
189+
ASSERT_NE(nullptr, pageTable->entries[1]->entries[1]->entries[1]);
190+
191+
for (uint32_t i = 0; i < 10; i++) {
192+
EXPECT_EQ(reinterpret_cast<void *>(address | 0x1), pageTable->entries[1]->entries[1]->entries[1]->entries[i]);
193+
address += pageSize;
194+
}
195+
}
196+
}
197+
131198
TEST_F(PageTableTests48, pageWalkSimple) {
132199
std::unique_ptr<PPGTTPageTable> pageTable(new PPGTTPageTable);
133200
uintptr_t addr1 = refAddr + (510 * pageSize) + 0x10;

0 commit comments

Comments
 (0)