Documentation
//! A crate for managing hypervisor functionality, particularly focused on
//! Extended Page Tables (EPT) and Model-Specific Register (MSR) bitmaps.
//! Includes support for primary and optional secondary EPTs.

use {
    crate::{ept::paging::Ept, error::HypervisorError, x86_64::addr::Addrtransfer}, alloc::boxed::Box
};

/// Represents shared data structures for hypervisor operations.
///
/// This struct manages the MSR (Model-Specific Register) bitmap and Extended Page Tables (EPT)
/// for the hypervisor, enabling memory virtualization and control over certain processor features.
#[repr(C)]
#[derive(Debug, Clone)]
pub struct SharedData<P: core::alloc::Allocator> {
    /// A bitmap for handling MSRs.
    pub msr_bitmap: Box<MsrBitmap, P>,

    /// The primary Extended Page Table.
    pub primary_ept: Box<Ept, P>,

    /// The pointer to the primary EPT (Extended Page Table Pointer).
    pub primary_eptp: u64,

    /// The secondary Extended Page Table.
    #[cfg(feature = "secondary-ept")]
    pub secondary_ept: Box<Ept, P>,

    /// The pointer to the secondary EPT.
    #[cfg(feature = "secondary-ept")]
    pub secondary_eptp: u64,

    // The hook manager.
    //pub hook_manager: Box<HookManager>,
}

impl<PYH> SharedData<PYH> 
    where PYH: core::alloc::Allocator,
{
    /// Creates a new instance of `SharedData` with primary and optionally secondary EPTs.
    ///
    /// This function initializes the MSR bitmap and sets up the EPTs.
    ///
    /// # Arguments
    ///
    /// * `primary_ept`: The primary EPT to be used.
    /// * `secondary_ept`: The secondary EPT to be used if the feature is enabled.
    ///
    /// # Returns
    /// A result containing a boxed `SharedData` instance or an error of type `HypervisorError`.
    #[cfg(feature = "secondary-ept")]
    pub fn new<T: Addrtransfer>(
        primary_ept: Box<Ept, PYH>,
        secondary_ept: Box<Ept, PYH>,
         msr_bitmap:Box<MsrBitmap,PYH>, 
         trans: &mut T
    ) -> Result<Box<Self>, HypervisorError> {
        log::trace!("Initializing shared data");

        let primary_eptp =  primary_ept.create_eptp_with_wb_and_4lvl_walk(trans)?;
        let secondary_eptp = secondary_ept.create_eptp_with_wb_and_4lvl_walk(trans)?;

        //let bitmap = MsrBitmap::new();
        //bitmap.hook_msr(IA32_EFER);

        Ok(Box::new(Self {
            msr_bitmap,
            primary_ept,
            primary_eptp,
            secondary_ept,
            secondary_eptp,
        }))
    }

    /// Creates a new instance of `SharedData` with primary EPTs.
    ///
    /// This function initializes the MSR bitmap and sets up the EPTs.
    ///
    /// # Arguments
    ///
    /// * `primary_ept`: The primary EPT to be used.
    ///
    /// # Returns
    /// A result containing a boxed `SharedData` instance or an error of type `HypervisorError`.
    #[cfg(not(feature = "secondary-ept"))]
    pub fn new(
        primary_ept: Box<Ept, PYH>,
       // hook_manager: Box<HookManager>,
    ) -> Result<Box<Self>, HypervisorError> {
        log::info!("Initializing shared data");

        let primary_eptp = primary_ept.create_eptp_with_wb_and_4lvl_walk()?;

        let bitmap = MsrBitmap::new();
        //bitmap.hook_msr(IA32_EFER);

        Ok(Box::new(Self {
            msr_bitmap: bitmap,
            primary_ept,
            primary_eptp,
            // hook_manager,
        }))
    }
}



#[repr(C, align(4096))]
#[derive(Debug,Clone,Copy)]
pub struct MsrBitmap {
    /// Read bitmap for low MSRs. Contains one bit for each MSR address in the range 00000000H to 00001FFFH.
    /// Determines whether an execution of RDMSR applied to that MSR causes a VM exit.
    pub read_low_msrs: [u8; 0x400],

    /// Read bitmap for high MSRs. Contains one bit for each MSR address in the range C0000000H to C0001FFFH.
    /// Determines whether an execution of RDMSR applied to that MSR causes a VM exit.
    pub read_high_msrs: [u8; 0x400],

    /// Write bitmap for low MSRs. Contains one bit for each MSR address in the range 00000000H to 00001FFFH.
    /// Determines whether an execution of WRMSR applied to that MSR causes a VM exit.
    pub write_low_msrs: [u8; 0x400],

    /// Write bitmap for high MSRs. Contains one bit for each MSR address in the range C0000000H to C0001FFFH.
    /// Determines whether an execution of WRMSR applied to that MSR causes a VM exit.
    pub write_high_msrs: [u8; 0x400],
}

impl MsrBitmap {
    /// Sets up the MSR Bitmap.
    ///
    /// # Returns
    /// * A `Result` indicating the success or failure of the setup process.
    pub fn new<PYH: core::alloc::Allocator>(mut _instance: Box<MsrBitmap,PYH>) -> Box<MsrBitmap, PYH> {
        //log::info!("Setting up MSR Bitmap");

        // let instance = Self {
        //     read_low_msrs: [0; 0x400],
        //     read_high_msrs: [0; 0x400],
        //     write_low_msrs: [0; 0x400],
        //     write_high_msrs: [0; 0x400],
        // };

        //log::info!("newed MSR Bitmap");
       // let mut instance = unsafe { Box::<Self, PYH>::try_new_zeroed_in::<PYH>(PYH).unwrap().assume_init() };

        //log::info!("Initializing MSR Bitmap");

        //Self::initialize_bitmap(instance.as_mut() as *mut _ as _);

        log::trace!("MSR Bitmap setup successfully!");

        _instance
    }

     // /// Initializes the MSR Bitmap.
     // ///
     // /// # Arguments
     // /// * `bitmap_ptr` - The virtual address of the MSR Bitmap.
    // fn initialize_bitmap(bitmap_ptr: *mut u64) {
    //     let mut bitmap_header: MaybeUninit<RTL_BITMAP> = MaybeUninit::uninit();
    //     let bitmap_header_ptr = bitmap_header.as_mut_ptr() as *mut _;

    //     unsafe {
    //         RtlInitializeBitMap(
    //             bitmap_header_ptr as _,
    //             bitmap_ptr as _,
    //             core::mem::size_of::<Self>() as u32,
    //         )
    //     }
    //     unsafe { RtlClearAllBits(bitmap_header_ptr as _) }
    // }
}



pub trait GetEPTP {
    fn get_data_eptp1(&self) -> u64 {
        0
    }

    fn get_data_eptp2(&self) -> u64 {
        0
    }
}