This series adds ARM support to the XenBusDxe driver. It consists of an implementation of the hypercall interface, changes to work around the lack of PCI, and a bugfix. Finally, patch #5 wires it up to the VirtFdtDxe driver that is used in the ARM VM port, and will also be used by the Xen/ARM targeted port.
Note that this is build tested only, both on ARM and x86. I am struggling to get access to suitable ARM hardware, and running Xen on my Macbook has proven to be a discouraging experience, hence the 'RFC' status of this patches. If anyone feels adventurous and bored, it would be good to know that I did not break x86 support in this series, so any testing is highly appreciated.
Ard Biesheuvel (5): Ovmf/Xen: move arch specific hypercall implementation to XenHypercallLib Ovmf/Xen: allow non-PCI usage of XenBusDxe Ovmf/Xen: add ARM and AArch64 support to XenBusDxe Ovmf/Xen: fix pointer to int cast in XenBusDxe ArmVirtualizationPkg/VirtFdtDxe: wire up XenBusDxe to "xen,xen" DT node
.../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 33 ++ .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 1 + .../Include/IndustryStandard/Xen/arch-arm/xen.h | 436 +++++++++++++++++++++ OvmfPkg/Include/IndustryStandard/Xen/xen.h | 2 +- OvmfPkg/Include/Library/XenHypercallLib.h | 36 ++ OvmfPkg/Include/Protocol/XenIo.h | 48 +++ .../Library/XenHypercallLib/Aarch64/Hypercall.S | 26 ++ OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S | 25 ++ .../XenHypercallLib}/Ia32/hypercall.nasm | 6 +- .../XenHypercallLib}/X64/hypercall.nasm | 6 +- .../Library/XenHypercallLib/XenHypercallLibArm.inf | 37 ++ .../Library/XenHypercallLib/XenHypercallLibIntel.c | 77 ++++ .../XenHypercallLib/XenHypercallLibIntel.inf | 48 +++ OvmfPkg/OvmfPkg.dec | 5 + OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/XenBusDxe/AtomicsGcc.c | 44 +++ OvmfPkg/XenBusDxe/ComponentName.c | 2 +- OvmfPkg/XenBusDxe/GrantTable.c | 9 +- OvmfPkg/XenBusDxe/GrantTable.h | 3 +- OvmfPkg/XenBusDxe/XenBus.c | 6 +- OvmfPkg/XenBusDxe/XenBusDxe.c | 192 +++++++-- OvmfPkg/XenBusDxe/XenBusDxe.h | 3 +- OvmfPkg/XenBusDxe/XenBusDxe.inf | 13 +- OvmfPkg/XenBusDxe/XenHypercall.c | 30 +- OvmfPkg/XenBusDxe/XenHypercall.h | 31 -- 27 files changed, 1002 insertions(+), 120 deletions(-) create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h create mode 100644 OvmfPkg/Include/Library/XenHypercallLib.h create mode 100644 OvmfPkg/Include/Protocol/XenIo.h create mode 100644 OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S create mode 100644 OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/Ia32/hypercall.nasm (81%) rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/X64/hypercall.nasm (78%) create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.c create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf create mode 100644 OvmfPkg/XenBusDxe/AtomicsGcc.c
For future ARM/AArch64 support in the XenBus code, move the implementation of hypercall invocation to a dedicated library. The use of a library rather than just an arch specific source in XenBusDxe.inf allows us to move the constructor dependency on the gXenInfoGuid HOB to the library implementation.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- OvmfPkg/Include/Library/XenHypercallLib.h | 36 ++++++++++ .../XenHypercallLib}/Ia32/hypercall.nasm | 6 +- .../XenHypercallLib}/X64/hypercall.nasm | 6 +- .../Library/XenHypercallLib/XenHypercallLibIntel.c | 77 ++++++++++++++++++++++ .../XenHypercallLib/XenHypercallLibIntel.inf | 48 ++++++++++++++ OvmfPkg/OvmfPkg.dec | 4 ++ OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/XenBusDxe/XenBusDxe.c | 7 -- OvmfPkg/XenBusDxe/XenBusDxe.h | 1 - OvmfPkg/XenBusDxe/XenBusDxe.inf | 9 +-- OvmfPkg/XenBusDxe/XenHypercall.c | 30 ++------- OvmfPkg/XenBusDxe/XenHypercall.h | 31 --------- 14 files changed, 179 insertions(+), 79 deletions(-) create mode 100644 OvmfPkg/Include/Library/XenHypercallLib.h rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/Ia32/hypercall.nasm (81%) rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/X64/hypercall.nasm (78%) create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.c create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
diff --git a/OvmfPkg/Include/Library/XenHypercallLib.h b/OvmfPkg/Include/Library/XenHypercallLib.h new file mode 100644 index 000000000000..408807a55356 --- /dev/null +++ b/OvmfPkg/Include/Library/XenHypercallLib.h @@ -0,0 +1,36 @@ +/** @file + Xen Hypercall Library definition + +Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR> +This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __XEN_HYPERCALL_LIB_H_ +#define __XEN_HYPERCALL_LIB_H_ + +/** + This function will put the two arguments in the right place (registers) and + invoke the hypercall identified by HypercallID. + + @param HypercallID The symbolic ID of the hypercall to be invoked + @param Arg1 First argument. + @param Arg2 Second argument. + + @return Return 0 if success otherwise it return an errno. +**/ +INTN +EFIAPI +XenHypercall2 ( + IN INTN HypercallID, + IN OUT INTN Arg1, + IN OUT INTN Arg2 + ); + +#endif diff --git a/OvmfPkg/XenBusDxe/Ia32/hypercall.nasm b/OvmfPkg/Library/XenHypercallLib/Ia32/hypercall.nasm similarity index 81% rename from OvmfPkg/XenBusDxe/Ia32/hypercall.nasm rename to OvmfPkg/Library/XenHypercallLib/Ia32/hypercall.nasm index 8547c30b81ee..e0fa71bb5ba8 100644 --- a/OvmfPkg/XenBusDxe/Ia32/hypercall.nasm +++ b/OvmfPkg/Library/XenHypercallLib/Ia32/hypercall.nasm @@ -2,13 +2,13 @@ SECTION .text
; INTN ; EFIAPI -; XenHypercall2 ( +; __XenHypercall2 ( ; IN VOID *HypercallAddr, ; IN OUT INTN Arg1, ; IN OUT INTN Arg2 ; ); -global ASM_PFX(XenHypercall2) -ASM_PFX(XenHypercall2): +global ASM_PFX(__XenHypercall2) +ASM_PFX(__XenHypercall2): ; Save only ebx, ecx is supposed to be a scratch register and needs to be ; saved by the caller push ebx diff --git a/OvmfPkg/XenBusDxe/X64/hypercall.nasm b/OvmfPkg/Library/XenHypercallLib/X64/hypercall.nasm similarity index 78% rename from OvmfPkg/XenBusDxe/X64/hypercall.nasm rename to OvmfPkg/Library/XenHypercallLib/X64/hypercall.nasm index 177f271ef094..5e6a0c05c5c4 100644 --- a/OvmfPkg/XenBusDxe/X64/hypercall.nasm +++ b/OvmfPkg/Library/XenHypercallLib/X64/hypercall.nasm @@ -3,13 +3,13 @@ SECTION .text
; INTN ; EFIAPI -; XenHypercall2 ( +; __XenHypercall2 ( ; IN VOID *HypercallAddr, ; IN OUT INTN Arg1, ; IN OUT INTN Arg2 ; ); -global ASM_PFX(XenHypercall2) -ASM_PFX(XenHypercall2): +global ASM_PFX(__XenHypercall2) +ASM_PFX(__XenHypercall2): push rdi push rsi ; Copy HypercallAddr to rax diff --git a/OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.c b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.c new file mode 100644 index 000000000000..1fc22b4f07c8 --- /dev/null +++ b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.c @@ -0,0 +1,77 @@ +/** @file + Xen Hypercall Library implementation for Intel architecture + +Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR> +This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <PiDxe.h> +#include <Library/HobLib.h> +#include <Library/DebugLib.h> +#include <Guid/XenInfo.h> + +STATIC VOID *HyperPage; + +// +// Interface exposed by the ASM implementation of the core hypercall +// +INTN +EFIAPI +__XenHypercall2 ( + IN VOID *HypercallAddr, + IN OUT INTN Arg1, + IN OUT INTN Arg2 + ); + +/** + Library constructor: retrieves the Hyperpage address + from the gEfiXenInfoGuid HOB +**/ + +RETURN_STATUS +EFIAPI +XenHypercallLibIntelInit ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + EFI_XEN_INFO *XenInfo; + + GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid); + if (GuidHob == NULL) { + return RETURN_NOT_FOUND; + } + XenInfo = (EFI_XEN_INFO *) GET_GUID_HOB_DATA (GuidHob); + HyperPage = XenInfo->HyperPages; + return RETURN_SUCCESS; +} + +/** + This function will put the two arguments in the right place (registers) and + invoke the hypercall identified by HypercallID. + + @param HypercallID The symbolic ID of the hypercall to be invoked + @param Arg1 First argument. + @param Arg2 Second argument. + + @return Return 0 if success otherwise it return an errno. +**/ +INTN +EFIAPI +XenHypercall2 ( + IN INTN HypercallID, + IN OUT INTN Arg1, + IN OUT INTN Arg2 + ) +{ + ASSERT (HyperPage != NULL); + + return __XenHypercall2 ((UINT8*)HyperPage + HypercallID * 32, Arg1, Arg2); +} diff --git a/OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf new file mode 100644 index 000000000000..3f393e1f0f94 --- /dev/null +++ b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf @@ -0,0 +1,48 @@ +## @file +# Xen Hypercall abstraction lib for Intel architecture +# +# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR> +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = XenHypercallLibIntel + FILE_GUID = B5EE9A32-CA5A-49A8-82E3-ADA4CCB77C7C + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = XenHypercallLib|DXE_DRIVER UEFI_DRIVER + CONSTRUCTOR = XenHypercallLibIntelInit + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + XenHypercallLibIntel.c + +[Sources.IA32] + Ia32/hypercall.nasm + +[Sources.X64] + X64/hypercall.nasm + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseLib + HobLib + +[Guids] + gEfiXenInfoGuid diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 33dcb82de232..314d97c258b3 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -39,6 +39,10 @@ # SerializeVariablesLib|Include/Library/SerializeVariablesLib.h
+ ## @libraryclass Invoke Xen hypercalls + # + XenHypercallLib|Include/Library/XenHypercallLib.h + [Guids] gUefiOvmfPkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}} gEfiXenInfoGuid = {0xd3b46f3b, 0xd441, 0x1244, {0x9a, 0x12, 0x0, 0x12, 0x27, 0x3f, 0xc1, 0x4d}} diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index dca7c6e51603..a896afa1bfb4 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -128,6 +128,7 @@ S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
[LibraryClasses.common] !if $(SECURE_BOOT_ENABLE) == TRUE diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 085f43eaf11b..a5c11578cc3c 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -133,6 +133,7 @@ S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
[LibraryClasses.common] !if $(SECURE_BOOT_ENABLE) == TRUE diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 17d674cd344d..70df1c8af1a4 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -133,6 +133,7 @@ S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf
[LibraryClasses.common] !if $(SECURE_BOOT_ENABLE) == TRUE diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c index 7a7fd82d559d..07336ff15bba 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.c +++ b/OvmfPkg/XenBusDxe/XenBusDxe.c @@ -348,13 +348,6 @@ XenBusDxeDriverBindingStart ( MmioAddr = BarDesc->AddrRangeMin; FreePool (BarDesc);
- Status = XenHyperpageInit (Dev); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "XenBus: Unable to retrieve the hyperpage.\n")); - Status = EFI_UNSUPPORTED; - goto ErrorAllocated; - } - Status = XenGetSharedInfoPage (Dev); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "XenBus: Unable to get the shared info page.\n")); diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h index 11640223ebf4..0879e9cd194f 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.h +++ b/OvmfPkg/XenBusDxe/XenBusDxe.h @@ -96,7 +96,6 @@ struct _XENBUS_DEVICE { EFI_DEVICE_PATH_PROTOCOL *DevicePath; LIST_ENTRY ChildList;
- VOID *Hyperpage; shared_info_t *SharedInfo; };
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf index 4ce474345452..2645267a1c6f 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf @@ -49,12 +49,10 @@ Helpers.c
[Sources.IA32] - Ia32/hypercall.nasm Ia32/InterlockedCompareExchange16.nasm Ia32/TestAndClearBit.nasm
[Sources.X64] - X64/hypercall.nasm X64/InterlockedCompareExchange16.nasm X64/TestAndClearBit.nasm
@@ -67,8 +65,7 @@ UefiLib DevicePathLib DebugLib - HobLib - + XenHypercallLib
[Protocols] gEfiDriverBindingProtocolGuid @@ -77,7 +74,3 @@ gEfiComponentNameProtocolGuid gXenBusProtocolGuid
- -[Guids] - gEfiXenInfoGuid - diff --git a/OvmfPkg/XenBusDxe/XenHypercall.c b/OvmfPkg/XenBusDxe/XenHypercall.c index 34d92e76b7e3..e9075cafcdcd 100644 --- a/OvmfPkg/XenBusDxe/XenHypercall.c +++ b/OvmfPkg/XenBusDxe/XenHypercall.c @@ -14,31 +14,13 @@ **/
#include <PiDxe.h> -#include <Library/HobLib.h> -#include <Guid/XenInfo.h>
#include "XenBusDxe.h" -#include "XenHypercall.h"
#include <IndustryStandard/Xen/hvm/params.h> #include <IndustryStandard/Xen/memory.h>
-EFI_STATUS -XenHyperpageInit ( - IN OUT XENBUS_DEVICE *Dev - ) -{ - EFI_HOB_GUID_TYPE *GuidHob; - EFI_XEN_INFO *XenInfo; - - GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid); - if (GuidHob == NULL) { - return EFI_NOT_FOUND; - } - XenInfo = (EFI_XEN_INFO *) GET_GUID_HOB_DATA (GuidHob); - Dev->Hyperpage = XenInfo->HyperPages; - return EFI_SUCCESS; -} +#include <Library/XenHypercallLib.h>
UINT64 XenHypercallHvmGetParam ( @@ -49,11 +31,9 @@ XenHypercallHvmGetParam ( xen_hvm_param_t Parameter; INTN Error;
- ASSERT (Dev->Hyperpage != NULL); - Parameter.domid = DOMID_SELF; Parameter.index = Index; - Error = XenHypercall2 ((UINT8*)Dev->Hyperpage + __HYPERVISOR_hvm_op * 32, + Error = XenHypercall2 (__HYPERVISOR_hvm_op, HVMOP_get_param, (INTN) &Parameter); if (Error != 0) { DEBUG ((EFI_D_ERROR, @@ -71,8 +51,7 @@ XenHypercallMemoryOp ( IN OUT VOID *Arguments ) { - ASSERT (Dev->Hyperpage != NULL); - return XenHypercall2 ((UINT8*)Dev->Hyperpage + __HYPERVISOR_memory_op * 32, + return XenHypercall2 (__HYPERVISOR_memory_op, Operation, (INTN) Arguments); }
@@ -83,8 +62,7 @@ XenHypercallEventChannelOp ( IN OUT VOID *Arguments ) { - ASSERT (Dev->Hyperpage != NULL); - return XenHypercall2 ((UINT8*)Dev->Hyperpage + __HYPERVISOR_event_channel_op * 32, + return XenHypercall2 (__HYPERVISOR_event_channel_op, Operation, (INTN) Arguments); }
diff --git a/OvmfPkg/XenBusDxe/XenHypercall.h b/OvmfPkg/XenBusDxe/XenHypercall.h index 06693830e16e..49244bc584f7 100644 --- a/OvmfPkg/XenBusDxe/XenHypercall.h +++ b/OvmfPkg/XenBusDxe/XenHypercall.h @@ -17,37 +17,6 @@ #define __XENBUS_DXE_HYPERCALL_H__
/** - This function will put the two arguments in the right place (registers) and - call HypercallAddr, which correspond to an entry in the hypercall pages. - - @param HypercallAddr A memory address where the hypercall to call is. - @param Arg1 First argument. - @param Arg2 Second argument. - - @return Return 0 if success otherwise it return an errno. -**/ -INTN -EFIAPI -XenHypercall2 ( - IN VOID *HypercallAddr, - IN OUT INTN Arg1, - IN OUT INTN Arg2 - ); - -/** - Get the page where all hypercall are from the XenInfo hob. - - @param Dev A XENBUS_DEVICE instance. - - @retval EFI_NOT_FOUND hyperpage could not be found. - @retval EFI_SUCCESS Successfully retrieve the hyperpage pointer. -**/ -EFI_STATUS -XenHyperpageInit ( - XENBUS_DEVICE *Dev - ); - -/** Return the value of the HVM parameter Index.
@param Dev A XENBUS_DEVICE instance.
While Xen on Intel uses a virtual PCI device to communicate the base address of the grant table, the ARM implementation uses a DT node, which is fundamentally incompatible with the way XenBusDxe is implemented, i.e., as a UEFI Driver Model implementation for a PCI device.
To allow the non-PCI implementations to use this driver anyway, this patch introduces an abstract XENIO_PROTOCOL protocol, which contains just the grant table base address. The Intel implementation is adapted to allocate such a protocol on the fly based on the PCI config space metadata, so it operates as before. Other users can invoke the driver by installing a XENIO_PROTOCOL instance on a handle, and invoking ConnectController()
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- OvmfPkg/Include/Protocol/XenIo.h | 48 ++++++++++ OvmfPkg/OvmfPkg.dec | 1 + OvmfPkg/XenBusDxe/ComponentName.c | 2 +- OvmfPkg/XenBusDxe/GrantTable.c | 5 +- OvmfPkg/XenBusDxe/GrantTable.h | 3 +- OvmfPkg/XenBusDxe/XenBus.c | 6 +- OvmfPkg/XenBusDxe/XenBusDxe.c | 185 ++++++++++++++++++++++++++++++++------ OvmfPkg/XenBusDxe/XenBusDxe.h | 2 + OvmfPkg/XenBusDxe/XenBusDxe.inf | 1 + 9 files changed, 215 insertions(+), 38 deletions(-) create mode 100644 OvmfPkg/Include/Protocol/XenIo.h
diff --git a/OvmfPkg/Include/Protocol/XenIo.h b/OvmfPkg/Include/Protocol/XenIo.h new file mode 100644 index 000000000000..510391f3b3e8 --- /dev/null +++ b/OvmfPkg/Include/Protocol/XenIo.h @@ -0,0 +1,48 @@ +/** @file + XenIo protocol to abstract arch specific details + + The Xen implementations for the Intel and ARM archictures differ in the way + the base address of the grant table is communicated to the guest. The former + uses a virtual PCI device, while the latter uses a device tree node. + In order to allow the XenBusDxe UEFI driver to be reused for the non-PCI + Xen implementation, this abstract protocol can be installed on a handle + with the appropriate base address. + + Copyright (C) 2014, Linaro Ltd. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PROTOCOL_XENIO_H__ +#define __PROTOCOL_XENIO_H__ + +#include <IndustryStandard/Xen/xen.h> + +#define XENIO_PROTOCOL_GUID \ + {0x6efac84f, 0x0ab0, 0x4747, {0x81, 0xbe, 0x85, 0x55, 0x62, 0x59, 0x04, 0x49}} + +/// +/// Forward declaration +/// +typedef struct _XENIO_PROTOCOL XENIO_PROTOCOL; + +/// +/// Protocol structure +/// +struct _XENIO_PROTOCOL { + // + // Protocol data fields + // + EFI_PHYSICAL_ADDRESS GrantTableAddress; +}; + +extern EFI_GUID gXenIoProtocolGuid; + +#endif diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 314d97c258b3..0233ae4ca754 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -52,6 +52,7 @@ gVirtioDeviceProtocolGuid = {0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}} gBlockMmioProtocolGuid = {0x6b558ce3, 0x69e5, 0x4c67, {0xa6, 0x34, 0xf7, 0xfe, 0x72, 0xad, 0xbe, 0x84}} gXenBusProtocolGuid = {0x3d3ca290, 0xb9a5, 0x11e3, {0xb7, 0x5d, 0xb8, 0xac, 0x6f, 0x7d, 0x65, 0xe6}} + gXenIoProtocolGuid = {0x6efac84f, 0x0ab0, 0x4747, {0x81, 0xbe, 0x85, 0x55, 0x62, 0x59, 0x04, 0x49}}
[PcdsFixedAtBuild] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0 diff --git a/OvmfPkg/XenBusDxe/ComponentName.c b/OvmfPkg/XenBusDxe/ComponentName.c index 4530509e65dc..3f2dd406c77d 100644 --- a/OvmfPkg/XenBusDxe/ComponentName.c +++ b/OvmfPkg/XenBusDxe/ComponentName.c @@ -155,7 +155,7 @@ XenBusDxeComponentNameGetControllerName ( Status = EfiTestManagedDevice ( ControllerHandle, gXenBusDxeDriverBinding.DriverBindingHandle, - &gEfiPciIoProtocolGuid + &gXenIoProtocolGuid ); if (EFI_ERROR (Status)) { return Status; diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c index 37d3bf786c64..ae9059c146f1 100644 --- a/OvmfPkg/XenBusDxe/GrantTable.c +++ b/OvmfPkg/XenBusDxe/GrantTable.c @@ -139,8 +139,7 @@ XenGrantTableEndAccess (
VOID XenGrantTableInit ( - IN XENBUS_DEVICE *Dev, - IN UINT64 MmioAddr + IN XENBUS_DEVICE *Dev ) { xen_add_to_physmap_t Parameters; @@ -155,7 +154,7 @@ XenGrantTableInit ( XenGrantTablePutFreeEntry ((grant_ref_t)Index); }
- GrantTable = (VOID*)(UINTN) MmioAddr; + GrantTable = (VOID*)(UINTN) Dev->XenIo->GrantTableAddress; for (Index = 0; Index < NR_GRANT_FRAMES; Index++) { Parameters.domid = DOMID_SELF; Parameters.idx = Index; diff --git a/OvmfPkg/XenBusDxe/GrantTable.h b/OvmfPkg/XenBusDxe/GrantTable.h index 5772c56662df..194275ba7ed5 100644 --- a/OvmfPkg/XenBusDxe/GrantTable.h +++ b/OvmfPkg/XenBusDxe/GrantTable.h @@ -29,8 +29,7 @@ **/ VOID XenGrantTableInit ( - IN XENBUS_DEVICE *Dev, - IN UINT64 MmioAddr + IN XENBUS_DEVICE *Dev );
/** diff --git a/OvmfPkg/XenBusDxe/XenBus.c b/OvmfPkg/XenBusDxe/XenBus.c index f69c27dd184a..ee9526c33252 100644 --- a/OvmfPkg/XenBusDxe/XenBus.c +++ b/OvmfPkg/XenBusDxe/XenBus.c @@ -138,7 +138,7 @@ XenBusAddDevice ( XENBUS_PRIVATE_DATA *Private; EFI_STATUS Status; XENBUS_DEVICE_PATH *TempXenBusPath; - VOID *ChildPciIo; + VOID *ChildXenIo;
AsciiSPrint (DevicePath, sizeof (DevicePath), "device/%a/%a", Type, Id); @@ -208,8 +208,8 @@ XenBusAddDevice ( }
Status = gBS->OpenProtocol (Dev->ControllerHandle, - &gEfiPciIoProtocolGuid, - &ChildPciIo, Dev->This->DriverBindingHandle, + &gXenIoProtocolGuid, + &ChildXenIo, Dev->This->DriverBindingHandle, Private->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER); if (EFI_ERROR (Status)) { diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c index 07336ff15bba..a03f7cb6d8b9 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.c +++ b/OvmfPkg/XenBusDxe/XenBusDxe.c @@ -194,6 +194,22 @@ XenBusDxeDriverBindingSupported ( EFI_PCI_IO_PROTOCOL *PciIo; PCI_TYPE00 Pci;
+ // + // If the ControllerHandle supports the XENIO_PROTOCOL, we can use + // it directly without having to bother with the PCI representation. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gXenIoProtocolGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + return Status; + } + Status = gBS->OpenProtocol ( ControllerHandle, &gEfiPciIoProtocolGuid, @@ -238,6 +254,137 @@ NotifyExitBoot ( }
/** + Opens the XENIO_PROTOCOL on ControllerHandle. + + If the protocol is not available, but the EFI_PCI_IO_PROTOCOL is, create + the XENIO_PROTOCOL protocol instance on the fly based on the PCI metadata + and install it on ControllerHandle. + + @param ControllerHandle The controller handle + @param DriverBindingHandle The driver binding handle + @param XenIo The XENIO_PROTOCOL return value + @param PciIo The EFI_PCI_IO_PROTOCOL return value, or NULL if + the XENIO_PROTOCOL already existed on Handle +**/ +STATIC +EFI_STATUS +OpenOrInstallXenIoProtocolOnHandle ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverBindingHandle, + OUT XENIO_PROTOCOL **XenIo, + OUT EFI_PCI_IO_PROTOCOL **PciIo + ) +{ + EFI_STATUS Status; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; + + // + // We support both EFI_PCI_IO_PROTOCOL and XENIO_PROTOCOL, the former only + // if the vendor and product IDs match up (as verified in .Supported()). + // The latter has precedence, and we install it on the fly if it is not + // supported. + // + *PciIo = NULL; + Status = gBS->OpenProtocol ( + ControllerHandle, + &gXenIoProtocolGuid, + (VOID**)XenIo, + DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + // + // This handle does not support XENIO_PROTOCOL yet, which implies that it + // does support the EFI_PCI_IO_PROTOCOL, or we wouldn't have been invoked. + // Get the grant table base address from the PCI config space, and allocate + // and install the XENIO_PROTOCOL instance on the fly. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + (VOID**)PciIo, + DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + ASSERT_EFI_ERROR (Status); + + *XenIo = AllocateZeroPool (sizeof(XENIO_PROTOCOL)); + ASSERT (*XenIo != NULL); + + // + // The BAR1 of this PCI device is used for shared memory and is supposed to + // look like MMIO. The address space of the BAR1 will be used to map the + // Grant Table. + // + Status = (*PciIo)->GetBarAttributes (*PciIo, PCI_BAR_IDX1, NULL, (VOID**) &BarDesc); + ASSERT_EFI_ERROR (Status); + ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM); + + /* Get a Memory address for mapping the Grant Table. */ + DEBUG ((EFI_D_INFO, "XenBus: BAR at %LX\n", BarDesc->AddrRangeMin)); + (*XenIo)->GrantTableAddress = BarDesc->AddrRangeMin; + FreePool (BarDesc); + + // + // Now install the XENIO_PROTOCOL protocol instance on Handle. + // This should only fail in extraordinary cases, as we have already + // established that the protocol does not exist yet on the handle. + // + Status = gBS->InstallProtocolInterface (ControllerHandle, + &gXenIoProtocolGuid, EFI_NATIVE_INTERFACE, *XenIo); + ASSERT_EFI_ERROR (Status); + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gXenIoProtocolGuid, + (VOID**)XenIo, + DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid, + DriverBindingHandle, ControllerHandle); + } + } + return Status; +} + +/** + Close or uninstall the XENIO_PROTOCOL instance on ControllerHandle + + Close the XENIO_PROTOCOL protocol instance on ControllerHandle, and + in case PciIo != NULL, uninstall and deallocate it as well. + + @param ControllerHandle The controller handle + @param DriverBindingHandle The driver binding handle + @param XenIo The XENIO_PROTOCOL protocol instance + @param PciIo The EFI_PCI_IO_PROTOCOL protocol instance, or NULL + if the XENIO_PROTOCOL already existed on + ControllerHandle +**/ +STATIC +VOID +CloseOrUninstallXenIoProtocolOnHandle ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverBindingHandle, + IN XENIO_PROTOCOL *XenIo, + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +{ + gBS->CloseProtocol (ControllerHandle, &gXenIoProtocolGuid, + DriverBindingHandle, ControllerHandle); + if (PciIo != NULL) { + gBS->UninstallProtocolInterface (ControllerHandle, &gXenIoProtocolGuid, XenIo); + FreePool (XenIo); + gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid, + DriverBindingHandle, ControllerHandle); + } +} + +/** Starts a bus controller.
The Start() function is designed to be invoked from the EFI boot service ConnectController(). @@ -284,19 +431,12 @@ XenBusDxeDriverBindingStart ( { EFI_STATUS Status; XENBUS_DEVICE *Dev; + XENIO_PROTOCOL *XenIo; EFI_PCI_IO_PROTOCOL *PciIo; - EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; - UINT64 MmioAddr; EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- Status = gBS->OpenProtocol ( - ControllerHandle, - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - This->DriverBindingHandle, - ControllerHandle, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); + Status = OpenOrInstallXenIoProtocolOnHandle (ControllerHandle, + This->DriverBindingHandle, &XenIo, &PciIo); if (EFI_ERROR (Status)) { return Status; } @@ -319,6 +459,7 @@ XenBusDxeDriverBindingStart ( Dev->This = This; Dev->ControllerHandle = ControllerHandle; Dev->PciIo = PciIo; + Dev->XenIo = XenIo; Dev->DevicePath = DevicePath; InitializeListHead (&Dev->ChildList);
@@ -334,20 +475,6 @@ XenBusDxeDriverBindingStart ( mMyDevice = Dev; EfiReleaseLock (&mMyDeviceLock);
- // - // The BAR1 of this PCI device is used for shared memory and is supposed to - // look like MMIO. The address space of the BAR1 will be used to map the - // Grant Table. - // - Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID**) &BarDesc); - ASSERT_EFI_ERROR (Status); - ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM); - - /* Get a Memory address for mapping the Grant Table. */ - DEBUG ((EFI_D_INFO, "XenBus: BAR at %LX\n", BarDesc->AddrRangeMin)); - MmioAddr = BarDesc->AddrRangeMin; - FreePool (BarDesc); - Status = XenGetSharedInfoPage (Dev); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "XenBus: Unable to get the shared info page.\n")); @@ -355,7 +482,7 @@ XenBusDxeDriverBindingStart ( goto ErrorAllocated; }
- XenGrantTableInit (Dev, MmioAddr); + XenGrantTableInit (Dev);
Status = XenStoreInit (Dev); ASSERT_EFI_ERROR (Status); @@ -375,8 +502,8 @@ ErrorAllocated: gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, ControllerHandle); ErrorOpenningProtocol: - gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, ControllerHandle); + CloseOrUninstallXenIoProtocolOnHandle (ControllerHandle, + This->DriverBindingHandle, XenIo, PciIo); return Status; }
@@ -465,8 +592,8 @@ XenBusDxeDriverBindingStop (
gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, ControllerHandle); - gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, ControllerHandle); + CloseOrUninstallXenIoProtocolOnHandle (ControllerHandle, + This->DriverBindingHandle, Dev->XenIo, Dev->PciIo);
mMyDevice = NULL; FreePool (Dev); diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h index 0879e9cd194f..81b73f8f1e0b 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.h +++ b/OvmfPkg/XenBusDxe/XenBusDxe.h @@ -45,6 +45,7 @@ // Consumed Protocols // #include <Protocol/PciIo.h> +#include <Protocol/XenIo.h>
// @@ -92,6 +93,7 @@ struct _XENBUS_DEVICE { EFI_DRIVER_BINDING_PROTOCOL *This; EFI_HANDLE ControllerHandle; EFI_PCI_IO_PROTOCOL *PciIo; + XENIO_PROTOCOL *XenIo; EFI_EVENT ExitBootEvent; EFI_DEVICE_PATH_PROTOCOL *DevicePath; LIST_ENTRY ChildList; diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf index 2645267a1c6f..1429a85e1d12 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf @@ -73,4 +73,5 @@ gEfiComponentName2ProtocolGuid gEfiComponentNameProtocolGuid gXenBusProtocolGuid + gXenIoProtocolGuid
This patch adds support to XenBusDxe for executing on ARM and AArch64 machines (the former only when built with GCC). It includes arch-specific implementations of XenHypercall2() and a GCC specific version of the XenBusDxe atomics. It also includes the ARM version of the xen.h header that originates in the Xen project.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- .../Include/IndustryStandard/Xen/arch-arm/xen.h | 436 +++++++++++++++++++++ OvmfPkg/Include/IndustryStandard/Xen/xen.h | 2 +- .../Library/XenHypercallLib/Aarch64/Hypercall.S | 26 ++ OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S | 25 ++ .../Library/XenHypercallLib/XenHypercallLibArm.inf | 37 ++ OvmfPkg/XenBusDxe/AtomicsGcc.c | 44 +++ OvmfPkg/XenBusDxe/XenBusDxe.inf | 3 + 7 files changed, 572 insertions(+), 1 deletion(-) create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h create mode 100644 OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S create mode 100644 OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf create mode 100644 OvmfPkg/XenBusDxe/AtomicsGcc.c
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h b/OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h new file mode 100644 index 000000000000..655a221f6337 --- /dev/null +++ b/OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h @@ -0,0 +1,436 @@ +/****************************************************************************** + * arch-arm.h + * + * Guest OS interface to ARM Xen. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Copyright 2011 (C) Citrix Systems + */ + +#ifndef __XEN_PUBLIC_ARCH_ARM_H__ +#define __XEN_PUBLIC_ARCH_ARM_H__ + +/* + * `incontents 50 arm_abi Hypercall Calling Convention + * + * A hypercall is issued using the ARM HVC instruction. + * + * A hypercall can take up to 5 arguments. These are passed in + * registers, the first argument in x0/r0 (for arm64/arm32 guests + * respectively irrespective of whether the underlying hypervisor is + * 32- or 64-bit), the second argument in x1/r1, the third in x2/r2, + * the forth in x3/r3 and the fifth in x4/r4. + * + * The hypercall number is passed in r12 (arm) or x16 (arm64). In both + * cases the relevant ARM procedure calling convention specifies this + * is an inter-procedure-call scratch register (e.g. for use in linker + * stubs). This use does not conflict with use during a hypercall. + * + * The HVC ISS must contain a Xen specific TAG: XEN_HYPERCALL_TAG. + * + * The return value is in x0/r0. + * + * The hypercall will clobber x16/r12 and the argument registers used + * by that hypercall (except r0 which is the return value) i.e. in + * addition to x16/r12 a 2 argument hypercall will clobber x1/r1 and a + * 4 argument hypercall will clobber x1/r1, x2/r2 and x3/r3. + * + * Parameter structs passed to hypercalls are laid out according to + * the Procedure Call Standard for the ARM Architecture (AAPCS, AKA + * EABI) and Procedure Call Standard for the ARM 64-bit Architecture + * (AAPCS64). Where there is a conflict the 64-bit standard should be + * used regardless of guest type. Structures which are passed as + * hypercall arguments are always little endian. + * + * All memory which is shared with other entities in the system + * (including the hypervisor and other guests) must reside in memory + * which is mapped as Normal Inner-cacheable. This applies to: + * - hypercall arguments passed via a pointer to guest memory. + * - memory shared via the grant table mechanism (including PV I/O + * rings etc). + * - memory shared with the hypervisor (struct shared_info, struct + * vcpu_info, the grant table, etc). + * + * Any Inner cache allocation strategy (Write-Back, Write-Through etc) + * is acceptable. There is no restriction on the Outer-cacheability. + */ + +/* + * `incontents 55 arm_hcall Supported Hypercalls + * + * Xen on ARM makes extensive use of hardware facilities and therefore + * only a subset of the potential hypercalls are required. + * + * Since ARM uses second stage paging any machine/physical addresses + * passed to hypercalls are Guest Physical Addresses (Intermediate + * Physical Addresses) unless otherwise noted. + * + * The following hypercalls (and sub operations) are supported on the + * ARM platform. Other hypercalls should be considered + * unavailable/unsupported. + * + * HYPERVISOR_memory_op + * All generic sub-operations. + * + * In addition the following arch specific sub-ops: + * * XENMEM_add_to_physmap + * * XENMEM_add_to_physmap_batch + * + * HYPERVISOR_domctl + * All generic sub-operations, with the exception of: + * * XEN_DOMCTL_iomem_permission (not yet implemented) + * * XEN_DOMCTL_irq_permission (not yet implemented) + * + * HYPERVISOR_sched_op + * All generic sub-operations, with the exception of: + * * SCHEDOP_block -- prefer wfi hardware instruction + * + * HYPERVISOR_console_io + * All generic sub-operations + * + * HYPERVISOR_xen_version + * All generic sub-operations + * + * HYPERVISOR_event_channel_op + * All generic sub-operations + * + * HYPERVISOR_physdev_op + * No sub-operations are currenty supported + * + * HYPERVISOR_sysctl + * All generic sub-operations, with the exception of: + * * XEN_SYSCTL_page_offline_op + * * XEN_SYSCTL_get_pmstat + * * XEN_SYSCTL_pm_op + * + * HYPERVISOR_hvm_op + * Exactly these sub-operations are supported: + * * HVMOP_set_param + * * HVMOP_get_param + * + * HYPERVISOR_grant_table_op + * All generic sub-operations + * + * HYPERVISOR_vcpu_op + * Exactly these sub-operations are supported: + * * VCPUOP_register_vcpu_info + * * VCPUOP_register_runstate_memory_area + * + * + * Other notes on the ARM ABI: + * + * - struct start_info is not exported to ARM guests. + * + * - struct shared_info is mapped by ARM guests using the + * HYPERVISOR_memory_op sub-op XENMEM_add_to_physmap, passing + * XENMAPSPACE_shared_info as space parameter. + * + * - All the per-cpu struct vcpu_info are mapped by ARM guests using the + * HYPERVISOR_vcpu_op sub-op VCPUOP_register_vcpu_info, including cpu0 + * struct vcpu_info. + * + * - The grant table is mapped using the HYPERVISOR_memory_op sub-op + * XENMEM_add_to_physmap, passing XENMAPSPACE_grant_table as space + * parameter. The memory range specified under the Xen compatible + * hypervisor node on device tree can be used as target gpfn for the + * mapping. + * + * - Xenstore is initialized by using the two hvm_params + * HVM_PARAM_STORE_PFN and HVM_PARAM_STORE_EVTCHN. They can be read + * with the HYPERVISOR_hvm_op sub-op HVMOP_get_param. + * + * - The paravirtualized console is initialized by using the two + * hvm_params HVM_PARAM_CONSOLE_PFN and HVM_PARAM_CONSOLE_EVTCHN. They + * can be read with the HYPERVISOR_hvm_op sub-op HVMOP_get_param. + * + * - Event channel notifications are delivered using the percpu GIC + * interrupt specified under the Xen compatible hypervisor node on + * device tree. + * + * - The device tree Xen compatible node is fully described under Linux + * at Documentation/devicetree/bindings/arm/xen.txt. + */ + +#define XEN_HYPERCALL_TAG 0XEA1 + +#define uint64_aligned_t UINT64 __attribute__((aligned(8))) + +#ifndef __ASSEMBLY__ +#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ + typedef union { type *p; unsigned long q; } \ + __guest_handle_ ## name; \ + typedef union { type *p; uint64_aligned_t q; } \ + __guest_handle_64_ ## name; + +/* + * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field + * in a struct in memory. On ARM is always 8 bytes sizes and 8 bytes + * aligned. + * XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an + * hypercall argument. It is 4 bytes on aarch and 8 bytes on aarch64. + */ +#define __DEFINE_XEN_GUEST_HANDLE(name, type) \ + ___DEFINE_XEN_GUEST_HANDLE(name, type); \ + ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type) +#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name) +#define __XEN_GUEST_HANDLE(name) __guest_handle_64_ ## name +#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name) +/* this is going to be changed on 64 bit */ +#define XEN_GUEST_HANDLE_PARAM(name) __guest_handle_ ## name +#define set_xen_guest_handle_raw(hnd, val) \ + do { \ + typeof(&(hnd)) _sxghr_tmp = &(hnd); \ + _sxghr_tmp->q = 0; \ + _sxghr_tmp->p = val; \ + } while ( 0 ) +#ifdef __XEN_TOOLS__ +#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0) +#endif +#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val) + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +/* Anonymous union includes both 32- and 64-bit names (e.g., r0/x0). */ +# define __DECL_REG(n64, n32) union { \ + UINT64 n64; \ + UINT32 n32; \ + } +#else +/* Non-gcc sources must always use the proper 64-bit name (e.g., x0). */ +#define __DECL_REG(n64, n32) UINT64 n64 +#endif + +struct vcpu_guest_core_regs +{ + /* Aarch64 Aarch32 */ + __DECL_REG(x0, r0_usr); + __DECL_REG(x1, r1_usr); + __DECL_REG(x2, r2_usr); + __DECL_REG(x3, r3_usr); + __DECL_REG(x4, r4_usr); + __DECL_REG(x5, r5_usr); + __DECL_REG(x6, r6_usr); + __DECL_REG(x7, r7_usr); + __DECL_REG(x8, r8_usr); + __DECL_REG(x9, r9_usr); + __DECL_REG(x10, r10_usr); + __DECL_REG(x11, r11_usr); + __DECL_REG(x12, r12_usr); + + __DECL_REG(x13, sp_usr); + __DECL_REG(x14, lr_usr); + + __DECL_REG(x15, __unused_sp_hyp); + + __DECL_REG(x16, lr_irq); + __DECL_REG(x17, sp_irq); + + __DECL_REG(x18, lr_svc); + __DECL_REG(x19, sp_svc); + + __DECL_REG(x20, lr_abt); + __DECL_REG(x21, sp_abt); + + __DECL_REG(x22, lr_und); + __DECL_REG(x23, sp_und); + + __DECL_REG(x24, r8_fiq); + __DECL_REG(x25, r9_fiq); + __DECL_REG(x26, r10_fiq); + __DECL_REG(x27, r11_fiq); + __DECL_REG(x28, r12_fiq); + + __DECL_REG(x29, sp_fiq); + __DECL_REG(x30, lr_fiq); + + /* Return address and mode */ + __DECL_REG(pc64, pc32); /* ELR_EL2 */ + UINT32 cpsr; /* SPSR_EL2 */ + + union { + UINT32 spsr_el1; /* AArch64 */ + UINT32 spsr_svc; /* AArch32 */ + }; + + /* AArch32 guests only */ + UINT32 spsr_fiq, spsr_irq, spsr_und, spsr_abt; + + /* AArch64 guests only */ + UINT64 sp_el0; + UINT64 sp_el1, elr_el1; +}; +typedef struct vcpu_guest_core_regs vcpu_guest_core_regs_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_guest_core_regs_t); + +#undef __DECL_REG + +typedef UINT64 xen_pfn_t; +#define PRI_xen_pfn PRIx64 + +/* Maximum number of virtual CPUs in legacy multi-processor guests. */ +/* Only one. All other VCPUS must use VCPUOP_register_vcpu_info */ +#define XEN_LEGACY_MAX_VCPUS 1 + +typedef UINT64 xen_ulong_t; +#define PRI_xen_ulong PRIx64 + +#if defined(__XEN__) || defined(__XEN_TOOLS__) +struct vcpu_guest_context { +#define _VGCF_online 0 +#define VGCF_online (1<<_VGCF_online) + UINT32 flags; /* VGCF_* */ + + struct vcpu_guest_core_regs user_regs; /* Core CPU registers */ + + UINT32 sctlr; + UINT64 ttbcr, ttbr0, ttbr1; +}; +typedef struct vcpu_guest_context vcpu_guest_context_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); +#endif + +struct arch_vcpu_info { +}; +typedef struct arch_vcpu_info arch_vcpu_info_t; + +struct arch_shared_info { +}; +typedef struct arch_shared_info arch_shared_info_t; +typedef UINT64 xen_callback_t; + +#endif + +#if defined(__XEN__) || defined(__XEN_TOOLS__) + +/* PSR bits (CPSR, SPSR)*/ + +#define PSR_THUMB (1<<5) /* Thumb Mode enable */ +#define PSR_FIQ_MASK (1<<6) /* Fast Interrupt mask */ +#define PSR_IRQ_MASK (1<<7) /* Interrupt mask */ +#define PSR_ABT_MASK (1<<8) /* Asynchronous Abort mask */ +#define PSR_BIG_ENDIAN (1<<9) /* arm32: Big Endian Mode */ +#define PSR_DBG_MASK (1<<9) /* arm64: Debug Exception mask */ +#define PSR_IT_MASK (0x0600fc00) /* Thumb If-Then Mask */ +#define PSR_JAZELLE (1<<24) /* Jazelle Mode */ + +/* 32 bit modes */ +#define PSR_MODE_USR 0x10 +#define PSR_MODE_FIQ 0x11 +#define PSR_MODE_IRQ 0x12 +#define PSR_MODE_SVC 0x13 +#define PSR_MODE_MON 0x16 +#define PSR_MODE_ABT 0x17 +#define PSR_MODE_HYP 0x1a +#define PSR_MODE_UND 0x1b +#define PSR_MODE_SYS 0x1f + +/* 64 bit modes */ +#define PSR_MODE_BIT 0x10 /* Set iff AArch32 */ +#define PSR_MODE_EL3h 0x0d +#define PSR_MODE_EL3t 0x0c +#define PSR_MODE_EL2h 0x09 +#define PSR_MODE_EL2t 0x08 +#define PSR_MODE_EL1h 0x05 +#define PSR_MODE_EL1t 0x04 +#define PSR_MODE_EL0t 0x00 + +#define PSR_GUEST32_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC) +#define PSR_GUEST64_INIT (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_EL1h) + +#define SCTLR_GUEST_INIT 0x00c50078 + +/* + * Virtual machine platform (memory layout, interrupts) + * + * These are defined for consistency between the tools and the + * hypervisor. Guests must not rely on these hardcoded values but + * should instead use the FDT. + */ + +/* Physical Address Space */ + +/* vGIC mappings: Only one set of mapping is used by the guest. + * Therefore they can overlap. + */ + +/* vGIC v2 mappings */ +#define GUEST_GICD_BASE 0x03001000ULL +#define GUEST_GICD_SIZE 0x00001000ULL +#define GUEST_GICC_BASE 0x03002000ULL +#define GUEST_GICC_SIZE 0x00000100ULL + +/* vGIC v3 mappings */ +#define GUEST_GICV3_GICD_BASE 0x03001000ULL +#define GUEST_GICV3_GICD_SIZE 0x00010000ULL + +#define GUEST_GICV3_RDIST_STRIDE 0x20000ULL +#define GUEST_GICV3_RDIST_REGIONS 1 + +#define GUEST_GICV3_GICR0_BASE 0x03020000ULL /* vCPU0 - vCPU7 */ +#define GUEST_GICV3_GICR0_SIZE 0x00100000ULL + +/* 16MB == 4096 pages reserved for guest to use as a region to map its + * grant table in. + */ +#define GUEST_GNTTAB_BASE 0x38000000ULL +#define GUEST_GNTTAB_SIZE 0x01000000ULL + +#define GUEST_MAGIC_BASE 0x39000000ULL +#define GUEST_MAGIC_SIZE 0x01000000ULL + +#define GUEST_RAM_BANKS 2 + +#define GUEST_RAM0_BASE 0x40000000ULL /* 3GB of low RAM @ 1GB */ +#define GUEST_RAM0_SIZE 0xc0000000ULL + +#define GUEST_RAM1_BASE 0x0200000000ULL /* 1016GB of RAM @ 8GB */ +#define GUEST_RAM1_SIZE 0xfe00000000ULL + +#define GUEST_RAM_BASE GUEST_RAM0_BASE /* Lowest RAM address */ +/* Largest amount of actual RAM, not including holes */ +#define GUEST_RAM_MAX (GUEST_RAM0_SIZE + GUEST_RAM1_SIZE) +/* Suitable for e.g. const uint64_t ramfoo[] = GUEST_RAM_BANK_FOOS; */ +#define GUEST_RAM_BANK_BASES { GUEST_RAM0_BASE, GUEST_RAM1_BASE } +#define GUEST_RAM_BANK_SIZES { GUEST_RAM0_SIZE, GUEST_RAM1_SIZE } + +/* Interrupts */ +#define GUEST_TIMER_VIRT_PPI 27 +#define GUEST_TIMER_PHYS_S_PPI 29 +#define GUEST_TIMER_PHYS_NS_PPI 30 +#define GUEST_EVTCHN_PPI 31 + +/* PSCI functions */ +#define PSCI_cpu_suspend 0 +#define PSCI_cpu_off 1 +#define PSCI_cpu_on 2 +#define PSCI_migrate 3 + +#endif + +#endif /* __XEN_PUBLIC_ARCH_ARM_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/OvmfPkg/Include/IndustryStandard/Xen/xen.h b/OvmfPkg/Include/IndustryStandard/Xen/xen.h index 79697fcb6152..f38a22be4e16 100644 --- a/OvmfPkg/Include/IndustryStandard/Xen/xen.h +++ b/OvmfPkg/Include/IndustryStandard/Xen/xen.h @@ -32,7 +32,7 @@ #if defined(MDE_CPU_IA32) || defined(MDE_CPU_X64) #include "arch-x86/xen.h" #elif defined(__arm__) || defined (__aarch64__) -#include "arch-arm.h" +#include "arch-arm/xen.h" #else #error "Unsupported architecture" #endif diff --git a/OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S b/OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S new file mode 100644 index 000000000000..b1b5d4cc3f28 --- /dev/null +++ b/OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S @@ -0,0 +1,26 @@ + +/** @file + AArch64 implementation of XenHypercall2 + + Copyright (C) 2014, Linaro Ltd. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <IndustryStandard/Xen/arch-arm/xen.h> + + .text + .global ASM_PFX(XenHypercall2) +ASM_PFX(XenHypercall2): + mov x16, x0 + mov x0, x1 + mov x1, x2 + hvc #XEN_HYPERCALL_TAG + ret diff --git a/OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S b/OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S new file mode 100644 index 000000000000..b38e1a8f18da --- /dev/null +++ b/OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S @@ -0,0 +1,25 @@ +/** @file + ARM (AArch32) implementation of XenHypercall2 + + Copyright (C) 2014, Linaro Ltd. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <IndustryStandard/Xen/arch-arm/xen.h> + + .text + .global ASM_PFX(XenHypercall2) +ASM_PFX(XenHypercall2): + mov r12, r0 + mov r0, r1 + mov r1, r2 + hvc #XEN_HYPERCALL_TAG + bx lr diff --git a/OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf new file mode 100644 index 000000000000..7ba513f39355 --- /dev/null +++ b/OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf @@ -0,0 +1,37 @@ +## @file +# Xen Hypercall abstraction lib for ARM architecture +# +# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR> +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = XenHypercallLibArm + FILE_GUID = 9607AC2E-FCB9-499B-9475-612282019568 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = XenHypercallLib|DXE_DRIVER UEFI_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = ARM AARCH64 +# + +[Sources.ARM] + Arm/Hypercall.S + +[Sources.AARCH64] + Aarch64/Hypercall.S + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec diff --git a/OvmfPkg/XenBusDxe/AtomicsGcc.c b/OvmfPkg/XenBusDxe/AtomicsGcc.c new file mode 100644 index 000000000000..a0bdcbf67440 --- /dev/null +++ b/OvmfPkg/XenBusDxe/AtomicsGcc.c @@ -0,0 +1,44 @@ +/** @file + Arch-independent implementations of XenBusDxe atomics using GCC __builtins + + Copyright (C) 2014, Linaro Ltd. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +UINT16 +EFIAPI +InternalSyncCompareExchange16 ( + IN volatile UINT16 *Value, + IN UINT16 CompareValue, + IN UINT16 ExchangeValue + ) +{ + return __sync_val_compare_and_swap_2 (Value, CompareValue, ExchangeValue); +} + +INT32 +EFIAPI +TestAndClearBit ( + IN INT32 Bit, + IN volatile VOID *Address + ) +{ + // + // Calculate the effective address relative to 'Address' based on the + // higher order bits of 'Bit'. Use signed shift instead of division to + // ensure we round towards -Inf, and end up with a positive shift in 'Bit', + // even if 'Bit' itself is negative. + // + Address += (Bit >> 5) * sizeof(INT32); + Bit &= 31; + + return (__sync_fetch_and_and_4 (Address, ~(1U << Bit)) & (1U << Bit)) != 0; +} diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf index 1429a85e1d12..19c9a5dd7927 100644 --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf @@ -56,6 +56,9 @@ X64/InterlockedCompareExchange16.nasm X64/TestAndClearBit.nasm
+[Sources.AARCH64, Sources.ARM] + AtomicsGcc.c | GCC + [LibraryClasses] UefiDriverEntryPoint UefiBootServicesTableLib
On ARM, xen_pfn_t is 64 bits but the size of a pointer is only 32 bits, so casting between them needs to go via (UINTN)
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- OvmfPkg/XenBusDxe/GrantTable.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c index ae9059c146f1..0d133db6954e 100644 --- a/OvmfPkg/XenBusDxe/GrantTable.c +++ b/OvmfPkg/XenBusDxe/GrantTable.c @@ -159,7 +159,7 @@ XenGrantTableInit ( Parameters.domid = DOMID_SELF; Parameters.idx = Index; Parameters.space = XENMAPSPACE_grant_table; - Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index; + Parameters.gpfn = (((xen_pfn_t)(UINTN) GrantTable) >> EFI_PAGE_SHIFT) + Index; ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameters); if (ReturnCode != 0) { DEBUG ((EFI_D_ERROR, "Xen GrantTable, add_to_physmap hypercall error: %d\n", ReturnCode)); @@ -181,7 +181,7 @@ XenGrantTableDeinit (
for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) { Parameters.domid = DOMID_SELF; - Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index; + Parameters.gpfn = (((xen_pfn_t)(UINTN) GrantTable) >> EFI_PAGE_SHIFT) + Index; DEBUG ((EFI_D_INFO, "Xen GrantTable, removing %X\n", Parameters.gpfn)); ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_remove_from_physmap, &Parameters); if (ReturnCode != 0) {
This patchs adds support to VirtFdtDxe for the Xen DT node which contains the base address of the Grant Table. This data is communicated to XenBusDxe using a XENIO_PROTOCOL instance.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 33 ++++++++++++++++++++++ .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 1 + 2 files changed, 34 insertions(+)
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c index d002e668aa48..c49f726a7f10 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c @@ -27,6 +27,7 @@ #include <libfdt.h>
#include <Guid/Fdt.h> +#include <Protocol/XenIo.h>
#pragma pack (1) typedef struct { @@ -44,6 +45,7 @@ typedef enum { PropertyTypeUart, PropertyTypeTimer, PropertyTypePsci, + PropertyTypeXen, } PROPERTY_TYPE;
typedef struct { @@ -59,6 +61,7 @@ STATIC CONST PROPERTY CompatibleProperties[] = { { PropertyTypeTimer, "arm,armv7-timer" }, { PropertyTypeTimer, "arm,armv8-timer" }, { PropertyTypePsci, "arm,psci-0.2" }, + { PropertyTypeXen, "xen,xen" }, { PropertyTypeUnknown, "" } };
@@ -115,6 +118,7 @@ InitializeVirtFdtDxe ( CONST INTERRUPT_PROPERTY *InterruptProp; INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum; CONST CHAR8 *PsciMethod; + XENIO_PROTOCOL *XenIo;
DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeBaseAddress); ASSERT (DeviceTreeBase != NULL); @@ -271,6 +275,35 @@ InitializeVirtFdtDxe ( } break;
+ case PropertyTypeXen: + ASSERT (Len == 16); + + // + // Retrieve the reg base from this node and add it to a + // XENIO_PROTOCOL instance installed on a new handle. + // + XenIo = AllocateZeroPool (sizeof *XenIo); + ASSERT (XenIo != NULL); + XenIo->GrantTableAddress = fdt64_to_cpu (((UINT64 *)RegProp)[0]); + + Handle = NULL; + Status = gBS->InstallProtocolInterface (&Handle, + &gXenIoProtocolGuid, EFI_NATIVE_INTERFACE, + XenIo); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: Failed to install the XENIO_PROTOCOL " + "protocol on a new handle (Status == %r)\n", + __FUNCTION__, Status)); + FreePool (XenIo); + break; + } + Status = gBS->ConnectController (Handle, NULL, NULL, TRUE); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a: Failed to invoke ConnectController () on " + "XENIO_PROTOCOL instance (Status == %r)\n", + __FUNCTION__, Status)); + } + default: break; } diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf index 1c9dd20580c4..16b5873d9451 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf @@ -57,6 +57,7 @@
[Protocols] gEfiDevicePathProtocolGuid + gXenIoProtocolGuid
[Depex] TRUE
On 01/02/15 11:45, Ard Biesheuvel wrote:
This series adds ARM support to the XenBusDxe driver. It consists of an implementation of the hypercall interface, changes to work around the lack of PCI, and a bugfix. Finally, patch #5 wires it up to the VirtFdtDxe driver that is used in the ARM VM port, and will also be used by the Xen/ARM targeted port.
Note that this is build tested only, both on ARM and x86. I am struggling to get access to suitable ARM hardware, and running Xen on my Macbook has proven to be a discouraging experience, hence the 'RFC' status of this patches. If anyone feels adventurous and bored, it would be good to know that I did not break x86 support in this series, so any testing is highly appreciated.
Ard Biesheuvel (5): Ovmf/Xen: move arch specific hypercall implementation to XenHypercallLib Ovmf/Xen: allow non-PCI usage of XenBusDxe Ovmf/Xen: add ARM and AArch64 support to XenBusDxe Ovmf/Xen: fix pointer to int cast in XenBusDxe ArmVirtualizationPkg/VirtFdtDxe: wire up XenBusDxe to "xen,xen" DT node
.../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 33 ++ .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 1 + .../Include/IndustryStandard/Xen/arch-arm/xen.h | 436 +++++++++++++++++++++ OvmfPkg/Include/IndustryStandard/Xen/xen.h | 2 +- OvmfPkg/Include/Library/XenHypercallLib.h | 36 ++ OvmfPkg/Include/Protocol/XenIo.h | 48 +++ .../Library/XenHypercallLib/Aarch64/Hypercall.S | 26 ++ OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S | 25 ++ .../XenHypercallLib}/Ia32/hypercall.nasm | 6 +- .../XenHypercallLib}/X64/hypercall.nasm | 6 +- .../Library/XenHypercallLib/XenHypercallLibArm.inf | 37 ++ .../Library/XenHypercallLib/XenHypercallLibIntel.c | 77 ++++ .../XenHypercallLib/XenHypercallLibIntel.inf | 48 +++ OvmfPkg/OvmfPkg.dec | 5 + OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/XenBusDxe/AtomicsGcc.c | 44 +++ OvmfPkg/XenBusDxe/ComponentName.c | 2 +- OvmfPkg/XenBusDxe/GrantTable.c | 9 +- OvmfPkg/XenBusDxe/GrantTable.h | 3 +- OvmfPkg/XenBusDxe/XenBus.c | 6 +- OvmfPkg/XenBusDxe/XenBusDxe.c | 192 +++++++-- OvmfPkg/XenBusDxe/XenBusDxe.h | 3 +- OvmfPkg/XenBusDxe/XenBusDxe.inf | 13 +- OvmfPkg/XenBusDxe/XenHypercall.c | 30 +- OvmfPkg/XenBusDxe/XenHypercall.h | 31 -- 27 files changed, 1002 insertions(+), 120 deletions(-) create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h create mode 100644 OvmfPkg/Include/Library/XenHypercallLib.h create mode 100644 OvmfPkg/Include/Protocol/XenIo.h create mode 100644 OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S create mode 100644 OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/Ia32/hypercall.nasm (81%) rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/X64/hypercall.nasm (78%) create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.c create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf create mode 100644 OvmfPkg/XenBusDxe/AtomicsGcc.c
Some meta-requests first: - please rebase the series to SVN r16578 first (or at least verify please that the rebase leaves your patchset intact), - if it's necessary to repost, please add --stat=150 to git-format-patch; edk2 uses very long pathnames and the diffstat is mostly useless in the above (ellipsis) form.
Thanks! Laszlo
On 2 January 2015 at 12:52, Laszlo Ersek lersek@redhat.com wrote:
On 01/02/15 11:45, Ard Biesheuvel wrote:
This series adds ARM support to the XenBusDxe driver. It consists of an implementation of the hypercall interface, changes to work around the lack of PCI, and a bugfix. Finally, patch #5 wires it up to the VirtFdtDxe driver that is used in the ARM VM port, and will also be used by the Xen/ARM targeted port.
Note that this is build tested only, both on ARM and x86. I am struggling to get access to suitable ARM hardware, and running Xen on my Macbook has proven to be a discouraging experience, hence the 'RFC' status of this patches. If anyone feels adventurous and bored, it would be good to know that I did not break x86 support in this series, so any testing is highly appreciated.
Ard Biesheuvel (5): Ovmf/Xen: move arch specific hypercall implementation to XenHypercallLib Ovmf/Xen: allow non-PCI usage of XenBusDxe Ovmf/Xen: add ARM and AArch64 support to XenBusDxe Ovmf/Xen: fix pointer to int cast in XenBusDxe ArmVirtualizationPkg/VirtFdtDxe: wire up XenBusDxe to "xen,xen" DT node
.../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 33 ++ .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 1 + .../Include/IndustryStandard/Xen/arch-arm/xen.h | 436 +++++++++++++++++++++ OvmfPkg/Include/IndustryStandard/Xen/xen.h | 2 +- OvmfPkg/Include/Library/XenHypercallLib.h | 36 ++ OvmfPkg/Include/Protocol/XenIo.h | 48 +++ .../Library/XenHypercallLib/Aarch64/Hypercall.S | 26 ++ OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S | 25 ++ .../XenHypercallLib}/Ia32/hypercall.nasm | 6 +- .../XenHypercallLib}/X64/hypercall.nasm | 6 +- .../Library/XenHypercallLib/XenHypercallLibArm.inf | 37 ++ .../Library/XenHypercallLib/XenHypercallLibIntel.c | 77 ++++ .../XenHypercallLib/XenHypercallLibIntel.inf | 48 +++ OvmfPkg/OvmfPkg.dec | 5 + OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/XenBusDxe/AtomicsGcc.c | 44 +++ OvmfPkg/XenBusDxe/ComponentName.c | 2 +- OvmfPkg/XenBusDxe/GrantTable.c | 9 +- OvmfPkg/XenBusDxe/GrantTable.h | 3 +- OvmfPkg/XenBusDxe/XenBus.c | 6 +- OvmfPkg/XenBusDxe/XenBusDxe.c | 192 +++++++-- OvmfPkg/XenBusDxe/XenBusDxe.h | 3 +- OvmfPkg/XenBusDxe/XenBusDxe.inf | 13 +- OvmfPkg/XenBusDxe/XenHypercall.c | 30 +- OvmfPkg/XenBusDxe/XenHypercall.h | 31 -- 27 files changed, 1002 insertions(+), 120 deletions(-) create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-arm/xen.h create mode 100644 OvmfPkg/Include/Library/XenHypercallLib.h create mode 100644 OvmfPkg/Include/Protocol/XenIo.h create mode 100644 OvmfPkg/Library/XenHypercallLib/Aarch64/Hypercall.S create mode 100644 OvmfPkg/Library/XenHypercallLib/Arm/Hypercall.S rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/Ia32/hypercall.nasm (81%) rename OvmfPkg/{XenBusDxe => Library/XenHypercallLib}/X64/hypercall.nasm (78%) create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibArm.inf create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.c create mode 100644 OvmfPkg/Library/XenHypercallLib/XenHypercallLibIntel.inf create mode 100644 OvmfPkg/XenBusDxe/AtomicsGcc.c
Some meta-requests first:
- please rebase the series to SVN r16578 first (or at least verify please that the rebase leaves your patchset intact),
Some breakage, but nothing major, and only in VirtFdtDxe.c
- if it's necessary to repost, please add --stat=150 to git-format-patch; edk2 uses very long pathnames and the diffstat is mostly useless in the above (ellipsis) form.
Yeah, I remember now that you mentioned that before. Will do.