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 + -
显示快捷键?