ISAMUX/ISANS Hypervisor Transitions

65 views
Skip to first unread message

lkcl

unread,
Jun 13, 2019, 2:30:47 AM6/13/19
to RISC-V ISA Dev
https://libre-riscv.org/isa_conflict_resolution/isamux_isans/

In the sections covering traps, best highlighted by Hypervisor Mode, is a bit of a conundrum.

As it stands, following the lead of ECALL and the convention of the trap being responsible for performing the context switch "by hand", using mscratch, sscratch or hscratch to do so, Hypervisor trap vectors would be executed in the FOREIGN architecture opcode space (hence the reason for a permutation of mtvec / stvec / htvec tables, one for each separate incompatible namespace).

The problem is the changeover point from the foreign namespace on change of the CSR to a "safe" namespace from which the "common" trap subroutine is called, and, more than that, the return from that subroutine also has to pop the CSR from a stack in a foreign arch!

Can anyone help think this through properly or think of better solutions?

Execution of foreign archs in hypervisor mode is an extreme case that, if solved, would mean that supervisor mode was also much easier to think through.

L.

Jacob Lifshay

unread,
Jun 13, 2019, 5:40:36 AM6/13/19
to Luke Kenneth Casson Leighton, RISC-V ISA Dev
I think that having a per-priv-level last-isans and trap-isans csrs would work. on taking a trap/syscall/interrupt the current isans would be saved in the last-isans of the new priv-level and the current isans would be set to the new priv-level's last-isans. on a return from the trap, the current isans would be set to last-isans for the old priv-level.

If support for per-trap isans values is needed, then there can be a per-priv-level trap-isans vector, similar to the trap-entry-point vectors, but the vector base address is specified in a different CSR.

--
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+u...@groups.riscv.org.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/isa-dev/8e01acb4-a263-401d-9472-c54bb185ad05%40groups.riscv.org.

lkcl

unread,
Jun 13, 2019, 9:03:00 AM6/13/19
to Jacob Lifshay, RISC-V ISA Dev


On Thursday, June 13, 2019, Jacob Lifshay <program...@gmail.com> wrote:
I think that having a per-priv-level last-isans and trap-isans csrs would work. on taking a trap/syscall/interrupt the current isans would be saved in the last-isans of the new priv-level and the current isans would be set to the new priv-level's last-isans. on a return from the trap, the current isans would be set to last-isans for the old priv-level.


Hmm.... this is close to the concept of the last-isans being the top of the stack, and as such, would need to be thought through very carefully when it comes to supervisor and hypervisor modes, when recursion may be involved.

Also not yet thought through: normally, attempting to read a priv CSR from one mode actually gives the CSR from another mode, I forget which ones.

The ISAMUX/NS CSR may need the same rules applied, so if software tries to read or set the M Mode CSR the S Mode one is set/returned instead, something like that.

If context switching latency really is a performance issue the last-isans concept would indeed help.




If support for per-trap isans values is needed, 

Per permutation of isans possibilities/combinations, yes. Per trap I do not believe so.


then there can be a per-priv-level trap-isans vector, similar to the trap-entry-point vectors, but the vector base address is specified in a different CSR. 

Hmmm...  yuk. Given that the vector would need to be written to, it would cause a memory write at the point of the exception. That would be a complicated design, makes me wary and would also have high latency. The trap could not exit until the write had completed, and it involves L1 and L2 and miss handlers.

On the foreign arch hypervisor bit, I realised a couple hours after writing, of course the foreign arch NS switch is to one specific binary-indexed NS.

Consequently, by the time the trap is reached (which is a specific base vector specifically for that foreign arch NS), there is *no need* to store the ISANS on the stack, because the context of the trap itself *is* the foreign arch's NS trap.

Doh.

Thus:

* Foreign arch is currently executing
* hypervisor trap occurs
* htvec SPECIFICALLY for that foreign arch is used
* foreign arch calls custom code to set RV isans
* next instruction is now in the *RV* (RV64GC) opcode space
* *RV* trap subroutine is called
* *RV* trap executes and exits
* CSRRW on ISAMUX/NS is set *BACK* to the foreign arch (still using RV opcodes here)
* *now* we exit the trap using a *FOREIGN* arch instruction to do so.

It is all quite spectacularly weird.

