From mboxrd@z Thu Jan 1 00:00:00 1970 From: Shannon Zhao Subject: Design doc of adding ACPI support for arm64 on Xen - version 5 Date: Fri, 28 Aug 2015 17:45:41 +0800 Message-ID: <55E02DC5.4090202@huawei.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel , Christoffer Dall , Ian Campbell , Stefano Stabellini , Julien Grall , Stefano Stabellini , Jan Beulich , Parth Dixit , andrew@fubar.geek.nz, Boris Ostrovsky , David Vrabel , Roger Pau Monne Cc: Hangaohuai , "Huangpeng (Peter)" , Shannon Zhao List-Id: xen-devel@lists.xenproject.org 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 welcome. Changes v4->v5: * change the description of section 4 to make it more generic * place EFI and ACPI tables at non-RAM space of Dom0 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 ---------------------------------------------------------- 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 over 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"; 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 https://github.com/torvalds/linux/blob/master/Documentation/arm/uefi.txt 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. This EFI System Table is a made up one not copy of the host. 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. b) Create EFI_MEMORY_DESCRIPTOR table 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 interrupt. 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 when 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 below url for details: http://wiki.xenproject.org/mediawiki/images/0/02/Status-override-table.pdf 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 EL1. All above tables will be mapped to Dom0 non-RAM space(e.g. the space after Dom0 RAM). 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 xlated_setup_gnttab_pages. 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 only) The definition of flag reusing the definition of xenv table. 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 HVMOP_get_param. 4. Map MMIO regions ------------------- Add a new XENMAPSPACE "XENMAPSPACE_dev_mmio" for mapping mmio region. Dom0 could use the hypercall XENMEM_add_to_physmap or XENMEM_add_to_physmap_batch to map the mmio regions of devices. The usage of the hypercall's parameters: - domid: DOMID_SELF. - space: XENMAPSPACE_dev_mmio. - size: Number of pages to go through. - idxs: native physical addresses. - gpfns: guest physical addresses where the mapping should appear. For example, Linux could register a bus_notifier for platform and amba bus. Within the notifier, check if the device is newly added, if so call the hypercall to map the mmio regions. And for PCI bus devices, Linux could reuse the existing PCI bus_notifier like X86. 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. Thanks, -- Shannon