hart_mask.rs 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. use core::mem::size_of;
  2. /// Hart mask structure reference
  3. #[derive(Debug, Clone)]
  4. pub struct HartMask {
  5. bit_vector: *const usize,
  6. base: usize,
  7. max_hart_id: usize,
  8. }
  9. impl HartMask {
  10. /// Construct a reference to hart mask from bit vector and starting hartid.
  11. ///
  12. /// # Parameters
  13. ///
  14. /// - The `vaddr` is a scalar bit-vector containing hartids.
  15. /// Should return address from supervisor level.
  16. /// - The `base` is the starting hartid from which bit-vector must be computed.
  17. /// If `base` equals `usize::MAX`, that means `vaddr` is ignored and all available harts must be considered.
  18. /// - The `max_hart_id` should be returned by SBI implementation for maximum hart id this hart mask supports.
  19. ///
  20. /// # Unsafety
  21. ///
  22. /// Caller must ensure all usize values in the bit vector is accessible.
  23. pub unsafe fn from_addr(vaddr: usize, base: usize, max_hart_id: usize) -> HartMask {
  24. HartMask {
  25. bit_vector: vaddr as *const usize,
  26. base,
  27. max_hart_id,
  28. }
  29. }
  30. /// Check if the `hart_id` is included in this hart mask structure.
  31. pub fn has_bit(&self, hart_id: usize) -> bool {
  32. assert!(hart_id <= self.max_hart_id);
  33. if self.base == usize::MAX {
  34. // If `base` equals `usize::MAX`, that means `vaddr` is ignored and all available harts must be considered.
  35. return true;
  36. }
  37. if hart_id < self.base {
  38. // `base` if the starting hartid
  39. return false;
  40. }
  41. let (i, j) = split_index_usize(hart_id - self.base);
  42. let cur_vector = unsafe { get_vaddr_usize(self.bit_vector.add(i)) };
  43. cur_vector & (1 << j) != 0
  44. }
  45. }
  46. #[inline]
  47. fn split_index_usize(index: usize) -> (usize, usize) {
  48. let bits_in_usize = size_of::<usize>() * 8;
  49. (index / bits_in_usize, index % bits_in_usize)
  50. }
  51. #[inline]
  52. unsafe fn get_vaddr_usize(vaddr_ptr: *const usize) -> usize {
  53. match () {
  54. #[cfg(target_arch = "riscv32")]
  55. () => {
  56. let mut ans: usize;
  57. core::arch::asm!("
  58. li {tmp}, (1 << 17)
  59. csrrs {tmp}, mstatus, {tmp}
  60. lw {ans}, 0({vmem})
  61. csrw mstatus, {tmp}
  62. ", ans = lateout(reg) ans, vmem = in(reg) vaddr_ptr, tmp = out(reg) _);
  63. ans
  64. }
  65. #[cfg(target_arch = "riscv64")]
  66. () => {
  67. let mut ans: usize;
  68. core::arch::asm!("
  69. li {tmp}, (1 << 17)
  70. csrrs {tmp}, mstatus, {tmp}
  71. ld {ans}, 0({vmem})
  72. csrw mstatus, {tmp}
  73. ", ans = lateout(reg) ans, vmem = in(reg) vaddr_ptr, tmp = out(reg) _);
  74. ans
  75. }
  76. #[cfg(target_arch = "riscv128")]
  77. () => {
  78. let mut ans: usize;
  79. core::arch::asm!("
  80. li {tmp}, (1 << 17)
  81. csrrs {tmp}, mstatus, {tmp}
  82. lq {ans}, 0({vmem})
  83. csrw mstatus, {tmp}
  84. ", ans = lateout(reg) ans, vmem = in(reg) vaddr_ptr, tmp = out(reg) _);
  85. ans
  86. }
  87. #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
  88. () => {
  89. drop(vaddr_ptr);
  90. unimplemented!("not RISC-V instruction set architecture")
  91. }
  92. }
  93. }