Skip to content
This repository has been archived by the owner on Jul 17, 2023. It is now read-only.

Commit

Permalink
acpi: add dbs-acpi support for Dragonball
Browse files Browse the repository at this point in the history
This is for initializing dbs-acpi.

fixes: #253

Signed-off-by: Chao Wu <[email protected]>
  • Loading branch information
studychao committed Jul 7, 2023
1 parent 7b2bae4 commit 6f51bc9
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]

members = [
"crates/dbs-acpi",
"crates/dbs-address-space",
"crates/dbs-allocator",
"crates/dbs-arch",
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Dragonball-sandbox is a collection of Rust crates to help build custom Virtual M
This repository contains the following crates:
| Name | Description | Links |
| --- | --- | --- |
| [dbs-acpi](crates/dbs-acpi) | acpi definitions for virtual machines| TBD |
| [dbs-address-space](crates/dbs-address-space) | manager for memory and MMIO resources resident in the guest physical address space | [![Crates.io](https://img.shields.io/crates/v/dbs-address-space)](https://crates.io/crates/dbs-address-space) |
| [dbs-allocator](crates/dbs-allocator) | allocator for vmm resource | [![Crates.io](https://img.shields.io/crates/v/dbs-allocator)](https://crates.io/crates/dbs-allocator) |
| [dbs-arch](crates/dbs-arch) | collections of CPU architecture related modules | [![Crates.io](https://img.shields.io/crates/v/dbs-arch)](https://crates.io/crates/dbs-arch) |
Expand Down
14 changes: 14 additions & 0 deletions crates/dbs-acpi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "dbs-acpi"
version = "0.1.0"
authors = ["Alibaba Dragonball Team"]
description = "acpi definitions for virtual machines."
license = "Apache-2.0"
edition = "2018"
homepage = "https://github.com/openanolis/dragonball-sandbox"
repository = "https://github.com/openanolis/dragonball-sandbox"
keywords = ["dragonball", "acpi", "vmm", "secure-sandbox"]
readme = "README.md"

[dependencies]
vm-memory = "0.9.0"
11 changes: 11 additions & 0 deletions crates/dbs-acpi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# dbs-acpi

`dbs-acpi` provides acpi data structures for VMM to emulate ACPI behavior.

## Acknowledgement

Part of the code is derived from the [Cloud Hypervisor](https://github.com/cloud-hypervisor/cloud-hypervisor) project.

## License

This project is licensed under [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
29 changes: 29 additions & 0 deletions crates/dbs-acpi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2019 Intel Corporation
// Copyright (c) 2023 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
pub mod rsdp;
pub mod sdt;

fn generate_checksum(data: &[u8]) -> u8 {
(255 - data.iter().fold(0u8, |acc, x| acc.wrapping_add(*x))).wrapping_add(1)
}

#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generate_checksum() {
let mut buf = [0x00; 8];
let sum = generate_checksum(&buf);
assert_eq!(sum, 0);
buf[0] = 0xff;
let sum = generate_checksum(&buf);
assert_eq!(sum, 1);
buf[0] = 0xaa;
buf[1] = 0xcc;
buf[4] = generate_checksum(&buf);
let sum = buf.iter().fold(0u8, |s, v| s.wrapping_add(*v));
assert_eq!(sum, 0);
}
}
60 changes: 60 additions & 0 deletions crates/dbs-acpi/src/rsdp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) 2019 Intel Corporation
// Copyright (c) 2023 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
// RSDP (Root System Description Pointer) is a data structure used in the ACPI programming interface.
use vm_memory::ByteValued;

#[repr(packed)]
#[derive(Clone, Copy, Default)]
pub struct Rsdp {
pub signature: [u8; 8],
pub checksum: u8,
pub oem_id: [u8; 6],
pub revision: u8,
_rsdt_addr: u32,
pub length: u32,
pub xsdt_addr: u64,
pub extended_checksum: u8,
_reserved: [u8; 3],
}

// SAFETY: Rsdp only contains a series of integers
unsafe impl ByteValued for Rsdp {}

impl Rsdp {
pub fn new(xsdt_addr: u64) -> Self {
let mut rsdp = Rsdp {
signature: *b"RSD PTR ",
checksum: 0,
oem_id: *b"ALICLD",
revision: 1,
_rsdt_addr: 0,
length: std::mem::size_of::<Rsdp>() as u32,
xsdt_addr,
extended_checksum: 0,
_reserved: [0; 3],
};
rsdp.checksum = super::generate_checksum(&rsdp.as_slice()[0..19]);
rsdp.extended_checksum = super::generate_checksum(rsdp.as_slice());
rsdp
}

pub fn len() -> usize {
std::mem::size_of::<Rsdp>()
}
}
#[cfg(test)]
mod tests {
use super::Rsdp;
use vm_memory::bytes::ByteValued;
#[test]
fn test_rsdp() {
let rsdp = Rsdp::new(0xa0000);
let sum = rsdp
.as_slice()
.iter()
.fold(0u8, |acc, x| acc.wrapping_add(*x));
assert_eq!(sum, 0);
}
}
137 changes: 137 additions & 0 deletions crates/dbs-acpi/src/sdt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright (c) 2019 Intel Corporation
// Copyright (c) 2023 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
#[repr(packed)]
pub struct GenericAddress {
pub address_space_id: u8,
pub register_bit_width: u8,
pub register_bit_offset: u8,
pub access_size: u8,
pub address: u64,
}

impl GenericAddress {
pub fn io_port_address<T>(address: u16) -> Self {
GenericAddress {
address_space_id: 1,
register_bit_width: 8 * std::mem::size_of::<T>() as u8,
register_bit_offset: 0,
access_size: std::mem::size_of::<T>() as u8,
address: u64::from(address),
}
}

pub fn mmio_address<T>(address: u64) -> Self {
GenericAddress {
address_space_id: 0,
register_bit_width: 8 * std::mem::size_of::<T>() as u8,
register_bit_offset: 0,
access_size: std::mem::size_of::<T>() as u8,
address,
}
}
}

pub struct Sdt {
data: Vec<u8>,
}

#[allow(clippy::len_without_is_empty)]
impl Sdt {
pub fn new(signature: [u8; 4], length: u32, revision: u8) -> Self {
assert!(length >= 36);
const OEM_ID: [u8; 6] = *b"ALICLD";
const OEM_TABLE: [u8; 8] = *b"RUND ";
const CREATOR_ID: [u8; 4] = *b"ALIC";
let mut data = Vec::with_capacity(length as usize);
data.extend_from_slice(&signature);
data.extend_from_slice(&length.to_le_bytes());
data.push(revision);
data.push(0); // checksum
data.extend_from_slice(&OEM_ID); // oem id u32
data.extend_from_slice(&OEM_TABLE); // oem table
data.extend_from_slice(&1u32.to_le_bytes()); // oem revision u32
data.extend_from_slice(&CREATOR_ID); // creator id u32
data.extend_from_slice(&1u32.to_le_bytes()); // creator revison u32
assert_eq!(data.len(), 36);
data.resize(length as usize, 0);
let mut sdt = Sdt { data };
sdt.update_checksum();
sdt
}

pub fn update_checksum(&mut self) {
self.data[9] = 0;
let checksum = super::generate_checksum(self.data.as_slice());
self.data[9] = checksum
}

pub fn as_slice(&self) -> &[u8] {
self.data.as_slice()
}

pub fn append<T>(&mut self, value: T) {
let orig_length = self.data.len();
let new_length = orig_length + std::mem::size_of::<T>();
self.data.resize(new_length, 0);
self.write_u32(4, new_length as u32);
self.write(orig_length, value);
}

pub fn append_slice(&mut self, data: &[u8]) {
let orig_length = self.data.len();
let new_length = orig_length + data.len();
self.write_u32(4, new_length as u32);
self.data.extend_from_slice(data);
self.update_checksum();
}

/// Write a value at the given offset
pub fn write<T>(&mut self, offset: usize, value: T) {
assert!((offset + (std::mem::size_of::<T>() - 1)) < self.data.len());
unsafe {
*(((self.data.as_mut_ptr() as usize) + offset) as *mut T) = value;
}
self.update_checksum();
}

pub fn write_u8(&mut self, offset: usize, val: u8) {
self.write(offset, val);
}

pub fn write_u16(&mut self, offset: usize, val: u16) {
self.write(offset, val);
}

pub fn write_u32(&mut self, offset: usize, val: u32) {
self.write(offset, val);
}

pub fn write_u64(&mut self, offset: usize, val: u64) {
self.write(offset, val);
}

pub fn len(&self) -> usize {
self.data.len()
}
}
#[cfg(test)]
mod tests {
use super::Sdt;
#[test]
fn test_sdt() {
let mut sdt = Sdt::new(*b"TEST", 40, 1);
let sum: u8 = sdt
.as_slice()
.iter()
.fold(0u8, |acc, x| acc.wrapping_add(*x));
assert_eq!(sum, 0);
sdt.write_u32(36, 0x12345678);
let sum: u8 = sdt
.as_slice()
.iter()
.fold(0u8, |acc, x| acc.wrapping_add(*x));
assert_eq!(sum, 0);
}
}

0 comments on commit 6f51bc9

Please sign in to comment.