mepc and mtval on instruction-fetch access faults (request for clarification)

730 views
Skip to first unread message

Clifford Wolf

unread,
Jan 11, 2018, 3:05:05 PM1/11/18
to RISC-V ISA Dev
Hi,

the context for my question is M-mode instruction-fetch access faults for
accessing addresses that are forbidden via PMA or PMP. (Possibly on an
M-mode only implementation, so let's not even bother thinking about virtual
memory right now.)

My question is which instruction triggers the instruction-fetch access
fault. Is it the instruction at the address that cannot be fetched or is it
the instruction that tried to set the PC to the address of that instruction?

In case of a jump or branch instruction that jumps to the middle of a
memory region that cannot be executed, it seems like the jump itself should
trigger the exception:

RISC-V Priv Spec V1.10, Section 3.1.19, Page 34:

The mepc register can never hold a PC value that would cause an
instruction-address-misaligned exception.

However, in case of an instruction that has its first half in an
executable memory region, and its second half in a non-executable memory
region, it looks like the instruction itself should trigger the exception,
not the instruction leading up to the instruction that is partly in
non-executable memory:

RISC-V Priv Spec V1.10, Section 3.1.21, Page 36:

For instruction-fetch access faults on RISC-V systems with
variable-length instructions, mtval will contain a pointer to the
portion of the instruction that caused the fault while mepc will
point to the beginning of the instruction.

If however there are two instructions at the boundary between executable
and non-executable memory (first one not a branch or jump), with the first
instruction completely inside executable memory and the 2nd one outside
executable memory, it cant be the 2nd instruction causing the exception
because then mepc would be set to an invalid PC value, so it must be the
first instruction that triggers the exception.

So for example consider the following program assuming an executable
segment from 00000000..0x000fffff and non-executable memory above that:

0x000ffff8 addi x1, x0, 0
0x000ffffc addi x1, x1, 1
0x00100000 addi x2, x1, 0

From 3.1.19 of the priv spec I would say that this must trigger an
exception with mepc=0x000ffffc. That would also mean that we have x1=0
because the instruction at 0x000ffffc trapped so its effects should be
rolled back so that the instruction "never happened". (I think it would
make sense for mtval=0x00100000, but I can't find something in the spec
that requires this explicitly.)

This whole behavior seems odd to me, but it looks to me like this is the
behavior that the spec describes.

