/* * Helper functions to write or read unsigned long values to/from * memory, when the access may fault.
*/ staticinlineint xen_safe_write_ulong(unsignedlong *addr, unsignedlong val)
{ int ret = 0;
#ifdef CONFIG_XEN_PV /* * When to use pfn_to_mfn(), __pfn_to_mfn() or get_phys_to_machine(): * - pfn_to_mfn() returns either INVALID_P2M_ENTRY or the mfn. No indicator * bits (identity or foreign) are set. * - __pfn_to_mfn() returns the found entry of the p2m table. A possibly set * identity or foreign indicator will be still set. __pfn_to_mfn() is * encapsulating get_phys_to_machine() which is called in special cases only. * - get_phys_to_machine() is to be called by __pfn_to_mfn() only in special * cases needing an extended handling.
*/ staticinlineunsignedlong __pfn_to_mfn(unsignedlong pfn)
{ unsignedlong mfn;
/* * Some x86 code are still using pfn_to_mfn instead of * pfn_to_mfn. This will have to be removed when we figured * out which call.
*/ if (xen_feature(XENFEAT_auto_translated_physmap)) return pfn;
mfn = __pfn_to_mfn(pfn);
if (mfn != INVALID_P2M_ENTRY)
mfn &= ~(FOREIGN_FRAME_BIT | IDENTITY_FRAME_BIT);
return mfn;
}
staticinlineint phys_to_machine_mapping_valid(unsignedlong pfn)
{ if (xen_feature(XENFEAT_auto_translated_physmap)) return 1;
return __pfn_to_mfn(pfn) != INVALID_P2M_ENTRY;
}
staticinlineunsignedlong mfn_to_pfn_no_overrides(unsignedlong mfn)
{ unsignedlong pfn; int ret;
if (unlikely(mfn >= machine_to_phys_nr)) return ~0;
/* * The array access can fail (e.g., device space beyond end of RAM). * In such cases it doesn't matter what we return (we return garbage), * but we must handle the fault without crashing!
*/
ret = xen_safe_read_ulong(&machine_to_phys_mapping[mfn], &pfn); if (ret < 0) return ~0;
/* * Some x86 code are still using mfn_to_pfn instead of * gfn_to_pfn. This will have to be removed when we figure * out which call.
*/ if (xen_feature(XENFEAT_auto_translated_physmap)) return mfn;
pfn = mfn_to_pfn_no_overrides(mfn); if (__pfn_to_mfn(pfn) != mfn)
pfn = ~0;
/* * pfn is ~0 if there are no entries in the m2p for mfn or the * entry doesn't map back to the mfn.
*/ if (pfn == ~0 && __pfn_to_mfn(mfn) == IDENTITY_FRAME(mfn))
pfn = mfn;
/* * We detect special mappings in one of two ways: * 1. If the MFN is an I/O page then Xen will set the m2p entry * to be outside our maximum possible pseudophys range. * 2. If the MFN belongs to a different domain then we will certainly * not have MFN in our p2m table. Conversely, if the page is ours, * then we'll have p2m(m2p(MFN))==MFN. * If we detect a special mapping then it doesn't have a 'struct page'. * We force !pfn_valid() by returning an out-of-range pointer. * * NB. These checks require that, for any MFN that is not in our reservation, * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN. * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety. * * NB2. When deliberately mapping foreign pages into the p2m table, you *must* * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we * require. In all the cases we care about, the FOREIGN_FRAME bit is * masked (e.g., pfn_to_mfn()) so behaviour there is correct.
*/ staticinlineunsignedlong bfn_to_local_pfn(unsignedlong mfn)
{ unsignedlong pfn;
if (xen_feature(XENFEAT_auto_translated_physmap)) return mfn;
pfn = mfn_to_pfn(mfn); if (__pfn_to_mfn(pfn) != mfn) return -1; /* force !pfn_valid() */ return pfn;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.