1 // Copyright 2006 Google Inc. All Rights Reserved.
2 // Author: nsanders, menderico
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
16 #ifndef STRESSAPPTEST_OS_H_ // NOLINT
17 #define STRESSAPPTEST_OS_H_
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
30 const char kPagemapPath[] = "/proc/self/pagemap";
31 const char kSysfsPath[] = "/sys/bus/pci/devices";
44 typedef vector<PCIDevice*> PCIDevices;
48 // This class implements OS/Platform specific funtions.
54 // Set the minimum amount of hugepages that should be available for testing.
55 // Must be set before Initialize().
56 void SetMinimumHugepagesSize(int64 min_bytes) {
57 min_hugepages_bytes_ = min_bytes;
60 // Set parameters needed to translate physical address to memory module.
61 void SetDramMappingParams(int interleave_size, int channel_width,
62 vector< vector<string> > *modules) {
63 interleave_size_ = interleave_size;
64 channel_width_ = channel_width;
68 // Initializes data strctures and open files.
69 // Returns false on error.
70 virtual bool Initialize();
72 // Virtual to physical. This implementation is optional for
73 // subclasses to implement.
74 // Takes a pointer, and returns the corresponding bus address.
75 virtual uint64 VirtualToPhysical(void *vaddr);
77 // Prints failed dimm. This implementation is optional for
78 // subclasses to implement.
79 // Takes a bus address and string, and prints the DIMM name
80 // into the string. Returns error status.
81 virtual int FindDimm(uint64 addr, char *buf, int len);
82 // Print dimm info, plus more available info.
83 virtual int FindDimmExtended(uint64 addr, char *buf, int len) {
84 return FindDimm(addr, buf, len);
88 // Classifies addresses according to "regions"
89 // This may mean different things on different platforms.
90 virtual int32 FindRegion(uint64 paddr);
91 // Find cpu cores associated with a region. Either NUMA or arbitrary.
92 virtual cpu_set_t *FindCoreMask(int32 region);
93 // Return cpu cores associated with a region in a hex string.
94 virtual string FindCoreMaskFormat(int32 region);
96 // Returns the HD device that contains this file.
97 virtual string FindFileDevice(string filename);
99 // Returns a list of paths coresponding to HD devices found on this machine.
100 virtual list<string> FindFileDevices();
102 // Polls for errors. This implementation is optional.
103 // This will poll once for errors and return zero iff no errors were found.
104 virtual int ErrorPoll();
106 // Delay an appropriate amount of time between polling.
107 virtual void ErrorWait();
109 // Report errors. This implementation is mandatory.
110 // This will output a machine readable line regarding the error.
111 virtual bool ErrorReport(const char *part, const char *symptom, int count);
113 // Flushes page cache. Used to circumvent the page cache when doing disk
114 // I/O. This will be a NOP until ActivateFlushPageCache() is called, which
115 // is typically done when opening a file with O_DIRECT fails.
116 // Returns false on error, true on success or NOP.
117 // Subclasses may implement this in machine specific ways..
118 virtual bool FlushPageCache(void);
119 // Enable FlushPageCache() to actually do the flush instead of being a NOP.
120 virtual void ActivateFlushPageCache(void);
122 // Flushes cacheline. Used to distinguish read or write errors.
123 // Subclasses may implement this in machine specific ways..
124 // Takes a pointer, and flushed the cacheline containing that pointer.
125 virtual void Flush(void *vaddr);
127 // Fast flush, for use in performance critical code.
128 // This is bound at compile time, and will not pick up
129 // any runtime machine configuration info.
130 inline static void FastFlush(void *vaddr) {
131 #ifdef STRESSAPPTEST_CPU_PPC
132 asm volatile("dcbf 0,%0; sync" : : "r" (vaddr));
133 #elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
134 // Put mfence before and after clflush to make sure:
135 // 1. The write before the clflush is committed to memory bus;
136 // 2. The read after the clflush is hitting the memory bus.
138 // From Intel manual:
139 // CLFLUSH is only ordered by the MFENCE instruction. It is not guaranteed
140 // to be ordered by any other fencing, serializing or other CLFLUSH
141 // instruction. For example, software can use an MFENCE instruction to
142 // insure that previous stores are included in the write-back.
143 asm volatile("mfence");
144 asm volatile("clflush (%0)" :: "r" (vaddr));
145 asm volatile("mfence");
146 #elif defined(STRESSAPPTEST_CPU_ARMV7A)
147 #warning "Unsupported CPU type ARMV7A: Unable to force cache flushes."
149 #warning "Unsupported CPU type: Unable to force cache flushes."
153 // Get time in cpu timer ticks. Useful for matching MCEs with software
155 inline static uint64 GetTimestamp(void) {
157 #ifdef STRESSAPPTEST_CPU_PPC
158 uint32 tbl, tbu, temp;
166 : "=r"(tbl), "=r"(tbu), "=r"(temp)
170 tsc = (static_cast<uint64>(tbu) << 32) | static_cast<uint64>(tbl);
171 #elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
173 __asm __volatile("rdtsc" : "=a" (data.l32.l), "=d"(data.l32.h));
175 #elif defined(STRESSAPPTEST_CPU_ARMV7A)
176 #warning "Unsupported CPU type ARMV7A: your build may not function correctly"
179 #warning "Unsupported CPU type: your build may not function correctly"
185 // Find the free memory on the machine.
186 virtual int64 FindFreeMemSize();
188 // Allocates test memory of length bytes.
189 // Subclasses must implement this.
190 // Call PepareTestMem to get a pointer.
191 virtual int64 AllocateAllMem(); // Returns length.
193 virtual bool AllocateTestMem(int64 length, uint64 paddr_base);
194 virtual void FreeTestMem();
196 // Prepares the memory for use. You must call this
197 // before using test memory, and after you are done.
198 virtual void *PrepareTestMem(uint64 offset, uint64 length);
199 virtual void ReleaseTestMem(void *addr, uint64 offset, uint64 length);
201 // Machine type detected. Can we implement all these functions correctly?
202 // Returns true if machine type is detected and implemented.
203 virtual bool IsSupported();
205 // Returns 32 for 32-bit, 64 for 64-bit.
206 virtual int AddressMode();
207 // Update OsLayer state regarding cpu support for various features.
208 virtual void GetFeatures();
210 // Open, read, write pci cfg through /proc/bus/pci. fd is /proc/pci file.
211 virtual int PciOpen(int bus, int device, int function);
212 virtual void PciWrite(int fd, uint32 offset, uint32 value, int width);
213 virtual uint32 PciRead(int fd, uint32 offset, int width);
216 virtual bool ReadMSR(uint32 core, uint32 address, uint64 *data);
217 virtual bool WriteMSR(uint32 core, uint32 address, uint64 *data);
219 // Extract bits [n+len-1, n] from a 32 bit word.
220 // so GetBitField(0x0f00, 8, 4) == 0xf.
221 virtual uint32 GetBitField(uint32 val, uint32 n, uint32 len);
223 // Platform and CPU specific CPU-stressing function.
224 // Returns true on success, false otherwise.
225 virtual bool CpuStressWorkload();
227 // Causes false errors for unittesting.
228 // Setting to "true" causes errors to be injected.
229 void set_error_injection(bool errors) { error_injection_ = errors; }
230 bool error_injection() const { return error_injection_; }
232 // Is SAT using normal malloc'd memory, or exotic mmap'd memory.
233 bool normal_mem() const { return normal_mem_; }
235 // Get numa config, if available..
236 int num_nodes() const { return num_nodes_; }
237 int num_cpus() const { return num_cpus_; }
239 // Handle to platform-specific error diagnoser.
240 ErrorDiag *error_diagnoser_;
242 // Detect all PCI Devices.
243 virtual PCIDevices GetPCIDevices();
245 // Disambiguate between different "warm" memcopies.
246 virtual bool AdlerMemcpyWarm(uint64 *dstmem, uint64 *srcmem,
247 unsigned int size_in_bytes,
248 AdlerChecksum *checksum);
250 // Store a callback to use to print
251 // app-specific info about the last error location.
252 // This call back is called with a physical address, and the app can fill in
253 // the most recent transaction that occurred at that address.
254 typedef bool (*ErrCallback)(uint64 paddr, string *buf);
255 void set_err_log_callback(
256 ErrCallback err_log_callback) {
257 err_log_callback_ = err_log_callback;
259 ErrCallback get_err_log_callback() { return err_log_callback_; }
262 void *testmem_; // Location of test memory.
263 uint64 testmemsize_; // Size of test memory.
264 int64 totalmemsize_; // Size of available memory.
265 int64 min_hugepages_bytes_; // Minimum hugepages size.
266 bool error_injection_; // Do error injection?
267 bool normal_mem_; // Memory DMA capable?
268 bool use_hugepages_; // Use hugepage shmem?
269 bool use_posix_shm_; // Use 4k page shmem?
270 bool dynamic_mapped_shmem_; // Conserve virtual address space.
271 int shmid_; // Handle to shmem
272 vector< vector<string> > *modules_; // Memory module names per channel.
273 int interleave_size_; // Channel interleaving chunk size.
274 int channel_width_; // Channel width in bits.
276 int64 regionsize_; // Size of memory "regions"
277 int regioncount_; // Number of memory "regions"
278 int num_cpus_; // Number of cpus in the system.
279 int num_nodes_; // Number of nodes in the system.
280 int num_cpus_per_node_; // Number of cpus per node in the system.
281 int address_mode_; // Are we running 32 or 64 bit?
282 bool has_sse2_; // Do we have sse2 instructions?
283 bool has_clflush_; // Do we have clflush instructions?
284 bool use_flush_page_cache_; // Do we need to flush the page cache?
287 time_t time_initialized_; // Start time of test.
289 vector<cpu_set_t> cpu_sets_; // Cache for cpu masks.
290 vector<bool> cpu_sets_valid_; // If the cpu mask cache is valid.
292 // Get file descriptor for dev msr.
293 virtual int OpenMSR(uint32 core, uint32 address);
294 // Auxiliary methods for PCI device configuration
295 int PCIGetValue(string name, string object);
296 int PCIGetResources(string name, PCIDevice *device);
298 // Look up how many hugepages there are.
299 virtual int64 FindHugePages();
301 // Link to find last transaction at an error location.
302 ErrCallback err_log_callback_;
305 DISALLOW_COPY_AND_ASSIGN(OsLayer);
308 // Selects and returns the proper OS and hardware interface. Does not call
309 // OsLayer::Initialize() on the new object.
310 OsLayer *OsLayerFactory(const std::map<std::string, std::string> &options);
312 #endif // STRESSAPPTEST_OS_H_ NOLINT