mm.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 618 行 · 第 1/2 页
C
618 行
{ mmuext_op_t op = { .cmd = MMUEXT_TLB_FLUSH_ALL, }; int count; HYPERVISOR_mmuext_op(&op, 1, &count, DOMID_SELF); }}void mem_test(unsigned long *start_add, unsigned long *end_add){ unsigned long mask = 0x10000; unsigned long *pointer; for(pointer = start_add; pointer < end_add; pointer++) { if(!(((unsigned long)pointer) & 0xfffff)) { printk("Writing to %lx\n", pointer); page_walk((unsigned long)pointer); } *pointer = (unsigned long)pointer & ~mask; } for(pointer = start_add; pointer < end_add; pointer++) { if(((unsigned long)pointer & ~mask) != *pointer) printk("Read error at 0x%lx. Read: 0x%lx, should read 0x%lx\n", (unsigned long)pointer, *pointer, ((unsigned long)pointer & ~mask)); }}static pgentry_t *get_pgt(unsigned long addr){ unsigned long mfn; pgentry_t *tab; unsigned offset; tab = (pgentry_t *)start_info.pt_base; mfn = virt_to_mfn(start_info.pt_base);#if defined(__x86_64__) offset = l4_table_offset(addr); if (!(tab[offset] & _PAGE_PRESENT)) return NULL; mfn = pte_to_mfn(tab[offset]); tab = mfn_to_virt(mfn);#endif offset = l3_table_offset(addr); if (!(tab[offset] & _PAGE_PRESENT)) return NULL; mfn = pte_to_mfn(tab[offset]); tab = mfn_to_virt(mfn); offset = l2_table_offset(addr); if (!(tab[offset] & _PAGE_PRESENT)) return NULL; mfn = pte_to_mfn(tab[offset]); tab = mfn_to_virt(mfn); offset = l1_table_offset(addr); return &tab[offset];}pgentry_t *need_pgt(unsigned long addr){ unsigned long mfn; pgentry_t *tab; unsigned long pt_pfn; unsigned offset; tab = (pgentry_t *)start_info.pt_base; mfn = virt_to_mfn(start_info.pt_base);#if defined(__x86_64__) offset = l4_table_offset(addr); if (!(tab[offset] & _PAGE_PRESENT)) { pt_pfn = virt_to_pfn(alloc_page()); new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME); } ASSERT(tab[offset] & _PAGE_PRESENT); mfn = pte_to_mfn(tab[offset]); tab = mfn_to_virt(mfn);#endif offset = l3_table_offset(addr); if (!(tab[offset] & _PAGE_PRESENT)) { pt_pfn = virt_to_pfn(alloc_page()); new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME); } ASSERT(tab[offset] & _PAGE_PRESENT); mfn = pte_to_mfn(tab[offset]); tab = mfn_to_virt(mfn); offset = l2_table_offset(addr); if (!(tab[offset] & _PAGE_PRESENT)) { pt_pfn = virt_to_pfn(alloc_page()); new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME); } ASSERT(tab[offset] & _PAGE_PRESENT); mfn = pte_to_mfn(tab[offset]); tab = mfn_to_virt(mfn); offset = l1_table_offset(addr); return &tab[offset];}static unsigned long demand_map_area_start;#ifdef __x86_64__#define DEMAND_MAP_PAGES ((128ULL << 30) / PAGE_SIZE)#else#define DEMAND_MAP_PAGES ((2ULL << 30) / PAGE_SIZE)#endif#ifdef HAVE_LIBCunsigned long heap, brk, heap_mapped, heap_end;#ifdef __x86_64__#define HEAP_PAGES ((128ULL << 30) / PAGE_SIZE)#else#define HEAP_PAGES ((1ULL << 30) / PAGE_SIZE)#endif#endifvoid arch_init_demand_mapping_area(unsigned long cur_pfn){ cur_pfn++; demand_map_area_start = (unsigned long) pfn_to_virt(cur_pfn); cur_pfn += DEMAND_MAP_PAGES; printk("Demand map pfns at %lx-%lx.\n", demand_map_area_start, pfn_to_virt(cur_pfn));#ifdef HAVE_LIBC cur_pfn++; heap_mapped = brk = heap = (unsigned long) pfn_to_virt(cur_pfn); cur_pfn += HEAP_PAGES; heap_end = (unsigned long) pfn_to_virt(cur_pfn); printk("Heap resides at %lx-%lx.\n", brk, heap_end);#endif}#define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))void do_map_frames(unsigned long addr, unsigned long *f, unsigned long n, unsigned long stride, unsigned long increment, domid_t id, int may_fail, unsigned long prot){ pgentry_t *pgt = NULL; unsigned long done = 0; unsigned long i; int rc; while (done < n) { unsigned long todo; if (may_fail) todo = 1; else todo = n - done; if (todo > MAP_BATCH) todo = MAP_BATCH; { mmu_update_t mmu_updates[todo]; for (i = 0; i < todo; i++, addr += PAGE_SIZE, pgt++) { if (!pgt || !(addr & L1_MASK)) pgt = need_pgt(addr); mmu_updates[i].ptr = virt_to_mach(pgt); mmu_updates[i].val = ((pgentry_t)(f[(done + i) * stride] + (done + i) * increment) << PAGE_SHIFT) | prot; } rc = HYPERVISOR_mmu_update(mmu_updates, todo, NULL, id); if (rc < 0) { if (may_fail) f[done * stride] |= 0xF0000000; else { printk("Map %ld (%lx, ...) at %p failed: %d.\n", todo, f[done * stride] + done * increment, addr, rc); do_exit(); } } } done += todo; }}unsigned long allocate_ondemand(unsigned long n, unsigned long alignment){ unsigned long x; unsigned long y = 0; /* Find a properly aligned run of n contiguous frames */ for (x = 0; x <= DEMAND_MAP_PAGES - n; x = (x + y + 1 + alignment - 1) & ~(alignment - 1)) { unsigned long addr = demand_map_area_start + x * PAGE_SIZE; pgentry_t *pgt = get_pgt(addr); for (y = 0; y < n; y++, addr += PAGE_SIZE) { if (!(addr & L1_MASK)) pgt = get_pgt(addr); if (pgt) { if (*pgt & _PAGE_PRESENT) break; pgt++; } } if (y == n) break; } if (y != n) { printk("Failed to find %ld frames!\n", n); return 0; } return demand_map_area_start + x * PAGE_SIZE;}void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride, unsigned long increment, unsigned long alignment, domid_t id, int may_fail, unsigned long prot){ unsigned long addr = allocate_ondemand(n, alignment); if (!addr) return NULL; /* Found it at x. Map it in. */ do_map_frames(addr, f, n, stride, increment, id, may_fail, prot); return (void *)addr;}static void clear_bootstrap(void){ pte_t nullpte = { }; /* Use first page as the CoW zero page */ memset(&_text, 0, PAGE_SIZE); mfn_zero = virt_to_mfn((unsigned long) &_text); if (HYPERVISOR_update_va_mapping(0, nullpte, UVMF_INVLPG)) printk("Unable to unmap NULL page\n");}void arch_init_p2m(unsigned long max_pfn){#define L1_P2M_SHIFT 9#define L2_P2M_SHIFT 18 #define L3_P2M_SHIFT 27 #define L1_P2M_ENTRIES (1 << L1_P2M_SHIFT) #define L2_P2M_ENTRIES (1 << (L2_P2M_SHIFT - L1_P2M_SHIFT)) #define L3_P2M_ENTRIES (1 << (L3_P2M_SHIFT - L2_P2M_SHIFT)) #define L1_P2M_MASK (L1_P2M_ENTRIES - 1) #define L2_P2M_MASK (L2_P2M_ENTRIES - 1) #define L3_P2M_MASK (L3_P2M_ENTRIES - 1) unsigned long *l1_list = NULL, *l2_list = NULL, *l3_list; unsigned long pfn; l3_list = (unsigned long *)alloc_page(); for(pfn=0; pfn<max_pfn; pfn++) { if(!(pfn % (L1_P2M_ENTRIES * L2_P2M_ENTRIES))) { l2_list = (unsigned long*)alloc_page(); if((pfn >> L3_P2M_SHIFT) > 0) { printk("Error: Too many pfns.\n"); do_exit(); } l3_list[(pfn >> L2_P2M_SHIFT)] = virt_to_mfn(l2_list); } if(!(pfn % (L1_P2M_ENTRIES))) { l1_list = (unsigned long*)alloc_page(); l2_list[(pfn >> L1_P2M_SHIFT) & L2_P2M_MASK] = virt_to_mfn(l1_list); } l1_list[pfn & L1_P2M_MASK] = pfn_to_mfn(pfn); } HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = virt_to_mfn(l3_list); HYPERVISOR_shared_info->arch.max_pfn = max_pfn;}void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p){ unsigned long start_pfn, max_pfn; printk(" _text: %p\n", &_text); printk(" _etext: %p\n", &_etext); printk(" _erodata: %p\n", &_erodata); printk(" _edata: %p\n", &_edata); printk(" stack start: %p\n", stack); printk(" _end: %p\n", &_end); /* First page follows page table pages and 3 more pages (store page etc) */ start_pfn = PFN_UP(to_phys(start_info.pt_base)) + start_info.nr_pt_frames + 3; max_pfn = start_info.nr_pages; printk(" start_pfn: %lx\n", start_pfn); printk(" max_pfn: %lx\n", max_pfn); build_pagetable(&start_pfn, &max_pfn); clear_bootstrap(); set_readonly(&_text, &_erodata); *start_pfn_p = start_pfn; *max_pfn_p = max_pfn;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?