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 "berberis/guest_state/guest_state.h"
18
19 #include "berberis/base/checks.h"
20 #include "berberis/guest_state/guest_state_arch.h"
21 #include "berberis/guest_state/guest_state_opaque.h"
22
23 namespace berberis {
24
SetReturnValueRegister(CPUState & cpu,GuestAddr val)25 void SetReturnValueRegister(CPUState& cpu, GuestAddr val) {
26 SetXReg<A0>(cpu, val);
27 }
28
GetReturnValueRegister(const CPUState & cpu)29 GuestAddr GetReturnValueRegister(const CPUState& cpu) {
30 return GetXReg<A0>(cpu);
31 }
32
SetStackRegister(CPUState & cpu,GuestAddr val)33 void SetStackRegister(CPUState& cpu, GuestAddr val) {
34 SetXReg<SP>(cpu, val);
35 }
36
GetStackRegister(const CPUState & cpu)37 GuestAddr GetStackRegister(const CPUState& cpu) {
38 return GetXReg<SP>(cpu);
39 }
40
SetLinkRegister(CPUState & cpu,GuestAddr val)41 void SetLinkRegister(CPUState& cpu, GuestAddr val) {
42 SetXReg<RA>(cpu, val);
43 }
44
GetLinkRegister(const CPUState & cpu)45 GuestAddr GetLinkRegister(const CPUState& cpu) {
46 return GetXReg<RA>(cpu);
47 }
48
SetTlsAddr(ThreadState & state,GuestAddr addr)49 void SetTlsAddr(ThreadState& state, GuestAddr addr) {
50 SetXReg<TP>(state.cpu, addr);
51 }
52
GetTlsAddr(const ThreadState & state)53 GuestAddr GetTlsAddr(const ThreadState& state) {
54 return GetXReg<TP>(state.cpu);
55 }
56
SetShadowCallStackPointer(CPUState & cpu,GuestAddr scs_sp)57 void SetShadowCallStackPointer(CPUState& cpu, GuestAddr scs_sp) {
58 SetXReg<GP>(cpu, scs_sp);
59 }
60
AdvanceInsnAddrBeyondSyscall(CPUState & cpu)61 void AdvanceInsnAddrBeyondSyscall(CPUState& cpu) {
62 // RV64I uses the same 4-byte ECALL instruction as RV32I.
63 // See ratified RISC-V unprivileged spec v2.1.
64 cpu.insn_addr += 4;
65 }
66
GetThreadStateRegOffset(int reg)67 std::size_t GetThreadStateRegOffset(int reg) {
68 return offsetof(ThreadState, cpu.x[reg]);
69 }
70
GetThreadStateFRegOffset(int freg)71 std::size_t GetThreadStateFRegOffset(int freg) {
72 return offsetof(ThreadState, cpu.f[freg]);
73 }
74
GetThreadStateVRegOffset(int vreg)75 std::size_t GetThreadStateVRegOffset(int vreg) {
76 return offsetof(ThreadState, cpu.v[vreg]);
77 }
78
GetThreadStateSimdRegOffset(int)79 std::size_t GetThreadStateSimdRegOffset(int /* simd_reg */) {
80 // RISCV64 does not have simd registers.
81 UNREACHABLE();
82 }
83
GetThreadStateReservationAddressOffset()84 std::size_t GetThreadStateReservationAddressOffset() {
85 return offsetof(ThreadState, cpu.reservation_address);
86 }
87
GetThreadStateReservationValueOffset()88 std::size_t GetThreadStateReservationValueOffset() {
89 return offsetof(ThreadState, cpu.reservation_value);
90 }
91
IsSimdOffset(size_t offset)92 bool IsSimdOffset(size_t offset) {
93 size_t v0_offset = offsetof(ThreadState, cpu.v);
94 return (offset >= v0_offset) && ((offset - v0_offset) < sizeof(ThreadState::cpu.v));
95 }
96
DoesCpuStateHaveFlags()97 bool DoesCpuStateHaveFlags() {
98 return false;
99 }
100
DoesCpuStateHaveDedicatedFpRegs()101 bool DoesCpuStateHaveDedicatedFpRegs() {
102 return true;
103 }
104
DoesCpuStateHaveDedicatedVecRegs()105 bool DoesCpuStateHaveDedicatedVecRegs() {
106 return true;
107 }
108
DoesCpuStateHaveDedicatedSimdRegs()109 bool DoesCpuStateHaveDedicatedSimdRegs() {
110 return false;
111 }
112
GetThreadStateFlagOffset()113 std::size_t GetThreadStateFlagOffset() {
114 // RISCV64 Does not have flags in its CPUState
115 CHECK(false);
116 }
117
118 } // namespace berberis
119