Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CPU

The CPU trait provides a way to get the current CPU ID. It is defined in awkernel_lib/src/cpu.rs as follows.

#![allow(unused)]
fn main() {
pub trait CPU {
    /// CPU ID returns the ID of the CPU.
    /// The ID is unique for each CPU and starts from 0 to `num_cpu() - 1`.
    fn cpu_id() -> usize;

    /// Raw CPU ID returns the ID of the CPU without any modification.
    fn raw_cpu_id() -> usize;
}
}

The cpu_id method returns the current CPU ID. The ID is unique for each CPU and ranges from 0 to num_cpu() - 1. The num_cpu function, which returns the number of CPUs, is also defined in awkernel_lib/src/cpu.rs.

The raw_cpu_id method returns the ID of the CPU without any modification. The ID is unique for each CPU, but it may not be in the range of 0 to num_cpu() - 1.

There are functions regarding CPU in awkernel_lib/src/cpu.rs as follows.

functiondescription
fn cpu_id() -> usizeReturn the ID of the CPU.
fn raw_cpu_id() -> usizeReturn the ID of the CPU without any modification.
fn num_cpu() -> usizeReturn the number of CPUs.

Implementation

x86_64

For x86_64, the X86 structure implements the CPU trait in awkernel_lib/src/arch/x86_64/cpu.rs as follows.

#![allow(unused)]
fn main() {
impl CPU for super::X86 {
    fn cpu_id() -> usize {
        let cpuid_leaf_1 = unsafe { core::arch::x86_64::__cpuid(1) };

        // Check if x2APIC is supported
        if (cpuid_leaf_1.ecx & (1 << 21)) != 0 {
            // Get x2APIC ID from leaf 1FH or leaf 0BH (1FH is preferred)
            let max_leaf = unsafe { core::arch::x86_64::__cpuid(0) }.eax;
            let edx = if max_leaf >= 0x1F {
                unsafe { core::arch::x86_64::__cpuid(0x1F).edx }
            } else {
                unsafe { core::arch::x86_64::__cpuid(0x0B).edx }
            };
            edx as usize
        } else {
            (cpuid_leaf_1.ebx >> 24 & 0xff) as usize
        }
    }

    fn raw_cpu_id() -> usize {
        Self::cpu_id()
    }
}
}

Awkernel uses core::arch::x86_64::__cpuid to get the CPU ID. It assumes that the CPU ID is unique for each CPU and ranges from 0 to num_cpu() - 1. If you find any hardware that does not follow this assumption, please let us know or send us a PR.

AArch64

For x86_64, the AArch64 structure implements the CPU trait in awkernel_lib/src/arch/aarch64/cpu.rs as follows.

#![allow(unused)]
fn main() {
impl CPU for super::AArch64 {
    fn cpu_id() -> usize {
        let mpidr = mpidr_el1::get();

        let aff0 = mpidr & 0xff;
        let aff1 = (mpidr >> 8) & 0xff;
        let aff2 = (mpidr >> 16) & 0xff;
        let aff3 = (mpidr >> 32) & 0xff;

        let result =
            unsafe { aff0 + AFF0_MAX * aff1 + AFF0_X_AFF1 * aff2 + AFF0_X_AFF1_X_AFF2 * aff3 };

        result as usize
    }

    fn raw_cpu_id() -> usize {
        mpidr_el1::get() as usize
    }
}
}

For AArch64, Awkernel calculates the CPU ID based on the MPIDR_EL1 register and the affinity information variables.