mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-22 04:25:21 +00:00
acpi: Implement SPCR on AArch64
This commit implements an AArch64-required ACPI table: Serial Port Console Redirection Table (SPCR). The table provides information about the configuration and use of the serial port or non-legacy UART interface. Signed-off-by: Henry Wang <Henry.Wang@arm.com>
This commit is contained in:
parent
9c5528490e
commit
213da7d862
@ -22,6 +22,15 @@ impl GenericAddress {
|
|||||||
address: u64::from(address),
|
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 {
|
pub struct Sdt {
|
||||||
|
@ -6,9 +6,12 @@ use crate::cpu::CpuManager;
|
|||||||
use crate::device_manager::DeviceManager;
|
use crate::device_manager::DeviceManager;
|
||||||
use crate::memory_manager::MemoryManager;
|
use crate::memory_manager::MemoryManager;
|
||||||
use crate::vm::NumaNodes;
|
use crate::vm::NumaNodes;
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use acpi_tables::sdt::GenericAddress;
|
use acpi_tables::sdt::GenericAddress;
|
||||||
use acpi_tables::{aml::Aml, rsdp::Rsdp, sdt::Sdt};
|
use acpi_tables::{aml::Aml, rsdp::Rsdp, sdt::Sdt};
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use arch::aarch64::DeviceInfoForFdt;
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use arch::DeviceType;
|
||||||
|
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
@ -282,6 +285,34 @@ fn create_gtdt_table() -> Sdt {
|
|||||||
gtdt
|
gtdt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
fn create_spcr_table(base_address: u64, gsi: u32) -> Sdt {
|
||||||
|
// SPCR
|
||||||
|
let mut spcr = Sdt::new(*b"SPCR", 80, 2, *b"CLOUDH", *b"CHSPCR ", 1);
|
||||||
|
// Interface Type
|
||||||
|
spcr.write(36, 3u8);
|
||||||
|
// Base Address in format ACPI Generic Address Structure
|
||||||
|
spcr.write(40, GenericAddress::mmio_address::<u8>(base_address));
|
||||||
|
// Interrupt Type: Bit[3] ARMH GIC interrupt
|
||||||
|
spcr.write(52, (1 << 3) as u8);
|
||||||
|
// Global System Interrupt used by the UART
|
||||||
|
spcr.write(54, (gsi as u32).to_le());
|
||||||
|
// Baud Rate: 3 = 9600
|
||||||
|
spcr.write(58, 3u8);
|
||||||
|
// Stop Bits: 1 Stop bit
|
||||||
|
spcr.write(60, 1u8);
|
||||||
|
// Flow Control: Bit[1] = RTS/CTS hardware flow control
|
||||||
|
spcr.write(61, (1 << 1) as u8);
|
||||||
|
// PCI Device ID: Not a PCI device
|
||||||
|
spcr.write(64, 0xffff_u16);
|
||||||
|
// PCI Vendor ID: Not a PCI device
|
||||||
|
spcr.write(66, 0xffff_u16);
|
||||||
|
|
||||||
|
spcr.update_checksum();
|
||||||
|
|
||||||
|
spcr
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_acpi_tables(
|
pub fn create_acpi_tables(
|
||||||
guest_mem: &GuestMemoryMmap,
|
guest_mem: &GuestMemoryMmap,
|
||||||
device_manager: &Arc<Mutex<DeviceManager>>,
|
device_manager: &Arc<Mutex<DeviceManager>>,
|
||||||
@ -339,15 +370,49 @@ pub fn create_acpi_tables(
|
|||||||
.write_slice(mcfg.as_slice(), mcfg_offset)
|
.write_slice(mcfg.as_slice(), mcfg_offset)
|
||||||
.expect("Error writing MCFG table");
|
.expect("Error writing MCFG table");
|
||||||
tables.push(mcfg_offset.0);
|
tables.push(mcfg_offset.0);
|
||||||
|
prev_tbl_len = mcfg.len() as u64;
|
||||||
|
prev_tbl_off = mcfg_offset;
|
||||||
|
|
||||||
|
// SPCR
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
{
|
||||||
|
let is_serial_on = device_manager
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.get_device_info()
|
||||||
|
.clone()
|
||||||
|
.get(&(DeviceType::Serial, DeviceType::Serial.to_string()))
|
||||||
|
.is_some();
|
||||||
|
let serial_device_addr = arch::layout::LEGACY_SERIAL_MAPPED_IO_START;
|
||||||
|
let serial_device_irq = if is_serial_on {
|
||||||
|
device_manager
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.get_device_info()
|
||||||
|
.clone()
|
||||||
|
.get(&(DeviceType::Serial, DeviceType::Serial.to_string()))
|
||||||
|
.unwrap()
|
||||||
|
.irq()
|
||||||
|
} else {
|
||||||
|
// If serial is turned off, add a fake device with invalid irq.
|
||||||
|
31
|
||||||
|
};
|
||||||
|
let spcr = create_spcr_table(serial_device_addr, serial_device_irq);
|
||||||
|
let spcr_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap();
|
||||||
|
guest_mem
|
||||||
|
.write_slice(spcr.as_slice(), spcr_offset)
|
||||||
|
.expect("Error writing SPCR table");
|
||||||
|
tables.push(spcr_offset.0);
|
||||||
|
prev_tbl_len = spcr.len() as u64;
|
||||||
|
prev_tbl_off = spcr_offset;
|
||||||
|
}
|
||||||
|
|
||||||
// SRAT and SLIT
|
// SRAT and SLIT
|
||||||
// Only created if the NUMA nodes list is not empty.
|
// Only created if the NUMA nodes list is not empty.
|
||||||
let (prev_tbl_len, prev_tbl_off) = if numa_nodes.is_empty() {
|
if !numa_nodes.is_empty() {
|
||||||
(mcfg.len(), mcfg_offset)
|
|
||||||
} else {
|
|
||||||
// SRAT
|
// SRAT
|
||||||
let srat = create_srat_table(numa_nodes);
|
let srat = create_srat_table(numa_nodes);
|
||||||
let srat_offset = mcfg_offset.checked_add(mcfg.len() as u64).unwrap();
|
let srat_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap();
|
||||||
guest_mem
|
guest_mem
|
||||||
.write_slice(srat.as_slice(), srat_offset)
|
.write_slice(srat.as_slice(), srat_offset)
|
||||||
.expect("Error writing SRAT table");
|
.expect("Error writing SRAT table");
|
||||||
@ -361,7 +426,8 @@ pub fn create_acpi_tables(
|
|||||||
.expect("Error writing SRAT table");
|
.expect("Error writing SRAT table");
|
||||||
tables.push(slit_offset.0);
|
tables.push(slit_offset.0);
|
||||||
|
|
||||||
(slit.len(), slit_offset)
|
prev_tbl_len = slit.len() as u64;
|
||||||
|
prev_tbl_off = slit_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
// XSDT
|
// XSDT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user