88// except according to those terms.
99
1010//! Provides types for the Interrupt Descriptor Table and its entries.
11+ //!
12+ //! # For the builds without the `abi_x86_interrupt` feature
13+ //! The following types are opaque and non-constructable instead of function pointers.
14+ //!
15+ //! - [`DivergingHandlerFunc`]
16+ //! - [`DivergingHandlerFuncWithErrCode`]
17+ //! - [`HandlerFunc`]
18+ //! - [`HandlerFuncWithErrCode`]
19+ //! - [`PageFaultHandlerFunc`]
20+ //!
21+ //! These types are defined for the compatibility with the Nightly Rust build.
1122
1223use crate :: { PrivilegeLevel , VirtAddr } ;
1324use bit_field:: BitField ;
@@ -593,17 +604,56 @@ impl<T> PartialEq for Entry<T> {
593604}
594605
595606/// A handler function for an interrupt or an exception without error code.
607+ ///
608+ /// This type alias is only usable with the `abi_x86_interrupt` feature enabled.
609+ #[ cfg( feature = "abi_x86_interrupt" ) ]
596610pub type HandlerFunc = extern "x86-interrupt" fn ( InterruptStackFrame ) ;
611+ /// This type is not usable without the `abi_x86_interrupt` feature.
612+ #[ cfg( not( feature = "abi_x86_interrupt" ) ) ]
613+ #[ derive( Copy , Clone , Debug ) ]
614+ pub struct HandlerFunc ( ( ) ) ;
615+
597616/// A handler function for an exception that pushes an error code.
617+ ///
618+ /// This type alias is only usable with the `abi_x86_interrupt` feature enabled.
619+ #[ cfg( feature = "abi_x86_interrupt" ) ]
598620pub type HandlerFuncWithErrCode = extern "x86-interrupt" fn ( InterruptStackFrame , error_code : u64 ) ;
621+ /// This type is not usable without the `abi_x86_interrupt` feature.
622+ #[ cfg( not( feature = "abi_x86_interrupt" ) ) ]
623+ #[ derive( Copy , Clone , Debug ) ]
624+ pub struct HandlerFuncWithErrCode ( ( ) ) ;
625+
599626/// A page fault handler function that pushes a page fault error code.
627+ ///
628+ /// This type alias is only usable with the `abi_x86_interrupt` feature enabled.
629+ #[ cfg( feature = "abi_x86_interrupt" ) ]
600630pub type PageFaultHandlerFunc =
601631 extern "x86-interrupt" fn ( InterruptStackFrame , error_code : PageFaultErrorCode ) ;
632+ /// This type is not usable without the `abi_x86_interrupt` feature.
633+ #[ cfg( not( feature = "abi_x86_interrupt" ) ) ]
634+ #[ derive( Copy , Clone , Debug ) ]
635+ pub struct PageFaultHandlerFunc ( ( ) ) ;
636+
602637/// A handler function that must not return, e.g. for a machine check exception.
638+ ///
639+ /// This type alias is only usable with the `abi_x86_interrupt` feature enabled.
640+ #[ cfg( feature = "abi_x86_interrupt" ) ]
603641pub type DivergingHandlerFunc = extern "x86-interrupt" fn ( InterruptStackFrame ) -> !;
642+ /// This type is not usable without the `abi_x86_interrupt` feature.
643+ #[ cfg( not( feature = "abi_x86_interrupt" ) ) ]
644+ #[ derive( Copy , Clone , Debug ) ]
645+ pub struct DivergingHandlerFunc ( ( ) ) ;
646+
604647/// A handler function with an error code that must not return, e.g. for a double fault exception.
648+ ///
649+ /// This type alias is only usable with the `abi_x86_interrupt` feature enabled.
650+ #[ cfg( feature = "abi_x86_interrupt" ) ]
605651pub type DivergingHandlerFuncWithErrCode =
606652 extern "x86-interrupt" fn ( InterruptStackFrame , error_code : u64 ) -> !;
653+ /// This type is not usable without the `abi_x86_interrupt` feature.
654+ #[ cfg( not( feature = "abi_x86_interrupt" ) ) ]
655+ #[ derive( Copy , Clone , Debug ) ]
656+ pub struct DivergingHandlerFuncWithErrCode ( ( ) ) ;
607657
608658impl < F > Entry < F > {
609659 /// Creates a non-present IDT entry (but sets the must-be-one bits).
@@ -627,11 +677,18 @@ impl<F> Entry<F> {
627677 ///
628678 /// The function returns a mutable reference to the entry's options that allows
629679 /// further customization.
680+ ///
681+ /// # Safety
682+ ///
683+ /// The caller must ensure that `addr` is the address of a valid interrupt handler function,
684+ /// and the signature of such a function is correct for the entry type.
630685 #[ cfg( feature = "instructions" ) ]
631686 #[ inline]
632- fn set_handler_addr ( & mut self , addr : u64 ) -> & mut EntryOptions {
687+ pub unsafe fn set_handler_addr ( & mut self , addr : VirtAddr ) -> & mut EntryOptions {
633688 use crate :: instructions:: segmentation:: { Segment , CS } ;
634689
690+ let addr = addr. as_u64 ( ) ;
691+
635692 self . pointer_low = addr as u16 ;
636693 self . pointer_middle = ( addr >> 16 ) as u16 ;
637694 self . pointer_high = ( addr >> 32 ) as u32 ;
@@ -652,7 +709,7 @@ impl<F> Entry<F> {
652709
653710macro_rules! impl_set_handler_fn {
654711 ( $h: ty) => {
655- #[ cfg( feature = "instructions" ) ]
712+ #[ cfg( all ( feature = "instructions" , feature = "abi_x86_interrupt" ) ) ]
656713 impl Entry <$h> {
657714 /// Set the handler function for the IDT entry and sets the present bit.
658715 ///
@@ -661,9 +718,13 @@ macro_rules! impl_set_handler_fn {
661718 ///
662719 /// The function returns a mutable reference to the entry's options that allows
663720 /// further customization.
721+ ///
722+ /// This method is only usable with the `abi_x86_interrupt` feature enabled. Without it, the
723+ /// unsafe [`Entry::set_handler_addr`] method has to be used instead.
664724 #[ inline]
665725 pub fn set_handler_fn( & mut self , handler: $h) -> & mut EntryOptions {
666- self . set_handler_addr( handler as u64 )
726+ let handler = VirtAddr :: new( handler as u64 ) ;
727+ unsafe { self . set_handler_addr( handler) }
667728 }
668729 }
669730 } ;
0 commit comments