From bd69b8704190e95b2ba16a0a943f4cb806d656ef Mon Sep 17 00:00:00 2001 From: liuyun Date: Tue, 13 Sep 2022 10:23:28 +0800 Subject: [PATCH] LoongArch: add kernel setvirtmap for runtime LoongArch inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I5OHOB -------------------------------- Signed-off-by: liuyun Change-Id: I6bca1ca0a6881ef497c97ed86aeb2fd5e6088157 --- arch/loongarch/kernel/efi.c | 99 +++++++++++++++++++ .../firmware/efi/libstub/efi-stub-helper.c | 2 +- drivers/firmware/efi/libstub/loongarch-stub.c | 5 +- 3 files changed, 101 insertions(+), 5 deletions(-) diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c index 1f1f755fb425..07e485105f98 100644 --- a/arch/loongarch/kernel/efi.c +++ b/arch/loongarch/kernel/efi.c @@ -22,6 +22,7 @@ #include #include +#include #include static unsigned long efi_nr_tables; @@ -30,8 +31,99 @@ static unsigned long efi_config_table; static efi_system_table_t *efi_systab; static efi_config_table_type_t arch_tables[] __initdata = {{},}; +static void __init create_tlb(u32 index, u64 vppn, u32 ps, u32 mat) +{ + unsigned long tlblo0, tlblo1; + + write_csr_pagesize(ps); + + tlblo0 = vppn | CSR_TLBLO0_V | CSR_TLBLO0_WE | + CSR_TLBLO0_GLOBAL | (mat << CSR_TLBLO0_CCA_SHIFT); + tlblo1 = tlblo0 + (1 << ps); + + csr_write64(vppn, LOONGARCH_CSR_TLBEHI); + csr_write64(tlblo0, LOONGARCH_CSR_TLBELO0); + csr_write64(tlblo1, LOONGARCH_CSR_TLBELO1); + csr_xchg32(0, CSR_TLBIDX_EHINV, LOONGARCH_CSR_TLBIDX); + csr_xchg32(index, CSR_TLBIDX_IDX, LOONGARCH_CSR_TLBIDX); + + tlb_write_indexed(); +} + +#define MTLB_ENTRY_INDEX 0x800 + +/* Create VA == PA mapping as UEFI */ +static void __init fix_efi_mapping(void) +{ + unsigned int index = MTLB_ENTRY_INDEX; + unsigned int tlbnr = boot_cpu_data.tlbsizemtlb - 2; + unsigned long i, vppn; + + /* Low Memory, Cached */ + create_tlb(index++, 0x00000000, PS_128M, 1); + /* MMIO Registers, Uncached */ + create_tlb(index++, 0x10000000, PS_128M, 0); + + /* High Memory, Cached */ + for (i = 0; i < tlbnr; i++) { + vppn = 0x80000000ULL + (i * SZ_2G); + create_tlb(index++, vppn, PS_1G, 1); + } +} + +/* + * set_virtual_map() - create a virtual mapping for the EFI memory map and call + * efi_set_virtual_address_map enter virtual for runtime service + * + * This function populates the virt_addr fields of all memory region descriptors + * in @memory_map whose EFI_MEMORY_RUNTIME attribute is set. Those descriptors + * are also copied to @runtime_map, and their total count is returned in @count. + */ +static int __init set_virtual_map(void) +{ + efi_status_t status; + int count = 0; + unsigned int size; + unsigned long attr; + efi_runtime_services_t *rt; + efi_set_virtual_address_map_t *svam; + efi_memory_desc_t *in, runtime_map[32]; + + size = sizeof(efi_memory_desc_t); + + for_each_efi_memory_desc(in) { + attr = in->attribute; + if (!(attr & EFI_MEMORY_RUNTIME)) + continue; + + if (attr & (EFI_MEMORY_WB | EFI_MEMORY_WT)) + in->virt_addr = TO_CACHE(in->phys_addr); + else + in->virt_addr = TO_UNCACHE(in->phys_addr); + + memcpy(&runtime_map[count++], in, size); + } + + rt = early_memremap_ro((unsigned long)efi_systab->runtime, sizeof(*rt)); + + /* Install the new virtual address map */ + svam = rt->set_virtual_address_map; + + fix_efi_mapping(); + + status = svam(size * count, size, efi.memmap.desc_version, + (efi_memory_desc_t *)TO_PHYS((unsigned long)runtime_map)); + + local_flush_tlb_all(); + write_csr_pagesize(PS_DEFAULT_SIZE); + + return 0; +} + void __init efi_runtime_init(void) { + efi_status_t status; + if (!efi_enabled(EFI_BOOT)) return; @@ -40,6 +132,13 @@ void __init efi_runtime_init(void) return; } + if (!efi_systab->runtime) + return; + + status = set_virtual_map(); + if (status < 0) + return; + efi.runtime = (efi_runtime_services_t *)efi_systab->runtime; efi.runtime_version = (unsigned int)efi.runtime->hdr.revision; diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 0e0033fa7d51..537db49c31b9 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -22,7 +22,7 @@ bool efi_nochunk; bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE); bool efi_noinitrd; int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT; -bool efi_novamap; +bool efi_novamap = IS_ENABLED(CONFIG_LOONGARCH); /* LoongArch call svam() in kernel */; static bool efi_nosoftreserve; static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA); diff --git a/drivers/firmware/efi/libstub/loongarch-stub.c b/drivers/firmware/efi/libstub/loongarch-stub.c index 9e71a27bac92..1eb848a556f9 100644 --- a/drivers/firmware/efi/libstub/loongarch-stub.c +++ b/drivers/firmware/efi/libstub/loongarch-stub.c @@ -52,8 +52,5 @@ void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt, un real_kernel_entry = (kernel_entry_t) ((unsigned long)&kernel_entry - entrypoint + VMLINUX_LOAD_ADDRESS); - if (!efi_novamap) - real_kernel_entry(true, fdt); - else - real_kernel_entry(false, fdt); + real_kernel_entry(true, fdt); } -- GitLab