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