The main thing that looks odd to me is that apparently sometimes the
instruction that is (at least partially) inside the invalid memory region
is the one that traps, and sometimes it is the instruction before that. But
in both cases mcause will be set to the same value (0x00000001) and it
seems as if only sometimes mtval points to the relevant address inside the
invalid memory region (or at least the spec isn't very explicit about that).

Also: At the bottom of page 36 the spec says that mtval does not even need
to be able to hold invalid adresses:

mtval is a WARL register that must be able to hold all valid
physical and virtual addresses and the value 0. It need not be
capable of holding all possible invalid addresses. Implementations
may convert some invalid address patterns into other invalid
addresses prior to writing them to mtval.

But doesn't the paragraph I quoted above ("mtval will contain a pointer to
the portion of the instruction that caused the fault") imply that mtval
should be able to hold at least some invalid address patterns without
mangling them, namely the first address of each continous region of invalid
addresses?

Clarifications are very welcome. Thanks.

regards,
- clifford

Andrew Waterman

unread,
Jan 11, 2018, 4:09:07 PM1/11/18
to Clifford Wolf, RISC-V ISA Dev
On Thu, Jan 11, 2018 at 12:05 PM, Clifford Wolf <clif...@clifford.at> wrote:
Hi,

the context for my question is M-mode instruction-fetch access faults for
accessing addresses that are forbidden via PMA or PMP. (Possibly on an
M-mode only implementation, so let's not even bother thinking about virtual
memory right now.)

My question is which instruction triggers the instruction-fetch access
fault. Is it the instruction at the address that cannot be fetched or is it
the instruction that tried to set the PC to the address of that instruction?

The instruction that cannot be fetched triggers the access exception.


In case of a jump or branch instruction that jumps to the middle of a
memory region that cannot be executed, it seems like the jump itself should
trigger the exception:

        RISC-V Priv Spec V1.10, Section 3.1.19, Page 34:

        The mepc register can never hold a PC value that would cause an
        instruction-address-misaligned exception.

Instruction-address-misaligned exceptions are treated differently than access exceptions; there, the fault is considered to be on the branch or jump that caused the misalignment.
mepc=mtval=100000 here.
 

This whole behavior seems odd to me, but it looks to me like this is the
behavior that the spec describes.

The main thing that looks odd to me is that apparently sometimes the
instruction that is (at least partially) inside the invalid memory region
is the one that traps, and sometimes it is the instruction before that. But
in both cases mcause will be set to the same value (0x00000001) and it
seems as if only sometimes mtval points to the relevant address inside the
invalid memory region (or at least the spec isn't very explicit about that).

Misalignment is the only case where mepc is set to the address of the branch that caused misalignment.  For other instruction faults (access exceptions and page faults), mepc=the address of the start of the inaccessible instruction and mtval=the address of the portion of the inaccessible instruction that faulted.


Also: At the bottom of page 36 the spec says that mtval does not even need
to be able to hold invalid adresses:

        mtval is a WARL register that must be able to hold all valid
        physical and virtual addresses and the value 0. It need not be
        capable of holding all possible invalid addresses. Implementations
        may convert some invalid address patterns into other invalid
        addresses prior to writing them to mtval.

But doesn't the paragraph I quoted above ("mtval will contain a pointer to
the portion of the instruction that caused the fault") imply that mtval
should be able to hold at least some invalid address patterns without
mangling them, namely the first address of each continous region of invalid
addresses?

If the trap is resumable (e.g., a page fault that can be resolved), that implies the address is valid, so mtval must be able to store it.

If the trap is not resumable (e.g., an access fault to an unimplemented part of the address space), mtval might not be able to represent it.
 

Clarifications are very welcome. Thanks.

regards,
 - clifford

--
You received this message because you are subscribed to the Google Groups "RISC-V ISA Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to isa-dev+unsubscribe@groups.riscv.org.
To post to this group, send email to isa...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/isa-dev/.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/isa-dev/20180111200503.GW19352%40clifford.at.

Clifford Wolf

unread,
Jan 11, 2018, 4:25:40 PM1/11/18
to Andrew Waterman, RISC-V ISA Dev
Hi,

thanks for your reply.

On Thu, Jan 11, 2018 at 01:08:42PM -0800, Andrew Waterman wrote:
> > In case of a jump or branch instruction that jumps to the middle of a
> > memory region that cannot be executed, it seems like the jump itself should
> > trigger the exception:
> >
> > RISC-V Priv Spec V1.10, Section 3.1.19, Page 34:
> >
> > The mepc register can never hold a PC value that would cause an
> > instruction-address-misaligned exception.
>
> Instruction-address-misaligned exceptions are treated differently than
> access exceptions; there, the fault is considered to be on the branch or
> jump that caused the misalignment.

Ah, sorry. I misread that as instruction-access-fault. (And once the wrong
thing got stuck in my head I consistently misread it until now. Oops.)

> If the trap is resumable (e.g., a page fault that can be resolved), that
> implies the address is valid, so mtval must be able to store it.
>
> If the trap is not resumable (e.g., an access fault to an unimplemented
> part of the address space), mtval might not be able to represent it.

and the same with mpec (RISC-V Priv Spec V1.10, Section 3.1.19, page 34):

mepc is a WARL register that must be able to hold all valid
physical and virtual addresses. It need not be capable of holding
all possible invalid addresses. Implementations may convert some
invalid address patterns into other invalid addresses prior to
writing them to mepc.

So that means that if the program jumps to an unimplemented part of the
address space, neither mtval nor mepc might be able to hold the address the
program did jump to. I.e. the exception handler is called, but in the
exception handler we might have no way of figuring out what just happened.
Is this correct?

regards,
- clifford

Andrew Waterman

unread,
Jan 11, 2018, 4:32:07 PM1/11/18
to Clifford Wolf, RISC-V ISA Dev
I suppose not.  But to mitigate this fact, implementations should preserve as much of the address as possible.  For example, if the processor implements a 40-bit address space in RV64, mtval can be implemented as a 41-bit register, with address >= 2^40 recoded as 2^40 + (address % 2^40), preserving the low 40 bits of the address.


regards,
 - clifford


Reply all
Reply to author
Forward
0 new messages