I am trying to write a driver with a custom mmap()
function for a PCIe BAR, with the goal of making this BAR cacheable in the processor cache. I know that this is not the best way to achieve maximum throughput and that the recording order is unpredictable (in this case, there are no problems).
This is similar to what is described in How to prevent caching of MMAP values?
Sandy Bridge i7 processor, PCIe device is Altera Stratix IV dev. board.
At first I tried to do this on CentOS 5 (2.6.18). I changed the MTRR settings to make sure that the BAR is not in the wrong MTRR and the io_remap_pfn_range()
bit is used with _PAGE_PCD
and _PAGE_PWT
. It reads the work as expected: it reads the returned correct values ββand the second read to the same address does not necessarily lead to the read being transferred to PCIe (the read counter is checked in FPGA). However, the entries caused the system to freeze and then reboot without messages in the logs or on the screen.
Secondly, I tried to do this on CentOS 6 (2.6.32), which supports PAT. The result is the same: reading works correctly, writing causes the system to freeze and reboot. Interestingly, continuous recording as a string (AVX / SSE), independent of time / recording, works as expected, i.e. They always go to FPGA, and FPGA observes the complete entry in the cache line, after which it reads the returned correct values. However, a simple 64-bit write still causes the system to freeze / reboot.
I also tried ioremap_cache()
and then iowrite32()
inside the driver code. The result is the same.
I think this is a hardware problem, but I would appreciate it if anyone could share any ideas on what was going on.
EDIT: I was able to capture the MCE message on CentOS 6: Exclude computer scan: 5 Bank 5: be2000000003110a.
I also tried the same code on a 2-piston Sandy Bridge (Romley): reading and non-temporal behavior of the record are the same, simple records do not cause MCE / crash, but do not affect the state of the system, that is, the value in memory does not change.
In addition, I tried the same code on an older system with two Nehalem sockets: simple entries also call MCE, although the codes are different.