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/runtime/execute_guest.h"
18 
19 #include "berberis/base/checks.h"
20 #include "berberis/base/config.h"
21 #include "berberis/base/tracing.h"
22 #include "berberis/guest_os_primitives/guest_thread.h"
23 #include "berberis/guest_state/guest_addr.h"
24 #include "berberis/guest_state/guest_state_opaque.h"
25 #include "berberis/runtime_primitives/runtime_library.h"
26 #include "berberis/runtime_primitives/translation_cache.h"
27 
28 namespace berberis {
29 
ExecuteGuest(ThreadState * state)30 void ExecuteGuest(ThreadState* state) {
31   CHECK(state);
32   GuestThread* thread = GetGuestThread(*state);
33   CHECK(thread);
34   CHECK_EQ(state, thread->state());
35 
36   TranslationCache* cache = TranslationCache::GetInstance();
37 
38   for (;;) {
39     auto pc = GetInsnAddr(GetCPUState(*state));
40 
41     if (ArePendingSignalsPresent(*state)) {
42       thread->ProcessPendingSignals();
43       // Signal handler can modify control flow, e.g. to recover from segfault.
44       if (pc != GetInsnAddr(GetCPUState(*state))) {
45         TRACE("PC modified by signal handler: old=%p new=%p",
46               ToHostAddr<void>(pc),
47               ToHostAddr<void>(GetInsnAddr(GetCPUState(*state))));
48         pc = GetInsnAddr(GetCPUState(*state));
49       }
50     }
51 
52     auto code = cache->GetHostCodePtr(pc)->load();
53     if (code == kEntryStop) {
54       break;
55     }
56 
57     if (config::kTraceGeneratedCode) {
58       TRACE("RunGeneratedCode @ 0x%zx", pc);
59     }
60 
61     // ATTENTION: this should be the only place to run translated code!
62     berberis_RunGeneratedCode(state, code);
63   }
64 }
65 
66 }  // namespace berberis
67