OxOOOO
0000 to
OxOOOO
OFFF,
and the peripheral is at
OxOOOO
1000), prefetching past the end
of
the
code will read the
peripheral.
Guarding storage also prevents prefetching past the end
of
memory. If the highest
memory
address is
left unguarded, the fetcher could attempt to fetch past the last valid address, potentially causing
machine checks on the fetches from
invalid addresses. While the machine checks
do
not actually
cause an exception until the processor attempts to execute an instruction at an invalid address, some
systems
could suffer from the attempt to access such an invalid address. For example, an external
memory controller might log an error.
System designers can avoid problems from speculative fetching without using the guarded storage
attributes. The rest
of
this section describes ways to prevent speculative instruction fetches to
sensitive addresses in unguarded memory regions.
3.8.2.1
Fetching Past an Interrupt-Causing
or
Interrupt-Returning
Instruction
Suppose a
bctr
or
blr
instruction closely follows an interrupt-causing or interrupt-returning instruction
(sc, rfi,
or
rfci).
The fetcher does not prevent speculatively fetching past one of these instructions. In
other words, the fetcher does not treat the interrupt-causing and interrupt-returning instructions
specially when deciding whether to predict down a branch path. Instructions after an
rfi,
for example,
are considered to be on the determined branch path.
To
understand the implications of this situation, consider the code sequence:
handler: aaa
bbb
rfi
subroutine: bctr
When executing the interrupt
handler, the fetcher does not recognize the
rfi
as a break in the program
flow, and speculatively fetches the target of the
bctr,
which is really the first instruction
of
a subroutine
that has not been
called. Therefore, the CTR might contain an invalid pOinter.
To
protect against such a prefetch, the software must insert an unconditional branch hang
(b
$) just
after the rfi. This prevents the hardware from prefetching the
invalid target address used by
bctr.
Consider also the above code sequence, with the
rfi
instruction replaced by an
sc
instruction used to
initialize the
CTR
with the appropriate value for the
bctr
to
branch to, upon return from the system
call. The
sc
handler returns to the instruction following the sc, which can't be a branch hang. Instead,
software could put a
mtctr
just before the
sc
to load a non-sensitive address into the CTR. This
address
will
be
used
as
the prediction address before the
sc
executes. An alternative would be to put
a
mfctr
or
mtctr
between the
sc
and the
bctr;
the
mtctr
prevents the fetcher from speculatively
accessing the address contained in the CTR before initialization.
3.8.2.2 Fetching Past
tw
or
twi Instructions
The interrupt-causing instructions,
tw
and
twi,
do not require the special handling described in
"Fetching Past an Interrupt-Causing
or
Interrupt-Returning Instruction" on page 3-39. These
instructions are
typically used by debuggers, which implement software breakpoints by substituting a
trap instruction for the instruction
originally at the breakpoint address.
In
a code sequence
mtlr
followed by
blr
(or
mtctr
followed by
bctr),
replacement
of
mtlr/mtctr
by
tw
or
twi
leaves the LR/CTR
uninitialized.
It would be inappropriate to fetch from the
blr/bctr
target address. This situation is
common, and the fetcher is designed to prevent the
problem.
Preliminary Programming Model 3-39