In the RV Isans space (both supervisor and hypervisor modes) things are slightly different. Here because the CSR is *unary* encoded, there needs to be...

Damn, it doesn't work. The number of permutations of potential NS options is so great that trying to allocate an htvel, mtvec and stvec for each permutation of possible NS bit combinations is just too much.

Instead I think you are right, Jacob, a "previous" isans CSR is needed, and a "default" ISANS has to be picked by the vendor and placed into the ISANS CSR at the time of the trap.

What that default value is may be up to the implementor to decide, or a case could be made for mandating the current (frozen) spec NS as of right now.

This to greatly simplify trap writing (as in: trap source code would not need to be modified).

My only concern is, are there circumstances where the last-isans could become corrupted due to recursive traps? One trap occurs then another, each overwriting last-isans?

Or is it sufficient to specify that only if the NS is non-default (non-zero) does the value get moved to the last-isans?

And, on exit from the trap, only a non-zero last-isans results in that value being written (moved) into the isans CSR (and last-isans set to zero)?

L.



On Wed, Jun 12, 2019, 23:30 lkcl <luke.l...@gmail.com> wrote:
https://libre-riscv.org/isa_conflict_resolution/isamux_isans/

In the sections covering traps, best highlighted by Hypervisor Mode, is a bit of a conundrum.

As it stands, following the lead of ECALL and the convention of the trap being responsible for performing the context switch "by hand", using mscratch, sscratch or hscratch to do so, Hypervisor trap vectors would be executed in the FOREIGN architecture opcode space (hence the reason for a permutation of mtvec / stvec / htvec tables, one for each separate incompatible namespace).

The problem is the changeover point from the foreign namespace on change of the CSR to a "safe" namespace from which the "common" trap subroutine is called, and, more than that, the return from that subroutine also has to pop the CSR from a stack in a foreign arch!

Can anyone help think this through properly or think of better solutions?

Execution of foreign archs in hypervisor mode is an extreme case that, if solved, would mean that supervisor mode was also much easier to think through.

L.

--
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.

Jacob Lifshay

unread,
Jun 13, 2019, 5:15:26 PM6/13/19
to Luke Kenneth Casson Leighton, RISC-V ISA Dev
On Thu, Jun 13, 2019, 06:02 lkcl <luke.l...@gmail.com> wrote:


On Thursday, June 13, 2019, Jacob Lifshay <program...@gmail.com> wrote:
I think that having a per-priv-level last-isans and trap-isans csrs would work. on taking a trap/syscall/interrupt the current isans would be saved in the last-isans of the new priv-level and the current isans would be set to the new priv-level's last-isans. on a return from the trap, the current isans would be set to last-isans for the old priv-level.


Hmm.... this is close to the concept of the last-isans being the top of the stack, and as such, would need to be thought through very carefully when it comes to supervisor and hypervisor modes, when recursion may be involved.

Also not yet thought through: normally, attempting to read a priv CSR from one mode actually gives the CSR from another mode, I forget which ones.

The ISAMUX/NS CSR may need the same rules applied, so if software tries to read or set the M Mode CSR the S Mode one is set/returned instead, something like that.

If context switching latency really is a performance issue the last-isans concept would indeed help.




If support for per-trap isans values is needed, 

Per permutation of isans possibilities/combinations, yes. Per trap I do not believe so.
Per isans combination is unsustainable, what happens when there 20 isans bits that independently switch parts of the address space, do you really need all 1M combinations to have a different trap vector? What about 30 bits, do you want it to take all available address space with 4GB of trap addresses on 32-bit implementations?!
per trap is sustainable as a similar scheme is already in use to hold the table of trap entry points.


then there can be a per-priv-level trap-isans vector, similar to the trap-entry-point vectors, but the vector base address is specified in a different CSR. 

Hmmm...  yuk. Given that the vector would need to be written to, it would cause a memory write at the point of the exception. 
I think you misunderstood, writing the algorithm in pseudo-code:

struct State<'a> {
    // ...
    isans: usize,
    priv_level: usize,
    prev_isans: [usize; PRIV_LEVELS],
    trap_isans: [usize; PRIV_LEVELS],
    trap_base_isans: [Option<&'a [usize]>; PRIV_LEVELS],
}

