Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve PMP support #350

Merged
merged 1 commit into from
Feb 5, 2024
Merged

Conversation

Timmmm
Copy link
Collaborator

@Timmmm Timmmm commented Nov 17, 2023

This implements a lot of missing functionality for PMPs.

  • Support 64 PMPs as well as 0 and 16.
  • Support read-only zero PMPs
  • Support setting PMP grain
  • Return correct address bits on read (some read as 0 or 1 depending on the grain and match type)
  • Unlock PMPs on reset
  • Implement pmpcfg WARL legalisation

Notes:

This is a moderately large PR and I am open to breaking it down if necessary. Also there are some caveats that I would like feedback on:

  • The pmp_writable is a 64-bit bitmask that is a little tricky to integrate into the OCaml CLI because it doesn't support 64-bit integers natively. If someone could help me with that that would be great. We could potentially just remove it since we only added it because a Codasip chip has a slightly unusual PMP configuration. I suspect there aren't many chips that implement PMPs but make some of them read-only zero.
  • I haven't updated the lem code yet. I am unsure how to test that.
  • There are no tests added (pending Bill's work on testing infrastructure). Additionally the PMP spec is one of the less clearly written parts of the spec. However we have been using this for some time now and haven't found any issues for a while.
  • The WARL legalisation is just one possible legalisation option. It is likely a reasonable one though. It should be made configurable at a future point (pending riscv-config support probably).

Here's a diagram I made to help me understand pmpaddr which may be helpful:

image

Copy link

Unit Test Results

712 tests  ±0   712 ✔️ ±0   0s ⏱️ ±0s
    6 suites ±0       0 💤 ±0 
    1 files   ±0       0 ±0 

Results for commit ccbeed5. ± Comparison against base commit 9f4cad6.

@allenjbaum
Copy link
Collaborator

allenjbaum commented Nov 17, 2023 via email

@Timmmm
Copy link
Collaborator Author

Timmmm commented Nov 17, 2023

You say you’re adding support for rdonly0- how are you passing which
registers are rdonly0 to Sail?

The sys_pmp_writable() is a 64-bit value that's used as a bitmask. If bit N of that is 0 then pmpaddrN is read-only zero.

if you want to implement 8 entries, then you need to pad the
last 8 with zeroes

But why not just say "you must implement 64 PMP entries but any can be read-only zero" (which is what it says for HPM counters) or "you can implement 0 to 64 PMP entries". Why have two different mechanisms for implementing less than 64 entries, and why restrict the count to 0, 16, or 64? Quite a strange bit of the spec IMO.

@allenjbaum
Copy link
Collaborator

allenjbaum commented Nov 17, 2023 via email

@Timmmm
Copy link
Collaborator Author

Timmmm commented Nov 17, 2023

The reason for specifying 0, 16, or 64 is so firmware can depend on accessing them without trapping

That's true if all 64 should always be implemented too though. I guess it's probably for historical reasons.

Technically the readonly value could be anything, not just zero.

Yeah I think ultimately this will be solved by riscv-config's WARL expressions. We just couldn't wait for that.

@Alasdair
Copy link
Collaborator

I don't know much about PMPs but the code is replacing some rather ugly copy+paste logic with generic logic that handles more PMP registers in a generic way, which I think is an improvement 👍

Copy link
Collaborator

@allenjbaum allenjbaum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a first step, but this should be modified to fully support 0,16 AND 64 sets of CSRs, not just 0 and 16 (there is some code that will handle 64, but others do not).
This implementation assumes architectural parameter values that need to be supplied by the vendor, and this will need to get updated - someday soon, but not right now. WARL fields will be difficult, but there should be hooks such that the implementation supplied configurations can be easily supplied in the future.

@jrtc27
Copy link
Collaborator

jrtc27 commented Dec 6, 2023

This is a first step, but this should be modified to and 0,16 AND 64 sets of CSRs, not just 0 and 16 (there is some code that will handle 64, but others do not. This implementation assumes architectural parameter values that need to be supplied by the vendor, and this will need to get updated. WARL fields will be difficult, but there should be hooks such that the implemetation supplied configurations can be easily supplied in the future.

How many of these things are features that are present today in the Sail model? Anything that is not present today should not block this refactoring, those are additional feature requests that can come later. This is not a "do everything you could possibly want for PMPs" PR.

@allenjbaum
Copy link
Collaborator

allenjbaum commented Dec 6, 2023 via email

@allenjbaum
Copy link
Collaborator

allenjbaum commented Dec 6, 2023 via email

Copy link
Collaborator Author

@Timmmm Timmmm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review!

model/riscv_pmp_control.sail Show resolved Hide resolved
model/riscv_pmp_control.sail Show resolved Hide resolved
model/riscv_pmp_regs.sail Show resolved Hide resolved
model/riscv_pmp_regs.sail Show resolved Hide resolved
model/riscv_insts_zicsr.sail Show resolved Hide resolved
@Timmmm
Copy link
Collaborator Author

Timmmm commented Dec 6, 2023

Ok I removed the pmp_writable mask, and fixed the 16s that should have been 64s.

Copy link

github-actions bot commented Dec 6, 2023

Test Results

712 tests  ±0   712 ✅ ±0   0s ⏱️ ±0s
  6 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit fc15346. ± Comparison against base commit 23f1820.

♻️ This comment has been updated with latest results.

@allenjbaum
Copy link
Collaborator

allenjbaum commented Dec 11, 2023 via email

@Timmmm
Copy link
Collaborator Author

Timmmm commented Dec 11, 2023

but I thought there were a bits-to-int and int-to bits functions that could be used to effectively do that.

There is unsigned() to go from bits to range. I can't see a way to do the inverse except bits(N) + an_int. But either way those are normal functions that can't be used with pattern matching.

Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks like a big improvement to me. I noticed a few places where the newer bitfield syntax can be used, but that should hopefully be diagosed automatically by the next sail release.

c_emulator/riscv_sim.c Show resolved Hide resolved
model/riscv_pmp_control.sail Outdated Show resolved Hide resolved
model/riscv_pmp_regs.sail Outdated Show resolved Hide resolved
model/riscv_pmp_regs.sail Outdated Show resolved Hide resolved
@billmcspadden-riscv
Copy link
Collaborator

billmcspadden-riscv commented Jan 16, 2024 via email

@arichardson
Copy link
Collaborator

Thanks, I can now mark comments as resolved.

Copy link
Collaborator

@billmcspadden-riscv billmcspadden-riscv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, but I did have one comment/question. Please respond and I'll resolve teh conversation and give approval.

c_emulator/riscv_platform_impl.c Outdated Show resolved Hide resolved
case OPT_PMP_COUNT:
pmp_count = atol(optarg);
fprintf(stderr, "PMP count: %lld\n", pmp_count);
rv_pmp_count = pmp_count;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to handle invalid optarg here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes the Sail assumes it is <=64 so we need to check that here. I'll add that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I added a check for pmp_grain too.

Copy link
Collaborator

@arichardson arichardson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One comment otherwise LGTM

@Timmmm
Copy link
Collaborator Author

Timmmm commented Feb 2, 2024

@billmcspadden-riscv can this be merged? Both @arichardson and @allenjbaum have reviewed it.

This implements a lot of missing functionality for PMPs.

* Support 64 PMPs as well as 0 and 16.
* Support setting PMP grain
* Return correct address bits on read (some read as 0 or 1 depending on the grain and match type)
* Unlock PMPs on reset
* Implement pmpcfg WARL legalisation

Co-authored-by: Ben Fletcher <[email protected]>
@billmcspadden-riscv billmcspadden-riscv merged commit 4de2bff into riscv:master Feb 5, 2024
2 checks passed
@Timmmm
Copy link
Collaborator Author

Timmmm commented Feb 5, 2024

Hooray, thanks! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants