Skip to content

Commit

Permalink
Version 0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Manami Mori authored and fukai-t committed Feb 7, 2022
0 parents commit 23bbe2d
Show file tree
Hide file tree
Showing 47 changed files with 4,723 additions and 0 deletions.
5 changes: 5 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Copyright (c) 2022 RIKEN
All rights reserved.

This software is released under the MIT License.
http://opensource.org/licenses/mit-license.php
1 change: 1 addition & 0 deletions src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/bin
51 changes: 51 additions & 0 deletions src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
MAKE = make -C
COMMON_MODULE = common
UEFI_MODULE = uefi
BOOTLOADER = hypervisor_bootloader
BOOTLOADER_ARCH = aarch64-uefi
KERNEL = hypervisor_kernel
KERNEL_ARCH = aarch64-none
CP = cp
MKDIR = mkdir -p
QEMU = qemu-system-aarch64
RM = rm -rf
MOUNT = mount
UMOUNT = umount
UEFI_FD ?= QEMU_EFI.fd

all: .FORCE
$(MAKE) $(BOOTLOADER)
$(MAKE) $(KERNEL)
$(MKDIR) bin/EFI/BOOT/
$(CP) $(BOOTLOADER)/target/$(BOOTLOADER_ARCH)/release/$(BOOTLOADER) bin/EFI/BOOT/BOOTAA64.EFI
$(CP) $(KERNEL)/target/$(KERNEL_ARCH)/release/$(KERNEL) bin/EFI/BOOT/$(KERNEL)

clean:
$(RM) bin
$(MAKE) $(COMMON_MODULE) clean
$(MAKE) $(UEFI_MODULE) clean
$(MAKE) $(BOOTLOADER) clean
$(MAKE) $(KERNEL) clean

fmt:
$(MAKE) $(COMMON_MODULE) fmt
$(MAKE) $(UEFI_MODULE) fmt
$(MAKE) $(BOOTLOADER) fmt
$(MAKE) $(KERNEL) fmt

run: all
$(QEMU) -m 1G -cpu cortex-a53 -machine virt-2.12,virtualization=on -smp 4 -nographic -bios $(UEFI_FD) -drive file=fat:rw:bin/,format=raw,media=disk

debug: all
$(QEMU) -m 1G -cpu cortex-a53 -machine virt-2.12,virtualization=on -smp 4 -monitor stdio -bios $(UEFI_FD) -drive file=fat:rw:bin/,format=raw,media=disk

write:
$(MOUNT) $(DEVICE) /mnt
$(CP) bin/EFI/BOOT/BOOTAA64.EFI /mnt/EFI/BOOT/BOOTAA64.EFI
$(CP) bin/EFI/BOOT/$(KERNEL) /mnt/EFI/BOOT/$(KERNEL)
$(UMOUNT) /mnt

default:
$(MAKE) all

.FORCE:
2 changes: 2 additions & 0 deletions src/common/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
/Cargo.lock
6 changes: 6 additions & 0 deletions src/common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "common"
version = "0.1.0"
edition = "2021"

[dependencies]
7 changes: 7 additions & 0 deletions src/common/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CARGO = cargo

clean:
$(CARGO) clean

fmt:
$(CARGO) fmt
113 changes: 113 additions & 0 deletions src/common/src/acpi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//!
//! Advanced Configuration and Power Interface
//!
//! Supported ACPI Version 6.4

pub mod madt;

const RSDP_SIGNATURE: [u8; 8] = *b"RSD PTR ";
const XSDT_SIGNATURE: [u8; 4] = *b"XSDT";

const XSDT_STRUCT_SIZE: usize = core::mem::size_of::<XSDT>();

#[repr(C, packed)]
struct RSDP {
signature: [u8; 8],
checksum: u8,
oem_id: [u8; 6],
revision: u8,
rsdt_address: u32,
length: u32,
xsdt_address: u64,
ex_checksum: u32,
reserved: [u8; 3],
}

#[repr(C, packed)]
struct XSDT {
signature: [u8; 4],
length: u32,
revison: u8,
checksum: u8,
oem_id: [u8; 6],
oem_table_id: u64,
oem_revision: u32,
creator_id: u32,
creator_revision: u32,
/* entries */
}

#[derive(Debug, Clone)]
pub struct GeneralAddressStructure {
address: u64,
address_type: u8,
}

#[derive(Debug)]
pub enum AcpiError {
InvalidSignature,
InvalidAddress,
TableNotFound,
}

impl GeneralAddressStructure {
pub const SPACE_ID_SYSTEM_MEMORY: u8 = 0x00;
const SPACE_ID_INVALID: u8 = 0x0B;

fn invalid() -> Self {
Self {
address: 0,
address_type: Self::SPACE_ID_INVALID,
}
}

pub fn new(a: &[u8; 12]) -> Self {
let address_type = a[0];
if address_type >= Self::SPACE_ID_INVALID {
return Self::invalid();
}
Self {
address_type,
address: u64::from_le_bytes((a[4..12]).try_into().unwrap()),
}
}

pub const fn is_invalid(&self) -> bool {
self.address_type == Self::SPACE_ID_INVALID
}

pub const fn get_address_type(&self) -> u8 {
self.address_type
}

pub const fn get_address(&self) -> u64 {
self.address
}
}

pub fn get_acpi_table(rsdp_address: usize, signature: &[u8; 4]) -> Result<usize, AcpiError> {
let rsdp = unsafe { &*(rsdp_address as *const RSDP) };
if rsdp.signature != RSDP_SIGNATURE {
return Err(AcpiError::InvalidSignature);
}
if rsdp.xsdt_address == 0 {
return Err(AcpiError::InvalidAddress);
}
let xsdt = unsafe { &*(rsdp.xsdt_address as *const XSDT) };

if xsdt.signature != XSDT_SIGNATURE {
return Err(AcpiError::InvalidSignature);
}

for table_index in 0..((xsdt.length as usize - XSDT_STRUCT_SIZE) >> 3) {
let table_address = unsafe {
*((rsdp.xsdt_address as usize + XSDT_STRUCT_SIZE + (table_index << 3)) as *const u64)
} as usize;

if unsafe { *(table_address as *const [u8; 4]) } == *signature {
return Ok(table_address);
}
}

return Err(AcpiError::TableNotFound);
}
100 changes: 100 additions & 0 deletions src/common/src/acpi/madt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//!
//! Multiple APIC Description Table
//!
//! Supported MADT Revision: ~ 5

pub const MADT_SIGNATURE: [u8; 4] = *b"APIC";

const MADT_STRUCT_SIZE: usize = core::mem::size_of::<MADT>();

const STRUCT_TYPE_GICC: u8 = 0xB;

const GICC_FLAGS_ENABLED: u32 = 1;

#[repr(C, packed)]
pub struct MADT {
signature: [u8; 4],
length: u32,
revision: u8,
checksum: u8,
oem_id: [u8; 6],
oem_table_id: [u8; 8],
oem_revision: u32,
creator_id: [u8; 4],
creator_revision: u32,
flags: u32,
local_interrupt_controller_address: u32,
/* interrupt_controller_structure: [struct; n] */
}

#[repr(C, packed)]
struct GicCpuInterfaceStructure {
struct_type: u8,
length: u8,
reserved_1: [u8; 2],
cpu_interface_number: u32,
acpi_processor_uid: u32,
flags: u32,
parking_protocol_version: u32,
performance_interrupt_gsiv: u32,
parked_address: u64,
physical_base_address: u64,
gicv: u64,
gich: u64,
vgic_maintenance_interrupt: u32,
gicr_base_address: u64,
mpidr: u64,
processor_power_efficiency_class: u8,
reserved_2: u8,
spe_overflow_interrupt: u16,
}

/// MADTのリストから順次GicCpuInterfaceStructureを検出し、MPIDRを返却するIterです
///
/// このIteratorはMADTのInterrupt Controller Structure配列からGicCpuInterfaceStructureを先頭から順に
/// 取得し、その中にあるMPIDRの値を返します。なお該当MPIDRが有効でない([`GICC_FLAGS_ENABLED`]が立ってない)
/// 場合はスキップします。
pub struct ProcessorIdIter {
base_address: usize,
pointer: usize,
length: usize,
}

impl MADT {
pub fn get_processor_id_list(&self) -> ProcessorIdIter {
let length = self.length as usize - MADT_STRUCT_SIZE;
let base_address = self as *const _ as usize + MADT_STRUCT_SIZE;

ProcessorIdIter {
base_address,
pointer: 0,
length,
}
}
}

impl Iterator for ProcessorIdIter {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
if self.pointer >= self.length {
return None;
}
let record_base = self.base_address + self.pointer;
let record_type = unsafe { *(record_base as *const u8) };
let record_length = unsafe { *((record_base + 1) as *const u8) };

self.pointer += record_length as usize;
match record_type {
STRUCT_TYPE_GICC => {
let gicc_struct = unsafe { &*(record_base as *const GicCpuInterfaceStructure) };
if (gicc_struct.flags & GICC_FLAGS_ENABLED) != 0 {
/* Enabled */
Some(gicc_struct.mpidr)
} else {
self.next()
}
}
_ => self.next(),
}
}
}
Loading

0 comments on commit 23bbe2d

Please sign in to comment.