X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/32b9a6d76790c73d3d2d36d9081a2581cc65d184..28c176b668c841a3b7fb093faccf0efa39257603:/lunaix-os/arch/x86/boot/i386/kremap32.c?ds=sidebyside diff --git a/lunaix-os/arch/x86/boot/i386/kremap32.c b/lunaix-os/arch/x86/boot/i386/kremap32.c new file mode 100644 index 0000000..c73c2a3 --- /dev/null +++ b/lunaix-os/arch/x86/boot/i386/kremap32.c @@ -0,0 +1,111 @@ +#define __BOOT_CODE__ + +#include +#include + +#include +#include + +bridge_farsym(__kexec_start); +bridge_farsym(__kexec_end); +bridge_farsym(__kexec_text_start); +bridge_farsym(__kexec_text_end); + +// define the initial page table layout +struct kernel_map; + +static struct kernel_map kernel_pt __section(".kpg"); +export_symbol(debug, boot, kernel_pt); + +struct kernel_map { + pte_t l0t[_PAGE_LEVEL_SIZE]; + pte_t pg_mnt[_PAGE_LEVEL_SIZE]; + + struct { + pte_t _lft[_PAGE_LEVEL_SIZE]; + } kernel_lfts[16]; +} align(4); + +static void boot_text +do_remap() +{ + struct kernel_map* kpt_pa = (struct kernel_map*)to_kphysical(&kernel_pt); + + size_t mia_casa_i = pfn_at(KERNEL_RESIDENT, L0T_SIZE); + pte_t* klptep = (pte_t*) &kpt_pa->l0t[mia_casa_i]; + pte_t* ktep = (pte_t*) kpt_pa->kernel_lfts; + pte_t* boot_l0tep = (pte_t*) kpt_pa; + + set_pte(boot_l0tep, pte_mkhuge(mkpte_prot(KERNEL_DATA))); + + // --- 将内核重映射至高半区 --- + + // Hook the kernel reserved LFTs onto L0T + pte_t pte = mkpte((ptr_t)ktep, KERNEL_DATA); + + for (u32_t i = 0; i < KEXEC_RSVD; i++) { + pte = pte_setpaddr(pte, (ptr_t)&kpt_pa->kernel_lfts[i]); + set_pte(klptep, pte); + + klptep++; + } + + // Ensure the size of kernel is within the reservation + pfn_t kimg_pagecount = + pfn(__far(__kexec_end) - __far(__kexec_start)); + if (kimg_pagecount > KEXEC_RSVD * _PAGE_LEVEL_SIZE) { + // ERROR: require more pages + // here should do something else other than head into blocking + asm("ud2"); + } + + // Now, map the kernel + + pfn_t kimg_end = pfn(to_kphysical(__far(__kexec_end))); + pfn_t i = pfn(to_kphysical(__far(__kexec_text_start))); + ktep += i; + + // kernel .text + pte = pte_setprot(pte, KERNEL_EXEC); + pfn_t ktext_end = pfn(to_kphysical(__far(__kexec_text_end))); + for (; i < ktext_end; i++) { + pte = pte_setpaddr(pte, page_addr(i)); + set_pte(ktep, pte); + + ktep++; + } + + // all remaining kernel sections + pte = pte_setprot(pte, KERNEL_DATA); + for (; i < kimg_end; i++) { + pte = pte_setpaddr(pte, page_addr(i)); + set_pte(ktep, pte); + + ktep++; + } + + // XXX: Mapping the kernel .rodata section? + + // set mount point + pte_t* kmntep = (pte_t*) &kpt_pa->l0t[pfn_at(PG_MOUNT_1, L0T_SIZE)]; + set_pte(kmntep, mkpte((ptr_t)kpt_pa->pg_mnt, KERNEL_DATA)); + + // Build up self-reference + int level = (VMS_SELF / L0T_SIZE) & _PAGE_LEVEL_MASK; + + pte = mkpte_root((ptr_t)kpt_pa, KERNEL_DATA); + set_pte(&boot_l0tep[level], pte); +} + +ptr_t boot_text +remap_kernel() +{ + ptr_t kmap_pa = to_kphysical(&kernel_pt); + for (size_t i = 0; i < sizeof(kernel_pt); i++) { + ((u8_t*)kmap_pa)[i] = 0; + } + + do_remap(); + + return kmap_pa; +} \ No newline at end of file