domain.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,879 行 · 第 1/4 页
C
1,879 行
case 'l': __arg = (unsigned long)va_arg(args, unsigned long); break; \ case 'h': __arg = (unsigned long)va_arg(args, void *); break; \ default: __arg = 0; BUG(); \ } \ __arg; \})DEFINE_PER_CPU(char, hc_preempted);unsigned long hypercall_create_continuation( unsigned int op, const char *format, ...){ struct mc_state *mcs = &this_cpu(mc_state); struct cpu_user_regs *regs; const char *p = format; unsigned long arg; unsigned int i; va_list args; va_start(args, format); if ( test_bit(_MCSF_in_multicall, &mcs->flags) ) { __set_bit(_MCSF_call_preempted, &mcs->flags); for ( i = 0; *p != '\0'; i++ ) mcs->call.args[i] = next_arg(p, args); if ( is_pv_32on64_domain(current->domain) ) { for ( ; i < 6; i++ ) mcs->call.args[i] = 0; } } else { regs = guest_cpu_user_regs(); regs->eax = op; /* * For PV guest, we update EIP to re-execute 'syscall' / 'int 0x82'; * HVM does not need this since 'vmcall' / 'vmmcall' is fault-like. */ if ( !is_hvm_vcpu(current) ) regs->eip -= 2; /* re-execute 'syscall' / 'int 0x82' */#ifdef __x86_64__ if ( !is_hvm_vcpu(current) ? !is_pv_32on64_vcpu(current) : (hvm_guest_x86_mode(current) == 8) ) { for ( i = 0; *p != '\0'; i++ ) { arg = next_arg(p, args); switch ( i ) { case 0: regs->rdi = arg; break; case 1: regs->rsi = arg; break; case 2: regs->rdx = arg; break; case 3: regs->r10 = arg; break; case 4: regs->r8 = arg; break; case 5: regs->r9 = arg; break; } } } else#endif { if ( supervisor_mode_kernel ) regs->eip &= ~31; /* re-execute entire hypercall entry stub */ for ( i = 0; *p != '\0'; i++ ) { arg = next_arg(p, args); switch ( i ) { case 0: regs->ebx = arg; break; case 1: regs->ecx = arg; break; case 2: regs->edx = arg; break; case 3: regs->esi = arg; break; case 4: regs->edi = arg; break; case 5: regs->ebp = arg; break; } } } this_cpu(hc_preempted) = 1; } va_end(args); return op;}#ifdef CONFIG_COMPATint hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...){ int rc = 0; struct mc_state *mcs = &this_cpu(mc_state); struct cpu_user_regs *regs; unsigned int i, cval = 0; unsigned long nval = 0; va_list args; BUG_ON(*id > 5); BUG_ON(mask & (1U << *id)); va_start(args, mask); if ( test_bit(_MCSF_in_multicall, &mcs->flags) ) { if ( !test_bit(_MCSF_call_preempted, &mcs->flags) ) return 0; for ( i = 0; i < 6; ++i, mask >>= 1 ) { if ( mask & 1 ) { nval = va_arg(args, unsigned long); cval = va_arg(args, unsigned int); if ( cval == nval ) mask &= ~1U; else BUG_ON(nval == (unsigned int)nval); } else if ( id && *id == i ) { *id = mcs->call.args[i]; id = NULL; } if ( (mask & 1) && mcs->call.args[i] == nval ) { mcs->call.args[i] = cval; ++rc; } else BUG_ON(mcs->call.args[i] != (unsigned int)mcs->call.args[i]); } } else { regs = guest_cpu_user_regs(); for ( i = 0; i < 6; ++i, mask >>= 1 ) { unsigned long *reg; switch ( i ) { case 0: reg = ®s->ebx; break; case 1: reg = ®s->ecx; break; case 2: reg = ®s->edx; break; case 3: reg = ®s->esi; break; case 4: reg = ®s->edi; break; case 5: reg = ®s->ebp; break; default: BUG(); reg = NULL; break; } if ( (mask & 1) ) { nval = va_arg(args, unsigned long); cval = va_arg(args, unsigned int); if ( cval == nval ) mask &= ~1U; else BUG_ON(nval == (unsigned int)nval); } else if ( id && *id == i ) { *id = *reg; id = NULL; } if ( (mask & 1) && *reg == nval ) { *reg = cval; ++rc; } else BUG_ON(*reg != (unsigned int)*reg); } } va_end(args); return rc;}#endifstatic int relinquish_memory( struct domain *d, struct list_head *list, unsigned long type){ struct list_head *ent; struct page_info *page; unsigned long x, y; int ret = 0; /* Use a recursive lock, as we may enter 'free_domheap_page'. */ spin_lock_recursive(&d->page_alloc_lock); ent = list->next; while ( ent != list ) { page = list_entry(ent, struct page_info, list); /* Grab a reference to the page so it won't disappear from under us. */ if ( unlikely(!get_page(page, d)) ) { /* Couldn't get a reference -- someone is freeing this page. */ ent = ent->next; list_move_tail(&page->list, &d->arch.relmem_list); continue; } if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) put_page_and_type(page); if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) put_page(page);#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION /* * Forcibly drop reference counts of page tables above top most (which * were skipped to prevent long latencies due to deep recursion - see * the special treatment in free_lX_table()). */ y = page->u.inuse.type_info; if ( (type < PGT_root_page_table) && unlikely(((y + PGT_type_mask) & (PGT_type_mask|PGT_validated)) == type) ) { BUG_ON((y & PGT_count_mask) >= (page->count_info & PGC_count_mask)); while ( y & PGT_count_mask ) { put_page_and_type(page); y = page->u.inuse.type_info; } }#endif /* * Forcibly invalidate top-most, still valid page tables at this point * to break circular 'linear page table' references. This is okay * because MMU structures are not shared across domains and this domain * is now dead. Thus top-most valid tables are not in use so a non-zero * count means circular reference. */ y = page->u.inuse.type_info; for ( ; ; ) { x = y; if ( likely((x & (PGT_type_mask|PGT_validated)) != (type|PGT_validated)) ) break; y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated); if ( likely(y == x) ) { free_page_type(page, type); break; } } /* Follow the list chain and /then/ potentially free the page. */ ent = ent->next; list_move_tail(&page->list, &d->arch.relmem_list); put_page(page); if ( hypercall_preempt_check() ) { ret = -EAGAIN; goto out; } } list_splice_init(&d->arch.relmem_list, list); out: spin_unlock_recursive(&d->page_alloc_lock); return ret;}static void vcpu_destroy_pagetables(struct vcpu *v){ struct domain *d = v->domain; unsigned long pfn;#ifdef __x86_64__ if ( is_pv_32on64_vcpu(v) ) { pfn = l4e_get_pfn(*(l4_pgentry_t *) __va(pagetable_get_paddr(v->arch.guest_table))); if ( pfn != 0 ) { if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); } l4e_write( (l4_pgentry_t *)__va(pagetable_get_paddr(v->arch.guest_table)), l4e_empty()); v->arch.cr3 = 0; return; }#endif pfn = pagetable_get_pfn(v->arch.guest_table); if ( pfn != 0 ) { if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); v->arch.guest_table = pagetable_null(); }#ifdef __x86_64__ /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */ pfn = pagetable_get_pfn(v->arch.guest_table_user); if ( pfn != 0 ) { if ( !is_pv_32bit_vcpu(v) ) { if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); } v->arch.guest_table_user = pagetable_null(); }#endif v->arch.cr3 = 0;}int domain_relinquish_resources(struct domain *d){ int ret; struct vcpu *v; BUG_ON(!cpus_empty(d->domain_dirty_cpumask)); switch ( d->arch.relmem ) { case RELMEM_not_started: /* Tear down paging-assistance stuff. */ paging_teardown(d); for_each_vcpu ( d, v ) { /* Drop the in-use references to page-table bases. */ vcpu_destroy_pagetables(v); /* * Relinquish GDT mappings. No need for explicit unmapping of the * LDT as it automatically gets squashed with the guest mappings. */ destroy_gdt(v); unmap_vcpu_info(v); } d->arch.relmem = RELMEM_xen; /* fallthrough */ /* Relinquish every page of memory. */ case RELMEM_xen: ret = relinquish_memory(d, &d->xenpage_list, ~0UL); if ( ret ) return ret;#if CONFIG_PAGING_LEVELS >= 4 d->arch.relmem = RELMEM_l4; /* fallthrough */ case RELMEM_l4: ret = relinquish_memory(d, &d->page_list, PGT_l4_page_table); if ( ret ) return ret;#endif#if CONFIG_PAGING_LEVELS >= 3 d->arch.relmem = RELMEM_l3; /* fallthrough */ case RELMEM_l3: ret = relinquish_memory(d, &d->page_list, PGT_l3_page_table); if ( ret ) return ret;#endif d->arch.relmem = RELMEM_l2; /* fallthrough */ case RELMEM_l2: ret = relinquish_memory(d, &d->page_list, PGT_l2_page_table); if ( ret ) return ret; d->arch.relmem = RELMEM_done; /* fallthrough */ case RELMEM_done:#ifdef DOMAIN_DESTRUCT_AVOID_RECURSION ret = relinquish_memory(d, &d->page_list, PGT_l1_page_table); if ( ret ) return ret;#endif break; default: BUG(); } /* Free page used by xen oprofile buffer. */ free_xenoprof_pages(d); if ( is_hvm_domain(d) ) hvm_domain_relinquish_resources(d); return 0;}void arch_dump_domain_info(struct domain *d){ paging_dump_domain_info(d);}void arch_dump_vcpu_info(struct vcpu *v){ paging_dump_vcpu_info(v);}void domain_cpuid( struct domain *d, unsigned int input, unsigned int sub_input, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx){ cpuid_input_t *cpuid; int i; for ( i = 0; i < MAX_CPUID_INPUT; i++ ) { cpuid = &d->arch.cpuids[i]; if ( (cpuid->input[0] == input) && ((cpuid->input[1] == XEN_CPUID_INPUT_UNUSED) || (cpuid->input[1] == sub_input)) ) { *eax = cpuid->eax; *ebx = cpuid->ebx; *ecx = cpuid->ecx; *edx = cpuid->edx; return; } } *eax = *ebx = *ecx = *edx = 0;}/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?