提交 bd69b870 编写于 作者: L liuyun 提交者: Hongchen Zhang

LoongArch: add kernel setvirtmap for runtime

LoongArch inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5OHOB

--------------------------------
Signed-off-by: Nliuyun <liuyun@loongson.cn>
Change-Id: I6bca1ca0a6881ef497c97ed86aeb2fd5e6088157
上级 eac918de
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <asm/early_ioremap.h> #include <asm/early_ioremap.h>
#include <asm/efi.h> #include <asm/efi.h>
#include <asm/tlb.h>
#include <asm/loongson.h> #include <asm/loongson.h>
static unsigned long efi_nr_tables; static unsigned long efi_nr_tables;
...@@ -30,8 +31,99 @@ static unsigned long efi_config_table; ...@@ -30,8 +31,99 @@ static unsigned long efi_config_table;
static efi_system_table_t *efi_systab; static efi_system_table_t *efi_systab;
static efi_config_table_type_t arch_tables[] __initdata = {{},}; 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) void __init efi_runtime_init(void)
{ {
efi_status_t status;
if (!efi_enabled(EFI_BOOT)) if (!efi_enabled(EFI_BOOT))
return; return;
...@@ -40,6 +132,13 @@ void __init efi_runtime_init(void) ...@@ -40,6 +132,13 @@ void __init efi_runtime_init(void)
return; 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 = (efi_runtime_services_t *)efi_systab->runtime;
efi.runtime_version = (unsigned int)efi.runtime->hdr.revision; efi.runtime_version = (unsigned int)efi.runtime->hdr.revision;
......
...@@ -22,7 +22,7 @@ bool efi_nochunk; ...@@ -22,7 +22,7 @@ bool efi_nochunk;
bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE); bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);
bool efi_noinitrd; bool efi_noinitrd;
int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT; 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_nosoftreserve;
static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA); static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
......
...@@ -52,8 +52,5 @@ void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt, un ...@@ -52,8 +52,5 @@ void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt, un
real_kernel_entry = (kernel_entry_t) real_kernel_entry = (kernel_entry_t)
((unsigned long)&kernel_entry - entrypoint + VMLINUX_LOAD_ADDRESS); ((unsigned long)&kernel_entry - entrypoint + VMLINUX_LOAD_ADDRESS);
if (!efi_novamap)
real_kernel_entry(true, fdt); real_kernel_entry(true, fdt);
else
real_kernel_entry(false, fdt);
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册