]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
(no commit message)
authorRoger Pau Monne <roger.pau@citrix.com>
Tue, 25 Jun 2024 16:16:40 +0000 (18:16 +0200)
committerRoger Pau Monne <roger.pau@citrix.com>
Thu, 27 Jun 2024 15:18:03 +0000 (17:18 +0200)
xen/arch/x86/include/asm/domain.h
xen/arch/x86/include/asm/mm.h
xen/arch/x86/mm.c
xen/arch/x86/pv/mm.c
xen/arch/x86/setup.c
xen/arch/x86/smpboot.c

index 0b527d958ad1b6ca880be3e65d3edec0c4a36e25..524319ef6d531727bea66cc2d34493af4b91ee12 100644 (file)
@@ -313,6 +313,8 @@ struct arch_domain
 {
     struct page_info *perdomain_l3_pg;
 
+    struct page_info *perdomain_l2_pgs[PERDOMAIN_SLOTS];
+
 #ifdef CONFIG_PV32
     unsigned int hv_compat_vstart;
 #endif
index fd1e814b1a8cfeff7365dc879e7023690a38f5ea..8cd360e0b3b938fad69a651f22506763d3d1b5c3 100644 (file)
@@ -632,4 +632,8 @@ static inline bool arch_mfns_in_directmap(unsigned long mfn, unsigned long nr)
     return (mfn + nr) <= (virt_to_mfn(eva - 1) + 1);
 }
 
+int allocate_perdomain_local_l3(unsigned int cpu);
+void free_perdomain_local_l3(unsigned int cpu);
+void setup_perdomain_slot(const struct vcpu *v, root_pgentry_t *root_pgt);
+
 #endif /* __ASM_X86_MM_H__ */
index e87eb19c3d9b72db74f26558ecfc11e57f137734..815eb2d865e6a91ddc4ac06cb1185b986fb4c9e7 100644 (file)
@@ -6083,6 +6083,7 @@ int create_perdomain_mapping(struct domain *d, unsigned long va,
         l2tab = __map_domain_page(pg);
         clear_page(l2tab);
         l3tab[l3_table_offset(va)] = l3e_from_page(pg, __PAGE_HYPERVISOR_RW);
+        d->arch.perdomain_l2_pgs[l3_table_offset(va)] = pg;
     }
     else
         l2tab = map_l2t_from_l3e(l3tab[l3_table_offset(va)]);
@@ -6372,11 +6373,69 @@ unsigned long get_upper_mfn_bound(void)
     return min(max_mfn, 1UL << (paddr_bits - PAGE_SHIFT)) - 1;
 }
 
-void setup_perdomain_slot(const struct vcpu *v, root_pgentry_t *root_pgt)
+static DEFINE_PER_CPU(l3_pgentry_t *, local_l3);
+
+int allocate_perdomain_local_l3(unsigned int cpu)
 {
+    l3_pgentry_t *l3;
+    root_pgentry_t *root_pgt = maddr_to_virt(idle_vcpu[cpu]->arch.cr3);
+
+    ASSERT(!per_cpu(local_l3, cpu));
+
+    if ( !opt_asi_pv && !opt_asi_hvm )
+        return 0;
+
+    l3 = alloc_xenheap_page();
+    if ( !l3 )
+        return -ENOMEM;
+
+    clear_page(l3);
+
+    per_cpu(local_l3, cpu) = l3;
+
+    /* Setup the slot in the idle page table. */
     root_pgt[root_table_offset(PERDOMAIN_VIRT_START)] =
-        l4e_from_page(v->domain->arch.perdomain_l3_pg,
-                      __PAGE_HYPERVISOR_RW);
+            l4e_from_mfn(virt_to_mfn(l3), __PAGE_HYPERVISOR_RW);
+
+    return 0;
+}
+
+void free_perdomain_local_l3(unsigned int cpu)
+{
+    l3_pgentry_t *l3 = per_cpu(local_l3, cpu);
+
+    if ( !l3 )
+        return;
+
+    per_cpu(local_l3, cpu) = NULL;
+    free_xenheap_page(l3);
+}
+
+void setup_perdomain_slot(const struct vcpu *v, root_pgentry_t *root_pgt)
+{
+    const struct domain *d = v->domain;
+
+    if ( is_pv_64bit_domain(d) && d->arch.pv.xpti )
+        root_pgt[root_table_offset(PERDOMAIN_VIRT_START)] =
+            l4e_from_page(v->domain->arch.perdomain_l3_pg,
+                          __PAGE_HYPERVISOR_RW);
+    else if ( d->arch.asi )
+    {
+        l3_pgentry_t *l3 = this_cpu(local_l3);
+        unsigned int i;
+
+        ASSERT(l3);
+
+        for ( i = 0; i < ARRAY_SIZE(d->arch.perdomain_l2_pgs); i++ )
+        {
+            const struct page_info *pg = d->arch.perdomain_l2_pgs[i];
+
+            l3[i] = pg ? l3e_from_page(pg, __PAGE_HYPERVISOR_RW) : l3e_empty();
+        }
+
+        root_pgt[root_table_offset(PERDOMAIN_VIRT_START)] =
+            l4e_from_mfn(virt_to_mfn(l3), __PAGE_HYPERVISOR_RW);
+    }
 
     if ( !is_pv_64bit_vcpu(v) )
         /*
index 7f560ea0880524998b0b576841922d1658136f17..9f3a85e04a95651763dbae49c7738b1b80b44bd2 100644 (file)
@@ -114,6 +114,8 @@ void pv_maybe_update_shadow_l4(struct vcpu *v)
                   _mfn(virt_to_mfn(this_cpu(root_pgt)))));
 
     copy_page(this_cpu(root_pgt), v->arch.pv.guest_l4);
+
+    setup_perdomain_slot(v, this_cpu(root_pgt));
 }
 
 mfn_t pv_maybe_shadow_l4(struct vcpu *v, mfn_t mfn)
index c4f6dbcb610d3e14274e789078afb985cc3a66f5..94f73a352a2b0d8a6e236501f10980c8f9827e47 100644 (file)
@@ -813,6 +813,9 @@ static void __init noreturn reinit_bsp_stack(void)
     rc = setup_cpu_root_pgt(0);
     if ( rc )
         panic("Error %d setting up PV root page table\n", rc);
+    rc = allocate_perdomain_local_l3(0);
+    if ( rc )
+        panic("Error %d setting up local per-domain L3\n", rc);
 
     if ( cpu_has_xen_shstk )
     {
index 302b1a0c759bc5e07b94c602ecb1a5f2266ec0aa..74a525a8d7aef400d2df61ea87efc6b875b8ba25 100644 (file)
@@ -995,6 +995,7 @@ static void cpu_smpboot_free(unsigned int cpu, bool remove)
     }
 
     cleanup_cpu_root_pgt(cpu);
+    free_perdomain_local_l3(cpu);
 
     if ( per_cpu(stubs.addr, cpu) )
     {
@@ -1109,6 +1110,9 @@ static int cpu_smpboot_alloc(unsigned int cpu)
     per_cpu(stubs.addr, cpu) = stub_page + STUB_BUF_CPU_OFFS(cpu);
 
     rc = setup_cpu_root_pgt(cpu);
+    if ( rc )
+        goto out;
+    rc = allocate_perdomain_local_l3(cpu);
     if ( rc )
         goto out;
     rc = -ENOMEM;