base.cc (9986:7cab06691984) base.cc (10073:2360411a16be)
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 49 unchanged lines hidden (view full) ---

58#include "sim/process.hh"
59#include "sim/system.hh"
60
61#include <signal.h>
62
63/* Used by some KVM macros */
64#define PAGE_SIZE pageSize
65
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 49 unchanged lines hidden (view full) ---

58#include "sim/process.hh"
59#include "sim/system.hh"
60
61#include <signal.h>
62
63/* Used by some KVM macros */
64#define PAGE_SIZE pageSize
65
66volatile bool timerOverflowed = false;
66static volatile __thread bool timerOverflowed = false;
67
68BaseKvmCPU::BaseKvmCPU(BaseKvmCPUParams *params)
69 : BaseCPU(params),
70 vm(*params->kvmVM),
71 _status(Idle),
72 dataPort(name() + ".dcache_port", this),
73 instPort(name() + ".icache_port", this),
74 threadContextDirty(true),

--- 12 unchanged lines hidden (view full) ---

87 panic("KVM: Failed to determine host page size (%i)\n",
88 errno);
89
90 thread = new SimpleThread(this, 0, params->system,
91 params->itb, params->dtb, params->isa[0]);
92 thread->setStatus(ThreadContext::Halted);
93 tc = thread->getTC();
94 threadContexts.push_back(tc);
67
68BaseKvmCPU::BaseKvmCPU(BaseKvmCPUParams *params)
69 : BaseCPU(params),
70 vm(*params->kvmVM),
71 _status(Idle),
72 dataPort(name() + ".dcache_port", this),
73 instPort(name() + ".icache_port", this),
74 threadContextDirty(true),

--- 12 unchanged lines hidden (view full) ---

87 panic("KVM: Failed to determine host page size (%i)\n",
88 errno);
89
90 thread = new SimpleThread(this, 0, params->system,
91 params->itb, params->dtb, params->isa[0]);
92 thread->setStatus(ThreadContext::Halted);
93 tc = thread->getTC();
94 threadContexts.push_back(tc);
95
96 setupCounters();
97
98 if (params->usePerfOverflow)
99 runTimer.reset(new PerfKvmTimer(hwCycles,
100 KVM_TIMER_SIGNAL,
101 params->hostFactor,
102 params->hostFreq));
103 else
104 runTimer.reset(new PosixKvmTimer(KVM_TIMER_SIGNAL, CLOCK_MONOTONIC,
105 params->hostFactor,
106 params->hostFreq));
107}
108
109BaseKvmCPU::~BaseKvmCPU()
110{
111 if (_kvmRun)
112 munmap(_kvmRun, vcpuMMapSize);
113 close(vcpuFD);
114}

--- 57 unchanged lines hidden (view full) ---

172 inform("KVM: Coalesced IO available\n");
173 mmioRing = (struct kvm_coalesced_mmio_ring *)(
174 (char *)_kvmRun + (mmioOffset * pageSize));
175 } else {
176 inform("KVM: Coalesced not supported by host OS\n");
177 }
178
179 thread->startup();
95}
96
97BaseKvmCPU::~BaseKvmCPU()
98{
99 if (_kvmRun)
100 munmap(_kvmRun, vcpuMMapSize);
101 close(vcpuFD);
102}

--- 57 unchanged lines hidden (view full) ---