impl State<'_> {
    fn take_trap_or_interrupt(&mut self, trap_number: usize) {
        let new_priv_level: usize;
        // ...
        self.priv_level = new_priv_level;
        self.prev_isans[new_priv_level] = self.isans;
        match self.trap_base_isans[new_priv_level] {
            Some(table) => self.isans = table[trap_number],
            None => self.isans = self.trap_isans[new_priv_level],
        }
    }
    fn execute_xret(&mut self, new_priv_level: usize) {
        // ...
        self.isans = self.prev_isans[self.priv_level];
        self.priv_level = new_priv_level;
    }
    // ...
}

To support nested exceptions, the prev_isans value would be saved to memory at the beginning of the trap then restored from memory before executing xret.

This is conceptually similar to how the interrupt flags in mstatus are handled or to how function call linkage is handled (jal stores the return address in ra, callee stores ra on stack then can call more functions, before ret, ra is restored from stack).

One case that is hard to support without the trap and xret operations switching isans is having a risc-v supervisor and x86_64 user.

Jacob

lkcl

unread,
Jun 14, 2019, 1:37:36 AM6/14/19
to Jacob Lifshay, RISC-V ISA Dev
On Thu, Jun 13, 2019 at 10:15 PM Jacob Lifshay <program...@gmail.com> wrote:
>> Per permutation of isans possibilities/combinations, yes. Per trap I do not believe so.
>
> Per isans combination is unsustainable, what happens when there
> 20 isans bits that independently switch parts of the address space,
> do you really need all 1M combinations to have a different trap vector?

yes, hence why, annoyingly, i mentioned yesterday that it's unworkable.

> What about 30 bits, do you want it to take all available address
> space with 4GB of trap addresses on 32-bit implementations?!

*sigh* :)

hence why i like the last-isans idea. also, interestingly it makes
hypervisor guests completely "clean". they won't even *need* to have
a custom mechanism added that would return them to the RV NS.
ok (1) is this the implementation in *hardware*, i.e. *of* the trap
mechanism, or is it in software?

(2) how are additional traps (higher priority levels in that same
privilege level) prevented and prohibited from occurring before the
opportunity to write to memory has been actioned?

(3) there was another question, as i was half asleep this morning, i
can't remember what it was. doh! oh yes, that was it: in what
namespace will the above assembly code be written, conforming to what
version of what spec?

i *believe* the answer to (2) : it's as simple as using the
MIE/SIE/UIE bit to atomically guarantee the saving. and, in addition,
the most sensible location i can see for where to write to memory is,
"the stack".

i believe the answer to (3) was in my previous reply: the default NS
really does have to be "all zeros". otherwise it gets complex, quite
quickly.

> This is conceptually similar to how the interrupt flags in mstatus
> are handled or to how function call linkage is handled
> (jal stores the return address in ra, callee stores ra on stack
> then can call more functions, before ret, ra is restored from stack).

oh! ha, you make it clear here that the location in memory is indeed the stack.

ok, so the restoration of the last-ISAMUX/ISANS CSR just before
exiting the trap (so that the *hardware* flips it into the
ISAMUX/ISANS CSR) has a very interesting beneficial side-effect.

because it was *last-isans* that was being modified, the new NS
(which may be a foreign arch) is *NOT* activated immediately, so the
problems that could occur due to mis-alignment of instructions across
a change of architectures do not occur.

and, furthermore, given that the *trap* is where the change of NS
will occur (atomically), execution will return to exactly where the
(foreign arch) execution left off.

that's way better than what i originally envisaged.

> One case that is hard to support without the trap and xret operations switching isans is having a risc-v supervisor and x86_64 user.

yehyeh: that's the point of this particular sub-discussion :)

l.

Jacob Lifshay

unread,
Jun 14, 2019, 1:53:19 AM6/14/19
to lkcl, RISC-V ISA Dev
hardware
>
> (2) how are additional traps (higher priority levels in that same
> privilege level) prevented and prohibited from occurring before the
> opportunity to write to memory has been actioned?
by designing the first few instructions in the trap handler such that
they don't trap, same way as registers in any other trap. Interrupts
are already disabled on trap entry by the MIE/SIE/UIE handling
hardware.
>
> (3) there was another question, as i was half asleep this morning, i
> can't remember what it was. doh! oh yes, that was it: in what
> namespace will the above assembly code be written, conforming to what
> version of what spec?
the trap handler will be written in whatever ISA corresponds to the
trap_isans value. Basically the processor is switched to using
trap_isans as the namespace to interpret the trap handler in by the
hardware trap mechanism.
>
> i *believe* the answer to (2) : it's as simple as using the
> MIE/SIE/UIE bit to atomically guarantee the saving. and, in addition,
> the most sensible location i can see for where to write to memory is,
> "the stack".

