Browse Source

macros: support pmu, console, susp and cppc extensions

Signed-off-by: Zhouqi Jiang <[email protected]>
Zhouqi Jiang 1 year ago
parent
commit
cf9f47e6c6
4 changed files with 317 additions and 135 deletions
  1. 58 2
      macros/src/lib.rs
  2. 139 0
      src/instance.rs
  3. 3 2
      src/lib.rs
  4. 117 131
      src/traits.rs

+ 58 - 2
macros/src/lib.rs

@@ -9,6 +9,10 @@ struct RustSBIImp {
     ipi: Option<Ident>,
     reset: Option<Ident>,
     timer: Option<Ident>,
+    pmu: Option<Ident>,
+    console: Option<Ident>,
+    susp: Option<Ident>,
+    cppc: Option<Ident>,
 }
 
 /// Implement RustSBI trait for structure of each extensions.
@@ -28,6 +32,14 @@ pub fn derive_rustsbi(input: TokenStream) -> TokenStream {
 
     let mut imp = RustSBIImp::default();
     for field in fields {
+        // for attr in field.attrs {
+        //     if let Meta::List(list) = attr.meta {
+        //         let vars =
+        //         Punctuated::<Ident, syn::Token![,]>::parse_terminated(
+        //           &list.tokens,
+        //         ).unwrap();
+        //     }
+        // }
         if let Some(name) = &field.ident {
             match name.to_string().as_str() {
                 "rfnc" | "fence" => imp.fence = Some(name.clone()),
@@ -35,6 +47,10 @@ pub fn derive_rustsbi(input: TokenStream) -> TokenStream {
                 "spi" | "ipi" => imp.ipi = Some(name.clone()),
                 "srst" | "reset" => imp.reset = Some(name.clone()),
                 "timer" => imp.timer = Some(name.clone()),
+                "pmu" => imp.pmu = Some(name.clone()),
+                "dbcn" | "console" => imp.console = Some(name.clone()),
+                "susp" => imp.susp = Some(name.clone()),
+                "cppc" => imp.cppc = Some(name.clone()),
                 _ => {}
             }
         }
@@ -52,6 +68,10 @@ fn impl_derive_rustsbi(name: &Ident, imp: &RustSBIImp) -> TokenStream {
     let ipi_probe: usize = if imp.ipi.is_some() { 1 } else { 0 };
     let reset_probe: usize = if imp.reset.is_some() { 1 } else { 0 };
     let timer_probe: usize = if imp.timer.is_some() { 1 } else { 0 };
+    let pmu_probe: usize = if imp.pmu.is_some() { 1 } else { 0 };
+    let console_probe: usize = if imp.console.is_some() { 1 } else { 0 };
+    let susp_probe: usize = if imp.susp.is_some() { 1 } else { 0 };
+    let cppc_probe: usize = if imp.cppc.is_some() { 1 } else { 0 };
     let base_procedure = quote! {
         ::rustsbi::spec::base::EID_BASE => ::rustsbi::_rustsbi_base_machine(param, function,
             ::rustsbi::_StandardExtensionProbe {
@@ -61,6 +81,10 @@ fn impl_derive_rustsbi(name: &Ident, imp: &RustSBIImp) -> TokenStream {
                 ipi: #ipi_probe,
                 reset: #reset_probe,
                 timer: #timer_probe,
+                pmu: #pmu_probe,
+                console: #console_probe,
+                susp: #susp_probe,
+                cppc: #cppc_probe,
             }),
     };
     let fence_procedure = if let Some(fence) = &imp.fence {
@@ -98,17 +122,49 @@ fn impl_derive_rustsbi(name: &Ident, imp: &RustSBIImp) -> TokenStream {
     } else {
         quote! {}
     };
+    let pmu_procedure = if let Some(pmu) = &imp.pmu {
+        quote! {
+            ::rustsbi::spec::pmu::EID_PMU => ::rustsbi::_rustsbi_pmu(&self.#pmu, param, function),
+        }
+    } else {
+        quote! {}
+    };
+    let console_procedure = if let Some(console) = &imp.console {
+        quote! {
+            ::rustsbi::spec::dbcn::EID_DBCN => ::rustsbi::_rustsbi_console(&self.#console, param, function),
+        }
+    } else {
+        quote! {}
+    };
+    let susp_procedure = if let Some(susp) = &imp.susp {
+        quote! {
+            ::rustsbi::spec::susp::EID_SUSP => ::rustsbi::_rustsbi_susp(&self.#susp, param, function),
+        }
+    } else {
+        quote! {}
+    };
+    let cppc_procedure = if let Some(cppc) = &imp.cppc {
+        quote! {
+            ::rustsbi::spec::cppc::EID_CPPC => ::rustsbi::_rustsbi_cppc(&self.#cppc, param, function),
+        }
+    } else {
+        quote! {}
+    };
     let gen = quote! {
     impl rustsbi::RustSBI for #name {
         #[inline]
         fn handle_ecall(&self, extension: usize, function: usize, param: [usize; 6]) -> ::rustsbi::spec::binary::SbiRet {
             match extension {
                 #fence_procedure
+                #timer_procedure
+                #ipi_procedure
                 #base_procedure
                 #hsm_procedure
-                #ipi_procedure
                 #reset_procedure
-                #timer_procedure
+                #pmu_procedure
+                #console_procedure
+                #susp_procedure
+                #cppc_procedure
                 _ => SbiRet::not_supported(),
             }
         }

+ 139 - 0
src/instance.rs

@@ -704,3 +704,142 @@ impl<T, I, R, H, S, P, C, SU, CP> Builder<T, I, R, H, S, P, C, SU, CP> {
         self.inner
     }
 }
+
+// Placeholder for a structure that implements all RustSBI traits but is never accessed
+
+// fixme: Should be replaced to never type `!` once it's stablized
+// https://github.com/rust-lang/rust/issues/35121
+
+// fixme: should be replaced to impl SomeTrait for ! once never type is stablized
+
+impl crate::Timer for Infallible {
+    fn set_timer(&self, _: u64) {
+        unreachable!()
+    }
+}
+
+impl crate::Ipi for Infallible {
+    fn send_ipi(&self, _: HartMask) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Fence for Infallible {
+    #[inline]
+    fn remote_fence_i(&self, _: HartMask) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_sfence_vma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_sfence_vma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_hfence_gvma_vmid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_hfence_gvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_hfence_vvma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+    #[inline]
+    fn remote_hfence_vvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Hsm for Infallible {
+    fn hart_start(&self, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn hart_stop(&self) -> SbiRet {
+        unreachable!()
+    }
+
+    fn hart_get_status(&self, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn hart_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Reset for Infallible {
+    fn system_reset(&self, _: u32, _: u32) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Pmu for Infallible {
+    fn num_counters(&self) -> usize {
+        unreachable!()
+    }
+
+    fn counter_get_info(&self, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_config_matching(&self, _: usize, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_start(&self, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_stop(&self, _: usize, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_fw_read(&self, _: usize) -> SbiRet {
+        unreachable!()
+    }
+
+    fn counter_fw_read_hi(&self, _: usize) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Console for Infallible {
+    fn write(&self, _: Physical<&[u8]>) -> SbiRet {
+        unreachable!()
+    }
+
+    fn read(&self, _: Physical<&mut [u8]>) -> SbiRet {
+        unreachable!()
+    }
+
+    fn write_byte(&self, _: u8) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Susp for Infallible {
+    fn system_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
+        unreachable!()
+    }
+}
+
+impl crate::Cppc for Infallible {
+    fn probe(&self, _: u32) -> SbiRet {
+        unreachable!()
+    }
+    fn read(&self, _: u32) -> SbiRet {
+        unreachable!()
+    }
+    fn read_hi(&self, _: u32) -> SbiRet {
+        unreachable!()
+    }
+    fn write(&self, _: u32, _: u64) -> SbiRet {
+        unreachable!()
+    }
+}

+ 3 - 2
src/lib.rs

@@ -566,8 +566,9 @@ pub use traits::RustSBI;
 // macro internal functions and structures
 #[doc(hidden)]
 pub use traits::{
-    _StandardExtensionProbe, _rustsbi_base_machine, _rustsbi_fence, _rustsbi_hsm, _rustsbi_ipi,
-    _rustsbi_srst, _rustsbi_timer,
+    _StandardExtensionProbe, _rustsbi_base_machine, _rustsbi_console, _rustsbi_cppc,
+    _rustsbi_fence, _rustsbi_hsm, _rustsbi_ipi, _rustsbi_pmu, _rustsbi_reset, _rustsbi_susp,
+    _rustsbi_timer,
 };
 
 // #[cfg(not(feature = "machine"))]

+ 117 - 131
src/traits.rs

@@ -1,5 +1,3 @@
-use core::convert::Infallible;
-
 use crate::HartMask;
 use riscv::register::{marchid, mimpid, mvendorid};
 use spec::binary::{Physical, SbiRet};
@@ -20,6 +18,10 @@ pub struct _StandardExtensionProbe {
     pub ipi: usize,
     pub hsm: usize,
     pub reset: usize,
+    pub pmu: usize,
+    pub console: usize,
+    pub susp: usize,
+    pub cppc: usize,
 }
 
 #[doc(hidden)]
@@ -56,7 +58,7 @@ fn probe_extension(extension: usize, probe: _StandardExtensionProbe) -> usize {
         spec::rfnc::EID_RFNC => probe.fence,
         spec::srst::EID_SRST => probe.reset,
         spec::hsm::EID_HSM => probe.hsm,
-        // spec::pmu::EID_PMU => self.pmu.is_some(),
+        spec::pmu::EID_PMU => probe.pmu,
         // spec::dbcn::EID_DBCN => self.dbcn.is_some(),
         // spec::susp::EID_SUSP => self.susp.is_some(),
         // spec::cppc::EID_CPPC => self.cppc.is_some(),
@@ -148,7 +150,7 @@ pub fn _rustsbi_hsm<T: crate::Hsm>(hsm: T, param: [usize; 6], function: usize) -
 
 #[doc(hidden)]
 #[inline(always)]
-pub fn _rustsbi_srst<T: crate::Reset>(reset: T, param: [usize; 6], function: usize) -> SbiRet {
+pub fn _rustsbi_reset<T: crate::Reset>(reset: T, param: [usize; 6], function: usize) -> SbiRet {
     let [param0, param1] = [param[0], param[1]];
     match function {
         spec::srst::SYSTEM_RESET => match (u32::try_from(param0), u32::try_from(param1)) {
@@ -159,141 +161,125 @@ pub fn _rustsbi_srst<T: crate::Reset>(reset: T, param: [usize; 6], function: usi
     }
 }
 
-// Placeholder for a structure that implements all RustSBI traits but is never accessed
-
-// fixme: Should be replaced to never type `!` once it's stablized
-// https://github.com/rust-lang/rust/issues/35121
-
-// fixme: should be replaced to impl SomeTrait for ! once never type is stablized
-
-impl crate::Timer for Infallible {
-    fn set_timer(&self, _: u64) {
-        unreachable!()
-    }
-}
-
-impl crate::Ipi for Infallible {
-    fn send_ipi(&self, _: HartMask) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl crate::Fence for Infallible {
-    #[inline]
-    fn remote_fence_i(&self, _: HartMask) -> SbiRet {
-        unreachable!()
-    }
-    #[inline]
-    fn remote_sfence_vma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-    #[inline]
-    fn remote_sfence_vma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-    #[inline]
-    fn remote_hfence_gvma_vmid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-    #[inline]
-    fn remote_hfence_gvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-    #[inline]
-    fn remote_hfence_vvma_asid(&self, _: HartMask, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-    #[inline]
-    fn remote_hfence_vvma(&self, _: HartMask, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl crate::Hsm for Infallible {
-    fn hart_start(&self, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn hart_stop(&self) -> SbiRet {
-        unreachable!()
-    }
-
-    fn hart_get_status(&self, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn hart_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl crate::Reset for Infallible {
-    fn system_reset(&self, _: u32, _: u32) -> SbiRet {
-        unreachable!()
-    }
-}
-
-impl crate::Pmu for Infallible {
-    fn num_counters(&self) -> usize {
-        unreachable!()
-    }
-
-    fn counter_get_info(&self, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_config_matching(&self, _: usize, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_start(&self, _: usize, _: usize, _: usize, _: u64) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_stop(&self, _: usize, _: usize, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_fw_read(&self, _: usize) -> SbiRet {
-        unreachable!()
-    }
-
-    fn counter_fw_read_hi(&self, _: usize) -> SbiRet {
-        unreachable!()
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_pmu<T: crate::Pmu>(pmu: T, param: [usize; 6], function: usize) -> SbiRet {
+    match () {
+        #[cfg(target_pointer_width = "64")]
+        () => {
+            let [param0, param1, param2, param3, param4] =
+                [param[0], param[1], param[2], param[3], param[4]];
+            match function {
+                spec::pmu::NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
+                spec::pmu::COUNTER_GET_INFO => pmu.counter_get_info(param0),
+                spec::pmu::COUNTER_CONFIG_MATCHING => {
+                    pmu.counter_config_matching(param0, param1, param2, param3, param4 as _)
+                }
+                spec::pmu::COUNTER_START => pmu.counter_start(param0, param1, param2, param3 as _),
+                spec::pmu::COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
+                spec::pmu::COUNTER_FW_READ => pmu.counter_fw_read(param0),
+                spec::pmu::COUNTER_FW_READ_HI => pmu.counter_fw_read_hi(param0),
+                _ => SbiRet::not_supported(),
+            }
+        }
+        #[cfg(target_pointer_width = "32")]
+        () => {
+            let [param0, param1, param2, param3, param4, param5] =
+                [param[0], param[1], param[2], param[3], param[4], param[5]];
+            match function {
+                spec::pmu::NUM_COUNTERS => SbiRet::success(pmu.num_counters()),
+                spec::pmu::COUNTER_GET_INFO => pmu.counter_get_info(param0),
+                spec::pmu::COUNTER_CONFIG_MATCHING => pmu.counter_config_matching(
+                    param0,
+                    param1,
+                    param2,
+                    param3,
+                    concat_u32(param5, param4),
+                ),
+                spec::pmu::COUNTER_START => {
+                    pmu.counter_start(param0, param1, param2, concat_u32(param4, param3))
+                }
+                spec::pmu::COUNTER_STOP => pmu.counter_stop(param0, param1, param2),
+                spec::pmu::COUNTER_FW_READ => pmu.counter_fw_read(param0),
+                spec::pmu::COUNTER_FW_READ_HI => pmu.counter_fw_read_hi(param0),
+                _ => SbiRet::not_supported(),
+            }
+        }
     }
 }
 
-impl crate::Console for Infallible {
-    fn write(&self, _: Physical<&[u8]>) -> SbiRet {
-        unreachable!()
-    }
-
-    fn read(&self, _: Physical<&mut [u8]>) -> SbiRet {
-        unreachable!()
-    }
-
-    fn write_byte(&self, _: u8) -> SbiRet {
-        unreachable!()
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_console<T: crate::Console>(
+    console: T,
+    param: [usize; 6],
+    function: usize,
+) -> SbiRet {
+    let [param0, param1, param2] = [param[0], param[1], param[2]];
+    match function {
+        spec::dbcn::CONSOLE_WRITE => {
+            let bytes = Physical::new(param0, param1, param2);
+            console.write(bytes)
+        }
+        spec::dbcn::CONSOLE_READ => {
+            let bytes = Physical::new(param0, param1, param2);
+            console.read(bytes)
+        }
+        spec::dbcn::CONSOLE_WRITE_BYTE => console.write_byte((param0 & 0xFF) as u8),
+        _ => SbiRet::not_supported(),
     }
 }
 
-impl crate::Susp for Infallible {
-    fn system_suspend(&self, _: u32, _: usize, _: usize) -> SbiRet {
-        unreachable!()
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_susp<T: crate::Susp>(susp: T, param: [usize; 6], function: usize) -> SbiRet {
+    let [param0, param1, param2] = [param[0], param[1], param[2]];
+    match function {
+        spec::susp::SUSPEND => match u32::try_from(param0) {
+            Ok(sleep_type) => susp.system_suspend(sleep_type, param1, param2),
+            _ => SbiRet::invalid_param(),
+        },
+        _ => SbiRet::not_supported(),
     }
 }
 
-impl crate::Cppc for Infallible {
-    fn probe(&self, _: u32) -> SbiRet {
-        unreachable!()
-    }
-    fn read(&self, _: u32) -> SbiRet {
-        unreachable!()
-    }
-    fn read_hi(&self, _: u32) -> SbiRet {
-        unreachable!()
-    }
-    fn write(&self, _: u32, _: u64) -> SbiRet {
-        unreachable!()
+#[doc(hidden)]
+#[inline(always)]
+pub fn _rustsbi_cppc<T: crate::Cppc>(cppc: T, param: [usize; 6], function: usize) -> SbiRet {
+    match () {
+        #[cfg(target_pointer_width = "64")]
+        () => {
+            let [param0, param1] = [param[0], param[1]];
+            match function {
+                spec::cppc::PROBE => match u32::try_from(param0) {
+                    Ok(reg_id) => cppc.probe(reg_id),
+                    _ => SbiRet::invalid_param(),
+                },
+                spec::cppc::READ => match u32::try_from(param0) {
+                    Ok(reg_id) => cppc.read(reg_id),
+                    _ => SbiRet::invalid_param(),
+                },
+                spec::cppc::READ_HI => match u32::try_from(param0) {
+                    Ok(reg_id) => cppc.read_hi(reg_id),
+                    _ => SbiRet::invalid_param(),
+                },
+                spec::cppc::WRITE => match u32::try_from(param0) {
+                    Ok(reg_id) => cppc.write(reg_id, param1 as _),
+                    _ => SbiRet::invalid_param(),
+                },
+                _ => SbiRet::not_supported(),
+            }
+        }
+        #[cfg(target_pointer_width = "32")]
+        () => {
+            let [param0, param1, param2] = [param[0], param[1], param[2]];
+            match function {
+                spec::cppc::PROBE => cppc.probe(param0 as _),
+                spec::cppc::READ => cppc.read(param0 as _),
+                spec::cppc::READ_HI => cppc.read_hi(param0 as _),
+                spec::cppc::WRITE => cppc.write(param0 as _, concat_u32(param2, param1)),
+                _ => SbiRet::not_supported(),
+            }
+        }
     }
 }