| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "KEHeader.h"
- extern uint64_t get_mpt(void);
- extern uint64_t kedump_mem_read(uint64_t data, unsigned long sz, void *buf);
- #if 0
- extern int sLOG(char *fmt, ...);
- #define LOG(fmt, ...) \
- do { \
- sLOG(fmt, ##__VA_ARGS__); \
- printf(fmt, ##__VA_ARGS__); \
- } while(0)
- #else
- #define LOG(fmt, ...)
- #endif
- static int read_mem(uint64_t paddr, void *buf, unsigned long size)
- {
- uint64_t ret = 0;
- ret = kedump_mem_read(paddr, size, buf);
- return (ret == size) ? 0 : -1;
- }
- #define PAGE_SIZE 4096
- #define PNUM_64 (PAGE_SIZE / sizeof(uint64_t))
- static uint64_t lxpage[PNUM_64];
- /* ARM PGD/PMD first 3 pages for userspace, last 1 pages for kernel space */
- #define PNUM_32 (PAGE_SIZE * 4 / sizeof(uint32_t))
- static uint32_t l1page32[PNUM_32];
- /* ARM L2 PTE 512 entry and each entry 4 bytes */
- #define PNUM_L2_32 512
- static uint32_t l2page32[PNUM_L2_32];
- static uint64_t mmutable_64_translate_l3(uint64_t vptr,
- uint64_t ptable)
- {
- int ret = 0;
- uint64_t pa;
- unsigned int lxidx = (vptr >> 12) & 0x1ff;
- if (lxidx >= PNUM_64) {
- LOG("address:0x%llx index:%d overflow error\n", vptr, lxidx);
- return 0;
- }
- memset(lxpage, 0, PAGE_SIZE);
- ret = read_mem(ptable, lxpage, PAGE_SIZE);
- if (ret == 0) {
- LOG("(%d)ent value:0x%llx\n", lxidx, lxpage[lxidx]);
- } else {
- return 0;
- }
- switch(lxpage[lxidx] & 3) {
- case 3:
- pa = (lxpage[lxidx] & 0x0000fffffffff000)
- + (vptr & 0xfff);
- break;
- default:
- LOG("invalid (%d)ent value:0x%llx\n", lxidx,
- lxpage[lxidx]);
- pa = 0;
- }
- return pa;
- }
- static uint64_t mmutable_64_translate_l2(uint64_t vptr,
- uint64_t ptable)
- {
- int ret = 0;
- uint64_t pa;
- uint64_t next_table_address;
- unsigned int lxidx = (vptr >> 21) & 0x1ff;
- if (lxidx >= PNUM_64) {
- LOG("address:0x%llx index:%d overflow error\n", vptr, lxidx);
- return 0;
- }
- memset(lxpage, 0, PAGE_SIZE);
- ret = read_mem(ptable, lxpage, PAGE_SIZE);
- if (ret == 0) {
- LOG("(%d)ent value:0x%llx\n", lxidx, lxpage[lxidx]);
- } else {
- return 0;
- }
- switch(lxpage[lxidx] & 3) {
- case 1:
- pa = (lxpage[lxidx] & 0x0000ffffffe00000)
- + (vptr & 0x1fffff);
- break;
- case 3:
- next_table_address = lxpage[lxidx]
- & 0x0000fffffffff000;
- pa = mmutable_64_translate_l3(vptr,
- next_table_address);
- break;
- default:
- LOG("invalid (%d)ent value:0x%llx\n", lxidx,
- lxpage[lxidx]);
- pa = 0;
- }
- return pa;
- }
- static uint64_t mmutable_64_translate_l1(uint64_t vptr,
- uint64_t ptable)
- {
- int ret = 0;
- uint64_t pa;
- uint64_t next_table_address;
- unsigned int lxidx = (vptr >> 30) & 0x1ff;
- if (lxidx >= PNUM_64) {
- LOG("address:0x%llx index:%d overflow error\n", vptr, lxidx);
- return 0;
- }
- memset(lxpage, 0, PAGE_SIZE);
- ret = read_mem(ptable, lxpage, PAGE_SIZE);
- if (ret == 0) {
- LOG("(%d)ent value:0x%llx\n", lxidx, lxpage[lxidx]);
- } else {
- return 0;
- }
- switch(lxpage[lxidx] & 3) {
- case 1:
- pa = (lxpage[lxidx] & 0x0000ffffc0000000)
- + (vptr & 0x3fffffff);
- break;
- case 3:
- next_table_address = lxpage[lxidx]
- & 0x0000fffffffff000;
- pa = mmutable_64_translate_l2(vptr,
- next_table_address);
- break;
- default:
- LOG("invalid (%d)ent value:0x%llx\n", lxidx,
- lxpage[lxidx]);
- pa = 0;
- }
- return pa;
- }
- uint64_t v2p_64(uint64_t vptr)
- {
- uint64_t mpt = get_mpt();
- /* LOG("mater_page_table:0x%llx, vptr:0x%llx\n", mpt, vptr); */
- if ((vptr & 0x8000000000000000) != 0) {
- return mmutable_64_translate_l1(vptr, mpt);
- } else {
- LOG("illegal address:0x%llx\n", vptr);
- }
- return 0;
- }
- static uint64_t mmutable_32_translate_l2(uint64_t vptr, uint64_t ptable)
- {
- int ret;
- uint64_t pa = 0;
- unsigned int lxidx = (vptr >> 12) & 0x1ff;
- memset(l2page32, 0, sizeof(l2page32));
- ret = read_mem(ptable, l2page32, sizeof(l2page32));
- if (ret == 0) {
- LOG("(%d)ent value:0x%x\n", lxidx, l2page32[lxidx]);
- } else {
- LOG("invalid l2 page table:0x%llx\n", ptable);
- return 0;
- }
- if (l2page32[lxidx] & 1)
- pa = (l2page32[lxidx] & 0xfffff000) + (vptr & 0xfff);
- else
- LOG("invalid (%d)ent value:0x%x\n", lxidx, l2page32[lxidx]);
- return pa;
- }
- static uint64_t mmutable_32_translate_l1(uint64_t vptr, uint64_t ptable)
- {
- int ret;
- uint64_t pa;
- uint64_t next_table_address;
- unsigned int lxidx = (vptr >> 20) & 0xfff;
- if (lxidx >= PNUM_32) {
- LOG("address:0x%llx index:%d overflow error\n", vptr, lxidx);
- return 0;
- }
- memset(l1page32, 0, sizeof(l1page32));
- ret = read_mem(ptable, l1page32, sizeof(l1page32));
- if (ret == 0) {
- LOG("(%d)ent value:0x%x\n", lxidx, l1page32[lxidx]);
- } else {
- LOG("invalid l1 page table:0x%llx\n", ptable);
- return 0;
- }
- switch(l1page32[lxidx] & 3) {
- case 1:
- /* PMD point address is 1KB allign */
- next_table_address = l1page32[lxidx] & 0xfffff000;
- pa = mmutable_32_translate_l2(vptr, next_table_address);
- break;
- case 2:
- /* [31:20]12bit as PMD index */
- pa = (l1page32[lxidx] & 0xfff00000) + (vptr & 0xfffff);
- break;
- default:
- LOG("invalid (%d)ent value:0x%x\n", lxidx, l1page32[lxidx]);
- pa = 0;
- }
- return pa;
- }
- uint64_t v2p_32(uint64_t vptr)
- {
- uint64_t mpt = get_mpt();
- if (vptr > 0xbf000000) {
- return mmutable_32_translate_l1(vptr, mpt);
- } else {
- LOG("illegal address:0x%llx\n", vptr);
- }
- return 0;
- }
|