>
> i believe the answer to (3) was in my previous reply: the default NS
> really does have to be "all zeros". otherwise it gets complex, quite
> quickly.
it doesn't have to be all zeros, since isans is set to the namespace
selected by the author of the trap handler code (by setting trap_isans
during boot) before executing the first instruction in the trap
handler.
>
> > This is conceptually similar to how the interrupt flags in mstatus
> > are handled or to how function call linkage is handled
> > (jal stores the return address in ra, callee stores ra on stack
> > then can call more functions, before ret, ra is restored from stack).
>
> oh! ha, you make it clear here that the location in memory is indeed the stack.
yeah, not to be confused with the table of isans values similar to the
table of trap/interrupt vectors (guess it could be called the
trap/interrupt isans vector table or something similar).

lkcl

unread,
Jun 14, 2019, 2:17:02 AM6/14/19
to Jacob Lifshay, RISC-V ISA Dev

lkcl

unread,
Jun 14, 2019, 2:57:34 AM6/14/19
to Jacob Lifshay, RISC-V ISA Dev
On Fri, Jun 14, 2019 at 6:53 AM Jacob Lifshay <program...@gmail.com> wrote:

> > ok (1) is this the implementation in *hardware*, i.e. *of* the trap
> > mechanism, or is it in software?
> hardware

eek! so the *hardware* is performing the write to the stack??
that's beginning to become CISC (and is unnecessary, as the exact same
algorithm can be done in software).

no wait...

> > (2) how are additional traps (higher priority levels in that same
> > privilege level) prevented and prohibited from occurring before the
> > opportunity to write to memory has been actioned?
> by designing the first few instructions in the trap handler such that
> they don't trap, same way as registers in any other trap.

now i am confused: above you imply that the write to the stack is
done as a (CISC-like) hardware implementation - this seems to now
imply that the change to...

no, i'm horribly confused, now. i think it comes down to not
understanding "fn take_trap_or_interrupt()". what is Some(table)?
where does it come from? what does "match" mean? what's the
difference between operator "=>" and operator "="?

much simpler pseudocode, and some comments, would have helped... :)


> Interrupts
> are already disabled on trap entry by the MIE/SIE/UIE handling
> hardware.

yes. this i get. so in software - in the trap - pushing the
last-isans to / from the stack is done atomically. Section 3.1.6.1
privspec V20190608-Priv-MSU_Ratified describes the purpose.

> >
> > (3) there was another question, as i was half asleep this morning, i
> > can't remember what it was. doh! oh yes, that was it: in what
> > namespace will the above assembly code be written, conforming to what
> > version of what spec?
> the trap handler will be written in whatever ISA corresponds to the
> trap_isans value.

i am utterly, utterly confused. what is trap_isans? what is its purpose?

> Basically the processor is switched to using
> trap_isans as the namespace to interpret the trap handler in by the
> hardware trap mechanism.

... i haven't got my head round it yet enough to be able to assess if
this will work or not. it *sounds* like it *might* be a global CSR
that indicates the default namespace of *all* trap handlers.

if so, that would be "safe", as all and any traps would have a
known-good NS in which they could be written, and, regardless of what
the current namespace was (outside of the trap), the traps are *going*
to be executed in that "safe" namespace.

if not, then we are back to the "permutations required" option, which
we've already established isn't going to work.

so, can you clarify:

* ISANS CSR is the current executing (non-trap) namespace
* LAST-ISANS CSR is used INSIDE a trap, containing the namespace of
the INTERRUPTED execution
* TRAP-ISANS is a declaration of the namespace that, on execution of a
trap, ISANS *MUST* be set to. all traps *MUST* be written in an
assembly language that is compatible with TRAP-ISANS.

per priv-level.

so, if we can write the hardware pseudo-code for "trap entry", it
would be like this:

