This repository has been archived by the owner on Jul 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
acpi: add dbs-acpi support for Dragonball
This is for initializing dbs-acpi. fixes: #253 Signed-off-by: Chao Wu <[email protected]>
- Loading branch information
Showing
7 changed files
with
253 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |