[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] Design doc of adding ACPI support for arm64 on Xen - version 4

This document is going to explain the design details of Xen booting with
ACPI on ARM. Maybe parts of it may not be appropriate. Any comments are

Changes v3->v4:
* add explanation for minimal DT and the properties
* drop "linux," prefix of the properties
* add explanation for the event channel flag
* create RSDP table since the "xsdt_physical_address" is changed
* since it uses hypervisor_id introduced by ACPI 6.0 to notify Dom0 the
  hypervisor ID, so it needs to limit minimum supported ACPI version for
  Xen on ARM to 6.0.

Changes v2->v3:
* remove the two HVM_PARAMs for grant table and let linux kernel use
  xlated_setup_gnttab_pages() to setup grant table.
* don't modify GTDT table
* add definition of event-channel interrupt flag
* state that route all Xen unused interrupt to Dom0
* state that reusing existing PCI bus_notifier for PCI devices MMIO
* mapping

To Xen itself booting with ACPI, this is similar to Linux kernel except
that Xen doesn't parse DSDT table. So I'll skip this part and focus on
how Xen prepares ACPI tables for Dom0 and how Xen passes them to Dom0.

1. Create minimal DT to pass required information to Dom0
Since there are no legacy interfaces like x86 for Dom0 to get the
booting required information on ARM, here we use the minimal DT which is
used by UEFI stub communicating with Linux kernel as well.

The UEFI stub is a feature that extends the Image/zImage into a valid
UEFI PE/COFF executable, including a loader application that makes it
possible to load the kernel directly from the UEFI shell, boot menu, or
one of the lightweight bootloaders like Gummiboot or rEFInd.

The kernel image built with stub support remains a valid kernel image
for booting in non-UEFI environments and the UEFI stub will be jumped
for non-UEFI environments.

When booting in UEFI mode, the UEFI stub will create a minimal DT in
order to pass the command line and other informations (such as the EFI
memory table) to the kernel. And when booting with ACPI, kernel will get
command line, ACPI root table address and memory map information from
the minimal DT. Also, it will check if the DT contains only the /chosen
node to know whether it boots with DT or ACPI.

In addition, the current names of these properties with a "linux,"
prefix in the minimal DT are Linux specified. It needs to standardize
them so that other OS(such as FreeBSD) could reuse them in the future.
So we drop the "linux," prefix of UEFI parameters and change the names
in Linux kernel as well.

An example of the minimal DT:
/ {
    #address-cells = <2>;
    #size-cells = <1>;
    chosen {
        bootargs = "kernel=Image console=hvc0 earlycon=pl011,0x1c090000
root=/dev/vda2 rw rootfstype=ext4 init=/bin/sh acpi=force efi=noruntime";
        linux,initrd-start = <0xXXXXXXXX>;
        linux,initrd-end = <0xXXXXXXXX>;
        uefi-system-table = <0xXXXXXXXX>;
        uefi-mmap-start = <0xXXXXXXXX>;
        uefi-mmap-size = <0xXXXXXXXX>;
        uefi-mmap-desc-size = <0xXXXXXXXX>;
        uefi-mmap-desc-ver = <0xXXXXXXXX>;

For details loook at [1].

2. Copy and change some EFI and ACPI tables
a) Create EFI_SYSTEM_TABLE table
Copy the header from the origin and change the value of FirmwareVendor.
Create only one ConfigurationTable to store VendorGuid and VendorTable.
The EFI System Table will be passed to Dom0 through the property
"uefi-system-table" in the above minimal DT. So Dom0 could get ACPI root
table address through the ConfigurationTable.

It needs to notify Dom0 where are the RAM regions. Add memory start and
size information of Dom0 in this table. It's passed to Dom0 through the
properties "uefi-mmap-start", "uefi-mmap-size", "uefi-mmap-desc-size"
and "uefi-mmap-desc-ver" of the minimal DT. Then Dom0 will get the
memory information through this EFI table.

c) Copy FADT table
Change the value of arm_boot_flags to enable PSCI and HVC.

Since there is no cpuid like x86 on ARM, here it's through the field
hypervisor_id of FADT table to tell Dom0 that the hypervisor is Xen.
Because hypervisor_id is introduced by ACPI 6.0, so it needs to limit
minimum supported ACPI version for Xen on ARM to 6.0.

Set the hypervisor_id to "XenVMM", then Dom0 could through HVM_PARAM to
get some informations for booting necessity, such as event-channel

d) Copy MADT table
It needs to change MADT table to restrict the number of vCPUs. We choose
to copy the first dom0_max_vcpus GICC entries of MADT to new created
MADT table as numa is not supported currently. If numa is supported in
the future, it would change the mpidr according to the cpu topology.
Also copy GICD as well.

e) Create STAO table
This table is a new added one that's used to define a list of ACPI
namespace names that are to be ignored by the OSPM in Dom0. Currently
we use it to tell OSPM that it should ignore UART defined in SPCR table.
Look at [2] for details.

f) Copy XSDT table
Add a new table entry for STAO and change other table's entries.

g) Copy RSDP table
Change the value of xsdt_physical_address in RSDP table. As we create a
new XSDT table and the address of XSDT is changed, so it needs to update
the value of "xsdt_physical_address" in RSDP. So Dom0 could get the
right XSDT table rather than the old one. And it needs to update the
value of VendorTable in EFI Configuration Table which is created in
above step a).

h) The rest of tables are not copied or changed. They are reused
including DSDT, SPCR, GTDT, etc. It doesn't mask EL2 resources for Dom0
because the Linux kernel would not use EL2 resources when it boots at

All these tables will be copied to Dom0 memory except that the reused
tables(DSDT, SPCR, GTDT, etc) will be mapped to Dom0.

3. Dom0 gets grant table and event channel irq information
The OS will have to find a place himself in the memory map for the grant
table region. For instance, Linux can make usage of

To event channel interrupt, reuse HVM_PARAM_CALLBACK_IRQ and add a new
delivery type to get it.
val[63:56] == 3: val[15:8] is flag: val[7:0] is a PPI (ARM and ARM64
The definition of flag reusing the definition of xenv table[3]. Bit 0
stands interrupt mode(1: edge triggered, 0: level triggered) and bit 1
stands interrupt polarity(1: active low, 0: active high).

As said above, we assign the hypervisor_id be "XenVMM" to tell Dom0 that
it runs on Xen hypervisor. Then Dom0 could get it through hypercall

4. Map MMIO regions
Register a bus_notifier for platform and amba bus in Linux. Add a new
XENMAPSPACE "XENMAPSPACE_dev_mmio". The usage of this hypercall
- domid: DOMID_SELF.
- space: XENMAPSPACE_dev_mmio.
- gpfns: guest physical addresses where the mapping should appear.

Within the register, check if the device is newly added, then call
hypercall XENMEM_add_to_physmap to map the mmio regions.

For PCI bus device, it could reuse the existing PCI bus_notifier like

5. Route device interrupts to Dom0
Route all the SPI interrupts to Dom0 before Dom0 booting, except the
interrupts used by Xen. For uart, it could get the interrupt from SPCR
table and exclude it. For SMMU, it could get the interrupts from IORT
table and exclude them as well.

[1] https://github.com/torvalds/linux/blob/master/Documentation/arm/uefi.txt


Xen-devel mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.