1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "gtest/gtest.h"
18
19 #include "berberis/guest_state/guest_addr.h"
20 #include "berberis/guest_state/guest_state.h"
21 #include "berberis/runtime_primitives/memory_region_reservation.h"
22
23 namespace berberis {
24
25 namespace {
26
27 static_assert(sizeof(Reservation) >= 8, "Reservation size is too small");
28
TEST(MemoryRegionReservation,Smoke)29 TEST(MemoryRegionReservation, Smoke) {
30 CPUState cpu{};
31
32 constexpr uint32_t kTestVal = 0xf1234567;
33
34 Reservation reservation = kTestVal;
35
36 GuestAddr addr = ToGuestAddr(&reservation) + sizeof(uint32_t);
37
38 ASSERT_EQ(0u, MemoryRegionReservation::Load<uint32_t>(&cpu, addr, std::memory_order_seq_cst));
39
40 ASSERT_EQ(
41 0u,
42 MemoryRegionReservation::Store<uint32_t>(&cpu, addr, kTestVal, std::memory_order_seq_cst));
43
44 ASSERT_EQ(reservation, (Reservation(kTestVal) << 32) | kTestVal);
45
46 ASSERT_EQ(
47 1u,
48 MemoryRegionReservation::Store<uint32_t>(&cpu, addr, ~kTestVal, std::memory_order_seq_cst));
49
50 ASSERT_EQ(reservation, (Reservation(kTestVal) << 32) | kTestVal);
51 }
52
TEST(MemoryRegionReservation,DoubleLoad)53 TEST(MemoryRegionReservation, DoubleLoad) {
54 CPUState cpu{};
55
56 constexpr uint32_t kTestVal1 = 0xf1234567;
57 constexpr uint32_t kTestVal2 = 0xdeadbeef;
58
59 Reservation reservation_1 = kTestVal1;
60 Reservation reservation_2 = kTestVal2;
61
62 ASSERT_EQ(kTestVal1,
63 MemoryRegionReservation::Load<uint32_t>(
64 &cpu, ToGuestAddr(&reservation_1), std::memory_order_seq_cst));
65
66 ASSERT_EQ(kTestVal2,
67 MemoryRegionReservation::Load<uint32_t>(
68 &cpu, ToGuestAddr(&reservation_2), std::memory_order_seq_cst));
69
70 ASSERT_EQ(0u,
71 MemoryRegionReservation::Store<uint32_t>(
72 &cpu, ToGuestAddr(&reservation_2), kTestVal1, std::memory_order_seq_cst));
73
74 ASSERT_EQ(kTestVal1, reservation_1);
75 ASSERT_EQ(kTestVal1, reservation_2);
76 }
77
TEST(MemoryRegionReservation,Steal)78 TEST(MemoryRegionReservation, Steal) {
79 CPUState cpu_1{};
80 CPUState cpu_2{};
81
82 constexpr uint32_t kTestVal1 = 0xf1234567;
83 constexpr uint32_t kTestVal2 = 0xdeadbeef;
84 constexpr uint32_t kTestVal3 = 0xabcdefab;
85
86 Reservation reservation = kTestVal1;
87
88 ASSERT_EQ(kTestVal1,
89 MemoryRegionReservation::Load<uint32_t>(
90 &cpu_1, ToGuestAddr(&reservation), std::memory_order_seq_cst));
91
92 ASSERT_EQ(kTestVal1,
93 MemoryRegionReservation::Load<uint32_t>(
94 &cpu_2, ToGuestAddr(&reservation), std::memory_order_seq_cst));
95
96 ASSERT_EQ(1u,
97 MemoryRegionReservation::Store<uint32_t>(
98 &cpu_1, ToGuestAddr(&reservation), kTestVal2, std::memory_order_seq_cst));
99
100 ASSERT_EQ(0u,
101 MemoryRegionReservation::Store<uint32_t>(
102 &cpu_2, ToGuestAddr(&reservation), kTestVal3, std::memory_order_seq_cst));
103
104 ASSERT_EQ(kTestVal3, reservation);
105 }
106
TEST(MemoryRegionReservation,StealEqual)107 TEST(MemoryRegionReservation, StealEqual) {
108 CPUState cpu_1{};
109 CPUState cpu_2{};
110
111 constexpr uint32_t kTestVal1 = 0xf1234567;
112 constexpr uint32_t kTestVal2 = 0xdeadbeef;
113
114 Reservation reservation = kTestVal1;
115
116 ASSERT_EQ(kTestVal1,
117 MemoryRegionReservation::Load<uint32_t>(
118 &cpu_1, ToGuestAddr(&reservation), std::memory_order_seq_cst));
119
120 ASSERT_EQ(kTestVal1,
121 MemoryRegionReservation::Load<uint32_t>(
122 &cpu_2, ToGuestAddr(&reservation), std::memory_order_seq_cst));
123
124 ASSERT_EQ(0u,
125 MemoryRegionReservation::Store<uint32_t>(
126 &cpu_2, ToGuestAddr(&reservation), kTestVal1, std::memory_order_seq_cst));
127
128 ASSERT_EQ(1u,
129 MemoryRegionReservation::Store<uint32_t>(
130 &cpu_1, ToGuestAddr(&reservation), kTestVal2, std::memory_order_seq_cst));
131
132 ASSERT_EQ(kTestVal1, reservation);
133 }
134
135 } // namespace
136
137 } // namespace berberis
138