chiark / gitweb /
1.0.6 update: Memory mapping features and stability fixes
[stressapptest] / src / os.h
1 // 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
30 const char kPagemapPath[] = "/proc/self/pagemap";
31 const char kSysfsPath[] = "/sys/bus/pci/devices";
32
33 struct PCIDevice {
34   int32 domain;
35   uint16 bus;
36   uint8 dev;
37   uint8 func;
38   uint16 vendor_id;
39   uint16 device_id;
40   uint64 base_addr[6];
41   uint64 size[6];
42 };
43
44 typedef vector<PCIDevice*> PCIDevices;
45
46 class ErrorDiag;
47
48 // This class implements OS/Platform specific funtions.
49 class OsLayer {
50  public:
51   OsLayer();
52   virtual ~OsLayer();
53
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;
58   }
59
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;
65     modules_ = modules;
66   }
67
68   // Initializes data strctures and open files.
69   // Returns false on error.
70   virtual bool Initialize();
71
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);
76
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);
85   }
86
87
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);
95
96   // Returns the HD device that contains this file.
97   virtual string FindFileDevice(string filename);
98
99   // Returns a list of paths coresponding to HD devices found on this machine.
100   virtual list<string> FindFileDevices();
101
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();
105
106   // Delay an appropriate amount of time between polling.
107   virtual void ErrorWait();
108
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);
112
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);
121
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);
126
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.
137     //
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."
148 #else
149   #warning "Unsupported CPU type: Unable to force cache flushes."
150 #endif
151   }
152
153   // Get time in cpu timer ticks. Useful for matching MCEs with software
154   // actions.
155   inline static uint64 GetTimestamp(void) {
156     uint64 tsc;
157 #ifdef STRESSAPPTEST_CPU_PPC
158     uint32 tbl, tbu, temp;
159     __asm __volatile(
160       "1:\n"
161       "mftbu  %2\n"
162       "mftb   %0\n"
163       "mftbu  %1\n"
164       "cmpw   %2,%1\n"
165       "bne    1b\n"
166       : "=r"(tbl), "=r"(tbu), "=r"(temp)
167       :
168       : "cc");
169
170     tsc = (static_cast<uint64>(tbu) << 32) | static_cast<uint64>(tbl);
171 #elif defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686)
172     datacast_t data;
173     __asm __volatile("rdtsc" : "=a" (data.l32.l), "=d"(data.l32.h));
174     tsc = data.l64;
175 #elif defined(STRESSAPPTEST_CPU_ARMV7A)
176   #warning "Unsupported CPU type ARMV7A: your build may not function correctly"
177     tsc = 0;
178 #else
179   #warning "Unsupported CPU type: your build may not function correctly"
180     tsc = 0;
181 #endif
182     return (tsc);
183   }
184
185   // Find the free memory on the machine.
186   virtual int64 FindFreeMemSize();
187
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.
192   // Returns success.
193   virtual bool AllocateTestMem(int64 length, uint64 paddr_base);
194   virtual void FreeTestMem();
195
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);
200
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();
204
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();
209
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);
214
215   // Read MSRs
216   virtual bool ReadMSR(uint32 core, uint32 address, uint64 *data);
217   virtual bool WriteMSR(uint32 core, uint32 address, uint64 *data);
218
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);
222
223   // Platform and CPU specific CPU-stressing function.
224   // Returns true on success, false otherwise.
225   virtual bool CpuStressWorkload();
226
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_; }
231
232   // Is SAT using normal malloc'd memory, or exotic mmap'd memory.
233   bool normal_mem() const { return normal_mem_; }
234
235   // Get numa config, if available..
236   int num_nodes() const { return num_nodes_; }
237   int num_cpus() const { return num_cpus_; }
238
239   // Handle to platform-specific error diagnoser.
240   ErrorDiag *error_diagnoser_;
241
242   // Detect all PCI Devices.
243   virtual PCIDevices GetPCIDevices();
244
245   // Disambiguate between different "warm" memcopies.
246   virtual bool AdlerMemcpyWarm(uint64 *dstmem, uint64 *srcmem,
247                                unsigned int size_in_bytes,
248                                AdlerChecksum *checksum);
249
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;
258   }
259   ErrCallback get_err_log_callback() { return err_log_callback_; }
260
261  protected:
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.
275
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?
285
286
287   time_t time_initialized_;      // Start time of test.
288
289   vector<cpu_set_t> cpu_sets_;   // Cache for cpu masks.
290   vector<bool> cpu_sets_valid_;  // If the cpu mask cache is valid.
291
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);
297
298   // Look up how many hugepages there are.
299   virtual int64 FindHugePages();
300
301   // Link to find last transaction at an error location.
302   ErrCallback err_log_callback_;
303
304  private:
305   DISALLOW_COPY_AND_ASSIGN(OsLayer);
306 };
307
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);
311
312 #endif  // STRESSAPPTEST_OS_H_ NOLINT