Skip to content

Commit 054954e

Browse files
jgross1David Vrabel
authored andcommitted
xen: switch to linear virtual mapped sparse p2m list
At start of the day the Xen hypervisor presents a contiguous mfn list to a pv-domain. In order to support sparse memory this mfn list is accessed via a three level p2m tree built early in the boot process. Whenever the system needs the mfn associated with a pfn this tree is used to find the mfn. Instead of using a software walked tree for accessing a specific mfn list entry this patch is creating a virtual address area for the entire possible mfn list including memory holes. The holes are covered by mapping a pre-defined page consisting only of "invalid mfn" entries. Access to a mfn entry is possible by just using the virtual base address of the mfn list and the pfn as index into that list. This speeds up the (hot) path of determining the mfn of a pfn. Kernel build on a Dell Latitude E6440 (2 cores, HT) in 64 bit Dom0 showed following improvements: Elapsed time: 32:50 -> 32:35 System: 18:07 -> 17:47 User: 104:00 -> 103:30 Tested with following configurations: - 64 bit dom0, 8GB RAM - 64 bit dom0, 128 GB RAM, PCI-area above 4 GB - 32 bit domU, 512 MB, 8 GB, 43 GB (more wouldn't work even without the patch) - 32 bit domU, ballooning up and down - 32 bit domU, save and restore - 32 bit domU with PCI passthrough - 64 bit domU, 8 GB, 2049 MB, 5000 MB - 64 bit domU, ballooning up and down - 64 bit domU, save and restore - 64 bit domU with PCI passthrough Signed-off-by: Juergen Gross <jgross@suse.com> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
1 parent 0aad568 commit 054954e

File tree

4 files changed

+347
-444
lines changed

4 files changed

+347
-444
lines changed

arch/x86/include/asm/xen/page.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,25 @@ extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
6565
* bits (identity or foreign) are set.
6666
* - __pfn_to_mfn() returns the found entry of the p2m table. A possibly set
6767
* identity or foreign indicator will be still set. __pfn_to_mfn() is
68-
* encapsulating get_phys_to_machine().
69-
* - get_phys_to_machine() is to be called by __pfn_to_mfn() only to allow
70-
* for future optimizations.
68+
* encapsulating get_phys_to_machine() which is called in special cases only.
69+
* - get_phys_to_machine() is to be called by __pfn_to_mfn() only in special
70+
* cases needing an extended handling.
7171
*/
7272
static inline unsigned long __pfn_to_mfn(unsigned long pfn)
7373
{
74-
return get_phys_to_machine(pfn);
74+
unsigned long mfn;
75+
76+
if (pfn < xen_p2m_size)
77+
mfn = xen_p2m_addr[pfn];
78+
else if (unlikely(pfn < xen_max_p2m_pfn))
79+
return get_phys_to_machine(pfn);
80+
else
81+
return IDENTITY_FRAME(pfn);
82+
83+
if (unlikely(mfn == INVALID_P2M_ENTRY))
84+
return get_phys_to_machine(pfn);
85+
86+
return mfn;
7587
}
7688

7789
static inline unsigned long pfn_to_mfn(unsigned long pfn)

arch/x86/xen/mmu.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,20 +1158,16 @@ static void __init xen_cleanhighmap(unsigned long vaddr,
11581158
* instead of somewhere later and be confusing. */
11591159
xen_mc_flush();
11601160
}
1161-
static void __init xen_pagetable_p2m_copy(void)
1161+
1162+
static void __init xen_pagetable_p2m_free(void)
11621163
{
11631164
unsigned long size;
11641165
unsigned long addr;
1165-
unsigned long new_mfn_list;
1166-
1167-
if (xen_feature(XENFEAT_auto_translated_physmap))
1168-
return;
11691166

11701167
size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long));
11711168

1172-
new_mfn_list = xen_revector_p2m_tree();
11731169
/* No memory or already called. */
1174-
if (!new_mfn_list || new_mfn_list == xen_start_info->mfn_list)
1170+
if ((unsigned long)xen_p2m_addr == xen_start_info->mfn_list)
11751171
return;
11761172

11771173
/* using __ka address and sticking INVALID_P2M_ENTRY! */
@@ -1189,8 +1185,6 @@ static void __init xen_pagetable_p2m_copy(void)
11891185

11901186
size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long));
11911187
memblock_free(__pa(xen_start_info->mfn_list), size);
1192-
/* And revector! Bye bye old array */
1193-
xen_start_info->mfn_list = new_mfn_list;
11941188

11951189
/* At this stage, cleanup_highmap has already cleaned __ka space
11961190
* from _brk_limit way up to the max_pfn_mapped (which is the end of
@@ -1214,14 +1208,26 @@ static void __init xen_pagetable_p2m_copy(void)
12141208
}
12151209
#endif
12161210

1217-
static void __init xen_pagetable_init(void)
1211+
static void __init xen_pagetable_p2m_setup(void)
12181212
{
1219-
paging_init();
1213+
if (xen_feature(XENFEAT_auto_translated_physmap))
1214+
return;
1215+
1216+
xen_vmalloc_p2m_tree();
1217+
12201218
#ifdef CONFIG_X86_64
1221-
xen_pagetable_p2m_copy();
1222-
#else
1223-
xen_revector_p2m_tree();
1219+
xen_pagetable_p2m_free();
12241220
#endif
1221+
/* And revector! Bye bye old array */
1222+
xen_start_info->mfn_list = (unsigned long)xen_p2m_addr;
1223+
}
1224+
1225+
static void __init xen_pagetable_init(void)
1226+
{
1227+
paging_init();
1228+
1229+
xen_pagetable_p2m_setup();
1230+
12251231
/* Allocate and initialize top and mid mfn levels for p2m structure */
12261232
xen_build_mfn_list_list();
12271233

0 commit comments

Comments
 (0)