Processor Counter Monitor
lspci.h
1 #ifndef CPUCounters_LSPCI_H
2 #define CPUCounters_LSPCI_H
3 
4 #include <vector>
5 #include <fstream>
6 #include "cpucounters.h"
7 
8 #if defined(_MSC_VER)
9 #define PCI_IDS_PATH "pci.ids"
10 #define PCI_IDS_NOT_FOUND "pci.ids file is not available. Download it from" \
11  " https://raw.githubusercontent.com/pciutils/pciids/master/pci.ids."
12 #elif defined (__FreeBSD__) || defined(__DragonFly__)
13 #define PCI_IDS_PATH "/usr/local/share/pciids/pci.ids"
14 #define PCI_IDS_NOT_FOUND "/usr/local/share/pciids/pci.ids file is not available." \
15  " Ensure that the \"pciids\" package is properly installed or download" \
16  " https://raw.githubusercontent.com/pciutils/pciids/master/pci.ids and" \
17  " copy it to the current directory."
18 #else
19 #define PCI_IDS_PATH "/usr/share/hwdata/pci.ids"
20 #define PCI_IDS_NOT_FOUND "/usr/share/hwdata/pci.ids file is not available." \
21  " Ensure that the \"hwdata\" package is properly installed or download" \
22  " https://raw.githubusercontent.com/pciutils/pciids/master/pci.ids and" \
23  " copy it to the current directory."
24 #endif
25 
26 using namespace std;
27 typedef uint32_t h_id;
28 typedef uint32_t v_id;
29 typedef map<std::pair<h_id,v_id>,uint64_t> ctr_data;
30 typedef vector<ctr_data> stack_content;
31 typedef vector<stack_content> result_content;
32 
33 struct bdf {
34  uint8_t busno;
35  uint8_t devno;
36  uint8_t funcno;
37 };
38 
39 struct pci {
40  bool exist = false;
41  struct bdf bdf;
42  union {
43  struct {
44  uint16_t vendor_id;
45  uint16_t device_id;
46  };
47  uint32_t offset_0;
48  };
49  int8_t header_type;
50  union {
51  struct {
52  uint8_t primary_bus_number;
53  uint8_t secondary_bus_number;
54  uint8_t subordinate_bus_number;
55  uint8_t junk;
56  };
57  uint32_t offset_18;
58  };
59  union {
60  struct {
61  uint16_t link_ctrl;
62  union {
63  struct {
64  uint16_t link_speed : 4;
65  uint16_t link_width : 6;
66  uint16_t undefined : 1;
67  uint16_t link_trained : 1;
68  };
69  uint16_t link_sta;
70  };
71  };
72  uint32_t link_info;
73  };
74 };
75 
76 struct counter {
77  string h_event_name;
78  string v_event_name;
79  IIOPMUCNTCTLRegister Opcodes;
80  int idx; /* Some counters need to be placed in specific index */
81  int multiplier;
82  int divider;
83  uint32_t h_id;
84  uint32_t v_id;
85  vector<result_content> data;
86 };
87 
88 struct iio_skx {
89  struct {
90  struct {
91  struct pci root_pci_dev; /* single device represent root port */
92  vector<struct pci> child_pci_devs; /* Contain child switch and end-point devices */
93  } parts[4]; /* part 0, 1, 2, 3 */
94  uint8_t busno; /* holding busno for each IIO stack */
95  string stack_name;
96  vector<uint64_t> values;
97  } stacks[6]; /* iio stack 0, 1, 2, 3, 4, 5 */
98  uint32_t socket_id;
99 };
100 
101 bool operator < (const bdf &l, const bdf &r) {
102  if (l.busno < r.busno)
103  return true;
104  if (l.busno > r.busno)
105  return false;
106  if (l.devno < r.devno)
107  return true;
108  if (l.devno > r.devno)
109  return false;
110  if (l.funcno < r.funcno)
111  return true;
112  if (l.funcno > r.funcno)
113  return false;
114 
115  return false; // bdf == bdf
116 };
117 
118 void probe_capability_pci_express(struct pci *p, uint32_t cap_ptr)
119 {
120  struct cap {
121  union {
122  struct {
123  uint8_t id;
124  union {
125  uint8_t next;
126  uint8_t cap_ptr;
127  };
128  uint16_t junk;
129  };
130  uint32 dw0;
131  };
132  } cap;
133  uint32 value;
134  PciHandleType h(0, p->bdf.busno, p->bdf.devno, p->bdf.funcno);
135  h.read32(cap_ptr, &value); //Capability pointer
136  cap.dw0 = value;
137  if (cap.id != 0x10 && cap.next != 0x00) {
138  probe_capability_pci_express(p, cap.cap_ptr);
139  } else {
140  if (cap.id == 0x10) { // We're in PCI express capability structure
141  h.read32(cap_ptr+0x10, &value);
142  p->link_info = value;
143  } else { /*Finish recursive searching but cannot find PCI express capability structure*/ }
144  }
145 }
146 
147 void probe_pci(struct pci *p)
148 {
149  uint32 value;
150  struct bdf *bdf = &p->bdf;
151  if (PciHandleType::exists(0, bdf->busno, bdf->devno, bdf->funcno)) {
152  p->exist = true;
153  PciHandleType h(0, bdf->busno, bdf->devno, bdf->funcno);
154  h.read32(0x0, &value); //VID:DID
155  p->offset_0 = value;
156  h.read32(0xc, &value);
157  p->header_type = (value >> 16) & 0x7f;
158  if (p->header_type == 0) {
159  h.read32(0x4, &value); //Status register
160  if (value & 0x100000) {//Capability list == true
161  h.read32(0x34, &value); //Capability pointer
162  probe_capability_pci_express(p, value);
163  }
164  } else if (p->header_type == 1) {
165  h.read32(0x18, &value);
166  p->offset_18 = value;
167  }
168  }
169  else
170  p->exist = false;
171 }
172 
173 /*
174  first : [vendorID] -> vencor name
175  second : [vendorID][deviceID] -> device name
176  */
177 typedef std::pair< std::map<int, std::string> ,std::map< int, std::map<int, std::string> > > PCIDB;
178 
179 void print_pci(struct pci p, const PCIDB & pciDB)
180 {
181  printf("Parent bridge info:");
182  printf("%x:%x.%d [%04x:%04x] %s %s %d P:%x S:%x S:%x ",
183  p.bdf.busno, p.bdf.devno, p.bdf.funcno,
184  p.vendor_id, p.device_id,
185  (pciDB.first.count(p.vendor_id) > 0)?pciDB.first.at(p.vendor_id).c_str():"unknown vendor",
186  (pciDB.second.count(p.vendor_id) > 0 && pciDB.second.at(p.vendor_id).count(p.device_id) > 0)?pciDB.second.at(p.vendor_id).at(p.device_id).c_str():"unknown device",
187  p.header_type,
188  p.primary_bus_number, p.secondary_bus_number, p.subordinate_bus_number);
189  printf("Device info:");
190  printf("%x:%x.%d [%04x:%04x] %s %s %d Gen%d x%d\n",
191  p.bdf.busno, p.bdf.devno, p.bdf.funcno,
192  p.vendor_id, p.device_id,
193  (pciDB.first.count(p.vendor_id) > 0)?pciDB.first.at(p.vendor_id).c_str():"unknown vendor",
194  (pciDB.second.count(p.vendor_id) > 0 && pciDB.second.at(p.vendor_id).count(p.device_id) > 0)?pciDB.second.at(p.vendor_id).at(p.device_id).c_str():"unknown device",
195  p.header_type,
196  p.link_speed, p.link_width);
197 }
198 
199 void load_PCIDB(PCIDB & pciDB)
200 {
201  std::ifstream in(PCI_IDS_PATH);
202  std::string line, item;
203 
204  if (!in.is_open())
205  {
206 #ifndef _MSC_VER
207  // On Unix, try the current directory if the default path failed
208  in.open("pci.ids");
209  }
210 
211  if (!in.is_open())
212  {
213 #endif
214  std::cerr << PCI_IDS_NOT_FOUND << endl;
215  return;
216  }
217 
218  int vendorID = -1;
219 
220  while (std::getline(in, line)) {
221  // Ignore any line starting with #
222  if (line.size() == 0 || line[0] == '#')
223  continue;
224 
225  if (line[0] == '\t' && line[1] == '\t')
226  {
227  // subvendor subdevice subsystem_name
228  continue;
229  }
230  if (line[0] == '\t')
231  {
232  int deviceID = stoi(line.substr(1,4),0,16);
233  //std::cout << vendorID << ";" << vendorName << ";" << deviceID << ";"<< line.substr(7) << endl;
234  pciDB.second[vendorID][deviceID] = line.substr(7);
235  continue;
236  }
237  // vendor
238  vendorID = stoi(line.substr(0,4),0,16);
239  pciDB.first[vendorID] = line.substr(6);
240  }
241 }
242 
243 #endif
Definition: lspci.h:76
Definition: lspci.h:39
Main CPU counters header.
Definition: types.h:889
Definition: lspci.h:88
Definition: lspci.h:33
Definition: pcm-iio.cpp:56