Re: [PATCH] riscv: Work to remove kernel dependence on the M-extension

Michael T. Kloos
2022-03-10T09:31:22Z

As far as I can tell, it's simply a compiler flag to enable or disable it.
The only complicating issue that I found was the BPF JIT. That is a
special case amounting to a compiler within the kernel itself and can be
patched or set to depend on M. There is still the BPF interpreter. The
kernel doesn't depend on the C-extension. I have grepped through the
source code where that symbol is referenced, the checking of instruction
alignment constraints, and various checks used to make that work are much
more extensive than I expected, yet that is supported. To quote the
commentary from the beginning of chapter 2 (Base-I) of the RISC-V spec:

> "RV32I was designed to be sufficient to form a compiler target and to
> support modern operating system environments. The ISA was also designed
> to reduce the hardware required in a minimal implementation. RV32I
> contains 40 unique instructions, though a simple implementation might
> cover the ECALL/EBREAK instructions with a single SYSTEM hardware
> instruction that always traps and might be able to implement the FENCE
> instruction as a NOP, reducing base instruction count to 38 total.
> RV32I can emulate almost any other ISA extension (except the A extension,
> which requires additional hardware support for atomicity).
>
> In practice, a hardware implementation including the machine-mode
> privileged architecture will also require the 6 CSR instructions.
>
> Subsets of the base integer ISA might be useful for pedagogical purposes,
> but the base has been defined such that there should be little incentive
> to subset a real hardware implementation beyond omitting support for
> misaligned memory accesses and treating all SYSTEM instructions
> as a single trap."

This is all a noble goal of RISC-V, to create a minimal, yet robust ISA.
I'm not arguing to support no-A, as stated in the commentary, atomic can
not be emulated (I mean, maybe you could by taking over sscratch) and
the atomic properties of the CSR instructions. But that does seem hacky.)
and everything else is handled in the Base-I (Not including Zicsr). The
kernel supports rv(32/64)ima so to draw the line in the sand that
rv(32/64)ia is unacceptable seems silly.

One of my concerns here is that if support is not added, that people may
start writing assembly that uses M instructions and other non-portable
stuff. This will make a future port more difficult.

I do not have real hardware like this but I do have an emulator that
implements rv32iasu. Eventually I want to build a HART implementation
out of real hardware logic chips. Adding M, adds hardware complexity and
I think that it is better to do in software for such a minimal case.
Sure it will be slower than having native hardware M support. Firmware
emulation will be even slower than that. I'd much rather have the option
in the kernel to switch this on or off.

I am not trying to argue that the kernel should bend over to support my
pet projects, but it seems quite strange and arbitrary to draw the line
here over such a beautifully modular and minimal ISA.

> there's an infinite amount of
> allowable RISC-V implementations, we'll all go crazy chasing them
> around.
2 points on that:

1) Then it would seem logical to have the kernel target the most minimal
implementation to get the widest support.

2) I actually don't think this is entirely true, or at least not in the
sense that it is relevant to the kernel. Atomics are needed for a modern
system. The kernel needs to know about the floating-point support because
it needs to handle the clean-up and context-switching of the additional
floating point registers. The kernel needs to know about the C extension
because of the ramifications to alignment. Everything else is just gravy.
If sometime in the future the L-extension or the B-extension are finished
and implemented in future hardware, unless they make some very strange
decisions, I don't see why a kernel built today couldn't run on that
hardware with userspace software taking advantage of those native features.
Sure, in that situation, the kernel binary wouldn't be taking advantage of
them. But then wouldn't you want to add CONFIG_RISCV_ISA_L and
CONFIG_RISCV_ISA_B in said future kernel so that the compiler is passed an
-march value such that the kernel can take advantage of these new native
hardware features?

It seems to me that this is the grand vision in the modularity of both the
RISC-V ISA and the C programming language. We aren't writing everything in
assembly for a reason. I don't think it makes sense to stop one extension
away from what the RISC-V spec documents themselves state is the intended
minimal system capable of running a full modern operating system. I think
it is an arbitrary limit to the portability of the kernel.

Michael

On 3/10/2022 2:34 AM, Palmer Dabbelt wrote:

> On Wed, 09 Mar 2022 23:06:22 PST (-0800), Christoph Hellwig wrote:
>> Why?
> I have no idea, but this has come up a few times before.
> IIRC the original port had a no-M flavor (don't remember if it even made
> it to the original patch submission, but it was around for a bit).  We
> decided to drop this under the theory that nobody would use it:
> essentially, if you can afford the handful of MiB of memory required to
> run Linux then you've probably got a multiplier.
> If someone has hardware that lacks M and users care about running Linux
> on that then I'm happy to support it.  I'll still point out the
> silliness of that decision, but if it's too late to change things then
> I'd rather support the hardware.  If it's one of these "fill out every
> possible allowed ISA flavor, even if nobody has one that runs Linux"
> then I don't see a reason to bother -- there's an infinite amount of
> allowable RISC-V implementations, we'll all go crazy chasing them
> around.
> FWIW: to a first order, that applies to the no-A stuff as well (though
> that got dropped because the Arm folks pointed out a way to support that
> was way better than ours).