[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 2/5] x86/p2m: collapse the two ->write_p2m_entry() hooks


  • To: Jan Beulich <jbeulich@xxxxxxxx>
  • From: Roger Pau Monné <roger.pau@xxxxxxxxxx>
  • Date: Tue, 10 Nov 2020 12:06:11 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=e0jYr58tjfamTxcEsgCw9lsAJ5QTh9ksPUArderUhmM=; b=hx8HaokcvfZxirMLaLg0a5Usv9f2BQBBBU6Uweuq/INXvz1tsZqH2JRYxdivM2vZ4WlPCVopfSMizGr+14rSMQl9LQ25uWkWW+07/Ox8kR7LJxzg+AcesStWLjq3n+oYiKQ0WzsYbu27d028+2AkLuZId/U8qivoHatxvfMOBi90ThsjK8QcV3pU09lOwiuXHAbzoGdVGWgmUtJCoHBgsccmOn2BDMtEWDb+lWX5SQg9KWMQ56FFYGoAEVEgLimDVnQGT4KDxmBYe4b2w3GEUTtUIx7ThPUjEYpmwf6NntlEwZWU+QJ8qMVLK9FKGxW3zOj7Gjl9O0gWBCC9Pt0NAA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FHiG0TsDCKl3rnbO6tjBVUm0RcgdQSKoYgWxWw77NeutuMpbASTm9yagXlH8AdMo2GY6pIcltuYJ1nHGXX9n60mbWOiOogeMI5VLZO0O+1i0YKocgVjso14Sfxk9SjLtzyw4bRlVExURItOLpFuNGYECe8qdGKSseHUybTCAOTG6EvwB328nk+ZB6koKgCNKNcDO/Or9cZ6iEq7BmbnMgunggpmugmV41Re9EoALy9nyrjgPJQSLFKf5UF5RJ7vw/oYadQx4/tY/tCtS58Rx2ZsiyWCaaAa7lVWlzT8EgyTC4cuFBxqgOYp9k3pQq1f5ucrNQ0KD0YPIU1HIqVCz5w==
  • Authentication-results: esa6.hc3370-68.iphmx.com; dkim=pass (signature verified) header.i=@citrix.onmicrosoft.com
  • Cc: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, George Dunlap <George.Dunlap@xxxxxxxxxxxxx>, Tim Deegan <tim@xxxxxxx>
  • Delivery-date: Tue, 10 Nov 2020 11:06:43 +0000
  • Ironport-sdr: 4tyJ30fWxdKDPOogYFRirC82FqLHUxjtxFwwHK36xTsQt5NlgEdCnN2+0p9kcoQxTDLA971PFb 9L6+QCo4Kqg9lYQVNGetrNrN2hK+EusKvUFiSWJbtZtRkdQtsWSQMoB+ro3tFRa7Qt8ax59pRG heTsdQf8ZQV1buBDQoQHwkFhDXdjWYAvRy21OQ1mRw19EreBa+ODxwnkGbj8VGKaSwuxmdLaqD //hQeXNLmt7Lcqe0ELQn6aa2NiDptht1blB+JjzEm1ag/YPZmoWvYCZr5OzHrc1/eGQHkCgjgS 8Dc=
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On Wed, Oct 28, 2020 at 10:22:58AM +0100, Jan Beulich wrote:
> The struct paging_mode instances get set to the same functions
> regardless of mode by both HAP and shadow code, hence there's no point
> having this hook there. The hook also doesn't need moving elsewhere - we
> can directly use struct p2m_domain's. This merely requires (from a
> strictly formal pov; in practice this may not even be needed) making
> sure we don't end up using safe_write_pte() for nested P2Ms.
> 
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> ---
> Like for the possibly unnecessary p2m_is_nestedp2m() I'm not really sure
> the paging_get_hostmode() check there is still needed either. But I
> didn't want to alter more aspects than necessary here.
> 
> Of course with the p2m_is_nestedp2m() check there and with all three of
> {hap,nestedp2m,shadow}_write_p2m_entry() now globally accessible, it's
> certainly an option to do away with the indirect call there altogether.
> In fact we may even be able to go further and fold the three functions:
> They're relatively similar, and this would "seamlessly" address the
> apparent bug of nestedp2m_write_p2m_entry() not making use of
> p2m_entry_modify().
> 
> --- a/xen/arch/x86/mm/hap/hap.c
> +++ b/xen/arch/x86/mm/hap/hap.c
> @@ -823,6 +823,11 @@ hap_write_p2m_entry(struct p2m_domain *p
>      return 0;
>  }
>  
> +void hap_p2m_init(struct p2m_domain *p2m)
> +{
> +    p2m->write_p2m_entry = hap_write_p2m_entry;
> +}
> +
>  static unsigned long hap_gva_to_gfn_real_mode(
>      struct vcpu *v, struct p2m_domain *p2m, unsigned long gva, uint32_t 
> *pfec)
>  {
> @@ -846,7 +851,6 @@ static const struct paging_mode hap_pagi
>      .p2m_ga_to_gfn          = hap_p2m_ga_to_gfn_real_mode,
>      .update_cr3             = hap_update_cr3,
>      .update_paging_modes    = hap_update_paging_modes,
> -    .write_p2m_entry        = hap_write_p2m_entry,
>      .flush_tlb              = flush_tlb,
>      .guest_levels           = 1
>  };
> @@ -858,7 +862,6 @@ static const struct paging_mode hap_pagi
>      .p2m_ga_to_gfn          = hap_p2m_ga_to_gfn_2_levels,
>      .update_cr3             = hap_update_cr3,
>      .update_paging_modes    = hap_update_paging_modes,
> -    .write_p2m_entry        = hap_write_p2m_entry,
>      .flush_tlb              = flush_tlb,
>      .guest_levels           = 2
>  };
> @@ -870,7 +873,6 @@ static const struct paging_mode hap_pagi
>      .p2m_ga_to_gfn          = hap_p2m_ga_to_gfn_3_levels,
>      .update_cr3             = hap_update_cr3,
>      .update_paging_modes    = hap_update_paging_modes,
> -    .write_p2m_entry        = hap_write_p2m_entry,
>      .flush_tlb              = flush_tlb,
>      .guest_levels           = 3
>  };
> @@ -882,7 +884,6 @@ static const struct paging_mode hap_pagi
>      .p2m_ga_to_gfn          = hap_p2m_ga_to_gfn_4_levels,
>      .update_cr3             = hap_update_cr3,
>      .update_paging_modes    = hap_update_paging_modes,
> -    .write_p2m_entry        = hap_write_p2m_entry,
>      .flush_tlb              = flush_tlb,
>      .guest_levels           = 4
>  };
> --- a/xen/arch/x86/mm/p2m-pt.c
> +++ b/xen/arch/x86/mm/p2m-pt.c
> @@ -126,8 +126,9 @@ static int write_p2m_entry(struct p2m_do
>  
>      if ( v->domain != d )
>          v = d->vcpu ? d->vcpu[0] : NULL;
> -    if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v)) )
> -        rc = paging_get_hostmode(v)->write_p2m_entry(p2m, gfn, p, new, 
> level);
> +    if ( likely(v && paging_mode_enabled(d) && paging_get_hostmode(v)) ||
> +         p2m_is_nestedp2m(p2m) )
> +        rc = p2m->write_p2m_entry(p2m, gfn, p, new, level);
>      else
>          safe_write_pte(p, new);
>  
> @@ -209,7 +210,7 @@ p2m_next_level(struct p2m_domain *p2m, v
>  
>          new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW);
>  
> -        rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1);
> +        rc = write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1);
>          if ( rc )
>              goto error;
>      }
> @@ -251,7 +252,7 @@ p2m_next_level(struct p2m_domain *p2m, v
>          {
>              new_entry = l1e_from_pfn(pfn | (i << ((level - 1) * 
> PAGETABLE_ORDER)),
>                                       flags);
> -            rc = p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, 
> level);
> +            rc = write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, level);
>              if ( rc )
>              {
>                  unmap_domain_page(l1_entry);
> @@ -262,8 +263,7 @@ p2m_next_level(struct p2m_domain *p2m, v
>          unmap_domain_page(l1_entry);
>  
>          new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW);
> -        rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry,
> -                                  level + 1);
> +        rc = write_p2m_entry(p2m, gfn, p2m_entry, new_entry, level + 1);
>          if ( rc )
>              goto error;
>      }
> @@ -335,7 +335,7 @@ static int p2m_pt_set_recalc_range(struc
>              if ( (l1e_get_flags(e) & _PAGE_PRESENT) && !needs_recalc(l1, e) )
>              {
>                  set_recalc(l1, e);
> -                err = p2m->write_p2m_entry(p2m, first_gfn, pent, e, level);
> +                err = write_p2m_entry(p2m, first_gfn, pent, e, level);
>                  if ( err )
>                  {
>                      ASSERT_UNREACHABLE();
> @@ -412,8 +412,8 @@ static int do_recalc(struct p2m_domain *
>                       !needs_recalc(l1, ent) )
>                  {
>                      set_recalc(l1, ent);
> -                    err = p2m->write_p2m_entry(p2m, gfn - remainder, 
> &ptab[i],
> -                                               ent, level);
> +                    err = write_p2m_entry(p2m, gfn - remainder, &ptab[i], 
> ent,
> +                                          level);
>                      if ( err )
>                      {
>                          ASSERT_UNREACHABLE();
> @@ -426,7 +426,7 @@ static int do_recalc(struct p2m_domain *
>              if ( !err )
>              {
>                  clear_recalc(l1, e);
> -                err = p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1);
> +                err = write_p2m_entry(p2m, gfn, pent, e, level + 1);
>                  ASSERT(!err);
>  
>                  recalc_done = true;
> @@ -474,7 +474,7 @@ static int do_recalc(struct p2m_domain *
>          }
>          else
>              clear_recalc(l1, e);
> -        err = p2m->write_p2m_entry(p2m, gfn, pent, e, level + 1);
> +        err = write_p2m_entry(p2m, gfn, pent, e, level + 1);
>          ASSERT(!err);
>  
>          recalc_done = true;
> @@ -618,7 +618,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m,
>              : l3e_empty();
>          entry_content.l1 = l3e_content.l3;
>  
> -        rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3);
> +        rc = write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 3);
>          /* NB: write_p2m_entry() handles tlb flushes properly */
>          if ( rc )
>              goto out;
> @@ -655,7 +655,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m,
>              entry_content = l1e_empty();
>  
>          /* level 1 entry */
> -        rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1);
> +        rc = write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 1);
>          /* NB: write_p2m_entry() handles tlb flushes properly */
>          if ( rc )
>              goto out;
> @@ -690,7 +690,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m,
>              : l2e_empty();
>          entry_content.l1 = l2e_content.l2;
>  
> -        rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2);
> +        rc = write_p2m_entry(p2m, gfn, p2m_entry, entry_content, 2);
>          /* NB: write_p2m_entry() handles tlb flushes properly */
>          if ( rc )
>              goto out;
> @@ -914,7 +914,7 @@ static void p2m_pt_change_entry_type_glo
>              int rc;
>  
>              set_recalc(l1, e);
> -            rc = p2m->write_p2m_entry(p2m, gfn, &tab[i], e, 4);
> +            rc = write_p2m_entry(p2m, gfn, &tab[i], e, 4);
>              if ( rc )
>              {
>                  ASSERT_UNREACHABLE();
> @@ -1132,7 +1132,13 @@ void p2m_pt_init(struct p2m_domain *p2m)
>      p2m->recalc = do_recalc;
>      p2m->change_entry_type_global = p2m_pt_change_entry_type_global;
>      p2m->change_entry_type_range = p2m_pt_change_entry_type_range;
> -    p2m->write_p2m_entry = write_p2m_entry;
> +
> +    /* Still too early to use paging_mode_hap(). */
> +    if ( hap_enabled(p2m->domain) )
> +        hap_p2m_init(p2m);
> +    else if ( IS_ENABLED(CONFIG_SHADOW_PAGING) )
> +        shadow_p2m_init(p2m);

There's already some logic in p2m_initialise that checks for
hap_enabled for EPT specific initialization. Do you think you could
move this there so that it's more contained?

I think having the initialization condition sprinkled all over the
different functions makes the logic more complicated to follow.

Also, should hap_p2m_init be limited to HAP and PT, as opposed to HAP
and EPT which doesn't use the helper AFAICT?

Maybe it would be clearer to unify shadow_write_p2m_entry with
hap_write_p2m_entry and call it p2m_pt_write_p2m_entry to match the
rest of the p2m PT helpers?

Thanks, Roger.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.