8
8
// except according to those terms.
9
9
10
10
//! 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.
11
22
12
23
use crate :: { PrivilegeLevel , VirtAddr } ;
13
24
use bit_field:: BitField ;
@@ -593,17 +604,56 @@ impl<T> PartialEq for Entry<T> {
593
604
}
594
605
595
606
/// 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" ) ]
596
610
pub 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
+
597
616
/// 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" ) ]
598
620
pub 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
+
599
626
/// 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" ) ]
600
630
pub type PageFaultHandlerFunc =
601
631
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
+
602
637
/// 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" ) ]
603
641
pub 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
+
604
647
/// 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" ) ]
605
651
pub type DivergingHandlerFuncWithErrCode =
606
652
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 ( ( ) ) ;
607
657
608
658
impl < F > Entry < F > {
609
659
/// Creates a non-present IDT entry (but sets the must-be-one bits).
@@ -627,11 +677,18 @@ impl<F> Entry<F> {
627
677
///
628
678
/// The function returns a mutable reference to the entry's options that allows
629
679
/// 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.
630
685
#[ cfg( feature = "instructions" ) ]
631
686
#[ 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 {
633
688
use crate :: instructions:: segmentation:: { Segment , CS } ;
634
689
690
+ let addr = addr. as_u64 ( ) ;
691
+
635
692
self . pointer_low = addr as u16 ;
636
693
self . pointer_middle = ( addr >> 16 ) as u16 ;
637
694
self . pointer_high = ( addr >> 32 ) as u32 ;
@@ -652,7 +709,7 @@ impl<F> Entry<F> {
652
709
653
710
macro_rules! impl_set_handler_fn {
654
711
( $h: ty) => {
655
- #[ cfg( feature = "instructions" ) ]
712
+ #[ cfg( all ( feature = "instructions" , feature = "abi_x86_interrupt" ) ) ]
656
713
impl Entry <$h> {
657
714
/// Set the handler function for the IDT entry and sets the present bit.
658
715
///
@@ -661,9 +718,13 @@ macro_rules! impl_set_handler_fn {
661
718
///
662
719
/// The function returns a mutable reference to the entry's options that allows
663
720
/// 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.
664
724
#[ inline]
665
725
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) }
667
728
}
668
729
}
669
730
} ;
0 commit comments