blob: b043b61b7de28d4fa461e40d96c6b61b6153d248 [file] [log] [blame]
Scott Andersonb0114cb2012-04-09 14:08:22 -07001// Copyright 2006 Google Inc. All Rights Reserved.
2// Author: nsanders, menderico
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#ifndef STRESSAPPTEST_OS_H_ // NOLINT
17#define STRESSAPPTEST_OS_H_
18
19#include <dirent.h>
20#include <string>
21#include <list>
22#include <map>
23#include <vector>
24
25// This file must work with autoconf on its public version,
26// so these includes are correct.
27#include "adler32memcpy.h" // NOLINT
28#include "sattypes.h" // NOLINT
29
30const char kSysfsPath[] = "/sys/bus/pci/devices";
31
32struct PCIDevice {
33 int32 domain;
34 uint16 bus;
35 uint8 dev;
36 uint8 func;
37 uint16 vendor_id;
38 uint16 device_id;
39 uint64 base_addr[6];
40 uint64 size[6];
41};
42
43typedef vector<PCIDevice*> PCIDevices;
44
45class ErrorDiag;
46
47// This class implements OS/Platform specific funtions.
48class OsLayer {
49 public:
50 OsLayer();
51 virtual ~OsLayer();
52
53 // Set the minimum amount of hugepages that should be available for testing.
54 // Must be set before Initialize().
55 void SetMinimumHugepagesSize(int64 min_bytes) {
56 min_hugepages_bytes_ = min_bytes;
57 }
58
59 // Initializes data strctures and open files.
60 // Returns false on error.
61 virtual bool Initialize();
62
63 // Virtual to physical. This implementation is optional for
64 // subclasses to implement.
65 // Takes a pointer, and returns the corresponding bus address.
66 virtual uint64 VirtualToPhysical(void *vaddr);
67
68 // Prints failed dimm. This implementation is optional for
69 // subclasses to implement.
70 // Takes a bus address and string, and prints the DIMM name
71 // into the string. Returns error status.
72 virtual int FindDimm(uint64 addr, char *buf, int len);
73 // Print dimm info, plus more available info.
74 virtual int FindDimmExtended(uint64 addr, char *buf, int len) {
75 return FindDimm(addr, buf, len);
76 }
77
78
79 // Classifies addresses according to "regions"
80 // This may mean different things on different platforms.
81 virtual int32 FindRegion(uint64 paddr);
82 // Find cpu cores associated with a region. Either NUMA or arbitrary.
83 virtual cpu_set_t *FindCoreMask(int32 region);
84 // Return cpu cores associated with a region in a hex string.
85 virtual string FindCoreMaskFormat(int32 region);
86
87 // Returns the HD device that contains this file.
88 virtual string FindFileDevice(string filename);
89
90 // Returns a list of paths coresponding to HD devices found on this machine.
91 virtual list<string> FindFileDevices();
92
93 // Polls for errors. This implementation is optional.
94 // This will poll once for errors and return zero iff no errors were found.
95 virtual int ErrorPoll();
96
97 // Delay an appropriate amount of time between polling.
98 virtual void ErrorWait();
99
100 // Report errors. This implementation is mandatory.
101 // This will output a machine readable line regarding the error.
102 virtual bool ErrorReport(const char *part, const char *symptom, int count);
103
Scott Anderson613ee1f2012-04-24 16:35:57 -0700104 // Flushes page cache. Used to circumvent the page cache when doing disk
105 // I/O. This will be a NOP until ActivateFlushPageCache() is called, which
106 // is typically done when opening a file with O_DIRECT fails.
107 // Returns false on error, true on success or NOP.
108 // Subclasses may implement this in machine specific ways..
109 virtual bool FlushPageCache(void);
110 // Enable FlushPageCache() to actually do the flush instead of being a NOP.
111 virtual void ActivateFlushPageCache(void);
112
Scott Andersonb0114cb2012-04-09 14:08:22 -0700113 // Flushes cacheline. Used to distinguish read or write errors.
114 // Subclasses may implement this in machine specific ways..
115 // Takes a pointer, and flushed the cacheline containing that pointer.
116 virtual void Flush(void *vaddr);
117
118 // Fast flush, for use in performance critical code.
119 // This is bound at compile time, and will not pick up
120 // any runtime machine configuration info.
121 inline static void FastFlush(void *vaddr) {
122#ifdef STRESSAPPTEST_CPU_PPC
123 asm volatile("dcbf 0,%0; sync" : : "r" (vaddr));
124#elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
125 // Put mfence before and after clflush to make sure:
126 // 1. The write before the clflush is committed to memory bus;
127 // 2. The read after the clflush is hitting the memory bus.
128 //
129 // From Intel manual:
130 // CLFLUSH is only ordered by the MFENCE instruction. It is not guaranteed
131 // to be ordered by any other fencing, serializing or other CLFLUSH
132 // instruction. For example, software can use an MFENCE instruction to
133 // insure that previous stores are included in the write-back.
134 asm volatile("mfence");
135 asm volatile("clflush (%0)" :: "r" (vaddr));
136 asm volatile("mfence");
137#elif defined(STRESSAPPTEST_CPU_ARMV7A)
138 #warning "Unsupported CPU type ARMV7A: Unable to force cache flushes."
139#else
140 #warning "Unsupported CPU type: Unable to force cache flushes."
141#endif
142 }
143
144 // Get time in cpu timer ticks. Useful for matching MCEs with software
145 // actions.
146 inline static uint64 GetTimestamp(void) {
147 uint64 tsc;
148#ifdef STRESSAPPTEST_CPU_PPC
149 uint32 tbl, tbu, temp;
150 __asm __volatile(
151 "1:\n"
152 "mftbu %2\n"
153 "mftb %0\n"
154 "mftbu %1\n"
155 "cmpw %2,%1\n"
156 "bne 1b\n"
157 : "=r"(tbl), "=r"(tbu), "=r"(temp)
158 :
159 : "cc");
160
161 tsc = (static_cast<uint64>(tbu) << 32) | static_cast<uint64>(tbl);
162#elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
163 datacast_t data;
164 __asm __volatile("rdtsc" : "=a" (data.l32.l), "=d"(data.l32.h));
165 tsc = data.l64;
166#elif defined(STRESSAPPTEST_CPU_ARMV7A)
167 #warning "Unsupported CPU type ARMV7A: your build may not function correctly"
168 tsc = 0;
169#else
170 #warning "Unsupported CPU type: your build may not function correctly"
171 tsc = 0;
172#endif
173 return (tsc);
174 }
175
176 // Find the free memory on the machine.
177 virtual int64 FindFreeMemSize();
178
179 // Allocates test memory of length bytes.
180 // Subclasses must implement this.
181 // Call PepareTestMem to get a pointer.
182 virtual int64 AllocateAllMem(); // Returns length.
183 // Returns success.
184 virtual bool AllocateTestMem(int64 length, uint64 paddr_base);
185 virtual void FreeTestMem();
186
187 // Prepares the memory for use. You must call this
188 // before using test memory, and after you are done.
189 virtual void *PrepareTestMem(uint64 offset, uint64 length);
190 virtual void ReleaseTestMem(void *addr, uint64 offset, uint64 length);
191
192 // Machine type detected. Can we implement all these functions correctly?
193 // Returns true if machine type is detected and implemented.
194 virtual bool IsSupported();
195
196 // Returns 32 for 32-bit, 64 for 64-bit.
197 virtual int AddressMode();
198 // Update OsLayer state regarding cpu support for various features.
199 virtual void GetFeatures();
200
201 // Open, read, write pci cfg through /proc/bus/pci. fd is /proc/pci file.
202 virtual int PciOpen(int bus, int device, int function);
203 virtual void PciWrite(int fd, uint32 offset, uint32 value, int width);
204 virtual uint32 PciRead(int fd, uint32 offset, int width);
205
206 // Read MSRs
207 virtual bool ReadMSR(uint32 core, uint32 address, uint64 *data);
208 virtual bool WriteMSR(uint32 core, uint32 address, uint64 *data);
209
210 // Extract bits [n+len-1, n] from a 32 bit word.
211 // so GetBitField(0x0f00, 8, 4) == 0xf.
212 virtual uint32 GetBitField(uint32 val, uint32 n, uint32 len);
213
214 // Platform and CPU specific CPU-stressing function.
215 // Returns true on success, false otherwise.
216 virtual bool CpuStressWorkload();
217
218 // Causes false errors for unittesting.
219 // Setting to "true" causes errors to be injected.
220 void set_error_injection(bool errors) { error_injection_ = errors; }
221 bool error_injection() const { return error_injection_; }
222
223 // Is SAT using normal malloc'd memory, or exotic mmap'd memory.
224 bool normal_mem() const { return normal_mem_; }
225
226 // Get numa config, if available..
227 int num_nodes() const { return num_nodes_; }
228 int num_cpus() const { return num_cpus_; }
229
230 // Handle to platform-specific error diagnoser.
231 ErrorDiag *error_diagnoser_;
232
233 // Detect all PCI Devices.
234 virtual PCIDevices GetPCIDevices();
235
236 // Disambiguate between different "warm" memcopies.
237 virtual bool AdlerMemcpyWarm(uint64 *dstmem, uint64 *srcmem,
238 unsigned int size_in_bytes,
239 AdlerChecksum *checksum);
240
241 // Store a callback to use to print
242 // app-specific info about the last error location.
243 // This call back is called with a physical address, and the app can fill in
244 // the most recent transaction that occurred at that address.
245 typedef bool (*ErrCallback)(uint64 paddr, string *buf);
246 void set_err_log_callback(
247 ErrCallback err_log_callback) {
248 err_log_callback_ = err_log_callback;
249 }
250 ErrCallback get_err_log_callback() { return err_log_callback_; }
251
252 protected:
253 void *testmem_; // Location of test memory.
254 uint64 testmemsize_; // Size of test memory.
255 int64 totalmemsize_; // Size of available memory.
256 int64 min_hugepages_bytes_; // Minimum hugepages size.
257 bool error_injection_; // Do error injection?
258 bool normal_mem_; // Memory DMA capable?
259 bool use_hugepages_; // Use hugepage shmem?
260 bool use_posix_shm_; // Use 4k page shmem?
261 bool dynamic_mapped_shmem_; // Conserve virtual address space.
262 int shmid_; // Handle to shmem
263
264 int64 regionsize_; // Size of memory "regions"
265 int regioncount_; // Number of memory "regions"
266 int num_cpus_; // Number of cpus in the system.
267 int num_nodes_; // Number of nodes in the system.
268 int num_cpus_per_node_; // Number of cpus per node in the system.
269 int address_mode_; // Are we running 32 or 64 bit?
270 bool has_sse2_; // Do we have sse2 instructions?
271 bool has_clflush_; // Do we have clflush instructions?
Scott Anderson613ee1f2012-04-24 16:35:57 -0700272 bool use_flush_page_cache_; // Do we need to flush the page cache?
Scott Andersonb0114cb2012-04-09 14:08:22 -0700273
274
275 time_t time_initialized_; // Start time of test.
276
277 vector<cpu_set_t> cpu_sets_; // Cache for cpu masks.
278 vector<bool> cpu_sets_valid_; // If the cpu mask cache is valid.
279
280 // Get file descriptor for dev msr.
281 virtual int OpenMSR(uint32 core, uint32 address);
282 // Auxiliary methods for PCI device configuration
283 int PCIGetValue(string name, string object);
284 int PCIGetResources(string name, PCIDevice *device);
285
286 // Look up how many hugepages there are.
287 virtual int64 FindHugePages();
288
289 // Link to find last transaction at an error location.
290 ErrCallback err_log_callback_;
291
292 private:
293 DISALLOW_COPY_AND_ASSIGN(OsLayer);
294};
295
296// Selects and returns the proper OS and hardware interface. Does not call
297// OsLayer::Initialize() on the new object.
298OsLayer *OsLayerFactory(const std::map<std::string, std::string> &options);
299
300#endif // STRESSAPPTEST_OS_H_ NOLINT