Skip to content

Commit

Permalink
Merge branch 'core-efi-for-linus' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/tip/tip

Pull EFI changes from Ingo Molnar:
 "The main changes in this cycle were:

   - further EFI code generalization to make it more workable for ARM64
   - various extensions, such as 64-bit framebuffer address support,
     UEFI v2.5 EFI_PROPERTIES_TABLE support
   - code modularization simplifications and cleanups
   - new debugging parameters
   - various fixes and smaller additions"

* 'core-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
  efi: Fix warning of int-to-pointer-cast on x86 32-bit builds
  efi: Use correct type for struct efi_memory_map::phys_map
  x86/efi: Fix kernel panic when CONFIG_DEBUG_VIRTUAL is enabled
  efi: Add "efi_fake_mem" boot option
  x86/efi: Rename print_efi_memmap() to efi_print_memmap()
  efi: Auto-load the efi-pstore module
  efi: Introduce EFI_NX_PE_DATA bit and set it from properties table
  efi: Add support for UEFIv2.5 Properties table
  efi: Add EFI_MEMORY_MORE_RELIABLE support to efi_md_typeattr_format()
  efifb: Add support for 64-bit frame buffer addresses
  efi/arm64: Clean up efi_get_fdt_params() interface
  arm64: Use core efi=debug instead of uefi_debug command line parameter
  efi/x86: Move efi=debug option parsing to core
  drivers/firmware: Make efi/esrt.c driver explicitly non-modular
  efi: Use the generic efi.memmap instead of 'memmap'
  acpi/apei: Use appropriate pgprot_t to map GHES memory
  arm64, acpi/apei: Implement arch_apei_get_mem_attributes()
  arm64/mm: Add PROT_DEVICE_nGnRnE and PROT_NORMAL_WT
  acpi, x86: Implement arch_apei_get_mem_attributes()
  efi, x86: Rearrange efi_mem_attributes()
  ...
  • Loading branch information
torvalds committed Nov 3, 2015
2 parents 7eeef2a + 78b9bc9 commit f5a8160
Show file tree
Hide file tree
Showing 26 changed files with 532 additions and 105 deletions.
2 changes: 0 additions & 2 deletions Documentation/arm/uefi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,3 @@ linux,uefi-mmap-desc-ver | 32-bit | Version of the mmap descriptor format.
--------------------------------------------------------------------------------
linux,uefi-stub-kern-ver | string | Copy of linux_banner from build.
--------------------------------------------------------------------------------

For verbose debug messages, specify 'uefi_debug' on the kernel command line.
15 changes: 15 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,21 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
you are really sure that your UEFI does sane gc and
fulfills the spec otherwise your board may brick.

efi_fake_mem= nn[KMG]@ss[KMG]:aa[,nn[KMG]@ss[KMG]:aa,..] [EFI; X86]
Add arbitrary attribute to specific memory range by
updating original EFI memory map.
Region of memory which aa attribute is added to is
from ss to ss+nn.
If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000
is specified, EFI_MEMORY_MORE_RELIABLE(0x10000)
attribute is added to range 0x100000000-0x180000000 and
0x10a0000000-0x1120000000.

Using this parameter you can do debugging of EFI memmap
related feature. For example, you can do debugging of
Address Range Mirroring feature even if your box
doesn't support it.

eisa_irq_edge= [PARISC,HW]
See header of drivers/parisc/eisa.c.

Expand Down
5 changes: 5 additions & 0 deletions arch/arm64/include/asm/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,9 @@ static inline const char *acpi_get_enable_method(int cpu)
{
return acpi_psci_present() ? "psci" : NULL;
}

#ifdef CONFIG_ACPI_APEI
pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
#endif

#endif /*_ASM_ACPI_H*/
1 change: 1 addition & 0 deletions arch/arm64/include/asm/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
#define MT_DEVICE_GRE 2
#define MT_NORMAL_NC 3
#define MT_NORMAL 4
#define MT_NORMAL_WT 5

/*
* Memory types for Stage-2 translation
Expand Down
2 changes: 2 additions & 0 deletions arch/arm64/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)

#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC))
#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_WT))
#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL))

#define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
Expand Down
29 changes: 29 additions & 0 deletions arch/arm64/kernel/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
#include <asm/cpu_ops.h>
#include <asm/smp_plat.h>

#ifdef CONFIG_ACPI_APEI
# include <linux/efi.h>
# include <asm/pgtable.h>
#endif

int acpi_noirq = 1; /* skip ACPI IRQ initialization */
int acpi_disabled = 1;
EXPORT_SYMBOL(acpi_disabled);
Expand Down Expand Up @@ -230,3 +235,27 @@ void __init acpi_gic_init(void)

early_acpi_os_unmap_memory((char *)table, tbl_size);
}