trap_entry()
{
if (ISANS != TRAP_ISANS) // musn't change if already there
{
LAST-ISANS = ISANS // record the old NS
ISANS = TRAP_ISANS // traps are executed in "trap" NS
}
}

and trap_exit:

trap_exit():
{
if (LAST-ISANS != TRAP_ISANS)
{
ISANS = LAST-ISANS
LAST-ISANS = TRAP_ISANS
}
}

one pair each of these being required and completely separate and
distinct, per privilege level.


> > i *believe* the answer to (2) : it's as simple as using the
> > MIE/SIE/UIE bit to atomically guarantee the saving. and, in addition,
> > the most sensible location i can see for where to write to memory is,
> > "the stack".
>
> >
> > i believe the answer to (3) was in my previous reply: the default NS
> > really does have to be "all zeros". otherwise it gets complex, quite
> > quickly.
> it doesn't have to be all zeros, since isans is set to the namespace
> selected by the author of the trap handler code (by setting trap_isans
> during boot) before executing the first instruction in the trap
> handler.

yes, this occurred to me yesterday evening, i didn't describe it in
detail as i thought it would be a complication. can you check the
pseudocode to make sure i got it right?

https://libre-riscv.org/isa_conflict_resolution/isamux_isans/#privtraps

> >
> > > This is conceptually similar to how the interrupt flags in mstatus
> > > are handled or to how function call linkage is handled
> > > (jal stores the return address in ra, callee stores ra on stack
> > > then can call more functions, before ret, ra is restored from stack).
> >
> > oh! ha, you make it clear here that the location in memory is indeed the stack.
> yeah, not to be confused with the table of isans values similar to the
> table of trap/interrupt vectors (guess it could be called the
> trap/interrupt isans vector table or something similar).

a *TABLE* of trap_isans values. so, where currently there is mtvec,
you are talking about something that can be named "mtisansvec"? its
name explains its purpose:

* m - M-Mode
* t - Table
* isans - of ISANS values
* vec - as a vector

that correspond directly with each entry in *mtvec*?

is that correct?

so, mtisansvec declares the *namespace* - the assembly language - in
which *EACH* entry in the mtvec / stvec / htvec / utvec is written?

if so: what would be the use-case for doing so, that is different from
just setting each and every single one of those entries in the
Xtisansvec table to e.g. zero [representing the default 2019 RV
official standard]?

l.

lkcl

unread,
Jun 14, 2019, 3:05:54 AM6/14/19
to Jacob Lifshay, RISC-V ISA Dev
https://libre-riscv.org/isa_conflict_resolution/isamux_isans/#trap-isans-vec

please review, do i understand correctly: pseudo-code added that takes
x_cause as the argument and uses it as an index into TRAP_ISANS.

if correct: first impressions, this is quite complex and likely
unnecessary. what is the use-case for it?

l.

Jacob Lifshay

unread,
Jun 14, 2019, 3:26:16 AM6/14/19
to Luke Kenneth Casson Leighton, RISC-V ISA Dev
Rewriting the Rust code into C for those who aren't familiar with Rust:

#include <stdint.h>
#include <stddef.h>

typedef size_t uXLEN;

#define PRIV_LEVELS 3 // or 4 for hypervisor support

// ...
uXLEN isans;
int priv_level;
uXLEN prev_isans[PRIV_LEVELS];
uXLEN trap_isans[PRIV_LEVELS];
const uXLEN *trap_base_isans[PRIV_LEVELS];

void take_trap_or_interrupt(int trap_number)
{
int new_priv_level;
// ...
priv_level = new_priv_level;
prev_isans[new_priv_level] = isans; // write prev_isans register
const uXLEN *table = trap_base_isans[new_priv_level]; // read
trap_base_isans register
if(table) // if table is non-null
isans = table[trap_number]; // load new isans from memory
else
isans = trap_isans[new_priv_level]; // read from trap_isans register
}

void execute_xret(int new_priv_level)
{
// ...
isans = prev_isans[priv_level]; // read from prev_isans register
priv_level = new_priv_level;
}

// ...

Jacob Lifshay

unread,
Jun 14, 2019, 3:28:30 AM6/14/19
to lkcl, RISC-V ISA Dev
On Fri, Jun 14, 2019 at 12:05 AM lkcl <luke.l...@gmail.com> wrote:
> if correct: first impressions, this is quite complex and likely
> unnecessary. what is the use-case for it?
check the new pseudo-code, it's much simpler than you were thinking.
If implementations don't want traps to do memory access, they can
hardwire the trap_base_isans registers to 0.

