diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 7d627a02ed82..d9026538cfdb 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -210,6 +210,9 @@ int __init efi_memblock_x86_reserve_range(void) struct efi_info *e = &boot_params.efi_info; unsigned long pmap; + if (efi_enabled(EFI_PARAVIRT)) + return 0; + #ifdef CONFIG_X86_32 /* Can't handle data above 4GB at this time */ if (e->efi_memmap_hi) { @@ -422,14 +425,24 @@ static int __init efi_runtime_init(void) * the runtime services table so that we can grab the physical * address of several of the EFI runtime functions, needed to * set the firmware into virtual mode. + * + * When EFI_PARAVIRT is in force then we could not map runtime + * service memory region because we do not have direct access to it. + * However, runtime services are available through proxy functions + * (e.g. in case of Xen dom0 EFI implementation they call special + * hypercall which executes relevant EFI functions) and that is why + * they are always enabled. */ - if (efi_enabled(EFI_64BIT)) - rv = efi_runtime_init64(); - else - rv = efi_runtime_init32(); - if (rv) - return rv; + if (!efi_enabled(EFI_PARAVIRT)) { + if (efi_enabled(EFI_64BIT)) + rv = efi_runtime_init64(); + else + rv = efi_runtime_init32(); + + if (rv) + return rv; + } set_bit(EFI_RUNTIME_SERVICES, &efi.flags); @@ -438,6 +451,9 @@ static int __init efi_runtime_init(void) static int __init efi_memmap_init(void) { + if (efi_enabled(EFI_PARAVIRT)) + return 0; + /* Map the EFI memory map */ memmap.map = early_memremap((unsigned long)memmap.phys_map, memmap.nr_map * memmap.desc_size); @@ -914,6 +930,9 @@ static void __init __efi_enter_virtual_mode(void) void __init efi_enter_virtual_mode(void) { + if (efi_enabled(EFI_PARAVIRT)) + return; + if (efi_setup) kexec_enter_virtual_mode(); else diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 023937a63a48..ac88ec05eb70 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -104,16 +104,19 @@ static struct attribute *efi_subsys_attrs[] = { static umode_t efi_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { - umode_t mode = attr->mode; + if (attr == &efi_attr_fw_vendor.attr) { + if (efi_enabled(EFI_PARAVIRT) || + efi.fw_vendor == EFI_INVALID_TABLE_ADDR) + return 0; + } else if (attr == &efi_attr_runtime.attr) { + if (efi.runtime == EFI_INVALID_TABLE_ADDR) + return 0; + } else if (attr == &efi_attr_config_table.attr) { + if (efi.config_table == EFI_INVALID_TABLE_ADDR) + return 0; + } - if (attr == &efi_attr_fw_vendor.attr) - return (efi.fw_vendor == EFI_INVALID_TABLE_ADDR) ? 0 : mode; - else if (attr == &efi_attr_runtime.attr) - return (efi.runtime == EFI_INVALID_TABLE_ADDR) ? 0 : mode; - else if (attr == &efi_attr_config_table.attr) - return (efi.config_table == EFI_INVALID_TABLE_ADDR) ? 0 : mode; - - return mode; + return attr->mode; } static struct attribute_group efi_subsys_attr_group = { diff --git a/include/linux/efi.h b/include/linux/efi.h index bac0f93dc473..c7a29a26e900 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -922,7 +922,8 @@ extern int __init efi_setup_pcdp_console(char *); #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ #define EFI_MEMMAP 4 /* Can we use EFI memory map? */ #define EFI_64BIT 5 /* Is the firmware 64-bit? */ -#define EFI_ARCH_1 6 /* First arch-specific bit */ +#define EFI_PARAVIRT 6 /* Access is via a paravirt interface */ +#define EFI_ARCH_1 7 /* First arch-specific bit */ #ifdef CONFIG_EFI /*