build-skip.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. use sbi_spec::binary::{Physical, SbiRet};
  2. use rustsbi::RustSBI;
  3. #[derive(RustSBI)]
  4. struct SkipExtension {
  5. console: DummyConsole,
  6. #[rustsbi(skip)]
  7. fence: DummyFence,
  8. info: DummyEnvInfo,
  9. }
  10. #[derive(RustSBI)]
  11. struct SkipEnvInfo {
  12. console: DummyConsole,
  13. fence: DummyFence,
  14. #[rustsbi(skip)]
  15. info: DummyEnvInfo,
  16. env_info: RealEnvInfo,
  17. }
  18. #[test]
  19. fn rustsbi_skip_extension() {
  20. let sbi = SkipExtension {
  21. console: DummyConsole,
  22. fence: DummyFence,
  23. info: DummyEnvInfo,
  24. };
  25. // 1. Skipped fields are neither used during RustSBI macro generation, ...
  26. assert_eq!(sbi.handle_ecall(0x4442434E, 0x0, [0; 6]), SbiRet::success(1));
  27. assert_eq!(sbi.handle_ecall(0x4442434E, 0x1, [0; 6]), SbiRet::success(2));
  28. assert_eq!(sbi.handle_ecall(0x4442434E, 0x2, [0; 6]), SbiRet::success(3));
  29. assert_eq!(sbi.handle_ecall(0x52464E43, 0x0, [0; 6]), SbiRet::not_supported());
  30. assert_eq!(sbi.handle_ecall(0x52464E43, 0x1, [0; 6]), SbiRet::not_supported());
  31. assert_eq!(sbi.handle_ecall(0x52464E43, 0x2, [0; 6]), SbiRet::not_supported());
  32. // 2. ... nor do they appear in extension detection in Base extension.
  33. // note that it's `assert_ne` - the handle_ecall should not return a success detection with
  34. // value 0 indicating this feature is not supported, ...
  35. assert_ne!(sbi.handle_ecall(0x10, 0x3, [0x4442434E, 0, 0, 0, 0, 0]), SbiRet::success(0));
  36. // ... and the `assert_eq` here means extension detection detected successfully that this
  37. // extension is not supported in SBI implementation `SkipExtension`.
  38. assert_eq!(sbi.handle_ecall(0x10, 0x3, [0x52464E43, 0, 0, 0, 0, 0]), SbiRet::success(0));
  39. // Additionally, we illustrate here that the skipped fields may be used elsewhere.
  40. let _ = sbi.fence;
  41. }
  42. #[test]
  43. fn rustsbi_skip_env_info() {
  44. let sbi = SkipEnvInfo {
  45. console: DummyConsole,
  46. fence: DummyFence,
  47. info: DummyEnvInfo,
  48. env_info: RealEnvInfo,
  49. };
  50. // The `env_info` instead of `info` field would be used by RustSBI macro; struct
  51. // `RealEnvInfo` would return 7, 8 and 9 for mvendorid, marchid and mimpid.
  52. assert_eq!(sbi.handle_ecall(0x10, 0x4, [0x4442434E, 0, 0, 0, 0, 0]), SbiRet::success(7));
  53. assert_eq!(sbi.handle_ecall(0x10, 0x5, [0x4442434E, 0, 0, 0, 0, 0]), SbiRet::success(8));
  54. assert_eq!(sbi.handle_ecall(0x10, 0x6, [0x4442434E, 0, 0, 0, 0, 0]), SbiRet::success(9));
  55. let _ = sbi.info;
  56. }
  57. // Return values of following trait impls are special values,
  58. // they are used by software to detect if one implementation is used by RustSBI.
  59. struct DummyConsole;
  60. impl rustsbi::Console for DummyConsole {
  61. fn write(&self, _: Physical<&[u8]>) -> SbiRet {
  62. SbiRet::success(1)
  63. }
  64. fn read(&self, _: Physical<&mut [u8]>) -> SbiRet {
  65. SbiRet::success(2)
  66. }
  67. fn write_byte(&self, _: u8) -> SbiRet {
  68. SbiRet::success(3)
  69. }
  70. }
  71. struct DummyFence;
  72. impl rustsbi::Fence for DummyFence {
  73. fn remote_fence_i(&self, _: rustsbi::HartMask) -> SbiRet {
  74. SbiRet::success(4)
  75. }
  76. fn remote_sfence_vma(&self, _: rustsbi::HartMask, _: usize, _: usize) -> SbiRet {
  77. SbiRet::success(5)
  78. }
  79. fn remote_sfence_vma_asid(&self, _: rustsbi::HartMask, _: usize, _: usize, _: usize) -> SbiRet {
  80. SbiRet::success(6)
  81. }
  82. }
  83. struct DummyEnvInfo;
  84. impl rustsbi::EnvInfo for DummyEnvInfo {
  85. fn mvendorid(&self) -> usize {
  86. unimplemented!()
  87. }
  88. fn marchid(&self) -> usize {
  89. unimplemented!()
  90. }
  91. fn mimpid(&self) -> usize {
  92. unimplemented!()
  93. }
  94. }
  95. struct RealEnvInfo;
  96. impl rustsbi::EnvInfo for RealEnvInfo {
  97. fn mvendorid(&self) -> usize {
  98. 7
  99. }
  100. fn marchid(&self) -> usize {
  101. 8
  102. }
  103. fn mimpid(&self) -> usize {
  104. 9
  105. }
  106. }