AR# 38389: 12.3 EDK - Interrupts cause multiple accesses to peripheral, corrupting data on PowerPC 440 designs
AR# 38389
|
12.3 EDK - Interrupts cause multiple accesses to peripheral, corrupting data on PowerPC 440 designs
描述
On a PowerPC 440 system, two accesses can occur to a peripheral location when an interrupt occurs during the first access. This can cause failures when the access is to a location that can only be read or written once for a particular transaction, such as peripheral FIFO location or status register.
What causes this behavior, and how do I avoid it?
解决方案
All memory locations that can only be accessed once for a particular value must be part of a Guarded address range in the TLB; see page 141 of the ppc440x5_um.pdf file: 5.6.4 Guarded (G)
The guarded storage attribute is provided to control "speculative" access to "non-well-behaved" memory locations. Storage is said to be "well-behaved" if the corresponding real storage exists and is not defective, and if the effects of a single access to it are indistinguishable from the effects of multiple identical accesses to it. As such, data and instructions can be fetched out-of-order from well-behaved storage without causing undesired side effects.
In general, storage that is not well-behaved should be marked as guarded. Because such storage may represent a control register on an I/O device or may include locations that do not exist, an out-of-order access to such storage may cause an I/O device to perform unintended operations or may result in a Machine Check exception. For example, if the input buffer of a serial I/O device is memory-mapped, then an out-of-order or speculative access to that location could result in the loss of an item of data from the input buffer, if the instruction execution is interrupted and later re-attempted.
Work-around:
Set the Guarded bit for all TLB entries that cover I/O peripheral ranges that cannot tolerate multiple accesses. For example, for setting the I/O ranges from 0x8000000-0x9FFFFFFF, use the following code:
#include "xtlb_l.h"
/* Initialize peripherals as guarded */ { unsigned short page; int attrib; int ts; /* Translation Space */