lkcl

unread,
Jun 14, 2019, 4:13:24 AM6/14/19
to Jacob Lifshay, RISC-V ISA Dev
Yep got it.  Name is xtisansvec in effect.

It is still very complex, involves adding an extra memory lookup (next to mtvec, another lookup is needed, this time @ (xtisansvec + mcause*4) and a use-case is yet to be determined.

*not* having a table (and a global per priv level trap-isans in its place) is far simpler, and makes the software and compiler toolchain a lot less complex.

So what use case exists?


Clearly, running foreign hypervisors is possible (foreign hypervisor kernels i mean), however this is  *RISCV* we are discussing. My feeling is that as this is RISCV, the hypervisor kernel should always be in RISCV assembler, not a foreign arch.

In a similar vein, in a foreign arch, RISCV trap causes are utterly meaningless. The concept of a foreign arch trap or interrupt is so completely alien to RISCV that it would NOT be adviseable to try to "translate" between foreign arch traps and RISCV traps in some automated fashion (or spec-mandated fashion).

We simply cannot go through every permutation of foreign arch out there. Instead I feel it should be considered "out of scope" of this spec, handled by software, and up to the vendor to sort out. At the very least, it should be a future revision.

So foreign traps are meaningless and do not translate to RISCV, the point of having an entire xtisansvec for them is invalidated.

That just leaves RV xtisansvec.

What is the use case for having xtisansvec (a per xcause lookup table) that allows each trap vector to execute in a *separate* RISCV namespace?

(you can tell that I think one trap-isans is enough, per priv level, however there may actually be a genuine use case. If so, I'd like to hear what it is)

L.

Jacob Lifshay

unread,
Jun 14, 2019, 4:25:08 AM6/14/19
to Luke Kenneth Casson Leighton, RISC-V ISA Dev
the reason I originally had was orthogonality.
one (admittedly pretty contrived) use case two different legacy proprietary user-space libraries that sets some interrupt handlers and only supports mutually exclusive isans settings.

The important parts are still there if trap_base_isans is removed. if trap_base_isans is desired, it can be added back in in a backward compatible way split out in another extension, rather than the base isans extension.

lkcl

unread,
Jun 14, 2019, 6:27:42 AM6/14/19
to Jacob Lifshay, RISC-V ISA Dev


On Friday, June 14, 2019, Jacob Lifshay <program...@gmail.com> wrote:


What is the use case for having xtisansvec (a per xcause lookup table) that allows each trap vector to execute in a *separate* RISCV namespace?

(you can tell that I think one trap-isans is enough, per priv level, however there may actually be a genuine use case. If so, I'd like to hear what it is)
the reason I originally had was orthogonality.

As good a reason as any :)
 
one (admittedly pretty contrived) use case two different legacy proprietary user-space libraries that sets some interrupt handlers and only supports mutually exclusive isans settings.

Here, if TRAPISANS is set to the preferred (global) default, in that (default) assembly code, one of them may work out which actually needs calling and treat the other as a subroutine.  ISANS for the appropriate NS being set before call and restored afterwards.

If both are binary and the source code lost or not available, both legacy subroutines may be treated in the same fashion by an "actual" trap handler that, once again, runs in the default TRAPISANS.


The important parts are still there if trap_base_isans is removed. if trap_base_isans is desired, it can be added back in in a backward compatible way split out in another extension, rather than the base isans extension.

Yyyeah that sounds reasonable.

L.
 

Jacob Lifshay

unread,
Jun 14, 2019, 6:29:31 AM6/14/19
to Luke Kenneth Casson Leighton, RISC-V ISA Dev
reviewing https://libre-riscv.org/isa_conflict_resolution/isamux_isans/#privtraps

in the priv-traps section, I don't think the trap/xRET functionality should be conditional on isans matching anything, as that makes the HW unnecessarily more complicated and the operations harder to understand.

unrelated note: there is no instruction named xret, xRET is shorthand for one of URET, SRET, MRET, or HRET (if that ever becomes a thing).

Jacob

Jacob Lifshay

unread,
Jun 14, 2019, 6:35:43 AM6/14/19
to Luke Kenneth Casson Leighton, RISC-V ISA Dev
On Fri, Jun 14, 2019, 03:27 lkcl <luke.l...@gmail.com> wrote:


On Friday, June 14, 2019, Jacob Lifshay <program...@gmail.com> wrote:


What is the use case for having xtisansvec (a per xcause lookup table) that allows each trap vector to execute in a *separate* RISCV namespace?

(you can tell that I think one trap-isans is enough, per priv level, however there may actually be a genuine use case. If so, I'd like to hear what it is)
the reason I originally had was orthogonality.

As good a reason as any :)
 
one (admittedly pretty contrived) use case two different legacy proprietary user-space libraries that sets some interrupt handlers and only supports mutually exclusive isans settings.

Here, if TRAPISANS is set to the preferred (global) default, in that (default) assembly code, one of them may work out which actually needs calling and treat the other as a subroutine.  ISANS for the appropriate NS being set before call and restored afterwards.

If both are binary and the source code lost or not available, both legacy subroutines may be treated in the same fashion by an "actual" trap handler that, once again, runs in the default TRAPISANS.
seems reasonable.


The important parts are still there if trap_base_isans is removed. if trap_base_isans is desired, it can be added back in in a backward compatible way split out in another extension, rather than the base isans extension.

Yyyeah that sounds reasonable.
maybe trap_base_isans can be included but allowed to be hardwired to 0, leaving essentially the same implementation as removing trap_base_isans.

L.
 

lkcl

unread,
Jun 14, 2019, 6:37:27 AM6/14/19
to Jacob Lifshay, RISC-V ISA Dev


On Friday, June 14, 2019, Jacob Lifshay <program...@gmail.com> wrote:
reviewing https://libre-riscv.org/isa_conflict_resolution/isamux_isans/#privtraps

in the priv-traps section, I don't think the trap/xRET functionality should be conditional on isans matching anything, as that makes the HW unnecessarily more complicated and the operations harder to understand.

Was thinking if it made any difference... it is just setting to a value that it's already set to, isn't it?
 

unrelated note: there is no instruction named xret, xRET is shorthand for one of URET, SRET, MRET, or HRET (if that ever becomes a thing).

Yes. Thought that was a well known convention.

L.

Jacob Lifshay

unread,
Jun 14, 2019, 6:43:25 AM6/14/19
to Luke Kenneth Casson Leighton, RISC-V ISA Dev


On Fri, Jun 14, 2019, 03:37 lkcl <luke.l...@gmail.com> wrote:


On Friday, June 14, 2019, Jacob Lifshay <program...@gmail.com> wrote:
reviewing https://libre-riscv.org/isa_conflict_resolution/isamux_isans/#privtraps

in the priv-traps section, I don't think the trap/xRET functionality should be conditional on isans matching anything, as that makes the HW unnecessarily more complicated and the operations harder to understand.

Was thinking if it made any difference... it is just setting to a value that it's already set to, isn't it?
the value that ends up in last-isans on trap and isans on xret differ, since those assignments are also inside the conditional.
 

unrelated note: there is no instruction named xret, xRET is shorthand for one of URET, SRET, MRET, or HRET (if that ever becomes a thing).

Yes. Thought that was a well known convention.
thought you might have missed that since you used xret instead of sret in an assembly block

L.

lkcl

unread,
Jun 14, 2019, 7:27:02 AM6/14/19
to Jacob Lifshay, RISC-V ISA Dev


On Friday, June 14, 2019, Jacob Lifshay <program...@gmail.com> wrote:

maybe trap_base_isans can be included but allowed to be hardwired to 0, leaving essentially the same implementation as removing trap_base_isans.


Options in standards result in an exponential implementation permutation / interaction space that often invalidates the standard or makes its implementation impractical.

Examples include 96boards "triple function pins" where 2 of the functions are optional (total nonsense if a group of pins can optionally be LVDS and optionally be MIPI for example: what's the probability that 2 manufacturers will multiplex the *exact* same combinations of MIPI and LVDS??)

Another is X25 which I gave 18 months ago.

Can anyone else think of either good use cases or weigh in on whether there is a benefit to making trap-isans a per-xcause vector, orthogonal to xtvec?

L.

Reply all
Reply to author
Forward
0 new messages