[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 6/8] x86/EPT: force re???evaluation of memory type as necessary
>>> On 27.03.14 at 14:08, <tim@xxxxxxx> wrote: > At 15:36 +0000 on 26 Mar (1395844584), Jan Beulich wrote: >> +bool_t ept_handle_misconfig(uint64_t gpa) >> +{ >> + struct vcpu *curr = current; >> + struct p2m_domain *p2m = p2m_get_hostp2m(curr->domain); >> + struct ept_data *ept = &p2m->ept; >> + unsigned int level = ept_get_wl(ept); >> + unsigned long gfn = PFN_DOWN(gpa); >> + unsigned long mfn = ept_get_asr(ept); >> + ept_entry_t *epte; >> + bool_t okay; >> + >> + if ( !mfn ) >> + return 0; >> + >> + p2m_lock(p2m); >> + >> + for ( okay = curr->arch.hvm_vmx.ept_spurious_misconfig; ; --level) { > > I'd prefer a 'while (1)' with the --level at the bottom of the loop > beside where mfn gets set to the next level's mfn. If not that, can > you at least move the init of 'okay' out to its own line? Moving it onto its own line is okay with me (albeit I think having it in the for() is expressing more clearly that this is the loop start state). >> + ept_entry_t e; >> + unsigned int i; >> + >> + epte = map_domain_page(mfn); >> + i = (gfn >> (level * EPT_TABLE_ORDER)) & (EPT_PAGETABLE_ENTRIES - >> 1); >> + e = atomic_read_ept_entry(&epte[i]); >> + >> + if ( level == 0 || is_epte_superpage(&e) ) >> + { >> + uint8_t ipat = 0; >> + struct vcpu *v; >> + >> + if ( e.emt != MTRR_NUM_TYPES ) >> + break; >> + >> + if ( level == 0 ) >> + { >> + for ( gfn -= i, i = 0; i < EPT_PAGETABLE_ENTRIES; ++i ) >> + { >> + e = atomic_read_ept_entry(&epte[i]); >> + if ( e.emt == MTRR_NUM_TYPES ) >> + e.emt = 0; >> + if ( !is_epte_valid(&e) || !is_epte_present(&e) ) >> + continue; >> + e.emt = epte_get_entry_emt(p2m->domain, gfn + i, >> + _mfn(e.mfn), &ipat, >> + e.sa_p2mt == >> p2m_mmio_direct); >> + e.ipat = ipat; >> + atomic_write_ept_entry(&epte[i], e); >> + } >> + } >> + else >> + { >> + e.emt = epte_get_entry_emt(p2m->domain, gfn, _mfn(e.mfn), >> + &ipat, >> + e.sa_p2mt == p2m_mmio_direct); >> + e.ipat = ipat; >> + atomic_write_ept_entry(&epte[i], e); >> + } >> + >> + for_each_vcpu ( curr->domain, v ) >> + v->arch.hvm_vmx.ept_spurious_misconfig = 1; >> + okay = 1; >> + break; >> + } >> + >> + if ( e.emt == MTRR_NUM_TYPES ) >> + { >> + ASSERT(is_epte_present(&e)); >> + e.emt = 0; >> + atomic_write_ept_entry(&epte[i], e); >> + unmap_domain_page(epte); >> + >> + ept_invalidate_emt(_mfn(e.mfn)); >> + okay = 1; > > Do you need to also set ept_spurious_misconfig flags here? At the > moment you set them when a present entry gets reset, but what about a > walk that hits a not-present entry (e.g. mmio_dm)? There, the first > CPU to take a fault will clear up the intermediate nodes, but not > make any chaneg at level 0 or set the ept_spurious_misconfig flags. Actually I think I need to swap the order of operations instead: first invalidate the next level, then clear .emt. Then the current model of needing to set the flag only when making an entry valid will be correct/consistent afaict. Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |