|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3 12/18] x86/mm: let Xen's page-table walker operate on a given root
map_pages_to_xen() and modify_xen_mappings() maintain Xen's own mappings,
walking from idle_pg_table, whose Xen slots every other root page-table
copies. A later patch introduces a second directmap hierarchy: page
tables for the directmap virtual address range that some guest contexts
use in place of idle_pg_table's. It needs the same maintenance at the
same virtual addresses.
Give virt_to_xen_l{3,2,1}e() the L4 to walk from, and move the bodies of
map_pages_to_xen() and modify_xen_mappings() into map_pages_in() and
modify_mappings_in(), which take the root as well. The public functions
pass idle_pg_table. The EFI runtime-services page-tables mirror
idle_pg_table's L4 entries only, so a newly allocated L3 is propagated
to them only when the root is idle_pg_table.
TLB flushing is unaffected: it is by virtual address, and the same
addresses are mapped in either hierarchy.
No functional change.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: George Dunlap <gwd@xxxxxxxxxxxxxx>
---
Changes in v3:
- New in this version.
---
xen/arch/x86/mm.c | 55 ++++++++++++++++++++++++++++++++++-------------
1 file changed, 40 insertions(+), 15 deletions(-)
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 7258935528..94b96c3d9b 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -5201,13 +5201,14 @@ static DEFINE_SPINLOCK(map_pgdir_lock);
/*
* For virt_to_xen_lXe() functions, they take a linear address and return a
- * pointer to Xen's LX entry. Caller needs to unmap the pointer.
+ * pointer to Xen's LX entry in the page-table hierarchy rooted at @root
+ * (idle_pg_table for Xen's own mappings). Caller needs to unmap the pointer.
*/
-static l3_pgentry_t *virt_to_xen_l3e(unsigned long v)
+static l3_pgentry_t *virt_to_xen_l3e(l4_pgentry_t *root, unsigned long v)
{
l4_pgentry_t *pl4e;
- pl4e = &idle_pg_table[l4_table_offset(v)];
+ pl4e = &root[l4_table_offset(v)];
if ( !(l4e_get_flags(*pl4e) & _PAGE_PRESENT) )
{
bool locking = system_state > SYS_STATE_boot;
@@ -5223,7 +5224,8 @@ static l3_pgentry_t *virt_to_xen_l3e(unsigned long v)
l4_pgentry_t l4e = l4e_from_mfn(l3mfn, __PAGE_HYPERVISOR);
l4e_write(pl4e, l4e);
- efi_update_l4_pgtable(l4_table_offset(v), l4e);
+ if ( root == idle_pg_table )
+ efi_update_l4_pgtable(l4_table_offset(v), l4e);
l3mfn = INVALID_MFN;
}
if ( locking )
@@ -5234,11 +5236,11 @@ static l3_pgentry_t *virt_to_xen_l3e(unsigned long v)
return map_l3t_from_l4e(*pl4e) + l3_table_offset(v);
}
-static l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
+static l2_pgentry_t *virt_to_xen_l2e(l4_pgentry_t *root, unsigned long v)
{
l3_pgentry_t *pl3e, l3e;
- pl3e = virt_to_xen_l3e(v);
+ pl3e = virt_to_xen_l3e(root, v);
if ( !pl3e )
return NULL;
@@ -5272,11 +5274,11 @@ static l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
return map_l2t_from_l3e(l3e) + l2_table_offset(v);
}
-static l1_pgentry_t *virt_to_xen_l1e(unsigned long v)
+static l1_pgentry_t *virt_to_xen_l1e(l4_pgentry_t *root, unsigned long v)
{
l2_pgentry_t *pl2e, l2e;
- pl2e = virt_to_xen_l2e(v);
+ pl2e = virt_to_xen_l2e(root, v);
if ( !pl2e )
return NULL;
@@ -5352,7 +5354,7 @@ mfn_t xen_map_to_mfn(unsigned long va)
bool locking = system_state > SYS_STATE_boot;
unsigned int l2_offset = l2_table_offset(va);
unsigned int l1_offset = l1_table_offset(va);
- const l3_pgentry_t *pl3e = virt_to_xen_l3e(va);
+ const l3_pgentry_t *pl3e = virt_to_xen_l3e(idle_pg_table, va);
const l2_pgentry_t *pl2e = NULL;
const l1_pgentry_t *pl1e = NULL;
struct page_info *l3page;
@@ -5392,7 +5394,12 @@ mfn_t xen_map_to_mfn(unsigned long va)
return ret;
}
-int map_pages_to_xen(
+/*
+ * map_pages_to_xen() in the hierarchy rooted at @root: idle_pg_table's, or
+ * another hierarchy sharing its virtual addresses.
+ */
+static int map_pages_in(
+ l4_pgentry_t *root,
unsigned long virt,
mfn_t mfn,
unsigned long nr_mfns,
@@ -5443,7 +5450,7 @@ int map_pages_to_xen(
UNMAP_DOMAIN_PAGE(pl3e);
UNMAP_DOMAIN_PAGE(pl2e);
- pl3e = virt_to_xen_l3e(virt);
+ pl3e = virt_to_xen_l3e(root, virt);
if ( !pl3e )
goto out;
@@ -5567,7 +5574,7 @@ int map_pages_to_xen(
free_xen_pagetable(l2mfn);
}
- pl2e = virt_to_xen_l2e(virt);
+ pl2e = virt_to_xen_l2e(root, virt);
if ( !pl2e )
goto out;
@@ -5612,7 +5619,7 @@ int map_pages_to_xen(
/* Normal page mapping. */
if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
{
- pl1e = virt_to_xen_l1e(virt);
+ pl1e = virt_to_xen_l1e(root, virt);
if ( pl1e == NULL )
goto out;
}
@@ -5797,6 +5804,15 @@ int map_pages_to_xen(
return rc;
}
+int map_pages_to_xen(
+ unsigned long virt,
+ mfn_t mfn,
+ unsigned long nr_mfns,
+ pte_attr_t flags)
+{
+ return map_pages_in(idle_pg_table, virt, mfn, nr_mfns, flags);
+}
+
int __init populate_pt_range(unsigned long virt, unsigned long nr_mfns)
{
return map_pages_to_xen(virt, INVALID_MFN, nr_mfns, MAP_SMALL_PAGES);
@@ -5813,8 +5829,12 @@ int __init populate_pt_range(unsigned long virt,
unsigned long nr_mfns)
* flags are ignored.
*
* It is an error to call with present flags over an unpopulated range.
+ *
+ * modify_mappings_in() does so in the hierarchy rooted at @root, as
+ * map_pages_in() does.
*/
-int modify_xen_mappings(unsigned long s, unsigned long e, pte_attr_t nf)
+static int modify_mappings_in(l4_pgentry_t *root, unsigned long s,
+ unsigned long e, pte_attr_t nf)
{
bool locking = system_state > SYS_STATE_boot;
l3_pgentry_t *pl3e = NULL;
@@ -5841,7 +5861,7 @@ int modify_xen_mappings(unsigned long s, unsigned long e,
pte_attr_t nf)
UNMAP_DOMAIN_PAGE(pl2e);
UNMAP_DOMAIN_PAGE(pl3e);
- pl3e = virt_to_xen_l3e(v);
+ pl3e = virt_to_xen_l3e(root, v);
if ( !pl3e )
goto out;
@@ -6092,6 +6112,11 @@ int modify_xen_mappings(unsigned long s, unsigned long
e, pte_attr_t nf)
#undef flush_area
+int modify_xen_mappings(unsigned long s, unsigned long e, pte_attr_t nf)
+{
+ return modify_mappings_in(idle_pg_table, s, e, nf);
+}
+
int destroy_xen_mappings(unsigned long s, unsigned long e)
{
return modify_xen_mappings(s, e, _PAGE_NONE);
--
2.55.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |