Lion: A formally verified, 5-stage pipeline RISC-V core
github.com
github.com
Still you have to start somewhere, I will be interested to see their progress as they tackle the things listed above.
If you write the basic cookie cutter "but but but, it's all just a spec, so we can't ever know anything!!!" it should be a requirement to submit a 5 page essay describing the algorithms/theory behind formal verification techniques, so they can prove they understand them, as opposed to only "understanding" how to make cookie-cutter bait posts.
No need to roast him.
Serious production HW is formal all over. GGP's opinion is sort of like going to Google's search-engine group and saying that internet connectivity is a bad idea because it'll never fully capture human emotion. It's not even wrong.
So you do some formal verification, good. But you still need to: - validate your model; and - validate your assumptions. This would always have to be done, but the fact that GP did not think about it means that, in the case of testing, it's not done. It's just "extensive testing", perhaps with some metric if we're lucky. Never "what are we testing for, and under what circumstances". (Except in places---aerospace, hardware---that welcome formal verification.)
Now, why does the above rant matter? Because GP is advocating the use of testing for a security property. Writing that test means you suspect there's something iffy that can happen with speculation. And if you know something iffy can happen, you can figure out what's not iffy and make that your spec for formal verification. You then get a proof that only the good (secure) behaviour takes place under clear assumptions, instead of getting the guarantee that none of the bad behaviours are exercised by your test suite.
An important point, and something people often get wrong when they mistakenly believe that they understand the basics of formal methods.
Here's an old quote about Sel4:
> The C code of the seL4 microkernel correctly implements the behaviour described in its abstract specification and nothing more.
The and nothing more part is vital. Not only are there no unexpected additional features, there are also no unexpected additional vulnerabilities. More precisely, if there are any vulnerabilities, they must either be in the spec, or be side-channel issues. Formal methods aren't very helpful against side-channel issues.
Reducing bugs to the spec has the same benefits as Rust reducing memory safety bugs to unsafe blocks
& to your point: Spectre & Meltdown took decades for real world testing to unearth. So now that we know them, it'd be nice to come up with a formalization in the spec to address observable information leaks so that future chips have reduced attack surface in the space of spec implementations
It's hard to prove you're safe from novel threats, but let's not let that stop us from proving we're safe from old tricks
You may start to see formal only verification on smaller/simpler blocks. E.g. imagine some bus adapter, with a decent set of formal properties that specify the bus functionality you may have to do very little work to verify it with formal tools.
There's also the use of SVAs within standard verification. This isn't formal verification but if you've done any formal work you end up with a bunch of new checks you can run in your standard verification flows too, again finding bugs more quickly. You can get nice feedback between the two, develop constraints to enable formal testing, those constraints become assertions in some other verification flow, it finds a violation of the constraint, you realise it needs adapting to cover some extra behaviour and your formal environment is improved (in effect you've found your spec bug).
View it as another tool in the toolbox, one that is becoming every more necessary as hardware designs become ever more complex.
The only relevant question is, are formal methods effective -- cost/benefit-wise -- in finding problems. Now there's a wide range of formal methods to the point that speaking about all of them as a single category is often not helpful, but the answer to this question is absolutely yes, in the sense that many formal methods have been found to be a very effective quality-assurance measure in many circumstances.
This doesn't stand up. In the software world, both the Sel4 [0] and CompCert [1] projects have surprised researchers unaccustomed to encountering bug-free software. The non-verified alternatives to both systems were always found to be buggy.
For an interesting case-study on the use of formal methods, and their effectiveness, take a look at [2].
> your spec can still be incomplete or buggy
Spec bugs are possible, but empirically they're much less of a problem than ordinary implementation bugs. [2] has good discussion of this topic.
> At the end of the day, there's no substitute for extensive real-world testing.
That's backward. Testing is no substitute for formal methods. Testing is never exhaustive.
I don't think formal methods are often used in the complete absence of testing.
[0] https://www.newscientist.com/article/mg22730392-600-unhackab...
Maybe I just don't know Haskell well enough, though.
[1] https://github.com/lowRISC/chisel
[2] https://llhd.io/
Also it looks like LLHD is perhaps analogous to LLVM in that they offer an intermediate representation instead of providing a language that you code in yourself. Chisel also offers this via FIRRTL [1]. I can't decide whether to be excited about the fact that there are multiple ideas in this space or frustrated that these disparate teams aren't simply collaborating.
This feels like some powerful algebraic property has been satisfied.
https://en.wikipedia.org/wiki/Popek_and_Goldberg_virtualizat...
When two technology vectors merge, it is really nice when the product is simpler and purer rather than the simple union of the two becoming a Simpson's-esque swiss army knife.
It can be dangerous when two similar ideas are too close, for whatever reason they formed to begin with will continue to hold and now you have competing factions along with the problem you are trying to solve. Everyone has to agree before you can start using regexps in your codebase. Oddly specific but true.
I am going to say hold your papers, but this problem is not going to be solved just yet, but in two or three iterations, it will be amazing. It won't just be a hardware description language, that is much too narrow, and it will arrived at in a kind of Erlang way, discovered through necessity, not from a formal system. But who knows?!
I do think that folks should adopt some sort of language above VHDL/Verilog.
scribe toMem . First . Just . InstrMem =<< dePC <<~ use fetchPC
just doesn't read very well if they don't know it Haskell, though I admit it's perfectly readable and understandable to me, and I think could be explained to a novice with a little help.If you want an alternative to SystemVerilog, another alternative is Bluespec. It's higher level than SV, but much more productive and easier to get right, too. (Incidentally, Bluespec is also a kind of Haskell, but it has two different kinds of syntax, one inspired by Haskell, and one inspired by SystemVerilog...)
But I remember that the precedence of lenses compared to binding operators is really important. It's just that I didn't write any lenses for a long time.
I really love writing RTL in haskell when compared to verilog/vhdl, but as a language I think it suffers from the same thing a lot of other languages do: too many ways to do the same thing. Mix that with a language that encourages meta-programming and you've got yourself a recipe for every complex haskell project basically becoming it's own little DSL. It's also often made worse because so much haskell is written by type-theorists and mathematicians churning out symbol-soup without a thought for the rest of us plebs.
IMO this is actually pretty readable and the implementation is stitched together nicely. There are some haskell/ml-isms like lenses/monad transformers/partial functions sprinkled in there that complicate a casual read-through, but if you've got a grasp on those most of this is reasonably clear.
It isn't the most complex beast (as others have pointed out, it skips things like the Zicsr and M extensions which add significant complexity) but it could serve very well as say, a companion core to some more complex piece of hardware. Perhaps one that requires reconfigurable logic that would be impractical in silicon but doesn't require realtime interrupts or fast math?
Get comfortable with an HDL. Use something like cocotb to generate testbenches.
It's open source as of about a year ago
> Maybe I just don't know Haskell well enough, though.
Speaking as someone who knows Haskell fairly well (and likes it), and has used Verilog at least a bit, I agree - it looks like they took all the worst parts of Verilog (especially the procedural parts), translated them into Haskell, and abandoned the occasional redeeming qualities.
(I suspect it's possible to shoehorn a decent (though not great) HDL into a Haskell DSL, but I've yet to see it actually done.)
But those are also probably way harder to verify.
What kind of consistency checks (other than register state being preserved by commands that do not write to the register in question)? Is there some standard best practise?
Why?
Because the very concept of side-channel depends on attacker capability! For example, does your attacker have physical access to the processor or not? With physical access you can exploit channels like power consumption through differential power analysis, or shoot laser pulses at target transistors to flip them and induce the processor to leak secrets. OTOH, without physical access, those channels don't meaningfully exist and you need to rely on, for example, speculation failure attacks and exfiltration via cache timing. So what counts as a side-channel is attacker-capability dependent.
Ie. a high security and a low security thread on the same CPU should not be able to get clues about what data the other has in its address space.
Offering stricter protection than that is pretty hard - simply the fact that one thread is using the floating point units a lot and causing the CPU to throttle is an info leak, so I don't think it's possible to really prevent small leaks of flow control information.
... leakage by timing side-channels depends in parts on how accurate your time-measurements are (e.g. Javascript's timer resolution was degraded, in order to make transient failure attacks like Spectre harder [1]).
I totally agree with your second point and believe, but cannot prove, that no current processor with any competitive performance is free from timing side-channels, the best we can currently do is put upper bounds on leakage rate. There are just so many other timing side channels, e.g. port contention [2]. They just keep popping up ...
Another dimension is the very meaning of thread. Presumably, as an end-user, you care about the threads/processes that the operating systems defines. But they don't map one-to-one to hardware threads, cores etc. Indeed I would argue that processors don't have threads in the sense that end-users care about. So the relevant security property must be regarding a hardware/software interface. Quite how to nail down this isolation property is active research I think. See e.g. [3] for work from 2016 in this direction.
Yet another dimension to this is through passwords and similar mechanisms: presumably you want to allow doing things like "sudo" so a low-priority thread can increase priority, provided the former knows the right password. But the very act of supplying a false password, leaks a tiny bit of information (that can be quantified in terms of Shannon-style information theory) about the password's search space.
[1] https://hackaday.com/2018/01/06/lowering-javascript-timer-re...
[2] A. Bhattacharyya, A. Sandulescu, M. Neugschwandtner, A. Sorniotti, B. Falsafi, M. Payer, A. Kurmus, SMoTherSpectre: Exploiting Speculative Execution through Port Contention. https://arxiv.org/abs/1903.01843
[3] D. Costanzo, Z. Shao, R. Gu, End-to-end verification of information flow security for C and assembly programs. https://6826.csail.mit.edu/2019/papers/certikos-sec.pdf
All IO with untrusted devices would be delayed until the real time exceeds the theoretical time the message was sent.
Then one can have as many timing sidechannels as one likes, and the running program can never learn about them.
Are you familiar with works like [1]? That is thinking in this direction, but from a different angle.
[1] G. Heiser, G. Klein, T. Murray, Can We Prove Time Protection?. https://arxiv.org/pdf/1901.08338.pdf
I think this is probably a fascinating area of study. It feels like there is a power/time/space non-linearity and being able to trade one for another.
How about the CPU is put into a fixed timestep mode, where all operations take the same amount of time.
If there was a hardware level concept of a thread, it could be a thread property.
Another option would be a queue of futures with a rate control based on the required security properties.
But that doesn't matter if how long it takes for your instructions to execute is data independent, no ?
The rate of leakage from a existing timing side-channel depends on how accurate your time-measurements are; the presence of such a side channel does not. (Though one shouldn't discount the value of degrading a side channel from kilobytes per second to millibits per hour, even the latter will only protect a reasonably-sized private key for a decade or two.)
I guess you could write some kind of AI that writes gadgets, then tries to find the optimal probability of correctly leaked data.
There are methodologies for doing this automatically published but it's in the "floats rather than books" category of behaviour since it's quite chaotic, so a formal proof would be hard.
Somebody will have to build from high end designs, spend billions doing so, and those would be the same commercial companies, which (if adopt RISC-V) will add their own proprietary spin.
https://twitter.com/marcan42/status/1366631459000258565
David Chisnall’s critique is also worth a read: https://lobste.rs/s/icegvf/will_risc_v_revolutionize_computi...
With that said for applications that are sensitive to power or transistor counts it wouldn’t surprise me if it takes over the low to midrange MCU market 10 years from now.
It will probably still have a binary blob for the GPU though, they are proposing to use an Imagination design.
'Distributed' is the tricky point, what counts as 'Distributed' in your eyes? The Skywater MPW is producing ~50 devices for each project I think, I'm sure some of those containing RISC-V CPUs will be distributed around to a few people but there won't be easy general availability of just being able to buy one.
I can't blame them for wanting the harness. By having a constant across everything that tapes-out where there are issues with dead or partially working chips it should be easier to track down what's going wrong. The specific project or something more general with the library, process or tools. There's lot of designs from people new to ASIC flows or without much experience in them, the harness allows efabless to help support people with bring-up.
Yes for an experienced ASIC designer it may be an annoyance but you are getting entirely free tape-outs of this. If you want to pay efabless or another company for a tape-out you can do your own thing with skywater PDK.
As for the majority of space are you sure? Take this project with layout photo: https://efabless.com/projects/34 to my eye the 'project' area which is the larger of the two distinct rectangular regions (the bottom smaller one is the harness) looks to be getting the lion's share of the area.
Formal verification aims to not just test and demonstrate correctness, but prove it. That is, under certain assumptions, one can prove that, for example, the actual transistors used to implement "add A and B", when connected in the intended way, have the same semantics ("do the same thing") as "add A and B".
In the extreme case, formal methods can replace testing. In practice, they can replace some portion of testing; but those assumptions that they're built on can be a bit shaky. Formal methods can also be /hard/ -- it can take more time to prove something correct than to just test it thoroughly enough to convince everyone. But, when done right, it does lead to higher confidence overall.
:)
Or, hell, some ARM-based Mac, these days.