160 inform("KVM: Coalesced IO available\n");
161 mmioRing = (struct kvm_coalesced_mmio_ring *)(
162 (char *)_kvmRun + (mmioOffset * pageSize));
163 } else {
164 inform("KVM: Coalesced not supported by host OS\n");
165 }
166
167 thread->startup();
168
169 Event *startupEvent(
170 new EventWrapper<BaseKvmCPU,
171 &BaseKvmCPU::startupThread>(this, true));
172 schedule(startupEvent, curTick());
180}
181
182void
173}
174
175void
176BaseKvmCPU::startupThread()
177{
178 // Do thread-specific initialization. We need to setup signal
179 // delivery for counters and timers from within the thread that
180 // will execute the event queue to ensure that signals are
181 // delivered to the right threads.
182 const BaseKvmCPUParams * const p(
183 dynamic_cast<const BaseKvmCPUParams *>(params()));
184
185 setupCounters();
186
187 if (p->usePerfOverflow)
188 runTimer.reset(new PerfKvmTimer(hwCycles,
189 KVM_TIMER_SIGNAL,
190 p->hostFactor,
191 p->hostFreq));
192 else
193 runTimer.reset(new PosixKvmTimer(KVM_TIMER_SIGNAL, CLOCK_MONOTONIC,
194 p->hostFactor,
195 p->hostFreq));
196
197}
198
199void
183BaseKvmCPU::regStats()
184{
185 using namespace Stats;
186
187 BaseCPU::regStats();
188
189 numInsts
190 .name(name() + ".committedInsts")

--- 848 unchanged lines hidden (view full) ---

1039 }
1040
1041 return ticks;
1042}
1043
1044/**
1045 * Cycle timer overflow when running in KVM. Forces the KVM syscall to
1046 * exit with EINTR and allows us to run the event queue.
200BaseKvmCPU::regStats()
201{
202 using namespace Stats;
203
204 BaseCPU::regStats();
205
206 numInsts
207 .name(name() + ".committedInsts")

--- 848 unchanged lines hidden (view full) ---

1056 }
1057
1058 return ticks;
1059}
1060
1061/**
1062 * Cycle timer overflow when running in KVM. Forces the KVM syscall to
1063 * exit with EINTR and allows us to run the event queue.
1064 *
1065 * @warn This function might not be called since some kernels don't
1066 * seem to deliver signals when the signal is only unmasked when
1067 * running in KVM. This doesn't matter though since we are only
1068 * interested in getting KVM to exit, which happens as expected. See
1069 * setupSignalHandler() and kvmRun() for details about KVM signal
1070 * handling.
1047 */
1048static void
1049onTimerOverflow(int signo, siginfo_t *si, void *data)
1050{
1051 timerOverflowed = true;
1052}
1053
1054/**

--- 19 unchanged lines hidden (view full) ---

1074
1075 memset(&sa, 0, sizeof(sa));
1076 sa.sa_sigaction = onInstEvent;
1077 sa.sa_flags = SA_SIGINFO | SA_RESTART;
1078 if (sigaction(KVM_INST_SIGNAL, &sa, NULL) == -1)
1079 panic("KVM: Failed to setup vCPU instruction signal handler\n");
1080
1081 sigset_t sigset;
1071 */
1072static void
1073onTimerOverflow(int signo, siginfo_t *si, void *data)
1074{
1075 timerOverflowed = true;
1076}
1077
1078/**

--- 19 unchanged lines hidden (view full) ---

1098
1099 memset(&sa, 0, sizeof(sa));
1100 sa.sa_sigaction = onInstEvent;
1101 sa.sa_flags = SA_SIGINFO | SA_RESTART;
1102 if (sigaction(KVM_INST_SIGNAL, &sa, NULL) == -1)
1103 panic("KVM: Failed to setup vCPU instruction signal handler\n");
1104
1105 sigset_t sigset;
1082 if (sigprocmask(SIG_BLOCK, NULL, &sigset) == -1)
1106 if (pthread_sigmask(SIG_BLOCK, NULL, &sigset) == -1)
1083 panic("KVM: Failed get signal mask\n");
1084
1085 // Request KVM to setup the same signal mask as we're currently
1107 panic("KVM: Failed get signal mask\n");
1108
1109 // Request KVM to setup the same signal mask as we're currently
1086 // running with. We'll sometimes need to mask the KVM_TIMER_SIGNAL
1087 // to cause immediate exits from KVM after servicing IO
1088 // requests. See kvmRun().
1110 // running with except for the KVM control signals. We'll
1111 // sometimes need to raise the KVM_TIMER_SIGNAL to cause immediate
1112 // exits from KVM after servicing IO requests. See kvmRun().
1113 sigdelset(&sigset, KVM_TIMER_SIGNAL);
1114 sigdelset(&sigset, KVM_INST_SIGNAL);
1089 setSignalMask(&sigset);
1090
1091 // Mask our control signals so they aren't delivered unless we're
1092 // actually executing inside KVM.
1093 sigaddset(&sigset, KVM_TIMER_SIGNAL);
1094 sigaddset(&sigset, KVM_INST_SIGNAL);
1115 setSignalMask(&sigset);
1116
1117 // Mask our control signals so they aren't delivered unless we're
1118 // actually executing inside KVM.
1119 sigaddset(&sigset, KVM_TIMER_SIGNAL);
1120 sigaddset(&sigset, KVM_INST_SIGNAL);
1095 if (sigprocmask(SIG_SETMASK, &sigset, NULL) == -1)
1121 if (pthread_sigmask(SIG_SETMASK, &sigset, NULL) == -1)
1096 panic("KVM: Failed mask the KVM control signals\n");
1097}
1098
1099bool
1100BaseKvmCPU::discardPendingSignal(int signum) const
1101{
1102 int discardedSignal;
1103

--- 137 unchanged lines hidden ---
1122 panic("KVM: Failed mask the KVM control signals\n");
1123}
1124
1125bool
1126BaseKvmCPU::discardPendingSignal(int signum) const
1127{
1128 int discardedSignal;
1129

--- 137 unchanged lines hidden ---