From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: Eric Shelton <eshelton@pobox.com>,
Daniel Kiper <daniel.kiper@oracle.com>
Cc: Tang Liang <liang.tang@oracle.com>,
Jan Beulich <jbeulich@suse.com>,
xen-devel <xen-devel@lists.xen.org>
Subject: Re: [REBASE] xen: patches (against Linux kernel) for supporting efi
Date: Fri, 24 May 2013 10:24:13 -0400 [thread overview]
Message-ID: <20130524142413.GH3900@phenom.dumpdata.com> (raw)
In-Reply-To: <CAPQw5rn_ch57rHxKy93Jp4RwhExZdpqFEGODLhVhkB1A=irFtA@mail.gmail.com>
On Thu, May 23, 2013 at 06:04:19AM -0400, Eric Shelton wrote:
> Please find attached and below a rebased version of the patches to the
> Linux kernel needed to get a Linux-based dom0 to come up under
> xen.efi, which were last posted by Tang on Feb 23, 2012. The provided
> patch was made against Linux 3.9.3, but should either apply against or
> be easily backported to older kernel versions (for example, only 2
> hunks fail against 3.7.10). I tried to take into account Jan's
> comments offered for the Feb 8, 2012 ver 1 of the patches.
Hey Eric!
>
> Using the provided patch, I am able to successfully do a native EFI
> boot using xen.efi on a 2012 MacBook Air, with refind kicking off the
> boot. I have noticed no difference from a non-Xen boot; KDE and wifi
> work normally, for example. A non-Xen boot of the patched 3.9.3
> kernel works fine as well. The below xen.cfg was used:
>
> video=gfx-1366x768x32
> options=debug console=vga loglvl=all guest_loglvl=all e820-verbose=1
> iommu=debug,verbose console_timestamps=true font=8x16
> kernel=393test.efi ro root=/dev/sda3 debug ignore_loglevel
> earlyprintk=xen i8042.noaux
Sweet!
>
> In order of importance, three items are outstanding:
> 1) The attached code only works on 64-bit systems, due to setting the
> EFI_64BIT in xen_efi_probe(). It looks like a new hypercall is needed
> or an existing hypercall needs to be added to check whether the EFI
> BIOS is 32- or 64-bit (see comment in code).
> 2) efivars is not tested
> 3) XEN_FW_EFI_PCI_ROM hypercall was added in the interim, but is unused in dom0
Right, that is needed for FrameBuffer handover right?
Are MacBook's the only ones that do this?
>
> I apologize for the attached patch not being split up into 5 pieces as
> previously presented, and for not observing the formalities for patch
> presentation (which is why I also include an attachment). I hope that
> someone with a little more experience and time can address the above
> items (particularly #1) and get it incorporated into the kernel this
> time around.
Cc-ing Daniel here. He is right now focusing on making Xen working
well with GRUB2-EFI and then focusing on making the Linux kernel EFI
work with Xen properly. This will be a good starting point
>
> Signed-off-by: Eric Shelton <eshelton@pobox.com>
>
>
> On February 23, 2012, Tang Liang wrote:
> > Hi
> >
> > The following patches introduce and implement efi support in dom0.
> > The efi memory is owned by Xen and efi run-time service can not be called
> > directly in dom0, so a new efi driver is needed by Xen efi.
> > These patches are based on v3.3.0-rc2+.
> >
> > Descriptions for these patches:
> >
> > The efi public functions are changed to function pointers in efi_init_funcs
> > struct. They act as efi generic functions as default.
> > As a benefit from this change, we can register xen efi init func.
> >
> > In order to add xen efi video support, it is required to add xen-efi's
> > new video type(XEN_VGATYPE_EFI_LFB) case handler in the function xen_init_vga
> > and set the video type to VIDEO_TYPE_EFI to enable efi video mode.
> >
> > I have tested this patch on Dell Opti 790.
> >
> > Xen efi boot support is added by Jan Beulich, more detail information can be
> > gotten from the url:
> > http://wiki.xen.org/xenwiki/XenParavirtOps, search "efi" in the page.
> >
> > The example of config file for efi boot:
> > kernel=vmlinuz-3.3.0-rc2+ root=xx ro console=tty0
> > ramdisk=initramfs-3.3.0-rc2+.img
> > video=gfx-x.0
> >
> > The detailed test which i have done:
> > First, Check efifb driver work well or not and check the kernel messesge ro
> > see the follow info:
> > [ 0.576705] efifb: probing for efifb
> > [ 0.577357] efifb: framebuffer at 0xd0000000, mapped to 0xffffc90005800000, using 3752k, total 65472k
> > [ 0.577360] efifb: mode is 800x600x32, linelength=3200, pages=1
> > [ 0.577362] efifb: scrolling: redraw
> > [ 0.577364] efifb: Truecolor: size=8:8:8:8, shift=24:16:8:0
> >
> > Second, Check efi systab and variable is work well or not.
> > cat the information in /sys/firmware/efi to check the efi systab and variable
> > is right or not.
> >
> > Third, Run Linux firmware testing tools which is downloaded from this Url.
> > http://linuxfirmwarekit.org/download.php
> >
> > Jan Beulich (1):
> > EFI: add efi driver for Xen efi
> >
> > Tang Liang (4):
> > EFI: Provide registration for efi_init.. etc efi public function
> > EFI: seperate get efi table info code to single function
> > Xen efi: Add xen efi enabled detect
> > Xen vga: add the xen efi video mode support
> >
> > arch/x86/platform/efi/Makefile | 2 +-
> > arch/x86/platform/efi/efi-xen.c | 460 ++++++++++++++++++++++++++++++++++++++
> > arch/x86/platform/efi/efi.c | 63 +++++-
> > arch/x86/xen/enlighten.c | 3 +
> > arch/x86/xen/vga.c | 7 +
> > include/linux/efi.h | 14 +-
> > include/xen/interface/platform.h | 122 ++++++++++
> > include/xen/interface/xen.h | 1 +
> > 8 files changed, 665 insertions(+), 7 deletions(-)
> >
> > Thanks
> > Liang.
>
> =========== PATCH BELOW ===========
>
> diff -urN a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
> --- a/arch/x86/platform/efi/efi.c 2013-05-22 20:37:13.432000000 -0400
> +++ b/arch/x86/platform/efi/efi.c 2013-05-23 02:23:03.384000000 -0400
> @@ -95,6 +95,29 @@
> }
> EXPORT_SYMBOL(efi_enabled);
>
> +static void efi_init_generic(void);
> +static void efi_late_init_generic(void);
> +
> +static void efi_enter_virtual_mode_generic(void);
> +static u32 efi_mem_type_generic(unsigned long phys_addr);
> +static u64 efi_mem_attributes_generic(unsigned long phys_addr);
> +static void efi_reserve_boot_services_generic(void);
> +static void efi_free_boot_services_generic(void);
> +static int efi_memblock_x86_reserve_range_generic(void);
> +
> +static const struct efi_init_funcs __initconst efi_generic_funcs = {
> + .init = efi_init_generic,
> + .late_init = efi_late_init_generic,
> + .reserve_boot_services = efi_reserve_boot_services_generic,
> + .free_boot_services = efi_free_boot_services_generic,
> + .enter_virtual_mode = efi_enter_virtual_mode_generic,
> + .mem_type = efi_mem_type_generic,
> + .mem_attributes = efi_mem_attributes_generic,
> + .x86_reserve_range = efi_memblock_x86_reserve_range_generic
> +};
> +
> +const struct efi_init_funcs *efi_override_funcs = &efi_generic_funcs;
> +
> static bool __initdata disable_runtime = false;
> static int __init setup_noefi(char *arg)
> {
> @@ -443,7 +466,7 @@
> sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
> }
>
> -int __init efi_memblock_x86_reserve_range(void)
> +int __init efi_memblock_x86_reserve_range_generic(void)
> {
> unsigned long pmap;
>
> @@ -475,6 +498,8 @@
> void *p;
> int i;
>
> + if (memmap.map == NULL) return;
> +
> for (p = memmap.map, i = 0;
> p < memmap.map_end;
> p += memmap.desc_size, i++) {
> @@ -488,7 +513,7 @@
> }
> #endif /* EFI_DEBUG */
>
> -void __init efi_reserve_boot_services(void)
> +static void efi_reserve_boot_services_generic(void)
> {
> void *p;
>
> @@ -529,7 +554,7 @@
> }
> }
>
> -void __init efi_free_boot_services(void)
> +void __init efi_free_boot_services_generic(void)
> {
> void *p;
>
> @@ -644,7 +669,7 @@
> return 0;
> }
>
> -static int __init efi_config_init(u64 tables, int nr_tables)
> +int __init efi_config_init(u64 tables, int nr_tables, struct efi *efi_t)
> {
> void *config_tables, *tablep;
> int i, sz;
> @@ -665,7 +690,7 @@
>
> tablep = config_tables;
> pr_info("");
> - for (i = 0; i < efi.systab->nr_tables; i++) {
> + for (i = 0; i < nr_tables; i++) {
> efi_guid_t guid;
> unsigned long table;
>
> @@ -679,7 +704,7 @@
> pr_cont("\n");
> pr_err("Table located above 4GB, disabling EFI.\n");
> early_iounmap(config_tables,
> - efi.systab->nr_tables * sz);
> + nr_tables * sz);
> return -EINVAL;
> }
> #endif
> @@ -688,33 +713,33 @@
> table = ((efi_config_table_32_t *)tablep)->table;
> }
> if (!efi_guidcmp(guid, MPS_TABLE_GUID)) {
> - efi.mps = table;
> + efi_t->mps = table;
> pr_cont(" MPS=0x%lx ", table);
> } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) {
> - efi.acpi20 = table;
> + efi_t->acpi20 = table;
> pr_cont(" ACPI 2.0=0x%lx ", table);
> } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) {
> - efi.acpi = table;
> + efi_t->acpi = table;
> pr_cont(" ACPI=0x%lx ", table);
> } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) {
> - efi.smbios = table;
> + efi_t->smbios = table;
> pr_cont(" SMBIOS=0x%lx ", table);
> #ifdef CONFIG_X86_UV
> } else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) {
> - efi.uv_systab = table;
> + efi_t->uv_systab = table;
> pr_cont(" UVsystab=0x%lx ", table);
> #endif
> } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) {
> - efi.hcdp = table;
> + efi_t->hcdp = table;
> pr_cont(" HCDP=0x%lx ", table);
> } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) {
> - efi.uga = table;
> + efi_t->uga = table;
> pr_cont(" UGA=0x%lx ", table);
> }
> tablep += sz;
> }
> pr_cont("\n");
> - early_iounmap(config_tables, efi.systab->nr_tables * sz);
> + early_iounmap(config_tables, nr_tables * sz);
> return 0;
> }
>
> @@ -770,7 +795,7 @@
> return 0;
> }
>
> -void __init efi_init(void)
> +static void efi_init_generic(void)
> {
> efi_char16_t *c16;
> char vendor[100] = "unknown";
> @@ -830,7 +855,7 @@
> efi.systab->hdr.revision >> 16,
> efi.systab->hdr.revision & 0xffff, vendor);
>
> - if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
> + if (efi_config_init(efi.systab->tables, efi.systab->nr_tables, &efi))
> return;
>
> set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
> @@ -865,9 +890,11 @@
> #endif
> }
>
> -void __init efi_late_init(void)
> +void __init efi_late_init_generic(void)
> {
> +#ifdef CONFIG_ACPI_BGRT
> efi_bgrt_init();
> +#endif
> }
>
> void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
> @@ -947,7 +974,7 @@
> * This enables the runtime services to be called without having to
> * thunk back into physical mode for every invocation.
> */
> -void __init efi_enter_virtual_mode(void)
> +static void efi_enter_virtual_mode_generic(void)
> {
> efi_memory_desc_t *md, *prev_md = NULL;
> efi_status_t status;
> @@ -1080,7 +1107,7 @@
> /*
> * Convenience functions to obtain memory types and attributes
> */
> -u32 efi_mem_type(unsigned long phys_addr)
> +static u32 efi_mem_type_generic(unsigned long phys_addr)
> {
> efi_memory_desc_t *md;
> void *p;
> @@ -1098,7 +1125,7 @@
> return 0;
> }
>
> -u64 efi_mem_attributes(unsigned long phys_addr)
> +static u64 efi_mem_attributes_generic(unsigned long phys_addr)
> {
> efi_memory_desc_t *md;
> void *p;
> @@ -1113,6 +1140,68 @@
> return 0;
> }
>
> +void efi_init_function_register(const struct efi_init_funcs *funcs)
> +{
> + efi_override_funcs = funcs;
> +}
> +
> +void __init efi_init(void)
> +{
> + if (efi_override_funcs->init)
> + {
> + efi_override_funcs->init();
> + }
> + else
> + {
> + memmap.map = NULL; /* Xen case */
> + }
> +}
> +
> +void __init efi_late_init(void)
> +{
> + if (efi_override_funcs->late_init)
> + efi_override_funcs->late_init();
> +}
> +
> +void __init efi_reserve_boot_services(void)
> +{
> + if (efi_override_funcs->reserve_boot_services)
> + efi_override_funcs->reserve_boot_services();
> +}
> +
> +void __init efi_free_boot_services(void)
> +{
> + if (efi_override_funcs->free_boot_services)
> + efi_override_funcs->free_boot_services();
> +}
> +
> +void __init efi_enter_virtual_mode(void)
> +{
> + if (efi_override_funcs->enter_virtual_mode)
> + efi_override_funcs->enter_virtual_mode();
> +}
> +
> +int __init efi_memblock_x86_reserve_range(void)
> +{
> + if (efi_override_funcs->x86_reserve_range)
> + return efi_override_funcs->x86_reserve_range();
> + return 0;
> +}
> +
> +u32 efi_mem_type(unsigned long phys_addr)
> +{
> + if (efi_override_funcs->mem_type)
> + return efi_override_funcs->mem_type(phys_addr);
> + return EFI_INVALID_TYPE;
> +}
> +
> +u64 efi_mem_attributes(unsigned long phys_addr)
> +{
> + if (efi_override_funcs->mem_attributes)
> + return efi_override_funcs->mem_attributes(phys_addr);
> + return EFI_INVALID_ATTRIBUTE;
> +}
> +
> /*
> * Some firmware has serious problems when using more than 50% of the EFI
> * variable store, i.e. it triggers bugs that can brick machines. Ensure that
> diff -urN a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
> --- a/arch/x86/platform/efi/Makefile 2013-05-22 20:39:05.260000000 -0400
> +++ b/arch/x86/platform/efi/Makefile 2013-05-23 02:04:00.048000000 -0400
> @@ -1,2 +1,5 @@
> obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
> +ifdef CONFIG_XEN
> +obj-$(CONFIG_EFI) += xen.o
> +endif
> obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
> diff -urN a/arch/x86/platform/efi/xen.c b/arch/x86/platform/efi/xen.c
> --- a/arch/x86/platform/efi/xen.c 1969-12-31 19:00:00.000000000 -0500
> +++ b/arch/x86/platform/efi/xen.c 2013-05-23 02:28:22.340000000 -0400
> @@ -0,0 +1,428 @@
> +/*
> + * Xen EFI (Extensible Firmware Interface) support functions
> + * Based on related efforts in SLE and SUSE trees
> + *
> + * Copyright (C) 1999 VA Linux Systems
> + * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
> + * Copyright (C) 1999-2002 Hewlett-Packard Co.
> + * David Mosberger-Tang <davidm@hpl.hp.com>
> + * Stephane Eranian <eranian@hpl.hp.com>
> + * Copyright (C) 2005-2008 Intel Co.
> + * Fenghua Yu <fenghua.yu@intel.com>
> + * Bibo Mao <bibo.mao@intel.com>
> + * Chandramouli Narayanan <mouli@linux.intel.com>
> + * Huang Ying <ying.huang@intel.com>
> + * Copyright (C) 2011 Novell Co.
> + * Jan Beulic <JBeulich@suse.com>
> + * Copyright (C) 2011-2012 Oracle Co.
> + * Liang Tang <liang.tang@oracle.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/efi.h>
> +#include <linux/export.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/time.h>
> +
> +#include <asm/setup.h>
> +#include <asm/efi.h>
> +#include <asm/time.h>
> +#include <asm/cacheflush.h>
> +#include <asm/tlbflush.h>
> +#include <asm/x86_init.h>
> +
> +#include <xen/interface/platform.h>
> +#include <asm/xen/hypercall.h>
> +
> +#define PFX "EFI: "
> +
> +#define call (op.u.efi_runtime_call)
> +#define DECLARE_CALL(what) \
> + struct xen_platform_op op; \
> + op.cmd = XENPF_efi_runtime_call; \
> + call.function = XEN_EFI_##what; \
> + call.misc = 0
> +
> +static void register_xen_efi_function(void);
> +
> +static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
> +{
> + int err;
> + DECLARE_CALL(get_time);
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + if (tm) {
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_time.time));
> + memcpy(tm, &call.u.get_time.time, sizeof(*tm));
> + }
> +
> + if (tc) {
> + tc->resolution = call.u.get_time.resolution;
> + tc->accuracy = call.u.get_time.accuracy;
> + tc->sets_to_zero = !!(call.misc &
> + XEN_EFI_GET_TIME_SET_CLEARS_NS);
> + }
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_set_time(efi_time_t *tm)
> +{
> + DECLARE_CALL(set_time);
> +
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_time));
> + memcpy(&call.u.set_time, tm, sizeof(*tm));
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
> + efi_bool_t *pending,
> + efi_time_t *tm)
> +{
> + int err;
> + DECLARE_CALL(get_wakeup_time);
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + if (tm) {
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_wakeup_time));
> + memcpy(tm, &call.u.get_wakeup_time, sizeof(*tm));
> + }
> +
> + if (enabled)
> + *enabled = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
> +
> + if (pending)
> + *pending = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
> +{
> + DECLARE_CALL(set_wakeup_time);
> +
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_wakeup_time));
> + if (enabled)
> + call.misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
> + if (tm)
> + memcpy(&call.u.set_wakeup_time, tm, sizeof(*tm));
> + else
> + call.misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_get_variable(efi_char16_t *name,
> + efi_guid_t *vendor,
> + u32 *attr,
> + unsigned long *data_size,
> + void *data)
> +{
> + int err;
> + DECLARE_CALL(get_variable);
> +
> + set_xen_guest_handle(call.u.get_variable.name, name);
> + BUILD_BUG_ON(sizeof(*vendor) !=
> + sizeof(call.u.get_variable.vendor_guid));
> + memcpy(&call.u.get_variable.vendor_guid, vendor, sizeof(*vendor));
> + call.u.get_variable.size = *data_size;
> + set_xen_guest_handle(call.u.get_variable.data, data);
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *data_size = call.u.get_variable.size;
> + *attr = call.misc; /* misc in struction is U32 variable*/
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
> + efi_char16_t *name,
> + efi_guid_t *vendor)
> +{
> + int err;
> + DECLARE_CALL(get_next_variable_name);
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> + call.u.get_next_variable_name.size = *name_size;
> + set_xen_guest_handle(call.u.get_next_variable_name.name, name);
> + BUILD_BUG_ON(sizeof(*vendor) !=
> + sizeof(call.u.get_next_variable_name.vendor_guid));
> + memcpy(&call.u.get_next_variable_name.vendor_guid, vendor,
> + sizeof(*vendor));
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *name_size = call.u.get_next_variable_name.size;
> + memcpy(vendor, &call.u.get_next_variable_name.vendor_guid,
> + sizeof(*vendor));
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_set_variable(efi_char16_t *name,
> + efi_guid_t *vendor,
> + u32 attr,
> + unsigned long data_size,
> + void *data)
> +{
> + DECLARE_CALL(set_variable);
> +
> + set_xen_guest_handle(call.u.set_variable.name, name);
> + call.misc = attr;
> + BUILD_BUG_ON(sizeof(*vendor) !=
> + sizeof(call.u.set_variable.vendor_guid));
> + memcpy(&call.u.set_variable.vendor_guid, vendor, sizeof(*vendor));
> + call.u.set_variable.size = data_size;
> + set_xen_guest_handle(call.u.set_variable.data, data);
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_query_variable_info(u32 attr,
> + u64 *storage_space,
> + u64 *remaining_space,
> + u64 *max_variable_size)
> +{
> + int err;
> + DECLARE_CALL(query_variable_info);
> +
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *storage_space = call.u.query_variable_info.max_store_size;
> + *remaining_space = call.u.query_variable_info.remain_store_size;
> + *max_variable_size = call.u.query_variable_info.max_size;
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
> +{
> + int err;
> + DECLARE_CALL(get_next_high_monotonic_count);
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *count = call.misc;
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
> + unsigned long count,
> + unsigned long sg_list)
> +{
> + DECLARE_CALL(update_capsule);
> +
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> +
> + set_xen_guest_handle(call.u.update_capsule.capsule_header_array,
> + capsules);
> + call.u.update_capsule.capsule_count = count;
> + call.u.update_capsule.sg_list = sg_list;
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t **capsules,
> + unsigned long count,
> + u64 *max_size,
> + int *reset_type)
> +{
> + int err;
> + DECLARE_CALL(query_capsule_capabilities);
> +
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> +
> + set_xen_guest_handle(call.u.query_capsule_capabilities.
> + capsule_header_array, capsules);
> + call.u.query_capsule_capabilities.capsule_count = count;
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *max_size = call.u.query_capsule_capabilities.max_capsule_size;
> + *reset_type = call.u.query_capsule_capabilities.reset_type;
> +
> + return call.status;
> +}
> +
> +#undef DECLARE_CALL
> +#undef call
> +
> +static const struct efi __initconst efi_xen = {
> + .mps = EFI_INVALID_TABLE_ADDR,
> + .acpi = EFI_INVALID_TABLE_ADDR,
> + .acpi20 = EFI_INVALID_TABLE_ADDR,
> + .smbios = EFI_INVALID_TABLE_ADDR,
> + .sal_systab = EFI_INVALID_TABLE_ADDR,
> + .boot_info = EFI_INVALID_TABLE_ADDR,
> + .hcdp = EFI_INVALID_TABLE_ADDR,
> + .uga = EFI_INVALID_TABLE_ADDR,
> + .uv_systab = EFI_INVALID_TABLE_ADDR,
> + .get_time = xen_efi_get_time,
> + .set_time = xen_efi_set_time,
> + .get_wakeup_time = xen_efi_get_wakeup_time,
> + .set_wakeup_time = xen_efi_set_wakeup_time,
> + .get_variable = xen_efi_get_variable,
> + .get_next_variable = xen_efi_get_next_variable,
> + .set_variable = xen_efi_set_variable,
> + .get_next_high_mono_count = xen_efi_get_next_high_mono_count,
> + .query_variable_info = xen_efi_query_variable_info,
> + .update_capsule = xen_efi_update_capsule,
> + .query_capsule_caps = xen_efi_query_capsule_caps,
> +};
> +
> +void xen_efi_probe(void)
> +{
> + static struct xen_platform_op __initdata op = {
> + .cmd = XENPF_firmware_info,
> + .u.firmware_info = {
> + .type = XEN_FW_EFI_INFO,
> + .index = XEN_FW_EFI_CONFIG_TABLE
> + }
> + };
> +
> + if (HYPERVISOR_dom0_op(&op) == 0) {
> + /*efi_enabled = 1;*/
> + set_bit(EFI_BOOT, &x86_efi_facility);
> + /* this should be set based on whether the EFI loader
> + * signature contains "EL64" (see arch/x86/kernel/setup.c).
> + * Looks like a new hypercall will be needed for this */
> + set_bit(EFI_64BIT, &x86_efi_facility);
> +
> + register_xen_efi_function();
> + }
> +}
> +
> +
> +static void __init efi_init_xen(void)
> +{
> + efi_char16_t c16[100];
> + char vendor[ARRAY_SIZE(c16)] = "unknown";
> + int ret, i;
> + struct xen_platform_op op;
> + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +
> + efi = efi_xen;
> + op.cmd = XENPF_firmware_info;
> + op.u.firmware_info.type = XEN_FW_EFI_INFO;
> +
> + /*
> + * Show what we know for posterity
> + */
> + op.u.firmware_info.index = XEN_FW_EFI_VENDOR;
> + info->vendor.bufsz = sizeof(c16);
> + set_xen_guest_handle(info->vendor.name, c16);
> + ret = HYPERVISOR_dom0_op(&op);
> + if (!ret) {
> + for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
> + vendor[i] = c16[i];
> + vendor[i] = '\0';
> + } else
> + pr_err("Could not get the firmware vendor!\n");
> +
> + op.u.firmware_info.index = XEN_FW_EFI_VERSION;
> + ret = HYPERVISOR_dom0_op(&op);
> + if (!ret)
> + pr_info("EFI-xen v%u.%.02u by %s\n",
> + info->version >> 16,
> + info->version & 0xffff, vendor);
> + else
> + pr_err("Could not get EFI revision!\n");
> +
> + op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION;
> + ret = HYPERVISOR_dom0_op(&op);
> + if (!ret)
> + efi.runtime_version = info->version;
> + else
> + pr_warn(PFX "Could not get runtime services revision.\n");
> + set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
> +
> + /*
> + * Let's see what config tables the firmware passed to us.
> + */
> + op.u.firmware_info.index = XEN_FW_EFI_CONFIG_TABLE;
> + if (HYPERVISOR_dom0_op(&op))
> + BUG();
> +
> + if (efi_config_init(info->cfg.addr, info->cfg.nent, &efi))
> + panic("Could not init EFI Configuration Tables!\n");
> + set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
> +
> + /* the EFI memory info is digested by the hypervisor and
> + * supplied to dom0 via E820 entries */
> + set_bit(EFI_MEMMAP, &x86_efi_facility);
> +
> + set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); /* not checked */
> +
> + /* NOTE: efi.c only does this for CONFIG_X86_32 */
> + x86_platform.get_wallclock = efi_get_time;
> + x86_platform.set_wallclock = efi_set_rtc_mmss;
> +}
> +
> +/*
> + * Convenience functions to obtain memory types and attributes
> + */
> +static u32 efi_mem_type_xen(unsigned long phys_addr)
> +{
> + struct xen_platform_op op;
> + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +
> + op.cmd = XENPF_firmware_info;
> + op.u.firmware_info.type = XEN_FW_EFI_INFO;
> + op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
> + info->mem.addr = phys_addr;
> + info->mem.size = 0;
> + return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.type;
> +}
> +
> +static u64 efi_mem_attributes_xen(unsigned long phys_addr)
> +{
> + struct xen_platform_op op;
> + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +
> + op.cmd = XENPF_firmware_info;
> + op.u.firmware_info.type = XEN_FW_EFI_INFO;
> + op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
> + info->mem.addr = phys_addr;
> + info->mem.size = 0;
> + return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.attr;
> +}
> +
> +static const struct __initconst efi_init_funcs xen_efi_funcs = {
> + .init = efi_init_xen,
> + .late_init = NULL,
> + .reserve_boot_services = NULL,
> + .free_boot_services = NULL,
> + .enter_virtual_mode = NULL,
> + .mem_type = efi_mem_type_xen,
> + .mem_attributes = efi_mem_attributes_xen,
> + .x86_reserve_range = NULL
> +};
> +
> +static void register_xen_efi_function(void)
> +{
> + efi_init_function_register(&xen_efi_funcs);
> +}
> diff -urN a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
> --- a/arch/x86/xen/enlighten.c 2013-05-22 20:36:48.608000000 -0400
> +++ b/arch/x86/xen/enlighten.c 2013-05-22 20:44:15.784000000 -0400
> @@ -31,6 +31,7 @@
> #include <linux/pci.h>
> #include <linux/gfp.h>
> #include <linux/memblock.h>
> +#include <linux/efi.h>
>
> #include <xen/xen.h>
> #include <xen/events.h>
> @@ -1532,6 +1533,8 @@
>
> xen_setup_runstate_info(0);
>
> + if (xen_initial_domain())
> + xen_efi_probe();
> /* Start the world */
> #ifdef CONFIG_X86_32
> i386_start_kernel();
> diff -urN a/include/linux/efi.h b/include/linux/efi.h
> --- a/include/linux/efi.h 2013-05-22 20:36:14.820000000 -0400
> +++ b/include/linux/efi.h 2013-05-23 02:22:12.544000000 -0400
> @@ -84,7 +84,10 @@
> #define EFI_PAL_CODE 13
> #define EFI_MAX_MEMORY_TYPE 14
>
> +#define EFI_INVALID_TYPE 0xffffffff
> +
> /* Attribute values: */
> +#define EFI_INVALID_ATTRIBUTE ((u64)0x0000000000000000ULL) /* invalid
> attribute*/
> #define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
> #define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
> #define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
> @@ -554,6 +557,17 @@
> efi_set_virtual_address_map_t *set_virtual_address_map;
> } efi;
>
> +struct efi_init_funcs {
> + void (*init)(void);
> + void (*late_init)(void);
> + void (*reserve_boot_services)(void);
> + void (*free_boot_services)(void);
> + void (*enter_virtual_mode)(void);
> + u32 (*mem_type)(unsigned long phys_addr);
> + u64 (*mem_attributes)(unsigned long phys_addr);
> + int (*x86_reserve_range)(void);
> +};
> +
> static inline int
> efi_guidcmp (efi_guid_t left, efi_guid_t right)
> {
> @@ -591,13 +605,16 @@
> extern u32 efi_mem_type (unsigned long phys_addr);
> extern u64 efi_mem_attributes (unsigned long phys_addr);
> extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size);
> -extern int __init efi_uart_console_only (void);
> +extern int efi_uart_console_only (void);
> extern void efi_initialize_iomem_resources(struct resource *code_resource,
> struct resource *data_resource, struct resource *bss_resource);
> extern unsigned long efi_get_time(void);
> extern int efi_set_rtc_mmss(unsigned long nowtime);
> extern void efi_reserve_boot_services(void);
> extern struct efi_memory_map memmap;
> +extern void efi_init_function_register(const struct efi_init_funcs *funcs);
> +extern int efi_config_init(u64 tables, int nr_tables, struct efi *efi_t);
> +extern void xen_efi_probe(void);
>
> /**
> * efi_range_is_wc - check the WC bit on an address range
> @@ -621,7 +638,7 @@
> }
>
> #ifdef CONFIG_EFI_PCDP
> -extern int __init efi_setup_pcdp_console(char *);
> +extern int efi_setup_pcdp_console(char *);
> #endif
>
> /*
> diff -urN a/include/xen/interface/platform.h b/include/xen/interface/platform.h
> --- a/include/xen/interface/platform.h 2013-05-22 20:35:50.280000000 -0400
> +++ b/include/xen/interface/platform.h 2013-05-22 20:43:17.068000000 -0400
> @@ -108,10 +108,111 @@
> };
> DEFINE_GUEST_HANDLE_STRUCT(xenpf_platform_quirk_t);
>
> +#define XENPF_efi_runtime_call 49
> +#define XEN_EFI_get_time 1
> +#define XEN_EFI_set_time 2
> +#define XEN_EFI_get_wakeup_time 3
> +#define XEN_EFI_set_wakeup_time 4
> +#define XEN_EFI_get_next_high_monotonic_count 5
> +#define XEN_EFI_get_variable 6
> +#define XEN_EFI_set_variable 7
> +#define XEN_EFI_get_next_variable_name 8
> +#define XEN_EFI_query_variable_info 9
> +#define XEN_EFI_query_capsule_capabilities 10
> +#define XEN_EFI_update_capsule 11
> +
> +struct xenpf_efi_runtime_call {
> + uint32_t function;
> + /*
> + * This field is generally used for per sub-function flags (defined
> + * below), except for the XEN_EFI_get_next_high_monotonic_count case,
> + * where it holds the single returned value.
> + */
> + uint32_t misc;
> + unsigned long status;
> + union {
> +#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001
> + struct {
> + struct xenpf_efi_time {
> + uint16_t year;
> + uint8_t month;
> + uint8_t day;
> + uint8_t hour;
> + uint8_t min;
> + uint8_t sec;
> + uint32_t ns;
> + int16_t tz;
> + uint8_t daylight;
> + } time;
> + uint32_t resolution;
> + uint32_t accuracy;
> + } get_time;
> +
> + struct xenpf_efi_time set_time;
> +
> +#define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001
> +#define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002
> + struct xenpf_efi_time get_wakeup_time;
> +
> +#define XEN_EFI_SET_WAKEUP_TIME_ENABLE 0x00000001
> +#define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002
> + struct xenpf_efi_time set_wakeup_time;
> +
> +#define XEN_EFI_VARIABLE_NON_VOLATILE 0x00000001
> +#define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
> +#define XEN_EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
> + struct {
> + GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
> + unsigned long size;
> + GUEST_HANDLE(void) data;
> + struct xenpf_efi_guid {
> + uint32_t data1;
> + uint16_t data2;
> + uint16_t data3;
> + uint8_t data4[8];
> + } vendor_guid;
> + } get_variable, set_variable;
> +
> + struct {
> + unsigned long size;
> + GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
> + struct xenpf_efi_guid vendor_guid;
> + } get_next_variable_name;
> +
> + struct {
> + uint32_t attr;
> + uint64_t max_store_size;
> + uint64_t remain_store_size;
> + uint64_t max_size;
> + } query_variable_info;
> +
> + struct {
> + GUEST_HANDLE(void) capsule_header_array;
> + unsigned long capsule_count;
> + uint64_t max_capsule_size;
> + unsigned int reset_type;
> + } query_capsule_capabilities;
> +
> + struct {
> + GUEST_HANDLE(void) capsule_header_array;
> + unsigned long capsule_count;
> + uint64_t sg_list; /* machine address */
> + } update_capsule;
> + } u;
> +};
> +DEFINE_GUEST_HANDLE_STRUCT(xenpf_efi_runtime_call);
> +
> #define XENPF_firmware_info 50
> #define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */
> #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
> #define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */
> +#define XEN_FW_EFI_INFO 4 /* from EFI */
> +#define XEN_FW_EFI_VERSION 0
> +#define XEN_FW_EFI_CONFIG_TABLE 1
> +#define XEN_FW_EFI_VENDOR 2
> +#define XEN_FW_EFI_MEM_INFO 3
> +#define XEN_FW_EFI_RT_VERSION 4
> +#define XEN_FW_EFI_PCI_ROM 5
> #define XEN_FW_KBD_SHIFT_FLAGS 5 /* Int16, Fn02: Get keyboard
> shift flags. */
> struct xenpf_firmware_info {
> /* IN variables. */
> @@ -143,6 +244,36 @@
> /* must refer to 128-byte buffer */
> GUEST_HANDLE(uchar) edid;
> } vbeddc_info; /* XEN_FW_VBEDDC_INFO */
> + union xenpf_efi_info {
> + uint32_t version;
> + struct {
> + uint64_t addr; /* EFI_CONFIGURATION_TABLE */
> + uint32_t nent;
> + } cfg;
> + struct {
> + uint32_t revision;
> + uint32_t bufsz; /* input, in bytes */
> + GUEST_HANDLE(void) name;
> + /* UCS-2/UTF-16 string */
> + } vendor;
> + struct {
> + uint64_t addr;
> + uint64_t size;
> + uint64_t attr;
> + uint32_t type;
> + } mem;
> + struct {
> + /* IN variables */
> + uint16_t segment;
> + uint8_t bus;
> + uint8_t devfn;
> + uint16_t vendor;
> + uint16_t devid;
> + /* OUT variables */
> + uint64_t address;
> + xen_ulong_t size;
> + } pci_rom;
> + } efi_info; /* XEN_FW_EFI_INFO */
>
> uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */
> } u;
> @@ -361,6 +492,7 @@
> struct xenpf_read_memtype read_memtype;
> struct xenpf_microcode_update microcode;
> struct xenpf_platform_quirk platform_quirk;
> + struct xenpf_efi_runtime_call efi_runtime_call;
> struct xenpf_firmware_info firmware_info;
> struct xenpf_enter_acpi_sleep enter_acpi_sleep;
> struct xenpf_change_freq change_freq;
> diff -urN a/init/main.c b/init/main.c
> --- a/init/main.c 2013-05-22 20:35:17.768000000 -0400
> +++ b/init/main.c 2013-05-22 20:43:51.468000000 -0400
> @@ -634,10 +634,12 @@
> acpi_early_init(); /* before LAPIC and SMP init */
> sfi_init_late();
>
> +#ifdef CONFIG_X86
> if (efi_enabled(EFI_RUNTIME_SERVICES)) {
> efi_late_init();
> efi_free_boot_services();
> }
> +#endif
>
> ftrace_init();
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
prev parent reply other threads:[~2013-05-24 14:24 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-23 10:04 [REBASE] xen: patches (against Linux kernel) for supporting efi Eric Shelton
2013-05-23 10:19 ` Jan Beulich
2013-05-23 11:05 ` Eric Shelton
2013-05-23 11:18 ` Jan Beulich
2013-05-23 14:11 ` Eric Shelton
2013-05-23 14:45 ` Jan Beulich
2013-05-24 14:24 ` Konrad Rzeszutek Wilk [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130524142413.GH3900@phenom.dumpdata.com \
--to=konrad.wilk@oracle.com \
--cc=daniel.kiper@oracle.com \
--cc=eshelton@pobox.com \
--cc=jbeulich@suse.com \
--cc=liang.tang@oracle.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).