From patchwork Wed Sep 10 00:51:52 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roy Franz X-Patchwork-Id: 37172 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ig0-f199.google.com (mail-ig0-f199.google.com [209.85.213.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 123DB20C93 for ; Wed, 10 Sep 2014 00:54:35 +0000 (UTC) Received: by mail-ig0-f199.google.com with SMTP id l13sf4834412iga.6 for ; Tue, 09 Sep 2014 17:54:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:cc:subject:precedence:list-id:list-unsubscribe:list-post :list-help:list-subscribe:mime-version:sender:errors-to :x-original-sender:x-original-authentication-results:mailing-list :list-archive:content-type:content-transfer-encoding; bh=hDY2JDIpBzQPiwpLRNnCJ/jVT3QxC1rA5yu7ywf/Tf0=; b=RfEuw0Z8VEApOr6VArILbzaAo+tZUfYkjNAZEuUTNE7EmkXMP3BVoRskUFSaL+aYqx w3ZRhQMNIjRBByBjWknxyNCuIf5P5jHznE8mWYXBw/4qWA/wni7daf1cRxf2KoxwpHR4 356BTFiuLNOxS0KrVAUG4k96C3XXnk44A6rUi+3A1vEdOWCI6EwEXJBypGmmlR3ytqkp j6BVHubxtb2KzfJi8zjt89BizvO/jS14kOVOiTd24LFzRrqZ0RmUu7nmyltJRGCfkq8s Q3M4IqgVth09IUZN/GWWHM1N2wOFImGFC29L7eRpIszPQpn7p1TBuFJclvu0znI4JuJF 2srA== X-Gm-Message-State: ALoCoQkRH7xSD9UBuF9xUd5gy7Q/nAjRMZa3pCeANDp+gl5nVhKNPS/7L3Qp8ZQPX6sgaT0gIebx X-Received: by 10.182.199.4 with SMTP id jg4mr23982155obc.43.1410310474665; Tue, 09 Sep 2014 17:54:34 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.82.228 with SMTP id h91ls811839qgd.77.gmail; Tue, 09 Sep 2014 17:54:34 -0700 (PDT) X-Received: by 10.220.168.74 with SMTP id t10mr14242598vcy.35.1410310474572; Tue, 09 Sep 2014 17:54:34 -0700 (PDT) Received: from mail-vc0-f169.google.com (mail-vc0-f169.google.com [209.85.220.169]) by mx.google.com with ESMTPS id m9si5815434vcl.104.2014.09.09.17.54.34 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 09 Sep 2014 17:54:34 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.169 as permitted sender) client-ip=209.85.220.169; Received: by mail-vc0-f169.google.com with SMTP id ik5so1347233vcb.14 for ; Tue, 09 Sep 2014 17:54:34 -0700 (PDT) X-Received: by 10.52.36.176 with SMTP id r16mr3227882vdj.70.1410310474460; Tue, 09 Sep 2014 17:54:34 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp363887vcb; Tue, 9 Sep 2014 17:54:33 -0700 (PDT) X-Received: by 10.140.32.36 with SMTP id g33mr18004691qgg.13.1410310472875; Tue, 09 Sep 2014 17:54:32 -0700 (PDT) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id e1si17153426qag.113.2014.09.09.17.54.32 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 09 Sep 2014 17:54:32 -0700 (PDT) Received-SPF: none (google.com: xen-devel-bounces@lists.xen.org does not designate permitted sender hosts) client-ip=50.57.142.19; Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1XRW91-0006BT-Gd; Wed, 10 Sep 2014 00:52:23 +0000 Received: from mail6.bemta4.messagelabs.com ([85.158.143.247]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1XRW8z-0006BD-Nd for xen-devel@lists.xen.org; Wed, 10 Sep 2014 00:52:22 +0000 Received: from [85.158.143.35:63803] by server-2.bemta-4.messagelabs.com id 9A/C5-04525-5C0AF045; Wed, 10 Sep 2014 00:52:21 +0000 X-Env-Sender: roy.franz@linaro.org X-Msg-Ref: server-13.tower-21.messagelabs.com!1410310337!5455560!1 X-Originating-IP: [209.85.223.173] X-SpamReason: No, hits=0.0 required=7.0 tests= X-StarScan-Received: X-StarScan-Version: 6.11.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 3944 invoked from network); 10 Sep 2014 00:52:19 -0000 Received: from mail-ie0-f173.google.com (HELO mail-ie0-f173.google.com) (209.85.223.173) by server-13.tower-21.messagelabs.com with RC4-SHA encrypted SMTP; 10 Sep 2014 00:52:19 -0000 Received: by mail-ie0-f173.google.com with SMTP id x19so2581608ier.4 for ; Tue, 09 Sep 2014 17:52:17 -0700 (PDT) X-Received: by 10.50.6.68 with SMTP id y4mr35636614igy.47.1410310337474; Tue, 09 Sep 2014 17:52:17 -0700 (PDT) Received: from rfranz-v430.caveonetworks.com (64.2.3.195.ptr.us.xo.net. [64.2.3.195]) by mx.google.com with ESMTPSA id dx10sm654825igb.4.2014.09.09.17.52.16 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Sep 2014 17:52:16 -0700 (PDT) From: Roy Franz To: xen-devel@lists.xen.org, ian.campbell@citrix.com, stefano.stabellini@citrix.com, tim@xen.org, jbeulich@suse.com, keir@xen.org Date: Tue, 9 Sep 2014 17:51:52 -0700 Message-Id: <1410310325-4509-3-git-send-email-roy.franz@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1410310325-4509-1-git-send-email-roy.franz@linaro.org> References: <1410310325-4509-1-git-send-email-roy.franz@linaro.org> Cc: Roy Franz , fu.wei@linaro.org Subject: [Xen-devel] [PATCH V4 02/15] Move x86 specific funtions/variables to arch header X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: List-Unsubscribe: , List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: roy.franz@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.169 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Archive: Move the global variables and functions that can be moved as-is from the common boot.c file to the x86 implementation header file. Signed-off-by: Roy Franz --- xen/common/efi/boot.c | 460 ++--------------------------------------- xen/include/asm-x86/efi-boot.h | 451 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 464 insertions(+), 447 deletions(-) create mode 100644 xen/include/asm-x86/efi-boot.h diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 14e2f46..ca604be 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -18,16 +18,6 @@ #include #include #include -#include -#include -#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */ -#include -#undef __ASSEMBLY__ -#include -#include - -/* Using SetVirtualAddressMap() is incompatible with kexec: */ -#undef USE_SET_VIRTUAL_ADDRESS_MAP #define SHIM_LOCK_PROTOCOL_GUID \ { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} } @@ -41,8 +31,10 @@ typedef struct { EFI_SHIM_LOCK_VERIFY Verify; } EFI_SHIM_LOCK_PROTOCOL; -extern char start[]; -extern u32 cpuid_ext_features; +static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer); +static CHAR16 *__init FormatHex(UINT64 Val, UINTN Width, CHAR16 *Buffer); +static void __init DisplayUint(UINT64 Val, INTN Width); +static CHAR16 *__init wstrcpy(CHAR16 *d, const CHAR16 *s); union string { CHAR16 *w; @@ -69,19 +61,18 @@ static UINT32 __initdata mdesc_ver; static struct file __initdata cfg; static struct file __initdata kernel; static struct file __initdata ramdisk; -static struct file __initdata ucode; static struct file __initdata xsm; - -static multiboot_info_t __initdata mbi = { - .flags = MBI_MODULES | MBI_LOADERNAME -}; -static module_t __initdata mb_modules[3]; - static CHAR16 __initdata newline[] = L"\r\n"; #define PrintStr(s) StdOut->OutputString(StdOut, s) #define PrintErr(s) StdErr->OutputString(StdErr, s) +/* + * Include architecture specific implementation here, which references the + * static globals defined above. + */ +#include + static CHAR16 *__init FormatDec(UINT64 Val, CHAR16 *Buffer) { if ( Val >= 10 ) @@ -255,32 +246,6 @@ static void __init PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode) blexit(mesg); } -static void __init place_string(u32 *addr, const char *s) -{ - static char *__initdata alloc = start; - - if ( s && *s ) - { - size_t len1 = strlen(s) + 1; - const char *old = (char *)(long)*addr; - size_t len2 = *addr ? strlen(old) + 1 : 0; - - alloc -= len1 + len2; - /* - * Insert new string before already existing one. This is needed - * for options passed on the command line to override options from - * the configuration file. - */ - memcpy(alloc, s, len1); - if ( *addr ) - { - alloc[len1 - 1] = ' '; - memcpy(alloc + len1, old, len2); - } - } - *addr = (long)alloc; -} - static unsigned int __init get_argv(unsigned int argc, CHAR16 **argv, CHAR16 *cmdline, UINTN cmdsize) { @@ -574,104 +539,6 @@ static void __init split_value(char *s) *s = 0; } -static void __init edd_put_string(u8 *dst, size_t n, const char *src) -{ - while ( n-- && *src ) - *dst++ = *src++; - if ( *src ) - PrintErrMesg(L"Internal error populating EDD info", - EFI_BUFFER_TOO_SMALL); - while ( n-- ) - *dst++ = ' '; -} -#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s) - -static void __init setup_efi_pci(void) -{ - EFI_STATUS status; - EFI_HANDLE *handles; - static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL; - UINTN i, nr_pci, size = 0; - struct efi_pci_rom *last = NULL; - - status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL); - if ( status == EFI_BUFFER_TOO_SMALL ) - status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles); - if ( !EFI_ERROR(status) ) - status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, - handles); - if ( EFI_ERROR(status) ) - size = 0; - - nr_pci = size / sizeof(*handles); - for ( i = 0; i < nr_pci; ++i ) - { - EFI_PCI_IO *pci = NULL; - u64 attributes; - struct efi_pci_rom *rom, *va; - UINTN segment, bus, device, function; - - status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci); - if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize ) - continue; - - status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0, - &attributes); - if ( EFI_ERROR(status) || - !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) || - EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device, - &function)) ) - continue; - - DisplayUint(segment, 4); - PrintStr(L":"); - DisplayUint(bus, 2); - PrintStr(L":"); - DisplayUint(device, 2); - PrintStr(L"."); - DisplayUint(function, 1); - PrintStr(L": ROM: "); - DisplayUint(pci->RomSize, 0); - PrintStr(L" bytes at "); - DisplayUint((UINTN)pci->RomImage, 0); - PrintStr(newline); - - size = pci->RomSize + sizeof(*rom); - status = efi_bs->AllocatePool(EfiRuntimeServicesData, size, - (void **)&rom); - if ( EFI_ERROR(status) ) - continue; - - rom->next = NULL; - rom->size = pci->RomSize; - - status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1, - &rom->vendor); - if ( !EFI_ERROR(status) ) - status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1, - &rom->devid); - if ( EFI_ERROR(status) ) - { - efi_bs->FreePool(rom); - continue; - } - - rom->segment = segment; - rom->bus = bus; - rom->devfn = (device << 3) | function; - memcpy(rom->data, pci->RomImage, pci->RomSize); - - va = (void *)rom + DIRECTMAP_VIRT_START; - if ( last ) - last->next = va; - else - efi_pci_roms = va; - last = rom; - } - - efi_bs->FreePool(handles); -} - static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz) { if ( bpp < 0 ) @@ -687,82 +554,6 @@ static int __init set_color(u32 mask, int bpp, u8 *pos, u8 *sz) return max(*pos + *sz, bpp); } -extern const intpte_t __page_tables_start[], __page_tables_end[]; -#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \ - (intpte_t *)(v) < __page_tables_end) - -#define PE_BASE_RELOC_ABS 0 -#define PE_BASE_RELOC_HIGHLOW 3 -#define PE_BASE_RELOC_DIR64 10 - -extern const struct pe_base_relocs { - u32 rva; - u32 size; - u16 entries[]; -} __base_relocs_start[], __base_relocs_end[]; - -static void __init relocate_image(unsigned long delta) -{ - const struct pe_base_relocs *base_relocs; - - for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; ) - { - unsigned int i, n; - - n = (base_relocs->size - sizeof(*base_relocs)) / - sizeof(*base_relocs->entries); - for ( i = 0; i < n; ++i ) - { - unsigned long addr = xen_phys_start + base_relocs->rva + - (base_relocs->entries[i] & 0xfff); - - switch ( base_relocs->entries[i] >> 12 ) - { - case PE_BASE_RELOC_ABS: - break; - case PE_BASE_RELOC_HIGHLOW: - if ( delta ) - { - *(u32 *)addr += delta; - if ( in_page_tables(addr) ) - *(u32 *)addr += xen_phys_start; - } - break; - case PE_BASE_RELOC_DIR64: - if ( delta ) - { - *(u64 *)addr += delta; - if ( in_page_tables(addr) ) - *(intpte_t *)addr += xen_phys_start; - } - break; - default: - blexit(L"Unsupported relocation type"); - } - } - base_relocs = (const void *)(base_relocs->entries + i + (i & 1)); - } -} - -extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[]; -extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[]; - -static void __init relocate_trampoline(unsigned long phys) -{ - const s32 *trampoline_ptr; - - trampoline_phys = phys; - /* Apply relocations to trampoline. */ - for ( trampoline_ptr = __trampoline_rel_start; - trampoline_ptr < __trampoline_rel_stop; - ++trampoline_ptr ) - *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys; - for ( trampoline_ptr = __trampoline_seg_start; - trampoline_ptr < __trampoline_seg_stop; - ++trampoline_ptr ) - *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4; -} - void EFIAPI __init noreturn efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { @@ -879,7 +670,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) PrintStr(L"Xen " __stringify(XEN_VERSION) "." __stringify(XEN_SUBVERSION) XEN_EXTRAVERSION " (c/s " XEN_CHANGESET ") EFI loader\r\n"); - relocate_image(0); + efi_arch_relocate_image(0); if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode, &cols, &rows) == EFI_SUCCESS ) @@ -1258,7 +1049,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) dmi_efi_get_table((void *)(long)efi.smbios); /* Collect PCI ROM contents. */ - setup_efi_pci(); + efi_arch_pci(); /* Get snapshot of variable store parameters. */ status = (efi_rs->Hdr.Revision >> 16) >= 2 ? @@ -1460,7 +1251,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START; efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START; - relocate_image(__XEN_VIRT_START - xen_phys_start); + efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start); memcpy((void *)trampoline_phys, trampoline_start, cfg.size); /* Set system registers and transfer control. */ @@ -1496,228 +1287,3 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) for( ; ; ); /* not reached */ } -#ifndef USE_SET_VIRTUAL_ADDRESS_MAP -static __init void copy_mapping(unsigned long mfn, unsigned long end, - bool_t (*is_valid)(unsigned long smfn, - unsigned long emfn)) -{ - unsigned long next; - - for ( ; mfn < end; mfn = next ) - { - l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)]; - l3_pgentry_t *l3src, *l3dst; - unsigned long va = (unsigned long)mfn_to_virt(mfn); - - next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT)); - if ( !is_valid(mfn, min(next, end)) ) - continue; - if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) - { - l3dst = alloc_xen_pagetable(); - BUG_ON(!l3dst); - clear_page(l3dst); - efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] = - l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR); - } - else - l3dst = l4e_to_l3e(l4e); - l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]); - l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)]; - } -} - -static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn) -{ - unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1; - - return !(smfn & pfn_hole_mask) && - find_next_bit(pdx_group_valid, sz, - pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz; -} - -static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn) -{ - return 1; -} -#endif - -#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \ - (EFI_PAGE_SHIFT + BITS_PER_LONG - 32)) - -void __init efi_init_memory(void) -{ - unsigned int i; -#ifndef USE_SET_VIRTUAL_ADDRESS_MAP - struct rt_extra { - struct rt_extra *next; - unsigned long smfn, emfn; - unsigned int prot; - } *extra, *extra_head = NULL; -#endif - - printk(XENLOG_INFO "EFI memory map:\n"); - for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) - { - EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; - u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; - unsigned long smfn, emfn; - unsigned int prot = PAGE_HYPERVISOR; - - printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64 - " type=%u attr=%016" PRIx64 "\n", - desc->PhysicalStart, desc->PhysicalStart + len - 1, - desc->Type, desc->Attribute); - - if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) ) - continue; - - desc->VirtualStart = INVALID_VIRTUAL_ADDRESS; - - smfn = PFN_DOWN(desc->PhysicalStart); - emfn = PFN_UP(desc->PhysicalStart + len); - - if ( desc->Attribute & EFI_MEMORY_WB ) - /* nothing */; - else if ( desc->Attribute & EFI_MEMORY_WT ) - prot |= _PAGE_PWT | MAP_SMALL_PAGES; - else if ( desc->Attribute & EFI_MEMORY_WC ) - prot |= _PAGE_PAT | MAP_SMALL_PAGES; - else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) ) - prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES; - else - { - printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n", - smfn, emfn - 1); - continue; - } - - if ( desc->Attribute & EFI_MEMORY_WP ) - prot &= _PAGE_RW; - if ( desc->Attribute & EFI_MEMORY_XP ) - prot |= _PAGE_NX_BIT; - - if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) && - !(smfn & pfn_hole_mask) && - !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) ) - { - if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END ) - prot &= ~_PAGE_GLOBAL; - if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn), - smfn, emfn - smfn, prot) == 0 ) - desc->VirtualStart = - (unsigned long)maddr_to_virt(desc->PhysicalStart); - else - printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n", - smfn, emfn - 1); - } -#ifndef USE_SET_VIRTUAL_ADDRESS_MAP - else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) && - (extra = xmalloc(struct rt_extra)) != NULL ) - { - extra->smfn = smfn; - extra->emfn = emfn; - extra->prot = prot & ~_PAGE_GLOBAL; - extra->next = extra_head; - extra_head = extra; - desc->VirtualStart = desc->PhysicalStart; - } -#endif - else - { -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP - /* XXX allocate e.g. down from FIXADDR_START */ -#endif - printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n", - smfn, emfn - 1); - } - } - -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP - efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size, - mdesc_ver, efi_memmap); -#else - /* Set up 1:1 page tables to do runtime calls in "physical" mode. */ - efi_l4_pgtable = alloc_xen_pagetable(); - BUG_ON(!efi_l4_pgtable); - clear_page(efi_l4_pgtable); - - copy_mapping(0, max_page, ram_range_valid); - - /* Insert non-RAM runtime mappings inside the direct map. */ - for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) - { - const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; - - if ( (desc->Attribute & EFI_MEMORY_RUNTIME) && - desc->VirtualStart != INVALID_VIRTUAL_ADDRESS && - desc->VirtualStart != desc->PhysicalStart ) - copy_mapping(PFN_DOWN(desc->PhysicalStart), - PFN_UP(desc->PhysicalStart + - (desc->NumberOfPages << EFI_PAGE_SHIFT)), - rt_range_valid); - } - - /* Insert non-RAM runtime mappings outside of the direct map. */ - while ( (extra = extra_head) != NULL ) - { - unsigned long addr = extra->smfn << PAGE_SHIFT; - l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)]; - l3_pgentry_t *pl3e; - l2_pgentry_t *pl2e; - l1_pgentry_t *l1t; - - if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) - { - pl3e = alloc_xen_pagetable(); - BUG_ON(!pl3e); - clear_page(pl3e); - efi_l4_pgtable[l4_table_offset(addr)] = - l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR); - } - else - pl3e = l4e_to_l3e(l4e); - pl3e += l3_table_offset(addr); - if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) ) - { - pl2e = alloc_xen_pagetable(); - BUG_ON(!pl2e); - clear_page(pl2e); - *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR); - } - else - { - BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE); - pl2e = l3e_to_l2e(*pl3e); - } - pl2e += l2_table_offset(addr); - if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) ) - { - l1t = alloc_xen_pagetable(); - BUG_ON(!l1t); - clear_page(l1t); - *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR); - } - else - { - BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE); - l1t = l2e_to_l1e(*pl2e); - } - for ( i = l1_table_offset(addr); - i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn; - ++i, ++extra->smfn ) - l1t[i] = l1e_from_pfn(extra->smfn, extra->prot); - - if ( extra->smfn == extra->emfn ) - { - extra_head = extra->next; - xfree(extra); - } - } - - /* Insert Xen mappings. */ - for ( i = l4_table_offset(HYPERVISOR_VIRT_START); - i < l4_table_offset(DIRECTMAP_VIRT_END); ++i ) - efi_l4_pgtable[i] = idle_pg_table[i]; -#endif -} diff --git a/xen/include/asm-x86/efi-boot.h b/xen/include/asm-x86/efi-boot.h new file mode 100644 index 0000000..4ad83ca --- /dev/null +++ b/xen/include/asm-x86/efi-boot.h @@ -0,0 +1,451 @@ +/* + * Architecture specific implementation for EFI boot code. This file + * is intended to be included by XXX _only_, and therefore can define + * arch specific global variables. + */ +#include +#include +#define __ASSEMBLY__ /* avoid pulling in ACPI stuff (conflicts with EFI) */ +#include +#undef __ASSEMBLY__ +#include +#include + +static struct file __initdata ucode; +static multiboot_info_t __initdata mbi = { + .flags = MBI_MODULES | MBI_LOADERNAME +}; +static module_t __initdata mb_modules[3]; + +static void noreturn blexit(const CHAR16 *str); +static void PrintErrMesg(const CHAR16 *mesg, EFI_STATUS ErrCode); + +/* Using SetVirtualAddressMap() is incompatible with kexec: */ +#undef USE_SET_VIRTUAL_ADDRESS_MAP +extern char start[]; +extern u32 cpuid_ext_features; + +static void __init edd_put_string(u8 *dst, size_t n, const char *src) +{ + while ( n-- && *src ) + *dst++ = *src++; + if ( *src ) + PrintErrMesg(L"Internal error populating EDD info", + EFI_BUFFER_TOO_SMALL); + while ( n-- ) + *dst++ = ' '; +} +#define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s) + +static void __init efi_arch_pci(void) +{ + EFI_STATUS status; + EFI_HANDLE *handles; + static EFI_GUID __initdata pci_guid = EFI_PCI_IO_PROTOCOL; + UINTN i, nr_pci, size = 0; + struct efi_pci_rom *last = NULL; + + status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, NULL); + if ( status == EFI_BUFFER_TOO_SMALL ) + status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles); + if ( !EFI_ERROR(status) ) + status = efi_bs->LocateHandle(ByProtocol, &pci_guid, NULL, &size, + handles); + if ( EFI_ERROR(status) ) + size = 0; + + nr_pci = size / sizeof(*handles); + for ( i = 0; i < nr_pci; ++i ) + { + EFI_PCI_IO *pci = NULL; + u64 attributes; + struct efi_pci_rom *rom, *va; + UINTN segment, bus, device, function; + + status = efi_bs->HandleProtocol(handles[i], &pci_guid, (void **)&pci); + if ( EFI_ERROR(status) || !pci || !pci->RomImage || !pci->RomSize ) + continue; + + status = pci->Attributes(pci, EfiPciIoAttributeOperationGet, 0, + &attributes); + if ( EFI_ERROR(status) || + !(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) || + EFI_ERROR(pci->GetLocation(pci, &segment, &bus, &device, + &function)) ) + continue; + + DisplayUint(segment, 4); + PrintStr(L":"); + DisplayUint(bus, 2); + PrintStr(L":"); + DisplayUint(device, 2); + PrintStr(L"."); + DisplayUint(function, 1); + PrintStr(L": ROM: "); + DisplayUint(pci->RomSize, 0); + PrintStr(L" bytes at "); + DisplayUint((UINTN)pci->RomImage, 0); + PrintStr(newline); + + size = pci->RomSize + sizeof(*rom); + status = efi_bs->AllocatePool(EfiRuntimeServicesData, size, + (void **)&rom); + if ( EFI_ERROR(status) ) + continue; + + rom->next = NULL; + rom->size = pci->RomSize; + + status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_VENDOR_ID, 1, + &rom->vendor); + if ( !EFI_ERROR(status) ) + status = pci->Pci.Read(pci, EfiPciIoWidthUint16, PCI_DEVICE_ID, 1, + &rom->devid); + if ( EFI_ERROR(status) ) + { + efi_bs->FreePool(rom); + continue; + } + + rom->segment = segment; + rom->bus = bus; + rom->devfn = (device << 3) | function; + memcpy(rom->data, pci->RomImage, pci->RomSize); + + va = (void *)rom + DIRECTMAP_VIRT_START; + if ( last ) + last->next = va; + else + efi_pci_roms = va; + last = rom; + } + + efi_bs->FreePool(handles); +} + +extern const intpte_t __page_tables_start[], __page_tables_end[]; +#define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \ + (intpte_t *)(v) < __page_tables_end) + +#define PE_BASE_RELOC_ABS 0 +#define PE_BASE_RELOC_HIGHLOW 3 +#define PE_BASE_RELOC_DIR64 10 + +extern const struct pe_base_relocs { + u32 rva; + u32 size; + u16 entries[]; +} __base_relocs_start[], __base_relocs_end[]; + +static void __init efi_arch_relocate_image(unsigned long delta) +{ + const struct pe_base_relocs *base_relocs; + + for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; ) + { + unsigned int i, n; + + n = (base_relocs->size - sizeof(*base_relocs)) / + sizeof(*base_relocs->entries); + for ( i = 0; i < n; ++i ) + { + unsigned long addr = xen_phys_start + base_relocs->rva + + (base_relocs->entries[i] & 0xfff); + + switch ( base_relocs->entries[i] >> 12 ) + { + case PE_BASE_RELOC_ABS: + break; + case PE_BASE_RELOC_HIGHLOW: + if ( delta ) + { + *(u32 *)addr += delta; + if ( in_page_tables(addr) ) + *(u32 *)addr += xen_phys_start; + } + break; + case PE_BASE_RELOC_DIR64: + if ( delta ) + { + *(u64 *)addr += delta; + if ( in_page_tables(addr) ) + *(intpte_t *)addr += xen_phys_start; + } + break; + default: + blexit(L"Unsupported relocation type"); + } + } + base_relocs = (const void *)(base_relocs->entries + i + (i & 1)); + } +} + +extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[]; +extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[]; + +static void __init relocate_trampoline(unsigned long phys) +{ + const s32 *trampoline_ptr; + + trampoline_phys = phys; + /* Apply relocations to trampoline. */ + for ( trampoline_ptr = __trampoline_rel_start; + trampoline_ptr < __trampoline_rel_stop; + ++trampoline_ptr ) + *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys; + for ( trampoline_ptr = __trampoline_seg_start; + trampoline_ptr < __trampoline_seg_stop; + ++trampoline_ptr ) + *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4; +} + +#ifndef USE_SET_VIRTUAL_ADDRESS_MAP +static __init void copy_mapping(unsigned long mfn, unsigned long end, + bool_t (*is_valid)(unsigned long smfn, + unsigned long emfn)) +{ + unsigned long next; + + for ( ; mfn < end; mfn = next ) + { + l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)]; + l3_pgentry_t *l3src, *l3dst; + unsigned long va = (unsigned long)mfn_to_virt(mfn); + + next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT)); + if ( !is_valid(mfn, min(next, end)) ) + continue; + if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) + { + l3dst = alloc_xen_pagetable(); + BUG_ON(!l3dst); + clear_page(l3dst); + efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] = + l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR); + } + else + l3dst = l4e_to_l3e(l4e); + l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]); + l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)]; + } +} + +static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn) +{ + unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1; + + return !(smfn & pfn_hole_mask) && + find_next_bit(pdx_group_valid, sz, + pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz; +} + +static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn) +{ + return 1; +} +#endif + +#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \ + (EFI_PAGE_SHIFT + BITS_PER_LONG - 32)) +void __init efi_init_memory(void) +{ + unsigned int i; +#ifndef USE_SET_VIRTUAL_ADDRESS_MAP + struct rt_extra { + struct rt_extra *next; + unsigned long smfn, emfn; + unsigned int prot; + } *extra, *extra_head = NULL; +#endif + + printk(XENLOG_INFO "EFI memory map:\n"); + for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) + { + EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; + u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT; + unsigned long smfn, emfn; + unsigned int prot = PAGE_HYPERVISOR; + + printk(XENLOG_INFO " %013" PRIx64 "-%013" PRIx64 + " type=%u attr=%016" PRIx64 "\n", + desc->PhysicalStart, desc->PhysicalStart + len - 1, + desc->Type, desc->Attribute); + + if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) ) + continue; + + desc->VirtualStart = INVALID_VIRTUAL_ADDRESS; + + smfn = PFN_DOWN(desc->PhysicalStart); + emfn = PFN_UP(desc->PhysicalStart + len); + + if ( desc->Attribute & EFI_MEMORY_WB ) + /* nothing */; + else if ( desc->Attribute & EFI_MEMORY_WT ) + prot |= _PAGE_PWT | MAP_SMALL_PAGES; + else if ( desc->Attribute & EFI_MEMORY_WC ) + prot |= _PAGE_PAT | MAP_SMALL_PAGES; + else if ( desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE) ) + prot |= _PAGE_PWT | _PAGE_PCD | MAP_SMALL_PAGES; + else + { + printk(XENLOG_ERR "Unknown cachability for MFNs %#lx-%#lx\n", + smfn, emfn - 1); + continue; + } + + if ( desc->Attribute & EFI_MEMORY_WP ) + prot &= _PAGE_RW; + if ( desc->Attribute & EFI_MEMORY_XP ) + prot |= _PAGE_NX_BIT; + + if ( pfn_to_pdx(emfn - 1) < (DIRECTMAP_SIZE >> PAGE_SHIFT) && + !(smfn & pfn_hole_mask) && + !((smfn ^ (emfn - 1)) & ~pfn_pdx_bottom_mask) ) + { + if ( (unsigned long)mfn_to_virt(emfn - 1) >= HYPERVISOR_VIRT_END ) + prot &= ~_PAGE_GLOBAL; + if ( map_pages_to_xen((unsigned long)mfn_to_virt(smfn), + smfn, emfn - smfn, prot) == 0 ) + desc->VirtualStart = + (unsigned long)maddr_to_virt(desc->PhysicalStart); + else + printk(XENLOG_ERR "Could not map MFNs %#lx-%#lx\n", + smfn, emfn - 1); + } +#ifndef USE_SET_VIRTUAL_ADDRESS_MAP + else if ( !((desc->PhysicalStart + len - 1) >> (VADDR_BITS - 1)) && + (extra = xmalloc(struct rt_extra)) != NULL ) + { + extra->smfn = smfn; + extra->emfn = emfn; + extra->prot = prot & ~_PAGE_GLOBAL; + extra->next = extra_head; + extra_head = extra; + desc->VirtualStart = desc->PhysicalStart; + } +#endif + else + { +#ifdef USE_SET_VIRTUAL_ADDRESS_MAP + /* XXX allocate e.g. down from FIXADDR_START */ +#endif + printk(XENLOG_ERR "No mapping for MFNs %#lx-%#lx\n", + smfn, emfn - 1); + } + } + +#ifdef USE_SET_VIRTUAL_ADDRESS_MAP + efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size, + mdesc_ver, efi_memmap); +#else + /* Set up 1:1 page tables to do runtime calls in "physical" mode. */ + efi_l4_pgtable = alloc_xen_pagetable(); + BUG_ON(!efi_l4_pgtable); + clear_page(efi_l4_pgtable); + + copy_mapping(0, max_page, ram_range_valid); + + /* Insert non-RAM runtime mappings inside the direct map. */ + for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size ) + { + const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i; + + if ( (desc->Attribute & EFI_MEMORY_RUNTIME) && + desc->VirtualStart != INVALID_VIRTUAL_ADDRESS && + desc->VirtualStart != desc->PhysicalStart ) + copy_mapping(PFN_DOWN(desc->PhysicalStart), + PFN_UP(desc->PhysicalStart + + (desc->NumberOfPages << EFI_PAGE_SHIFT)), + rt_range_valid); + } + + /* Insert non-RAM runtime mappings outside of the direct map. */ + while ( (extra = extra_head) != NULL ) + { + unsigned long addr = extra->smfn << PAGE_SHIFT; + l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(addr)]; + l3_pgentry_t *pl3e; + l2_pgentry_t *pl2e; + l1_pgentry_t *l1t; + + if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) + { + pl3e = alloc_xen_pagetable(); + BUG_ON(!pl3e); + clear_page(pl3e); + efi_l4_pgtable[l4_table_offset(addr)] = + l4e_from_paddr(virt_to_maddr(pl3e), __PAGE_HYPERVISOR); + } + else + pl3e = l4e_to_l3e(l4e); + pl3e += l3_table_offset(addr); + if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) ) + { + pl2e = alloc_xen_pagetable(); + BUG_ON(!pl2e); + clear_page(pl2e); + *pl3e = l3e_from_paddr(virt_to_maddr(pl2e), __PAGE_HYPERVISOR); + } + else + { + BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE); + pl2e = l3e_to_l2e(*pl3e); + } + pl2e += l2_table_offset(addr); + if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) ) + { + l1t = alloc_xen_pagetable(); + BUG_ON(!l1t); + clear_page(l1t); + *pl2e = l2e_from_paddr(virt_to_maddr(l1t), __PAGE_HYPERVISOR); + } + else + { + BUG_ON(l2e_get_flags(*pl2e) & _PAGE_PSE); + l1t = l2e_to_l1e(*pl2e); + } + for ( i = l1_table_offset(addr); + i < L1_PAGETABLE_ENTRIES && extra->smfn < extra->emfn; + ++i, ++extra->smfn ) + l1t[i] = l1e_from_pfn(extra->smfn, extra->prot); + + if ( extra->smfn == extra->emfn ) + { + extra_head = extra->next; + xfree(extra); + } + } + + /* Insert Xen mappings. */ + for ( i = l4_table_offset(HYPERVISOR_VIRT_START); + i < l4_table_offset(DIRECTMAP_VIRT_END); ++i ) + efi_l4_pgtable[i] = idle_pg_table[i]; +#endif +} + +static void __init place_string(u32 *addr, const char *s) +{ + static char *__initdata alloc = start; + + if ( s && *s ) + { + size_t len1 = strlen(s) + 1; + const char *old = (char *)(long)*addr; + size_t len2 = *addr ? strlen(old) + 1 : 0; + + alloc -= len1 + len2; + /* + * Insert new string before already existing one. This is needed + * for options passed on the command line to override options from + * the configuration file. + */ + memcpy(alloc, s, len1); + if ( *addr ) + { + alloc[len1 - 1] = ' '; + memcpy(alloc + len1, old, len2); + } + } + *addr = (long)alloc; +}