xref: /aosp_15_r20/external/stressapptest/src/os.cc (revision 424fb153c814cbcb3e8904974796228774b3229a)
1*424fb153SAndroid Build Coastguard Worker // Copyright 2006 Google Inc. All Rights Reserved.
2*424fb153SAndroid Build Coastguard Worker // Author: nsanders, menderico
3*424fb153SAndroid Build Coastguard Worker 
4*424fb153SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*424fb153SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*424fb153SAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*424fb153SAndroid Build Coastguard Worker 
8*424fb153SAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
9*424fb153SAndroid Build Coastguard Worker 
10*424fb153SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*424fb153SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*424fb153SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*424fb153SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*424fb153SAndroid Build Coastguard Worker // limitations under the License.
15*424fb153SAndroid Build Coastguard Worker 
16*424fb153SAndroid Build Coastguard Worker // os.cc : os and machine specific implementation
17*424fb153SAndroid Build Coastguard Worker // This file includes an abstracted interface
18*424fb153SAndroid Build Coastguard Worker // for linux-distro specific and HW specific
19*424fb153SAndroid Build Coastguard Worker // interfaces.
20*424fb153SAndroid Build Coastguard Worker 
21*424fb153SAndroid Build Coastguard Worker #include "os.h"
22*424fb153SAndroid Build Coastguard Worker 
23*424fb153SAndroid Build Coastguard Worker #include <errno.h>
24*424fb153SAndroid Build Coastguard Worker #include <fcntl.h>
25*424fb153SAndroid Build Coastguard Worker #include <linux/types.h>
26*424fb153SAndroid Build Coastguard Worker #include <malloc.h>
27*424fb153SAndroid Build Coastguard Worker #include <stdio.h>
28*424fb153SAndroid Build Coastguard Worker #include <stdlib.h>
29*424fb153SAndroid Build Coastguard Worker #include <string.h>
30*424fb153SAndroid Build Coastguard Worker #include <sys/mman.h>
31*424fb153SAndroid Build Coastguard Worker #include <sys/ioctl.h>
32*424fb153SAndroid Build Coastguard Worker #include <sys/time.h>
33*424fb153SAndroid Build Coastguard Worker #include <sys/types.h>
34*424fb153SAndroid Build Coastguard Worker #include <sys/ipc.h>
35*424fb153SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SHM_H
36*424fb153SAndroid Build Coastguard Worker #include <sys/shm.h>
37*424fb153SAndroid Build Coastguard Worker #endif
38*424fb153SAndroid Build Coastguard Worker #include <unistd.h>
39*424fb153SAndroid Build Coastguard Worker 
40*424fb153SAndroid Build Coastguard Worker #ifndef SHM_HUGETLB
41*424fb153SAndroid Build Coastguard Worker #define SHM_HUGETLB      04000  // remove when glibc defines it
42*424fb153SAndroid Build Coastguard Worker #endif
43*424fb153SAndroid Build Coastguard Worker 
44*424fb153SAndroid Build Coastguard Worker #include <string>
45*424fb153SAndroid Build Coastguard Worker #include <list>
46*424fb153SAndroid Build Coastguard Worker 
47*424fb153SAndroid Build Coastguard Worker // This file must work with autoconf on its public version,
48*424fb153SAndroid Build Coastguard Worker // so these includes are correct.
49*424fb153SAndroid Build Coastguard Worker #include "sattypes.h"
50*424fb153SAndroid Build Coastguard Worker #include "error_diag.h"
51*424fb153SAndroid Build Coastguard Worker #include "clock.h"
52*424fb153SAndroid Build Coastguard Worker 
53*424fb153SAndroid Build Coastguard Worker // OsLayer initialization.
OsLayer()54*424fb153SAndroid Build Coastguard Worker OsLayer::OsLayer() {
55*424fb153SAndroid Build Coastguard Worker   testmem_ = 0;
56*424fb153SAndroid Build Coastguard Worker   testmemsize_ = 0;
57*424fb153SAndroid Build Coastguard Worker   totalmemsize_ = 0;
58*424fb153SAndroid Build Coastguard Worker   min_hugepages_bytes_ = 0;
59*424fb153SAndroid Build Coastguard Worker   reserve_mb_ = 0;
60*424fb153SAndroid Build Coastguard Worker   normal_mem_ = true;
61*424fb153SAndroid Build Coastguard Worker   use_hugepages_ = false;
62*424fb153SAndroid Build Coastguard Worker   use_posix_shm_ = false;
63*424fb153SAndroid Build Coastguard Worker   dynamic_mapped_shmem_ = false;
64*424fb153SAndroid Build Coastguard Worker   mmapped_allocation_ = false;
65*424fb153SAndroid Build Coastguard Worker   shmid_ = 0;
66*424fb153SAndroid Build Coastguard Worker   channels_ = NULL;
67*424fb153SAndroid Build Coastguard Worker 
68*424fb153SAndroid Build Coastguard Worker   time_initialized_ = 0;
69*424fb153SAndroid Build Coastguard Worker 
70*424fb153SAndroid Build Coastguard Worker   regionsize_ = 0;
71*424fb153SAndroid Build Coastguard Worker   regioncount_ = 1;
72*424fb153SAndroid Build Coastguard Worker   num_cpus_ = 0;
73*424fb153SAndroid Build Coastguard Worker   num_nodes_ = 0;
74*424fb153SAndroid Build Coastguard Worker   num_cpus_per_node_ = 0;
75*424fb153SAndroid Build Coastguard Worker   error_diagnoser_ = 0;
76*424fb153SAndroid Build Coastguard Worker   err_log_callback_ = 0;
77*424fb153SAndroid Build Coastguard Worker   error_injection_ = false;
78*424fb153SAndroid Build Coastguard Worker 
79*424fb153SAndroid Build Coastguard Worker   void *pvoid = 0;
80*424fb153SAndroid Build Coastguard Worker   address_mode_ = sizeof(pvoid) * 8;
81*424fb153SAndroid Build Coastguard Worker 
82*424fb153SAndroid Build Coastguard Worker   has_clflush_ = false;
83*424fb153SAndroid Build Coastguard Worker   has_vector_ = false;
84*424fb153SAndroid Build Coastguard Worker 
85*424fb153SAndroid Build Coastguard Worker   use_flush_page_cache_ = false;
86*424fb153SAndroid Build Coastguard Worker 
87*424fb153SAndroid Build Coastguard Worker   clock_ = NULL;
88*424fb153SAndroid Build Coastguard Worker }
89*424fb153SAndroid Build Coastguard Worker 
90*424fb153SAndroid Build Coastguard Worker // OsLayer cleanup.
~OsLayer()91*424fb153SAndroid Build Coastguard Worker OsLayer::~OsLayer() {
92*424fb153SAndroid Build Coastguard Worker   if (error_diagnoser_)
93*424fb153SAndroid Build Coastguard Worker     delete error_diagnoser_;
94*424fb153SAndroid Build Coastguard Worker   if (clock_)
95*424fb153SAndroid Build Coastguard Worker     delete clock_;
96*424fb153SAndroid Build Coastguard Worker }
97*424fb153SAndroid Build Coastguard Worker 
98*424fb153SAndroid Build Coastguard Worker // OsLayer initialization.
Initialize()99*424fb153SAndroid Build Coastguard Worker bool OsLayer::Initialize() {
100*424fb153SAndroid Build Coastguard Worker   if (!clock_) {
101*424fb153SAndroid Build Coastguard Worker     clock_ = new Clock();
102*424fb153SAndroid Build Coastguard Worker   }
103*424fb153SAndroid Build Coastguard Worker 
104*424fb153SAndroid Build Coastguard Worker   time_initialized_ = clock_->Now();
105*424fb153SAndroid Build Coastguard Worker   // Detect asm support.
106*424fb153SAndroid Build Coastguard Worker   GetFeatures();
107*424fb153SAndroid Build Coastguard Worker 
108*424fb153SAndroid Build Coastguard Worker   if (num_cpus_ == 0) {
109*424fb153SAndroid Build Coastguard Worker     num_nodes_ = 1;
110*424fb153SAndroid Build Coastguard Worker     num_cpus_ = sysconf(_SC_NPROCESSORS_ONLN);
111*424fb153SAndroid Build Coastguard Worker     num_cpus_per_node_ = num_cpus_ / num_nodes_;
112*424fb153SAndroid Build Coastguard Worker   }
113*424fb153SAndroid Build Coastguard Worker   logprintf(5, "Log: %d nodes, %d cpus.\n", num_nodes_, num_cpus_);
114*424fb153SAndroid Build Coastguard Worker   sat_assert(CPU_SETSIZE >= num_cpus_);
115*424fb153SAndroid Build Coastguard Worker   cpu_sets_.resize(num_nodes_);
116*424fb153SAndroid Build Coastguard Worker   cpu_sets_valid_.resize(num_nodes_);
117*424fb153SAndroid Build Coastguard Worker   // Create error diagnoser.
118*424fb153SAndroid Build Coastguard Worker   error_diagnoser_ = new ErrorDiag();
119*424fb153SAndroid Build Coastguard Worker   if (!error_diagnoser_->set_os(this))
120*424fb153SAndroid Build Coastguard Worker     return false;
121*424fb153SAndroid Build Coastguard Worker   return true;
122*424fb153SAndroid Build Coastguard Worker }
123*424fb153SAndroid Build Coastguard Worker 
124*424fb153SAndroid Build Coastguard Worker // Machine type detected. Can we implement all these functions correctly?
IsSupported()125*424fb153SAndroid Build Coastguard Worker bool OsLayer::IsSupported() {
126*424fb153SAndroid Build Coastguard Worker   if (kOpenSource) {
127*424fb153SAndroid Build Coastguard Worker     // There are no explicitly supported systems in open source version.
128*424fb153SAndroid Build Coastguard Worker     return true;
129*424fb153SAndroid Build Coastguard Worker   }
130*424fb153SAndroid Build Coastguard Worker 
131*424fb153SAndroid Build Coastguard Worker   // This is the default empty implementation.
132*424fb153SAndroid Build Coastguard Worker   // SAT won't report full error information.
133*424fb153SAndroid Build Coastguard Worker   return false;
134*424fb153SAndroid Build Coastguard Worker }
135*424fb153SAndroid Build Coastguard Worker 
AddressMode()136*424fb153SAndroid Build Coastguard Worker int OsLayer::AddressMode() {
137*424fb153SAndroid Build Coastguard Worker   // Detect 32/64 bit binary.
138*424fb153SAndroid Build Coastguard Worker   void *pvoid = 0;
139*424fb153SAndroid Build Coastguard Worker   return sizeof(pvoid) * 8;
140*424fb153SAndroid Build Coastguard Worker }
141*424fb153SAndroid Build Coastguard Worker 
142*424fb153SAndroid Build Coastguard Worker // Translates user virtual to physical address.
VirtualToPhysical(void * vaddr)143*424fb153SAndroid Build Coastguard Worker uint64 OsLayer::VirtualToPhysical(void *vaddr) {
144*424fb153SAndroid Build Coastguard Worker   uint64 frame, paddr, pfnmask, pagemask;
145*424fb153SAndroid Build Coastguard Worker   int pagesize = sysconf(_SC_PAGESIZE);
146*424fb153SAndroid Build Coastguard Worker   off64_t off = ((uintptr_t)vaddr) / pagesize * 8;
147*424fb153SAndroid Build Coastguard Worker   int fd = open(kPagemapPath, O_RDONLY);
148*424fb153SAndroid Build Coastguard Worker 
149*424fb153SAndroid Build Coastguard Worker   /*
150*424fb153SAndroid Build Coastguard Worker    * https://www.kernel.org/doc/Documentation/vm/pagemap.txt
151*424fb153SAndroid Build Coastguard Worker    * API change (July 2015)
152*424fb153SAndroid Build Coastguard Worker    * https://patchwork.kernel.org/patch/6787991/
153*424fb153SAndroid Build Coastguard Worker    */
154*424fb153SAndroid Build Coastguard Worker 
155*424fb153SAndroid Build Coastguard Worker   if (fd < 0)
156*424fb153SAndroid Build Coastguard Worker     return 0;
157*424fb153SAndroid Build Coastguard Worker 
158*424fb153SAndroid Build Coastguard Worker   if (lseek64(fd, off, SEEK_SET) != off || read(fd, &frame, 8) != 8) {
159*424fb153SAndroid Build Coastguard Worker     int err = errno;
160*424fb153SAndroid Build Coastguard Worker     string errtxt = ErrorString(err);
161*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Process Error: failed to access %s with errno %d (%s)\n",
162*424fb153SAndroid Build Coastguard Worker               kPagemapPath, err, errtxt.c_str());
163*424fb153SAndroid Build Coastguard Worker     if (fd >= 0)
164*424fb153SAndroid Build Coastguard Worker       close(fd);
165*424fb153SAndroid Build Coastguard Worker     return 0;
166*424fb153SAndroid Build Coastguard Worker   }
167*424fb153SAndroid Build Coastguard Worker   close(fd);
168*424fb153SAndroid Build Coastguard Worker 
169*424fb153SAndroid Build Coastguard Worker   /* Check if page is present and not swapped. */
170*424fb153SAndroid Build Coastguard Worker   if (!(frame & (1ULL << 63)) || (frame & (1ULL << 62)))
171*424fb153SAndroid Build Coastguard Worker     return 0;
172*424fb153SAndroid Build Coastguard Worker 
173*424fb153SAndroid Build Coastguard Worker   /* pfn is bits 0-54. */
174*424fb153SAndroid Build Coastguard Worker   pfnmask = ((1ULL << 55) - 1);
175*424fb153SAndroid Build Coastguard Worker   /* Pagesize had better be a power of 2. */
176*424fb153SAndroid Build Coastguard Worker   pagemask = pagesize - 1;
177*424fb153SAndroid Build Coastguard Worker 
178*424fb153SAndroid Build Coastguard Worker   paddr = ((frame & pfnmask) * pagesize) | ((uintptr_t)vaddr & pagemask);
179*424fb153SAndroid Build Coastguard Worker   return paddr;
180*424fb153SAndroid Build Coastguard Worker }
181*424fb153SAndroid Build Coastguard Worker 
182*424fb153SAndroid Build Coastguard Worker // Returns the HD device that contains this file.
FindFileDevice(string filename)183*424fb153SAndroid Build Coastguard Worker string OsLayer::FindFileDevice(string filename) {
184*424fb153SAndroid Build Coastguard Worker   return "hdUnknown";
185*424fb153SAndroid Build Coastguard Worker }
186*424fb153SAndroid Build Coastguard Worker 
187*424fb153SAndroid Build Coastguard Worker // Returns a list of locations corresponding to HD devices.
FindFileDevices()188*424fb153SAndroid Build Coastguard Worker list<string> OsLayer::FindFileDevices() {
189*424fb153SAndroid Build Coastguard Worker   // No autodetection on unknown systems.
190*424fb153SAndroid Build Coastguard Worker   list<string> locations;
191*424fb153SAndroid Build Coastguard Worker   return locations;
192*424fb153SAndroid Build Coastguard Worker }
193*424fb153SAndroid Build Coastguard Worker 
194*424fb153SAndroid Build Coastguard Worker 
195*424fb153SAndroid Build Coastguard Worker // Get HW core features from cpuid instruction.
GetFeatures()196*424fb153SAndroid Build Coastguard Worker void OsLayer::GetFeatures() {
197*424fb153SAndroid Build Coastguard Worker #if defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
198*424fb153SAndroid Build Coastguard Worker   unsigned int eax = 1, ebx, ecx, edx;
199*424fb153SAndroid Build Coastguard Worker   cpuid(&eax, &ebx, &ecx, &edx);
200*424fb153SAndroid Build Coastguard Worker   has_clflush_ = (edx >> 19) & 1;
201*424fb153SAndroid Build Coastguard Worker   has_vector_ = (edx >> 26) & 1;  // SSE2 caps bit.
202*424fb153SAndroid Build Coastguard Worker 
203*424fb153SAndroid Build Coastguard Worker   logprintf(9, "Log: has clflush: %s, has sse2: %s\n",
204*424fb153SAndroid Build Coastguard Worker             has_clflush_ ? "true" : "false",
205*424fb153SAndroid Build Coastguard Worker             has_vector_ ? "true" : "false");
206*424fb153SAndroid Build Coastguard Worker #elif defined(STRESSAPPTEST_CPU_PPC)
207*424fb153SAndroid Build Coastguard Worker   // All PPC implementations have cache flush instructions.
208*424fb153SAndroid Build Coastguard Worker   has_clflush_ = true;
209*424fb153SAndroid Build Coastguard Worker #elif defined(STRESSAPPTEST_CPU_ARMV7A)
210*424fb153SAndroid Build Coastguard Worker   // TODO(nsanders): add detect from /proc/cpuinfo or /proc/self/auxv.
211*424fb153SAndroid Build Coastguard Worker   // For now assume neon and don't run -W if you don't have it.
212*424fb153SAndroid Build Coastguard Worker   has_vector_ = true; // NEON.
213*424fb153SAndroid Build Coastguard Worker #warning "Unsupported CPU type ARMV7A: unable to determine feature set."
214*424fb153SAndroid Build Coastguard Worker #else
215*424fb153SAndroid Build Coastguard Worker #warning "Unsupported CPU type: unable to determine feature set."
216*424fb153SAndroid Build Coastguard Worker #endif
217*424fb153SAndroid Build Coastguard Worker }
218*424fb153SAndroid Build Coastguard Worker 
219*424fb153SAndroid Build Coastguard Worker 
220*424fb153SAndroid Build Coastguard Worker // Enable FlushPageCache to be functional instead of a NOP.
ActivateFlushPageCache(void)221*424fb153SAndroid Build Coastguard Worker void OsLayer::ActivateFlushPageCache(void) {
222*424fb153SAndroid Build Coastguard Worker   logprintf(9, "Log: page cache will be flushed as needed\n");
223*424fb153SAndroid Build Coastguard Worker   use_flush_page_cache_ = true;
224*424fb153SAndroid Build Coastguard Worker }
225*424fb153SAndroid Build Coastguard Worker 
226*424fb153SAndroid Build Coastguard Worker // Flush the page cache to ensure reads come from the disk.
FlushPageCache(void)227*424fb153SAndroid Build Coastguard Worker bool OsLayer::FlushPageCache(void) {
228*424fb153SAndroid Build Coastguard Worker   if (!use_flush_page_cache_)
229*424fb153SAndroid Build Coastguard Worker     return true;
230*424fb153SAndroid Build Coastguard Worker 
231*424fb153SAndroid Build Coastguard Worker   // First, ask the kernel to write the cache to the disk.
232*424fb153SAndroid Build Coastguard Worker   sync();
233*424fb153SAndroid Build Coastguard Worker 
234*424fb153SAndroid Build Coastguard Worker   // Second, ask the kernel to empty the cache by writing "1" to
235*424fb153SAndroid Build Coastguard Worker   // "/proc/sys/vm/drop_caches".
236*424fb153SAndroid Build Coastguard Worker   static const char *drop_caches_file = "/proc/sys/vm/drop_caches";
237*424fb153SAndroid Build Coastguard Worker   int dcfile = open(drop_caches_file, O_WRONLY);
238*424fb153SAndroid Build Coastguard Worker   if (dcfile < 0) {
239*424fb153SAndroid Build Coastguard Worker     int err = errno;
240*424fb153SAndroid Build Coastguard Worker     string errtxt = ErrorString(err);
241*424fb153SAndroid Build Coastguard Worker     logprintf(3, "Log: failed to open %s - err %d (%s)\n",
242*424fb153SAndroid Build Coastguard Worker               drop_caches_file, err, errtxt.c_str());
243*424fb153SAndroid Build Coastguard Worker     return false;
244*424fb153SAndroid Build Coastguard Worker   }
245*424fb153SAndroid Build Coastguard Worker 
246*424fb153SAndroid Build Coastguard Worker   ssize_t bytes_written = write(dcfile, "1", 1);
247*424fb153SAndroid Build Coastguard Worker   close(dcfile);
248*424fb153SAndroid Build Coastguard Worker 
249*424fb153SAndroid Build Coastguard Worker   if (bytes_written != 1) {
250*424fb153SAndroid Build Coastguard Worker     int err = errno;
251*424fb153SAndroid Build Coastguard Worker     string errtxt = ErrorString(err);
252*424fb153SAndroid Build Coastguard Worker     logprintf(3, "Log: failed to write %s - err %d (%s)\n",
253*424fb153SAndroid Build Coastguard Worker               drop_caches_file, err, errtxt.c_str());
254*424fb153SAndroid Build Coastguard Worker     return false;
255*424fb153SAndroid Build Coastguard Worker   }
256*424fb153SAndroid Build Coastguard Worker   return true;
257*424fb153SAndroid Build Coastguard Worker }
258*424fb153SAndroid Build Coastguard Worker 
259*424fb153SAndroid Build Coastguard Worker 
260*424fb153SAndroid Build Coastguard Worker // We need to flush the cacheline here.
Flush(void * vaddr)261*424fb153SAndroid Build Coastguard Worker void OsLayer::Flush(void *vaddr) {
262*424fb153SAndroid Build Coastguard Worker   // Use the generic flush. This function is just so we can override
263*424fb153SAndroid Build Coastguard Worker   // this if we are so inclined.
264*424fb153SAndroid Build Coastguard Worker   if (has_clflush_) {
265*424fb153SAndroid Build Coastguard Worker     OsLayer::FastFlush(vaddr);
266*424fb153SAndroid Build Coastguard Worker   }
267*424fb153SAndroid Build Coastguard Worker }
268*424fb153SAndroid Build Coastguard Worker 
269*424fb153SAndroid Build Coastguard Worker 
270*424fb153SAndroid Build Coastguard Worker // Run C or ASM copy as appropriate..
AdlerMemcpyWarm(uint64 * dstmem,uint64 * srcmem,unsigned int size_in_bytes,AdlerChecksum * checksum)271*424fb153SAndroid Build Coastguard Worker bool OsLayer::AdlerMemcpyWarm(uint64 *dstmem, uint64 *srcmem,
272*424fb153SAndroid Build Coastguard Worker                               unsigned int size_in_bytes,
273*424fb153SAndroid Build Coastguard Worker                               AdlerChecksum *checksum) {
274*424fb153SAndroid Build Coastguard Worker   if (has_vector_) {
275*424fb153SAndroid Build Coastguard Worker     return AdlerMemcpyAsm(dstmem, srcmem, size_in_bytes, checksum);
276*424fb153SAndroid Build Coastguard Worker   } else {
277*424fb153SAndroid Build Coastguard Worker     return AdlerMemcpyWarmC(dstmem, srcmem, size_in_bytes, checksum);
278*424fb153SAndroid Build Coastguard Worker   }
279*424fb153SAndroid Build Coastguard Worker }
280*424fb153SAndroid Build Coastguard Worker 
281*424fb153SAndroid Build Coastguard Worker 
282*424fb153SAndroid Build Coastguard Worker // Translate physical address to memory module/chip name.
283*424fb153SAndroid Build Coastguard Worker // Assumes interleaving between two memory channels based on the XOR of
284*424fb153SAndroid Build Coastguard Worker // all address bits in the 'channel_hash' mask, with repeated 'channel_width_'
285*424fb153SAndroid Build Coastguard Worker // blocks with bits distributed from each chip in that channel.
FindDimm(uint64 addr,char * buf,int len)286*424fb153SAndroid Build Coastguard Worker int OsLayer::FindDimm(uint64 addr, char *buf, int len) {
287*424fb153SAndroid Build Coastguard Worker   if (!channels_) {
288*424fb153SAndroid Build Coastguard Worker     snprintf(buf, len, "DIMM Unknown");
289*424fb153SAndroid Build Coastguard Worker     return -1;
290*424fb153SAndroid Build Coastguard Worker   }
291*424fb153SAndroid Build Coastguard Worker 
292*424fb153SAndroid Build Coastguard Worker   // Find channel by XORing address bits in channel_hash mask.
293*424fb153SAndroid Build Coastguard Worker   uint32 low = static_cast<uint32>(addr & channel_hash_);
294*424fb153SAndroid Build Coastguard Worker   uint32 high = static_cast<uint32>((addr & channel_hash_) >> 32);
295*424fb153SAndroid Build Coastguard Worker   vector<string>& channel = (*channels_)[
296*424fb153SAndroid Build Coastguard Worker       __builtin_parity(high) ^ __builtin_parity(low)];
297*424fb153SAndroid Build Coastguard Worker 
298*424fb153SAndroid Build Coastguard Worker   // Find dram chip by finding which byte within the channel
299*424fb153SAndroid Build Coastguard Worker   // by address mod channel width, then divide the channel
300*424fb153SAndroid Build Coastguard Worker   // evenly among the listed dram chips. Note, this will not work
301*424fb153SAndroid Build Coastguard Worker   // with x4 dram.
302*424fb153SAndroid Build Coastguard Worker   int chip = (addr % (channel_width_ / 8)) /
303*424fb153SAndroid Build Coastguard Worker              ((channel_width_ / 8) / channel.size());
304*424fb153SAndroid Build Coastguard Worker   string name = channel[chip];
305*424fb153SAndroid Build Coastguard Worker   snprintf(buf, len, "%s", name.c_str());
306*424fb153SAndroid Build Coastguard Worker   return 1;
307*424fb153SAndroid Build Coastguard Worker }
308*424fb153SAndroid Build Coastguard Worker 
309*424fb153SAndroid Build Coastguard Worker 
310*424fb153SAndroid Build Coastguard Worker // Classifies addresses according to "regions"
311*424fb153SAndroid Build Coastguard Worker // This isn't really implemented meaningfully here..
FindRegion(uint64 addr)312*424fb153SAndroid Build Coastguard Worker int32 OsLayer::FindRegion(uint64 addr) {
313*424fb153SAndroid Build Coastguard Worker   static bool warned = false;
314*424fb153SAndroid Build Coastguard Worker 
315*424fb153SAndroid Build Coastguard Worker   if (regionsize_ == 0) {
316*424fb153SAndroid Build Coastguard Worker     regionsize_ = totalmemsize_ / 8;
317*424fb153SAndroid Build Coastguard Worker     if (regionsize_ < 512 * kMegabyte)
318*424fb153SAndroid Build Coastguard Worker       regionsize_ = 512 * kMegabyte;
319*424fb153SAndroid Build Coastguard Worker     regioncount_ = totalmemsize_ / regionsize_;
320*424fb153SAndroid Build Coastguard Worker     if (regioncount_ < 1) regioncount_ = 1;
321*424fb153SAndroid Build Coastguard Worker   }
322*424fb153SAndroid Build Coastguard Worker 
323*424fb153SAndroid Build Coastguard Worker   int32 region_num = addr / regionsize_;
324*424fb153SAndroid Build Coastguard Worker   if (region_num >= regioncount_) {
325*424fb153SAndroid Build Coastguard Worker     if (!warned) {
326*424fb153SAndroid Build Coastguard Worker         logprintf(0, "Log: region number %d exceeds region count %d\n",
327*424fb153SAndroid Build Coastguard Worker                   region_num, regioncount_);
328*424fb153SAndroid Build Coastguard Worker         warned = true;
329*424fb153SAndroid Build Coastguard Worker     }
330*424fb153SAndroid Build Coastguard Worker     region_num = region_num % regioncount_;
331*424fb153SAndroid Build Coastguard Worker   }
332*424fb153SAndroid Build Coastguard Worker   return region_num;
333*424fb153SAndroid Build Coastguard Worker }
334*424fb153SAndroid Build Coastguard Worker 
335*424fb153SAndroid Build Coastguard Worker // Report which cores are associated with a given region.
FindCoreMask(int32 region)336*424fb153SAndroid Build Coastguard Worker cpu_set_t *OsLayer::FindCoreMask(int32 region) {
337*424fb153SAndroid Build Coastguard Worker   sat_assert(region >= 0);
338*424fb153SAndroid Build Coastguard Worker   region %= num_nodes_;
339*424fb153SAndroid Build Coastguard Worker   if (!cpu_sets_valid_[region]) {
340*424fb153SAndroid Build Coastguard Worker     CPU_ZERO(&cpu_sets_[region]);
341*424fb153SAndroid Build Coastguard Worker     for (int i = 0; i < num_cpus_per_node_; ++i) {
342*424fb153SAndroid Build Coastguard Worker       CPU_SET(i + region * num_cpus_per_node_, &cpu_sets_[region]);
343*424fb153SAndroid Build Coastguard Worker     }
344*424fb153SAndroid Build Coastguard Worker     cpu_sets_valid_[region] = true;
345*424fb153SAndroid Build Coastguard Worker     logprintf(5, "Log: Region %d mask 0x%s\n",
346*424fb153SAndroid Build Coastguard Worker                  region, FindCoreMaskFormat(region).c_str());
347*424fb153SAndroid Build Coastguard Worker   }
348*424fb153SAndroid Build Coastguard Worker   return &cpu_sets_[region];
349*424fb153SAndroid Build Coastguard Worker }
350*424fb153SAndroid Build Coastguard Worker 
351*424fb153SAndroid Build Coastguard Worker // Return cores associated with a given region in hex string.
FindCoreMaskFormat(int32 region)352*424fb153SAndroid Build Coastguard Worker string OsLayer::FindCoreMaskFormat(int32 region) {
353*424fb153SAndroid Build Coastguard Worker   cpu_set_t* mask = FindCoreMask(region);
354*424fb153SAndroid Build Coastguard Worker   string format = cpuset_format(mask);
355*424fb153SAndroid Build Coastguard Worker   if (format.size() < 8)
356*424fb153SAndroid Build Coastguard Worker     format = string(8 - format.size(), '0') + format;
357*424fb153SAndroid Build Coastguard Worker   return format;
358*424fb153SAndroid Build Coastguard Worker }
359*424fb153SAndroid Build Coastguard Worker 
360*424fb153SAndroid Build Coastguard Worker // Report an error in an easily parseable way.
ErrorReport(const char * part,const char * symptom,int count)361*424fb153SAndroid Build Coastguard Worker bool OsLayer::ErrorReport(const char *part, const char *symptom, int count) {
362*424fb153SAndroid Build Coastguard Worker   time_t now = clock_->Now();
363*424fb153SAndroid Build Coastguard Worker   int ttf = now - time_initialized_;
364*424fb153SAndroid Build Coastguard Worker   if (strlen(symptom) && strlen(part)) {
365*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Report Error: %s : %s : %d : %ds\n",
366*424fb153SAndroid Build Coastguard Worker               symptom, part, count, ttf);
367*424fb153SAndroid Build Coastguard Worker   } else {
368*424fb153SAndroid Build Coastguard Worker     // Log something so the error still shows up, but this won't break the
369*424fb153SAndroid Build Coastguard Worker     // parser.
370*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Warning: Invalid Report Error: "
371*424fb153SAndroid Build Coastguard Worker               "%s : %s : %d : %ds\n", symptom, part, count, ttf);
372*424fb153SAndroid Build Coastguard Worker   }
373*424fb153SAndroid Build Coastguard Worker   return true;
374*424fb153SAndroid Build Coastguard Worker }
375*424fb153SAndroid Build Coastguard Worker 
376*424fb153SAndroid Build Coastguard Worker // Read the number of hugepages out of the kernel interface in proc.
FindHugePages()377*424fb153SAndroid Build Coastguard Worker int64 OsLayer::FindHugePages() {
378*424fb153SAndroid Build Coastguard Worker   char buf[65] = "0";
379*424fb153SAndroid Build Coastguard Worker 
380*424fb153SAndroid Build Coastguard Worker   // This is a kernel interface to query the numebr of hugepages
381*424fb153SAndroid Build Coastguard Worker   // available in the system.
382*424fb153SAndroid Build Coastguard Worker   static const char *hugepages_info_file = "/proc/sys/vm/nr_hugepages";
383*424fb153SAndroid Build Coastguard Worker   int hpfile = open(hugepages_info_file, O_RDONLY);
384*424fb153SAndroid Build Coastguard Worker 
385*424fb153SAndroid Build Coastguard Worker   ssize_t bytes_read = read(hpfile, buf, 64);
386*424fb153SAndroid Build Coastguard Worker   close(hpfile);
387*424fb153SAndroid Build Coastguard Worker 
388*424fb153SAndroid Build Coastguard Worker   if (bytes_read <= 0) {
389*424fb153SAndroid Build Coastguard Worker     logprintf(12, "Log: /proc/sys/vm/nr_hugepages "
390*424fb153SAndroid Build Coastguard Worker                   "read did not provide data\n");
391*424fb153SAndroid Build Coastguard Worker     return 0;
392*424fb153SAndroid Build Coastguard Worker   }
393*424fb153SAndroid Build Coastguard Worker 
394*424fb153SAndroid Build Coastguard Worker   if (bytes_read == 64) {
395*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Process Error: /proc/sys/vm/nr_hugepages "
396*424fb153SAndroid Build Coastguard Worker                  "is surprisingly large\n");
397*424fb153SAndroid Build Coastguard Worker     return 0;
398*424fb153SAndroid Build Coastguard Worker   }
399*424fb153SAndroid Build Coastguard Worker 
400*424fb153SAndroid Build Coastguard Worker   // Add a null termintation to be string safe.
401*424fb153SAndroid Build Coastguard Worker   buf[bytes_read] = '\0';
402*424fb153SAndroid Build Coastguard Worker   // Read the page count.
403*424fb153SAndroid Build Coastguard Worker   int64 pages = strtoull(buf, NULL, 10);  // NOLINT
404*424fb153SAndroid Build Coastguard Worker 
405*424fb153SAndroid Build Coastguard Worker   return pages;
406*424fb153SAndroid Build Coastguard Worker }
407*424fb153SAndroid Build Coastguard Worker 
FindFreeMemSize()408*424fb153SAndroid Build Coastguard Worker int64 OsLayer::FindFreeMemSize() {
409*424fb153SAndroid Build Coastguard Worker   int64 size = 0;
410*424fb153SAndroid Build Coastguard Worker   int64 minsize = 0;
411*424fb153SAndroid Build Coastguard Worker   if (totalmemsize_ > 0)
412*424fb153SAndroid Build Coastguard Worker     return totalmemsize_;
413*424fb153SAndroid Build Coastguard Worker 
414*424fb153SAndroid Build Coastguard Worker   int64 pages = sysconf(_SC_PHYS_PAGES);
415*424fb153SAndroid Build Coastguard Worker   int64 avpages = sysconf(_SC_AVPHYS_PAGES);
416*424fb153SAndroid Build Coastguard Worker   int64 pagesize = sysconf(_SC_PAGESIZE);
417*424fb153SAndroid Build Coastguard Worker   int64 physsize = pages * pagesize;
418*424fb153SAndroid Build Coastguard Worker   int64 avphyssize = avpages * pagesize;
419*424fb153SAndroid Build Coastguard Worker 
420*424fb153SAndroid Build Coastguard Worker   // Assume 2MB hugepages.
421*424fb153SAndroid Build Coastguard Worker   int64 hugepagesize = FindHugePages() * 2 * kMegabyte;
422*424fb153SAndroid Build Coastguard Worker 
423*424fb153SAndroid Build Coastguard Worker   if ((pages == -1) || (pagesize == -1)) {
424*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Process Error: sysconf could not determine memory size.\n");
425*424fb153SAndroid Build Coastguard Worker     return 0;
426*424fb153SAndroid Build Coastguard Worker   }
427*424fb153SAndroid Build Coastguard Worker 
428*424fb153SAndroid Build Coastguard Worker   // We want to leave enough stuff for things to run.
429*424fb153SAndroid Build Coastguard Worker   // If the user specified a minimum amount of memory to expect, require that.
430*424fb153SAndroid Build Coastguard Worker   // Otherwise, if more than 2GB is present, leave 192M + 5% for other stuff.
431*424fb153SAndroid Build Coastguard Worker   // If less than 2GB is present use 85% of what's available.
432*424fb153SAndroid Build Coastguard Worker   // These are fairly arbitrary numbers that seem to work OK.
433*424fb153SAndroid Build Coastguard Worker   //
434*424fb153SAndroid Build Coastguard Worker   // TODO(nsanders): is there a more correct way to determine target
435*424fb153SAndroid Build Coastguard Worker   // memory size?
436*424fb153SAndroid Build Coastguard Worker   if (hugepagesize > 0) {
437*424fb153SAndroid Build Coastguard Worker     if (min_hugepages_bytes_ > 0) {
438*424fb153SAndroid Build Coastguard Worker       minsize = min_hugepages_bytes_;
439*424fb153SAndroid Build Coastguard Worker     } else {
440*424fb153SAndroid Build Coastguard Worker       minsize = hugepagesize;
441*424fb153SAndroid Build Coastguard Worker     }
442*424fb153SAndroid Build Coastguard Worker   } else {
443*424fb153SAndroid Build Coastguard Worker     if (physsize < 2048LL * kMegabyte) {
444*424fb153SAndroid Build Coastguard Worker       minsize = ((pages * 85) / 100) * pagesize;
445*424fb153SAndroid Build Coastguard Worker     } else {
446*424fb153SAndroid Build Coastguard Worker       minsize = ((pages * 95) / 100) * pagesize - (192 * kMegabyte);
447*424fb153SAndroid Build Coastguard Worker     }
448*424fb153SAndroid Build Coastguard Worker     // Make sure that at least reserve_mb_ is left for the system.
449*424fb153SAndroid Build Coastguard Worker     if (reserve_mb_ > 0) {
450*424fb153SAndroid Build Coastguard Worker       int64 totalsize = pages * pagesize;
451*424fb153SAndroid Build Coastguard Worker       int64 reserve_kb = reserve_mb_ * kMegabyte;
452*424fb153SAndroid Build Coastguard Worker       if (reserve_kb > totalsize) {
453*424fb153SAndroid Build Coastguard Worker         logprintf(0, "Procedural Error: %lld is bigger than the total memory "
454*424fb153SAndroid Build Coastguard Worker                   "available %lld\n", reserve_kb, totalsize);
455*424fb153SAndroid Build Coastguard Worker       } else if (reserve_kb > totalsize - minsize) {
456*424fb153SAndroid Build Coastguard Worker         logprintf(5, "Warning: Overriding memory to use: original %lld, "
457*424fb153SAndroid Build Coastguard Worker                   "current %lld\n", minsize, totalsize - reserve_kb);
458*424fb153SAndroid Build Coastguard Worker         minsize = totalsize - reserve_kb;
459*424fb153SAndroid Build Coastguard Worker       }
460*424fb153SAndroid Build Coastguard Worker     }
461*424fb153SAndroid Build Coastguard Worker   }
462*424fb153SAndroid Build Coastguard Worker 
463*424fb153SAndroid Build Coastguard Worker   // Use hugepage sizing if available.
464*424fb153SAndroid Build Coastguard Worker   if (hugepagesize > 0) {
465*424fb153SAndroid Build Coastguard Worker     if (hugepagesize < minsize) {
466*424fb153SAndroid Build Coastguard Worker       logprintf(0, "Procedural Error: Not enough hugepages. "
467*424fb153SAndroid Build Coastguard Worker                    "%lldMB available < %lldMB required.\n",
468*424fb153SAndroid Build Coastguard Worker                 hugepagesize / kMegabyte,
469*424fb153SAndroid Build Coastguard Worker                 minsize / kMegabyte);
470*424fb153SAndroid Build Coastguard Worker       // Require the calculated minimum amount of memory.
471*424fb153SAndroid Build Coastguard Worker       size = minsize;
472*424fb153SAndroid Build Coastguard Worker     } else {
473*424fb153SAndroid Build Coastguard Worker       // Require that we get all hugepages.
474*424fb153SAndroid Build Coastguard Worker       size = hugepagesize;
475*424fb153SAndroid Build Coastguard Worker     }
476*424fb153SAndroid Build Coastguard Worker   } else {
477*424fb153SAndroid Build Coastguard Worker     // Require the calculated minimum amount of memory.
478*424fb153SAndroid Build Coastguard Worker     size = minsize;
479*424fb153SAndroid Build Coastguard Worker   }
480*424fb153SAndroid Build Coastguard Worker 
481*424fb153SAndroid Build Coastguard Worker   logprintf(5, "Log: Total %lld MB. Free %lld MB. Hugepages %lld MB. "
482*424fb153SAndroid Build Coastguard Worker                "Targeting %lld MB (%lld%%)\n",
483*424fb153SAndroid Build Coastguard Worker             physsize / kMegabyte,
484*424fb153SAndroid Build Coastguard Worker             avphyssize / kMegabyte,
485*424fb153SAndroid Build Coastguard Worker             hugepagesize / kMegabyte,
486*424fb153SAndroid Build Coastguard Worker             size / kMegabyte,
487*424fb153SAndroid Build Coastguard Worker             size * 100 / physsize);
488*424fb153SAndroid Build Coastguard Worker 
489*424fb153SAndroid Build Coastguard Worker   totalmemsize_ = size;
490*424fb153SAndroid Build Coastguard Worker   return size;
491*424fb153SAndroid Build Coastguard Worker }
492*424fb153SAndroid Build Coastguard Worker 
493*424fb153SAndroid Build Coastguard Worker // Allocates all memory available.
AllocateAllMem()494*424fb153SAndroid Build Coastguard Worker int64 OsLayer::AllocateAllMem() {
495*424fb153SAndroid Build Coastguard Worker   int64 length = FindFreeMemSize();
496*424fb153SAndroid Build Coastguard Worker   bool retval = AllocateTestMem(length, 0);
497*424fb153SAndroid Build Coastguard Worker   if (retval)
498*424fb153SAndroid Build Coastguard Worker     return length;
499*424fb153SAndroid Build Coastguard Worker   else
500*424fb153SAndroid Build Coastguard Worker     return 0;
501*424fb153SAndroid Build Coastguard Worker }
502*424fb153SAndroid Build Coastguard Worker 
503*424fb153SAndroid Build Coastguard Worker // Allocate the target memory. This may be from malloc, hugepage pool
504*424fb153SAndroid Build Coastguard Worker // or other platform specific sources.
AllocateTestMem(int64 length,uint64 paddr_base)505*424fb153SAndroid Build Coastguard Worker bool OsLayer::AllocateTestMem(int64 length, uint64 paddr_base) {
506*424fb153SAndroid Build Coastguard Worker   // Try hugepages first.
507*424fb153SAndroid Build Coastguard Worker   void *buf = 0;
508*424fb153SAndroid Build Coastguard Worker 
509*424fb153SAndroid Build Coastguard Worker   sat_assert(length >= 0);
510*424fb153SAndroid Build Coastguard Worker 
511*424fb153SAndroid Build Coastguard Worker   if (paddr_base)
512*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Process Error: non zero paddr_base %#llx is not supported,"
513*424fb153SAndroid Build Coastguard Worker               " ignore.\n", paddr_base);
514*424fb153SAndroid Build Coastguard Worker 
515*424fb153SAndroid Build Coastguard Worker   // Determine optimal memory allocation path.
516*424fb153SAndroid Build Coastguard Worker   bool prefer_hugepages = false;
517*424fb153SAndroid Build Coastguard Worker   bool prefer_posix_shm = false;
518*424fb153SAndroid Build Coastguard Worker   bool prefer_dynamic_mapping = false;
519*424fb153SAndroid Build Coastguard Worker 
520*424fb153SAndroid Build Coastguard Worker   // Are there enough hugepages?
521*424fb153SAndroid Build Coastguard Worker   int64 hugepagesize = FindHugePages() * 2 * kMegabyte;
522*424fb153SAndroid Build Coastguard Worker   // TODO(nsanders): Is there enough /dev/shm? Is there enough free memeory?
523*424fb153SAndroid Build Coastguard Worker   if ((length >= 1400LL * kMegabyte) && (address_mode_ == 32)) {
524*424fb153SAndroid Build Coastguard Worker     prefer_dynamic_mapping = true;
525*424fb153SAndroid Build Coastguard Worker     prefer_posix_shm = true;
526*424fb153SAndroid Build Coastguard Worker     logprintf(3, "Log: Prefer POSIX shared memory allocation.\n");
527*424fb153SAndroid Build Coastguard Worker     logprintf(3, "Log: You may need to run "
528*424fb153SAndroid Build Coastguard Worker                  "'sudo mount -o remount,size=100\% /dev/shm.'\n");
529*424fb153SAndroid Build Coastguard Worker   } else if (hugepagesize >= length) {
530*424fb153SAndroid Build Coastguard Worker     prefer_hugepages = true;
531*424fb153SAndroid Build Coastguard Worker     logprintf(3, "Log: Prefer using hugepage allocation.\n");
532*424fb153SAndroid Build Coastguard Worker   } else {
533*424fb153SAndroid Build Coastguard Worker     logprintf(3, "Log: Prefer plain malloc memory allocation.\n");
534*424fb153SAndroid Build Coastguard Worker   }
535*424fb153SAndroid Build Coastguard Worker 
536*424fb153SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SHM_H
537*424fb153SAndroid Build Coastguard Worker   // Allocate hugepage mapped memory.
538*424fb153SAndroid Build Coastguard Worker   if (prefer_hugepages) {
539*424fb153SAndroid Build Coastguard Worker     do { // Allow break statement.
540*424fb153SAndroid Build Coastguard Worker       int shmid;
541*424fb153SAndroid Build Coastguard Worker       void *shmaddr;
542*424fb153SAndroid Build Coastguard Worker 
543*424fb153SAndroid Build Coastguard Worker       if ((shmid = shmget(2, length,
544*424fb153SAndroid Build Coastguard Worker               SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
545*424fb153SAndroid Build Coastguard Worker         int err = errno;
546*424fb153SAndroid Build Coastguard Worker         string errtxt = ErrorString(err);
547*424fb153SAndroid Build Coastguard Worker         logprintf(3, "Log: failed to allocate shared hugepage "
548*424fb153SAndroid Build Coastguard Worker                       "object - err %d (%s)\n",
549*424fb153SAndroid Build Coastguard Worker                   err, errtxt.c_str());
550*424fb153SAndroid Build Coastguard Worker         logprintf(3, "Log: sysctl -w vm.nr_hugepages=XXX allows hugepages.\n");
551*424fb153SAndroid Build Coastguard Worker         break;
552*424fb153SAndroid Build Coastguard Worker       }
553*424fb153SAndroid Build Coastguard Worker 
554*424fb153SAndroid Build Coastguard Worker       shmaddr = shmat(shmid, NULL, 0);
555*424fb153SAndroid Build Coastguard Worker       if (shmaddr == reinterpret_cast<void*>(-1)) {
556*424fb153SAndroid Build Coastguard Worker         int err = errno;
557*424fb153SAndroid Build Coastguard Worker         string errtxt = ErrorString(err);
558*424fb153SAndroid Build Coastguard Worker         logprintf(0, "Log: failed to attach shared "
559*424fb153SAndroid Build Coastguard Worker                      "hugepage object - err %d (%s).\n",
560*424fb153SAndroid Build Coastguard Worker                   err, errtxt.c_str());
561*424fb153SAndroid Build Coastguard Worker         if (shmctl(shmid, IPC_RMID, NULL) < 0) {
562*424fb153SAndroid Build Coastguard Worker           int err = errno;
563*424fb153SAndroid Build Coastguard Worker           string errtxt = ErrorString(err);
564*424fb153SAndroid Build Coastguard Worker           logprintf(0, "Log: failed to remove shared "
565*424fb153SAndroid Build Coastguard Worker                        "hugepage object - err %d (%s).\n",
566*424fb153SAndroid Build Coastguard Worker                     err, errtxt.c_str());
567*424fb153SAndroid Build Coastguard Worker         }
568*424fb153SAndroid Build Coastguard Worker         break;
569*424fb153SAndroid Build Coastguard Worker       }
570*424fb153SAndroid Build Coastguard Worker       use_hugepages_ = true;
571*424fb153SAndroid Build Coastguard Worker       shmid_ = shmid;
572*424fb153SAndroid Build Coastguard Worker       buf = shmaddr;
573*424fb153SAndroid Build Coastguard Worker       logprintf(0, "Log: Using shared hugepage object 0x%x at %p.\n",
574*424fb153SAndroid Build Coastguard Worker                 shmid, shmaddr);
575*424fb153SAndroid Build Coastguard Worker     } while (0);
576*424fb153SAndroid Build Coastguard Worker   }
577*424fb153SAndroid Build Coastguard Worker 
578*424fb153SAndroid Build Coastguard Worker   if ((!use_hugepages_) && prefer_posix_shm) {
579*424fb153SAndroid Build Coastguard Worker     do {
580*424fb153SAndroid Build Coastguard Worker       int shm_object;
581*424fb153SAndroid Build Coastguard Worker       void *shmaddr = NULL;
582*424fb153SAndroid Build Coastguard Worker 
583*424fb153SAndroid Build Coastguard Worker       shm_object = shm_open("/stressapptest", O_CREAT | O_RDWR, S_IRWXU);
584*424fb153SAndroid Build Coastguard Worker       if (shm_object < 0) {
585*424fb153SAndroid Build Coastguard Worker         int err = errno;
586*424fb153SAndroid Build Coastguard Worker         string errtxt = ErrorString(err);
587*424fb153SAndroid Build Coastguard Worker         logprintf(3, "Log: failed to allocate shared "
588*424fb153SAndroid Build Coastguard Worker                       "smallpage object - err %d (%s)\n",
589*424fb153SAndroid Build Coastguard Worker                   err, errtxt.c_str());
590*424fb153SAndroid Build Coastguard Worker         break;
591*424fb153SAndroid Build Coastguard Worker       }
592*424fb153SAndroid Build Coastguard Worker 
593*424fb153SAndroid Build Coastguard Worker       if (0 > ftruncate(shm_object, length)) {
594*424fb153SAndroid Build Coastguard Worker         int err = errno;
595*424fb153SAndroid Build Coastguard Worker         string errtxt = ErrorString(err);
596*424fb153SAndroid Build Coastguard Worker         logprintf(3, "Log: failed to ftruncate shared "
597*424fb153SAndroid Build Coastguard Worker                       "smallpage object - err %d (%s)\n",
598*424fb153SAndroid Build Coastguard Worker                   err, errtxt.c_str());
599*424fb153SAndroid Build Coastguard Worker         break;
600*424fb153SAndroid Build Coastguard Worker       }
601*424fb153SAndroid Build Coastguard Worker 
602*424fb153SAndroid Build Coastguard Worker       // 32 bit linux apps can only use ~1.4G of address space.
603*424fb153SAndroid Build Coastguard Worker       // Use dynamic mapping for allocations larger than that.
604*424fb153SAndroid Build Coastguard Worker       // Currently perf hit is ~10% for this.
605*424fb153SAndroid Build Coastguard Worker       if (prefer_dynamic_mapping) {
606*424fb153SAndroid Build Coastguard Worker         dynamic_mapped_shmem_ = true;
607*424fb153SAndroid Build Coastguard Worker       } else {
608*424fb153SAndroid Build Coastguard Worker         // Do a full mapping here otherwise.
609*424fb153SAndroid Build Coastguard Worker         shmaddr = mmap64(NULL, length, PROT_READ | PROT_WRITE,
610*424fb153SAndroid Build Coastguard Worker                          MAP_SHARED | MAP_NORESERVE | MAP_LOCKED | MAP_POPULATE,
611*424fb153SAndroid Build Coastguard Worker                          shm_object, 0);
612*424fb153SAndroid Build Coastguard Worker         if (shmaddr == reinterpret_cast<void*>(-1)) {
613*424fb153SAndroid Build Coastguard Worker           int err = errno;
614*424fb153SAndroid Build Coastguard Worker           string errtxt = ErrorString(err);
615*424fb153SAndroid Build Coastguard Worker           logprintf(0, "Log: failed to map shared "
616*424fb153SAndroid Build Coastguard Worker                        "smallpage object - err %d (%s).\n",
617*424fb153SAndroid Build Coastguard Worker                     err, errtxt.c_str());
618*424fb153SAndroid Build Coastguard Worker           break;
619*424fb153SAndroid Build Coastguard Worker         }
620*424fb153SAndroid Build Coastguard Worker       }
621*424fb153SAndroid Build Coastguard Worker 
622*424fb153SAndroid Build Coastguard Worker       use_posix_shm_ = true;
623*424fb153SAndroid Build Coastguard Worker       shmid_ = shm_object;
624*424fb153SAndroid Build Coastguard Worker       buf = shmaddr;
625*424fb153SAndroid Build Coastguard Worker       char location_message[256] = "";
626*424fb153SAndroid Build Coastguard Worker       if (dynamic_mapped_shmem_) {
627*424fb153SAndroid Build Coastguard Worker         sprintf(location_message, "mapped as needed");
628*424fb153SAndroid Build Coastguard Worker       } else {
629*424fb153SAndroid Build Coastguard Worker         sprintf(location_message, "at %p", shmaddr);
630*424fb153SAndroid Build Coastguard Worker       }
631*424fb153SAndroid Build Coastguard Worker       logprintf(0, "Log: Using posix shared memory object 0x%x %s.\n",
632*424fb153SAndroid Build Coastguard Worker                 shm_object, location_message);
633*424fb153SAndroid Build Coastguard Worker     } while (0);
634*424fb153SAndroid Build Coastguard Worker     shm_unlink("/stressapptest");
635*424fb153SAndroid Build Coastguard Worker   }
636*424fb153SAndroid Build Coastguard Worker #endif  // HAVE_SYS_SHM_H
637*424fb153SAndroid Build Coastguard Worker 
638*424fb153SAndroid Build Coastguard Worker   if (!use_hugepages_ && !use_posix_shm_) {
639*424fb153SAndroid Build Coastguard Worker     // If the page size is what SAT is expecting explicitly perform mmap()
640*424fb153SAndroid Build Coastguard Worker     // allocation.
641*424fb153SAndroid Build Coastguard Worker     if (sysconf(_SC_PAGESIZE) >= 4096) {
642*424fb153SAndroid Build Coastguard Worker       void *map_buf = mmap(NULL, length, PROT_READ | PROT_WRITE,
643*424fb153SAndroid Build Coastguard Worker                            MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
644*424fb153SAndroid Build Coastguard Worker       if (map_buf != MAP_FAILED) {
645*424fb153SAndroid Build Coastguard Worker         buf = map_buf;
646*424fb153SAndroid Build Coastguard Worker         mmapped_allocation_ = true;
647*424fb153SAndroid Build Coastguard Worker         logprintf(0, "Log: Using mmap() allocation at %p.\n", buf);
648*424fb153SAndroid Build Coastguard Worker       }
649*424fb153SAndroid Build Coastguard Worker     }
650*424fb153SAndroid Build Coastguard Worker     if (!mmapped_allocation_) {
651*424fb153SAndroid Build Coastguard Worker       // Use memalign to ensure that blocks are aligned enough for disk direct
652*424fb153SAndroid Build Coastguard Worker       // IO.
653*424fb153SAndroid Build Coastguard Worker       buf = static_cast<char*>(memalign(4096, length));
654*424fb153SAndroid Build Coastguard Worker       if (buf) {
655*424fb153SAndroid Build Coastguard Worker         logprintf(0, "Log: Using memaligned allocation at %p.\n", buf);
656*424fb153SAndroid Build Coastguard Worker       } else {
657*424fb153SAndroid Build Coastguard Worker         logprintf(0, "Process Error: memalign returned 0\n");
658*424fb153SAndroid Build Coastguard Worker         if ((length >= 1499LL * kMegabyte) && (address_mode_ == 32)) {
659*424fb153SAndroid Build Coastguard Worker           logprintf(0, "Log: You are trying to allocate > 1.4G on a 32 "
660*424fb153SAndroid Build Coastguard Worker                        "bit process. Please setup shared memory.\n");
661*424fb153SAndroid Build Coastguard Worker         }
662*424fb153SAndroid Build Coastguard Worker       }
663*424fb153SAndroid Build Coastguard Worker     }
664*424fb153SAndroid Build Coastguard Worker   }
665*424fb153SAndroid Build Coastguard Worker 
666*424fb153SAndroid Build Coastguard Worker   testmem_ = buf;
667*424fb153SAndroid Build Coastguard Worker   if (buf || dynamic_mapped_shmem_) {
668*424fb153SAndroid Build Coastguard Worker     testmemsize_ = length;
669*424fb153SAndroid Build Coastguard Worker   } else {
670*424fb153SAndroid Build Coastguard Worker     testmemsize_ = 0;
671*424fb153SAndroid Build Coastguard Worker   }
672*424fb153SAndroid Build Coastguard Worker 
673*424fb153SAndroid Build Coastguard Worker   return (buf != 0) || dynamic_mapped_shmem_;
674*424fb153SAndroid Build Coastguard Worker }
675*424fb153SAndroid Build Coastguard Worker 
676*424fb153SAndroid Build Coastguard Worker // Free the test memory.
FreeTestMem()677*424fb153SAndroid Build Coastguard Worker void OsLayer::FreeTestMem() {
678*424fb153SAndroid Build Coastguard Worker   if (testmem_) {
679*424fb153SAndroid Build Coastguard Worker     if (use_hugepages_) {
680*424fb153SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SHM_H
681*424fb153SAndroid Build Coastguard Worker       shmdt(testmem_);
682*424fb153SAndroid Build Coastguard Worker       shmctl(shmid_, IPC_RMID, NULL);
683*424fb153SAndroid Build Coastguard Worker #endif
684*424fb153SAndroid Build Coastguard Worker     } else if (use_posix_shm_) {
685*424fb153SAndroid Build Coastguard Worker       if (!dynamic_mapped_shmem_) {
686*424fb153SAndroid Build Coastguard Worker         munmap(testmem_, testmemsize_);
687*424fb153SAndroid Build Coastguard Worker       }
688*424fb153SAndroid Build Coastguard Worker       close(shmid_);
689*424fb153SAndroid Build Coastguard Worker     } else if (mmapped_allocation_) {
690*424fb153SAndroid Build Coastguard Worker       munmap(testmem_, testmemsize_);
691*424fb153SAndroid Build Coastguard Worker     } else {
692*424fb153SAndroid Build Coastguard Worker       free(testmem_);
693*424fb153SAndroid Build Coastguard Worker     }
694*424fb153SAndroid Build Coastguard Worker     testmem_ = 0;
695*424fb153SAndroid Build Coastguard Worker     testmemsize_ = 0;
696*424fb153SAndroid Build Coastguard Worker   }
697*424fb153SAndroid Build Coastguard Worker }
698*424fb153SAndroid Build Coastguard Worker 
699*424fb153SAndroid Build Coastguard Worker 
700*424fb153SAndroid Build Coastguard Worker // Prepare the target memory. It may requre mapping in, or this may be a noop.
PrepareTestMem(uint64 offset,uint64 length)701*424fb153SAndroid Build Coastguard Worker void *OsLayer::PrepareTestMem(uint64 offset, uint64 length) {
702*424fb153SAndroid Build Coastguard Worker   sat_assert((offset + length) <= testmemsize_);
703*424fb153SAndroid Build Coastguard Worker   if (dynamic_mapped_shmem_) {
704*424fb153SAndroid Build Coastguard Worker     // TODO(nsanders): Check if we can support MAP_NONBLOCK,
705*424fb153SAndroid Build Coastguard Worker     // and evaluate performance hit from not using it.
706*424fb153SAndroid Build Coastguard Worker #ifdef HAVE_MMAP64
707*424fb153SAndroid Build Coastguard Worker     void * mapping = mmap64(NULL, length, PROT_READ | PROT_WRITE,
708*424fb153SAndroid Build Coastguard Worker                      MAP_SHARED | MAP_NORESERVE | MAP_LOCKED | MAP_POPULATE,
709*424fb153SAndroid Build Coastguard Worker                      shmid_, offset);
710*424fb153SAndroid Build Coastguard Worker #else
711*424fb153SAndroid Build Coastguard Worker     void * mapping = mmap(NULL, length, PROT_READ | PROT_WRITE,
712*424fb153SAndroid Build Coastguard Worker                      MAP_SHARED | MAP_NORESERVE | MAP_LOCKED | MAP_POPULATE,
713*424fb153SAndroid Build Coastguard Worker                      shmid_, offset);
714*424fb153SAndroid Build Coastguard Worker #endif
715*424fb153SAndroid Build Coastguard Worker     if (mapping == MAP_FAILED) {
716*424fb153SAndroid Build Coastguard Worker       string errtxt = ErrorString(errno);
717*424fb153SAndroid Build Coastguard Worker       logprintf(0, "Process Error: PrepareTestMem mmap64(%llx, %llx) failed. "
718*424fb153SAndroid Build Coastguard Worker                    "error: %s.\n",
719*424fb153SAndroid Build Coastguard Worker                 offset, length, errtxt.c_str());
720*424fb153SAndroid Build Coastguard Worker       sat_assert(0);
721*424fb153SAndroid Build Coastguard Worker     }
722*424fb153SAndroid Build Coastguard Worker     return mapping;
723*424fb153SAndroid Build Coastguard Worker   }
724*424fb153SAndroid Build Coastguard Worker 
725*424fb153SAndroid Build Coastguard Worker   return reinterpret_cast<void*>(reinterpret_cast<char*>(testmem_) + offset);
726*424fb153SAndroid Build Coastguard Worker }
727*424fb153SAndroid Build Coastguard Worker 
728*424fb153SAndroid Build Coastguard Worker // Release the test memory resources, if any.
ReleaseTestMem(void * addr,uint64 offset,uint64 length)729*424fb153SAndroid Build Coastguard Worker void OsLayer::ReleaseTestMem(void *addr, uint64 offset, uint64 length) {
730*424fb153SAndroid Build Coastguard Worker   if (dynamic_mapped_shmem_) {
731*424fb153SAndroid Build Coastguard Worker     int retval = munmap(addr, length);
732*424fb153SAndroid Build Coastguard Worker     if (retval == -1) {
733*424fb153SAndroid Build Coastguard Worker       string errtxt = ErrorString(errno);
734*424fb153SAndroid Build Coastguard Worker       logprintf(0, "Process Error: ReleaseTestMem munmap(%p, %llx) failed. "
735*424fb153SAndroid Build Coastguard Worker                    "error: %s.\n",
736*424fb153SAndroid Build Coastguard Worker                 addr, length, errtxt.c_str());
737*424fb153SAndroid Build Coastguard Worker       sat_assert(0);
738*424fb153SAndroid Build Coastguard Worker     }
739*424fb153SAndroid Build Coastguard Worker   }
740*424fb153SAndroid Build Coastguard Worker }
741*424fb153SAndroid Build Coastguard Worker 
742*424fb153SAndroid Build Coastguard Worker // No error polling on unknown systems.
ErrorPoll()743*424fb153SAndroid Build Coastguard Worker int OsLayer::ErrorPoll() {
744*424fb153SAndroid Build Coastguard Worker   return 0;
745*424fb153SAndroid Build Coastguard Worker }
746*424fb153SAndroid Build Coastguard Worker 
747*424fb153SAndroid Build Coastguard Worker // Generally, poll for errors once per second.
ErrorWait()748*424fb153SAndroid Build Coastguard Worker void OsLayer::ErrorWait() {
749*424fb153SAndroid Build Coastguard Worker   sat_sleep(1);
750*424fb153SAndroid Build Coastguard Worker   return;
751*424fb153SAndroid Build Coastguard Worker }
752*424fb153SAndroid Build Coastguard Worker 
753*424fb153SAndroid Build Coastguard Worker // Open a PCI bus-dev-func as a file and return its file descriptor.
754*424fb153SAndroid Build Coastguard Worker // Error is indicated by return value less than zero.
PciOpen(int bus,int device,int function)755*424fb153SAndroid Build Coastguard Worker int OsLayer::PciOpen(int bus, int device, int function) {
756*424fb153SAndroid Build Coastguard Worker   char dev_file[256];
757*424fb153SAndroid Build Coastguard Worker 
758*424fb153SAndroid Build Coastguard Worker   snprintf(dev_file, sizeof(dev_file), "/proc/bus/pci/%02x/%02x.%x",
759*424fb153SAndroid Build Coastguard Worker            bus, device, function);
760*424fb153SAndroid Build Coastguard Worker 
761*424fb153SAndroid Build Coastguard Worker   int fd = open(dev_file, O_RDWR);
762*424fb153SAndroid Build Coastguard Worker   if (fd == -1) {
763*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Process Error: Unable to open PCI bus %d, device %d, "
764*424fb153SAndroid Build Coastguard Worker                  "function %d (errno %d).\n",
765*424fb153SAndroid Build Coastguard Worker               bus, device, function, errno);
766*424fb153SAndroid Build Coastguard Worker     return -1;
767*424fb153SAndroid Build Coastguard Worker   }
768*424fb153SAndroid Build Coastguard Worker 
769*424fb153SAndroid Build Coastguard Worker   return fd;
770*424fb153SAndroid Build Coastguard Worker }
771*424fb153SAndroid Build Coastguard Worker 
772*424fb153SAndroid Build Coastguard Worker 
773*424fb153SAndroid Build Coastguard Worker // Read and write functions to access PCI config.
PciRead(int fd,uint32 offset,int width)774*424fb153SAndroid Build Coastguard Worker uint32 OsLayer::PciRead(int fd, uint32 offset, int width) {
775*424fb153SAndroid Build Coastguard Worker   // Strict aliasing rules lawyers will cause data corruption
776*424fb153SAndroid Build Coastguard Worker   // on cast pointers in some gccs.
777*424fb153SAndroid Build Coastguard Worker   union {
778*424fb153SAndroid Build Coastguard Worker     uint32 l32;
779*424fb153SAndroid Build Coastguard Worker     uint16 l16;
780*424fb153SAndroid Build Coastguard Worker     uint8 l8;
781*424fb153SAndroid Build Coastguard Worker   } datacast;
782*424fb153SAndroid Build Coastguard Worker   datacast.l32 = 0;
783*424fb153SAndroid Build Coastguard Worker   uint32 size = width / 8;
784*424fb153SAndroid Build Coastguard Worker 
785*424fb153SAndroid Build Coastguard Worker   sat_assert((width == 32) || (width == 16) || (width == 8));
786*424fb153SAndroid Build Coastguard Worker   sat_assert(offset <= (256 - size));
787*424fb153SAndroid Build Coastguard Worker 
788*424fb153SAndroid Build Coastguard Worker   if (lseek(fd, offset, SEEK_SET) < 0) {
789*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Process Error: Can't seek %x\n", offset);
790*424fb153SAndroid Build Coastguard Worker     return 0;
791*424fb153SAndroid Build Coastguard Worker   }
792*424fb153SAndroid Build Coastguard Worker   if (read(fd, &datacast, size) != static_cast<ssize_t>(size)) {
793*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Process Error: Can't read %x\n", offset);
794*424fb153SAndroid Build Coastguard Worker     return 0;
795*424fb153SAndroid Build Coastguard Worker   }
796*424fb153SAndroid Build Coastguard Worker 
797*424fb153SAndroid Build Coastguard Worker   // Extract the data.
798*424fb153SAndroid Build Coastguard Worker   switch (width) {
799*424fb153SAndroid Build Coastguard Worker     case 8:
800*424fb153SAndroid Build Coastguard Worker       sat_assert(&(datacast.l8) == reinterpret_cast<uint8*>(&datacast));
801*424fb153SAndroid Build Coastguard Worker       return datacast.l8;
802*424fb153SAndroid Build Coastguard Worker     case 16:
803*424fb153SAndroid Build Coastguard Worker       sat_assert(&(datacast.l16) == reinterpret_cast<uint16*>(&datacast));
804*424fb153SAndroid Build Coastguard Worker       return datacast.l16;
805*424fb153SAndroid Build Coastguard Worker     case 32:
806*424fb153SAndroid Build Coastguard Worker       return datacast.l32;
807*424fb153SAndroid Build Coastguard Worker   }
808*424fb153SAndroid Build Coastguard Worker   return 0;
809*424fb153SAndroid Build Coastguard Worker }
810*424fb153SAndroid Build Coastguard Worker 
PciWrite(int fd,uint32 offset,uint32 value,int width)811*424fb153SAndroid Build Coastguard Worker void OsLayer::PciWrite(int fd, uint32 offset, uint32 value, int width) {
812*424fb153SAndroid Build Coastguard Worker   // Strict aliasing rules lawyers will cause data corruption
813*424fb153SAndroid Build Coastguard Worker   // on cast pointers in some gccs.
814*424fb153SAndroid Build Coastguard Worker   union {
815*424fb153SAndroid Build Coastguard Worker     uint32 l32;
816*424fb153SAndroid Build Coastguard Worker     uint16 l16;
817*424fb153SAndroid Build Coastguard Worker     uint8 l8;
818*424fb153SAndroid Build Coastguard Worker   } datacast;
819*424fb153SAndroid Build Coastguard Worker   datacast.l32 = 0;
820*424fb153SAndroid Build Coastguard Worker   uint32 size = width / 8;
821*424fb153SAndroid Build Coastguard Worker 
822*424fb153SAndroid Build Coastguard Worker   sat_assert((width == 32) || (width == 16) || (width == 8));
823*424fb153SAndroid Build Coastguard Worker   sat_assert(offset <= (256 - size));
824*424fb153SAndroid Build Coastguard Worker 
825*424fb153SAndroid Build Coastguard Worker   // Cram the data into the right alignment.
826*424fb153SAndroid Build Coastguard Worker   switch (width) {
827*424fb153SAndroid Build Coastguard Worker     case 8:
828*424fb153SAndroid Build Coastguard Worker       sat_assert(&(datacast.l8) == reinterpret_cast<uint8*>(&datacast));
829*424fb153SAndroid Build Coastguard Worker       datacast.l8 = value;
830*424fb153SAndroid Build Coastguard Worker     case 16:
831*424fb153SAndroid Build Coastguard Worker       sat_assert(&(datacast.l16) == reinterpret_cast<uint16*>(&datacast));
832*424fb153SAndroid Build Coastguard Worker       datacast.l16 = value;
833*424fb153SAndroid Build Coastguard Worker     case 32:
834*424fb153SAndroid Build Coastguard Worker       datacast.l32 = value;
835*424fb153SAndroid Build Coastguard Worker   }
836*424fb153SAndroid Build Coastguard Worker 
837*424fb153SAndroid Build Coastguard Worker   if (lseek(fd, offset, SEEK_SET) < 0) {
838*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Process Error: Can't seek %x\n", offset);
839*424fb153SAndroid Build Coastguard Worker     return;
840*424fb153SAndroid Build Coastguard Worker   }
841*424fb153SAndroid Build Coastguard Worker   if (write(fd, &datacast, size) != static_cast<ssize_t>(size)) {
842*424fb153SAndroid Build Coastguard Worker     logprintf(0, "Process Error: Can't write %x to %x\n", datacast.l32, offset);
843*424fb153SAndroid Build Coastguard Worker     return;
844*424fb153SAndroid Build Coastguard Worker   }
845*424fb153SAndroid Build Coastguard Worker 
846*424fb153SAndroid Build Coastguard Worker   return;
847*424fb153SAndroid Build Coastguard Worker }
848*424fb153SAndroid Build Coastguard Worker 
849*424fb153SAndroid Build Coastguard Worker 
850*424fb153SAndroid Build Coastguard Worker 
851*424fb153SAndroid Build Coastguard Worker // Open dev msr.
OpenMSR(uint32 core,uint32 address)852*424fb153SAndroid Build Coastguard Worker int OsLayer::OpenMSR(uint32 core, uint32 address) {
853*424fb153SAndroid Build Coastguard Worker   char buf[256];
854*424fb153SAndroid Build Coastguard Worker   snprintf(buf, sizeof(buf), "/dev/cpu/%d/msr", core);
855*424fb153SAndroid Build Coastguard Worker   int fd = open(buf, O_RDWR);
856*424fb153SAndroid Build Coastguard Worker   if (fd < 0)
857*424fb153SAndroid Build Coastguard Worker     return fd;
858*424fb153SAndroid Build Coastguard Worker 
859*424fb153SAndroid Build Coastguard Worker   uint32 pos = lseek(fd, address, SEEK_SET);
860*424fb153SAndroid Build Coastguard Worker   if (pos != address) {
861*424fb153SAndroid Build Coastguard Worker     close(fd);
862*424fb153SAndroid Build Coastguard Worker     logprintf(5, "Log: can't seek to msr %x, cpu %d\n", address, core);
863*424fb153SAndroid Build Coastguard Worker     return -1;
864*424fb153SAndroid Build Coastguard Worker   }
865*424fb153SAndroid Build Coastguard Worker 
866*424fb153SAndroid Build Coastguard Worker   return fd;
867*424fb153SAndroid Build Coastguard Worker }
868*424fb153SAndroid Build Coastguard Worker 
ReadMSR(uint32 core,uint32 address,uint64 * data)869*424fb153SAndroid Build Coastguard Worker bool OsLayer::ReadMSR(uint32 core, uint32 address, uint64 *data) {
870*424fb153SAndroid Build Coastguard Worker   int fd = OpenMSR(core, address);
871*424fb153SAndroid Build Coastguard Worker   if (fd < 0)
872*424fb153SAndroid Build Coastguard Worker     return false;
873*424fb153SAndroid Build Coastguard Worker 
874*424fb153SAndroid Build Coastguard Worker   // Read from the msr.
875*424fb153SAndroid Build Coastguard Worker   bool res = (sizeof(*data) == read(fd, data, sizeof(*data)));
876*424fb153SAndroid Build Coastguard Worker 
877*424fb153SAndroid Build Coastguard Worker   if (!res)
878*424fb153SAndroid Build Coastguard Worker     logprintf(5, "Log: Failed to read msr %x core %d\n", address, core);
879*424fb153SAndroid Build Coastguard Worker 
880*424fb153SAndroid Build Coastguard Worker   close(fd);
881*424fb153SAndroid Build Coastguard Worker 
882*424fb153SAndroid Build Coastguard Worker   return res;
883*424fb153SAndroid Build Coastguard Worker }
884*424fb153SAndroid Build Coastguard Worker 
WriteMSR(uint32 core,uint32 address,uint64 * data)885*424fb153SAndroid Build Coastguard Worker bool OsLayer::WriteMSR(uint32 core, uint32 address, uint64 *data) {
886*424fb153SAndroid Build Coastguard Worker   int fd = OpenMSR(core, address);
887*424fb153SAndroid Build Coastguard Worker   if (fd < 0)
888*424fb153SAndroid Build Coastguard Worker     return false;
889*424fb153SAndroid Build Coastguard Worker 
890*424fb153SAndroid Build Coastguard Worker   // Write to the msr
891*424fb153SAndroid Build Coastguard Worker   bool res = (sizeof(*data) == write(fd, data, sizeof(*data)));
892*424fb153SAndroid Build Coastguard Worker 
893*424fb153SAndroid Build Coastguard Worker   if (!res)
894*424fb153SAndroid Build Coastguard Worker     logprintf(5, "Log: Failed to write msr %x core %d\n", address, core);
895*424fb153SAndroid Build Coastguard Worker 
896*424fb153SAndroid Build Coastguard Worker   close(fd);
897*424fb153SAndroid Build Coastguard Worker 
898*424fb153SAndroid Build Coastguard Worker   return res;
899*424fb153SAndroid Build Coastguard Worker }
900*424fb153SAndroid Build Coastguard Worker 
901*424fb153SAndroid Build Coastguard Worker // Extract bits [n+len-1, n] from a 32 bit word.
902*424fb153SAndroid Build Coastguard Worker // so GetBitField(0x0f00, 8, 4) == 0xf.
GetBitField(uint32 val,uint32 n,uint32 len)903*424fb153SAndroid Build Coastguard Worker uint32 OsLayer::GetBitField(uint32 val, uint32 n, uint32 len) {
904*424fb153SAndroid Build Coastguard Worker   return (val >> n) & ((1<<len) - 1);
905*424fb153SAndroid Build Coastguard Worker }
906*424fb153SAndroid Build Coastguard Worker 
907*424fb153SAndroid Build Coastguard Worker // Generic CPU stress workload that would work on any CPU/Platform.
908*424fb153SAndroid Build Coastguard Worker // Float-point array moving average calculation.
CpuStressWorkload()909*424fb153SAndroid Build Coastguard Worker bool OsLayer::CpuStressWorkload() {
910*424fb153SAndroid Build Coastguard Worker   double float_arr[100];
911*424fb153SAndroid Build Coastguard Worker   double sum = 0;
912*424fb153SAndroid Build Coastguard Worker #ifdef HAVE_RAND_R
913*424fb153SAndroid Build Coastguard Worker   unsigned int seed = 12345;
914*424fb153SAndroid Build Coastguard Worker #endif
915*424fb153SAndroid Build Coastguard Worker 
916*424fb153SAndroid Build Coastguard Worker   // Initialize array with random numbers.
917*424fb153SAndroid Build Coastguard Worker   for (int i = 0; i < 100; i++) {
918*424fb153SAndroid Build Coastguard Worker #ifdef HAVE_RAND_R
919*424fb153SAndroid Build Coastguard Worker     float_arr[i] = rand_r(&seed);
920*424fb153SAndroid Build Coastguard Worker     if (rand_r(&seed) % 2)
921*424fb153SAndroid Build Coastguard Worker       float_arr[i] *= -1.0;
922*424fb153SAndroid Build Coastguard Worker #else
923*424fb153SAndroid Build Coastguard Worker     srand(time(NULL));
924*424fb153SAndroid Build Coastguard Worker     float_arr[i] = rand();  // NOLINT
925*424fb153SAndroid Build Coastguard Worker     if (rand() % 2)         // NOLINT
926*424fb153SAndroid Build Coastguard Worker       float_arr[i] *= -1.0;
927*424fb153SAndroid Build Coastguard Worker #endif
928*424fb153SAndroid Build Coastguard Worker   }
929*424fb153SAndroid Build Coastguard Worker 
930*424fb153SAndroid Build Coastguard Worker   // Calculate moving average.
931*424fb153SAndroid Build Coastguard Worker   for (int i = 0; i < 100000000; i++) {
932*424fb153SAndroid Build Coastguard Worker     float_arr[i % 100] =
933*424fb153SAndroid Build Coastguard Worker       (float_arr[i % 100] + float_arr[(i + 1) % 100] +
934*424fb153SAndroid Build Coastguard Worker        float_arr[(i + 99) % 100]) / 3;
935*424fb153SAndroid Build Coastguard Worker     sum += float_arr[i % 100];
936*424fb153SAndroid Build Coastguard Worker   }
937*424fb153SAndroid Build Coastguard Worker 
938*424fb153SAndroid Build Coastguard Worker   // Artificial printf so the loops do not get optimized away.
939*424fb153SAndroid Build Coastguard Worker   if (sum == 0.0)
940*424fb153SAndroid Build Coastguard Worker     logprintf(12, "Log: I'm Feeling Lucky!\n");
941*424fb153SAndroid Build Coastguard Worker   return true;
942*424fb153SAndroid Build Coastguard Worker }
943