#ifdef CONFIG_ACPI_APEI
pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
{
/*
* According to "Table 8 Map: EFI memory types to AArch64 memory
* types" of UEFI 2.5 section 2.3.6.1, each EFI memory type is
* mapped to a corresponding MAIR attribute encoding.
* The EFI memory attribute advises all possible capabilities
* of a memory region. We use the most efficient capability.
*/

u64 attr;

attr = efi_mem_attributes(addr);
if (attr & EFI_MEMORY_WB)
return PAGE_KERNEL;
if (attr & EFI_MEMORY_WT)
return __pgprot(PROT_NORMAL_WT);
if (attr & EFI_MEMORY_WC)
return __pgprot(PROT_NORMAL_NC);
return __pgprot(PROT_DEVICE_nGnRnE);
}
#endif
23 changes: 7 additions & 16 deletions arch/arm64/kernel/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,6 @@ static struct mm_struct efi_mm = {
INIT_MM_CONTEXT(efi_mm)
};

static int uefi_debug __initdata;
static int __init uefi_debug_setup(char *str)
{
uefi_debug = 1;

return 0;
}
early_param("uefi_debug", uefi_debug_setup);

static int __init is_normal_ram(efi_memory_desc_t *md)
{
if (md->attribute & EFI_MEMORY_WB)
Expand Down Expand Up @@ -171,14 +162,14 @@ static __init void reserve_regions(void)
efi_memory_desc_t *md;
u64 paddr, npages, size;

if (uefi_debug)
if (efi_enabled(EFI_DBG))
pr_info("Processing EFI memory map:\n");

for_each_efi_memory_desc(&memmap, md) {
paddr = md->phys_addr;
npages = md->num_pages;

if (uefi_debug) {
if (efi_enabled(EFI_DBG)) {
char buf[64];

pr_info(" 0x%012llx-0x%012llx %s",
Expand All @@ -194,11 +185,11 @@ static __init void reserve_regions(void)

if (is_reserve_region(md)) {
memblock_reserve(paddr, size);
if (uefi_debug)
if (efi_enabled(EFI_DBG))
pr_cont("*");
}

if (uefi_debug)
if (efi_enabled(EFI_DBG))
pr_cont("\n");
}

Expand All @@ -210,14 +201,14 @@ void __init efi_init(void)
struct efi_fdt_params params;

/* Grab UEFI information placed in FDT by stub */
if (!efi_get_fdt_params(&params, uefi_debug))
if (!efi_get_fdt_params(&params))
return;

efi_system_table = params.system_table;

memblock_reserve(params.mmap & PAGE_MASK,
PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
memmap.phys_map = (void *)params.mmap;
memmap.phys_map = params.mmap;
memmap.map = early_memremap(params.mmap, params.mmap_size);
memmap.map_end = memmap.map + params.mmap_size;
memmap.desc_size = params.desc_size;
Expand Down Expand Up @@ -291,7 +282,7 @@ static int __init arm64_enable_runtime_services(void)
pr_info("Remapping and enabling EFI services.\n");

mapsize = memmap.map_end - memmap.map;
memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
mapsize);
if (!memmap.map) {
pr_err("Failed to remap EFI memory map\n");
Expand Down
4 changes: 3 additions & 1 deletion arch/arm64/mm/proc.S
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,14 @@ ENTRY(__cpu_setup)
* DEVICE_GRE 010 00001100
* NORMAL_NC 011 01000100
* NORMAL 100 11111111
* NORMAL_WT 101 10111011
*/
ldr x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \
MAIR(0x04, MT_DEVICE_nGnRE) | \
MAIR(0x0c, MT_DEVICE_GRE) | \
MAIR(0x44, MT_NORMAL_NC) | \
MAIR(0xff, MT_NORMAL)
MAIR(0xff, MT_NORMAL) | \
MAIR(0xbb, MT_NORMAL_WT)
msr mair_el1, x5
/*
* Prepare SCTLR
Expand Down
28 changes: 22 additions & 6 deletions arch/x86/boot/compressed/eboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
static efi_status_t
__gop_query32(struct efi_graphics_output_protocol_32 *gop32,
struct efi_graphics_output_mode_info **info,
unsigned long *size, u32 *fb_base)
unsigned long *size, u64 *fb_base)
{
struct efi_graphics_output_protocol_mode_32 *mode;
efi_status_t status;
Expand All @@ -650,7 +650,8 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
unsigned long nr_gops;
u16 width, height;
u32 pixels_per_scan_line;
u32 fb_base;
u32 ext_lfb_base;
u64 fb_base;
struct efi_pixel_bitmask pixel_info;
int pixel_format;
efi_status_t status;
Expand All @@ -667,7 +668,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
bool conout_found = false;
void *dummy = NULL;
u32 h = handles[i];
u32 current_fb_base;
u64 current_fb_base;

status = efi_call_early(handle_protocol, h,
proto, (void **)&gop32);
Expand Down Expand Up @@ -715,6 +716,13 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
si->lfb_width = width;
si->lfb_height = height;
si->lfb_base = fb_base;

ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
if (ext_lfb_base) {
si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
si->ext_lfb_base = ext_lfb_base;
}

si->pages = 1;

setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
Expand All @@ -729,7 +737,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
static efi_status_t
__gop_query64(struct efi_graphics_output_protocol_64 *gop64,
struct efi_graphics_output_mode_info **info,
unsigned long *size, u32 *fb_base)
unsigned long *size, u64 *fb_base)
{
struct efi_graphics_output_protocol_mode_64 *mode;
efi_status_t status;
Expand All @@ -755,7 +763,8 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
unsigned long nr_gops;
u16 width, height;
u32 pixels_per_scan_line;
u32 fb_base;
u32 ext_lfb_base;
u64 fb_base;
struct efi_pixel_bitmask pixel_info;
int pixel_format;
efi_status_t status;
Expand All @@ -772,7 +781,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
bool conout_found = false;
void *dummy = NULL;
u64 h = handles[i];
u32 current_fb_base;
u64 current_fb_base;

status = efi_call_early(handle_protocol, h,
proto, (void **)&gop64);
Expand Down Expand Up @@ -820,6 +829,13 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
si->lfb_width = width;
si->lfb_height = height;
si->lfb_base = fb_base;

ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
if (ext_lfb_base) {
si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
si->ext_lfb_base = ext_lfb_base;
}

si->pages = 1;

setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/boot/header.S
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ extra_header_fields:
#else
.quad 0 # ImageBase
#endif
.long CONFIG_PHYSICAL_ALIGN # SectionAlignment
.long 0x20 # SectionAlignment
.long 0x20 # FileAlignment
.word 0 # MajorOperatingSystemVersion
.word 0 # MinorOperatingSystemVersion
Expand Down
23 changes: 23 additions & 0 deletions arch/x86/include/asm/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include <asm/mpspec.h>
#include <asm/realmode.h>

#ifdef CONFIG_ACPI_APEI
# include <asm/pgtable_types.h>
#endif

#ifdef CONFIG_ACPI
extern int acpi_lapic;
extern int acpi_ioapic;
Expand Down Expand Up @@ -147,4 +151,23 @@ extern int x86_acpi_numa_init(void);

#define acpi_unlazy_tlb(x) leave_mm(x)

#ifdef CONFIG_ACPI_APEI
static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
{
/*
* We currently have no way to look up the EFI memory map
* attributes for a region in a consistent way, because the
* memmap is discarded after efi_free_boot_services(). So if
* you call efi_mem_attributes() during boot and at runtime,
* you could theoretically see different attributes.
*
* Since we are yet to see any x86 platforms that require
* anything other than PAGE_KERNEL (some arm64 platforms
* require the equivalent of PAGE_KERNEL_NOCACHE), return that
* until we know differently.
*/
return PAGE_KERNEL;
}
#endif

#endif /* _ASM_X86_ACPI_H */
1 change: 1 addition & 0 deletions arch/x86/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
extern int __init efi_memblock_x86_reserve_range(void);
extern pgd_t * __init efi_call_phys_prolog(void);
extern void __init efi_call_phys_epilog(pgd_t *save_pgd);
extern void __init efi_print_memmap(void);
extern void __init efi_unmap_memmap(void);
extern void __init efi_memory_uc(u64 addr, unsigned long size);
extern void __init efi_map_region(efi_memory_desc_t *md);
Expand Down
4 changes: 3 additions & 1 deletion arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1079,8 +1079,10 @@ void __init setup_arch(char **cmdline_p)
memblock_set_current_limit(ISA_END_ADDRESS);
memblock_x86_fill();

if (efi_enabled(EFI_BOOT))
if (efi_enabled(EFI_BOOT)) {
efi_fake_memmap();
efi_find_mirror();
}

/*
* The EFI specification says that boot service code won't be called
Expand Down
9 changes: 6 additions & 3 deletions arch/x86/mm/pageattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -647,9 +647,12 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc)
set_pte(&pbase[i], pfn_pte(pfn, canon_pgprot(ref_prot)));

if (pfn_range_is_mapped(PFN_DOWN(__pa(address)),
PFN_DOWN(__pa(address)) + 1))
split_page_count(level);
if (virt_addr_valid(address)) {
unsigned long pfn = PFN_DOWN(__pa(address));

if (pfn_range_is_mapped(pfn, pfn + 1))
split_page_count(level);
}

/*
* Install the new, split up pagetable.
Expand Down
9 changes: 7 additions & 2 deletions arch/x86/platform/efi/efi-bgrt.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,16 @@ void __init efi_bgrt_init(void)
bgrt_tab->version);
return;
}
if (bgrt_tab->status != 1) {
pr_err("Ignoring BGRT: invalid status %u (expected 1)\n",
if (bgrt_tab->status & 0xfe) {
pr_err("Ignoring BGRT: reserved status bits are non-zero %u\n",
bgrt_tab->status);
return;
}
if (bgrt_tab->status != 1) {
pr_debug("Ignoring BGRT: invalid status %u (expected 1)\n",
bgrt_tab->status);
return;
}
if (bgrt_tab->image_type != 0) {
pr_err("Ignoring BGRT: invalid image type %u (expected 0)\n",
bgrt_tab->image_type);
Expand Down
Loading

0 comments on commit f5a8160

Please sign in to comment.