Skip to content

Commit

Permalink
efi: Introduce EFI_PARAVIRT flag
Browse files Browse the repository at this point in the history
Introduce EFI_PARAVIRT flag. If it is set then kernel runs
on EFI platform but it has not direct control on EFI stuff
like EFI runtime, tables, structures, etc. If not this means
that Linux Kernel has direct access to EFI infrastructure
and everything runs as usual.

This functionality is used in Xen dom0 because hypervisor
has full control on EFI stuff and all calls from dom0 to
EFI must be requested via special hypercall which in turn
executes relevant EFI code in behalf of dom0.

Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
  • Loading branch information
Daniel Kiper authored and Matt Fleming committed Jul 18, 2014
1 parent 67a9b9c commit 9f27bc5
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 16 deletions.
31 changes: 25 additions & 6 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down
21 changes: 12 additions & 9 deletions drivers/firmware/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
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;
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;
}

return mode;
return attr->mode;
}

static struct attribute_group efi_subsys_attr_group = {
Expand Down
3 changes: 2 additions & 1 deletion include/linux/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
/*
Expand Down

0 comments on commit 9f27bc5

Please sign in to comment.