vminer-core 0.1.0

Core library for vminer
Documentation
use crate::{arch, endian::RuntimeEndian, Endianness, HasVcpus, PhysicalAddress, VirtualAddress};

#[derive(Debug, Clone, Copy)]
pub enum Architecture {
    X86_64(arch::X86_64),
    Aarch64(arch::Aarch64),
}

#[derive(Debug, Clone, Copy)]
pub enum Registers {
    X86_64(arch::x86_64::Registers),
    Aarch64(arch::aarch64::Registers),
}

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, Copy)]
pub enum SpecialRegisters {
    X86_64(arch::x86_64::SpecialRegisters),
    Aarch64(arch::aarch64::SpecialRegisters),
}

#[derive(Debug, Clone, Copy)]
pub enum OtherRegisters {
    X86_64(arch::x86_64::OtherRegisters),
    Aarch64(arch::aarch64::OtherRegisters),
}

macro_rules! dispatch {
    ($val:expr => |$arch:ident| $expr:expr) => {
        match $val {
            Architecture::X86_64($arch) => $expr,
            Architecture::Aarch64($arch) => $expr,
        }
    };
    ($val:expr, $vcpus:ident => |$arch:ident| $expr:expr) => {
        match $val {
            Architecture::X86_64($arch) => {
                let $vcpus = &super::AssumeX86_64($vcpus);
                $expr
            }
            Architecture::Aarch64($arch) => {
                let $vcpus = &super::AssumeAarch64($vcpus);
                $expr
            }
        }
    };
}

impl arch::Architecture for Architecture {
    type Endian = RuntimeEndian;

    type Registers = Registers;
    type SpecialRegisters = SpecialRegisters;
    type OtherRegisters = OtherRegisters;

    #[inline]
    fn into_runtime(self) -> Architecture {
        self
    }

    #[inline]
    fn endianness(&self) -> RuntimeEndian {
        dispatch!(self => |arch|arch.endianness().as_runtime_endian())
    }

    #[inline]
    fn virtual_to_physical<M: crate::Memory + ?Sized>(
        &self,
        memory: &M,
        mmu_addr: PhysicalAddress,
        addr: VirtualAddress,
    ) -> crate::TranslationResult<PhysicalAddress> {
        dispatch!(self => |arch| arch.virtual_to_physical(memory, mmu_addr, addr))
    }

    #[inline]
    fn find_kernel_pgd<M: crate::Memory + ?Sized>(
        &self,
        memory: &M,
        vcpus: &(impl HasVcpus<Arch = Self> + ?Sized),
        use_per_cpu: bool,
        additional: &[VirtualAddress],
    ) -> crate::VmResult<Option<PhysicalAddress>> {
        dispatch!(self, vcpus => |arch| arch.find_kernel_pgd(memory, vcpus, use_per_cpu, additional))
    }

    #[inline]
    fn find_in_kernel_memory_raw<M: crate::Memory + ?Sized>(
        &self,
        memory: &M,
        mmu_addr: PhysicalAddress,
        base_search_addr: VirtualAddress,
        finder: &memchr::memmem::Finder,
        buf: &mut [u8],
    ) -> crate::MemoryAccessResult<Option<VirtualAddress>> {
        dispatch!(self => |arch| arch.find_in_kernel_memory_raw(memory, mmu_addr, base_search_addr, finder, buf))
    }

    #[inline]
    fn find_in_kernel_memory<M: crate::Memory + ?Sized>(
        &self,
        memory: &M,
        mmu_addr: PhysicalAddress,
        needle: &[u8],
    ) -> crate::MemoryAccessResult<Option<VirtualAddress>> {
        dispatch!(self => |arch| arch.find_in_kernel_memory(memory, mmu_addr, needle))
    }

    #[inline]
    fn kernel_base(&self) -> VirtualAddress {
        dispatch!(self => |arch| arch.kernel_base())
    }

    #[inline]
    fn instruction_pointer<Vcpus: HasVcpus<Arch = Self> + ?Sized>(
        &self,
        vcpus: &Vcpus,
        vcpu: crate::VcpuId,
    ) -> crate::VcpuResult<VirtualAddress> {
        dispatch!(self, vcpus => |arch| arch.instruction_pointer(vcpus, vcpu))
    }

    #[inline]
    fn stack_pointer<Vcpus: HasVcpus<Arch = Self> + ?Sized>(
        &self,
        vcpus: &Vcpus,
        vcpu: crate::VcpuId,
    ) -> crate::VcpuResult<VirtualAddress> {
        dispatch!(self, vcpus => |arch| arch.stack_pointer(vcpus, vcpu))
    }

    #[inline]
    fn base_pointer<Vcpus: HasVcpus<Arch = Self> + ?Sized>(
        &self,
        vcpus: &Vcpus,
        vcpu: crate::VcpuId,
    ) -> crate::VcpuResult<Option<VirtualAddress>> {
        dispatch!(self, vcpus => |arch| arch.base_pointer(vcpus, vcpu))
    }

    #[inline]
    fn pgd<Vcpus: HasVcpus<Arch = Self> + ?Sized>(
        &self,
        vcpus: &Vcpus,
        vcpu: crate::VcpuId,
    ) -> crate::VcpuResult<PhysicalAddress> {
        dispatch!(self, vcpus => |arch| arch.pgd(vcpus, vcpu))
    }

    #[inline]
    fn kernel_per_cpu<Vcpus: HasVcpus<Arch = Self> + ?Sized>(
        &self,
        vcpus: &Vcpus,
        vcpu: crate::VcpuId,
    ) -> crate::VcpuResult<Option<VirtualAddress>> {
        dispatch!(self, vcpus => |arch| arch.kernel_per_cpu(vcpus, vcpu))
    }
}