This would make no sense, because for every real device it is ESSENTIAL
that the ISR be able to read or write the control registers for the
device. Since the page tables that hold this mapping treat virtual
addresses on devices as if they are honorary members of the non-paged
pool, the kernel maps would never be paged out.
There is not a single instance of code in existence in Windows, nor has
there EVER been, that lets the processor access physical memory from an
instruction. The code stream can ONLY issue virtual (32 or 64 bit)
addresses. The only way you can access addresses that are on the bus is
if there is a page table entry that provides this mapping. And the page
tables to the nonpaged pool, for obvious reasons, are not paged.
When you get a BAR address from a PCI card, it is the bus-relative address
that has been assigned by the PCI BIOS and friends. Before you can axcess
it, you must call HalTranslateBusAddress, and you get back a virtual
address that will map to the correct physical address coming out of the
CPU so that ultimately the right device will respond to that signal. In
modern drivers, this is done for you by the PNP system, and this is
presented to you, the driver writer, as the “translated” resources in the
IRP_MJ_PNP:IRP_MN_START_DEVICE notifivation, and is handled in the KMDF
framework as partof the “notification” handling, so you never see the
antique legacy HAL calls in a PnP or KMDF-based driver.
The two most important registers which you MUST access for a PCI device is
a status indication somewhere that says “I have asserted interrupt” and
whatever register values must be manipulated to tell the device, “Thank
you very much, I am handling the interrupt, so please deassert the
interrupt signal”. You simply can’t write an ISR for a PCI device without
accessing and manipulating this state.
Note that since it is IMPOSSIBLE for instructions that are executing with
Virtual Memory enabled to create a bus-relative physical address, you can
ONLY use virtual addresses.
Some years ago I taught a one-shot course in kernel debugging. This was a
weird experience; the students gave ME homework! On Monday, they handed
me a crash dump and said “Tell us what went wrong”. I was given no other
detail. It was taking a BSOD on a MOV instruction that was reading a
device register. There were lots of possible causes, but I was asking
questions during my presentation of the analysis, and discovered that this
particular device was the disk controller driver, and about every 3 months
the server would die. I told them it was a hardware problem, quite likely
caused by an out-of-spec device on the bus screwing up the bus signals.
Turns out not one of these driver guys had a clue as to how a PCI bus
actually works! So I improvised a three-hour lecture on the PCI bus
architecture, pointing out that it was not necessarily their device that
was defective; it might have been the victim of collateral damage from a
drive-by waveform distortion. A device with bad bus protocol down to the
level of small-number-of-nanoseconds timing skews was probably the
problem. I suggested ideas like remove any cards that are not essential
and if te problem goes away, it might be one of those cards; if the
problem stays, it might be your card. Or not. I gave them a 20-minute
nanocourse on analog signals, impedances, reflected signals, capacitative
and inductive bus loading, etc. It was all new to them. I even mentioned
ground loops (in one infamous incident, a colleague was told the driver
was defective because it would reprogram the color maps in the display
with apparently random values. Using a PCI bus analyzer and many days of
analysis, he showed that at the time the screen went weird, there were no
bus cycles addressing the palette registers. Turns out te problem was a
ground loop under the video chip. I told them several other stories along
this line, such as the tape drive controller whose status register would
quite often deliver random bits. We knew this because the value had many
of the “unused, always returns 0” bits set to 1s. The programmer modified
the driver so that it had to get three successive identical values before
it would trust the status bits. The overnight backups stopped failing
with “unrecoverable tape drive error”. But the guys I was lecturing
thought that new hardware always worked perfectly. So I told them about
my uncle, who had been in the Nigerian army, and had $30,000,00 in gold
stashed away and I needed their help to get it out of the country. I
figured, if these guys believe new hardware is perfect, they’ll believe
anything!)
But the key part of the analysis was that you will NOT get an invalid
address when you access a device unless you have accidentally clobbered
the page table entry for that mapping or the device is determined to be
non-responsive. The first was unlikely because the address I was seeing
was in valid device space, a register located immediately before it had
been successfully read about 200 instructions earlier, and the problem
happened very rarely for a device that was handling hundreds of bus-level
transactions per second. I led them through a complete failure-tree
analysis and explained why I was reasonably confident about ruling out
most of the branches.
joe
As far I read Windows Internals and I was just curious about this topic
Anyway IIRC when driver’s ISR code is running (in interrupt context) it
shouldn’t access controlled device’s registers via VAs because it could
incurr in a BSOD (page tables could be paget out) So i guess ISR should
use always CPU-relative physical addresses
Does it make sense ? Thanks
NTDEV is sponsored by OSR
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer