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.


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 */

for (ts=0;ts<=1;ts++){

/* 0x8000_0000 to 0x8FFF_FFFF */
page = XTlb_FindPage(0x80000000, 0x0, ts);
attrib = XTlb_GetStorAttribAccessCtrl(page);
XTlb_SetStorAttribAccessCtrl(page, ((short) attrib) | ( 1 << 8 ));

/* 0x9000_0000 to 0x9FFF_FFFF */
page = XTlb_FindPage(0x90000000, 0x0, ts);
attrib = XTlb_GetStorAttribAccessCtrl(page);
XTlb_SetStorAttribAccessCtrl(page, ((short) attrib) | ( 1 << 8 ));

AR# 38389
Date 12/20/2010
Status Active
Type General Article
Tools More Less
People Also Viewed