Message ID | 20181220192338.17526-5-julien.grall@arm.com |
---|---|
State | New |
Headers | show |
Series | xen/arm: Add xentrace support | expand |
On Thu, 20 Dec 2018, Julien Grall wrote: > Current, foreign mappings can only be read-write. A follow-up patch will > extend foreign mapping for Xen backend memory (via XEN_DOMID), some of > that memory should only be read accessible for the mapping domain. > > Introduce a new p2m_type to cater read-only foreign mappings. For now, > the decision between the two foreign mapping type is based on the type > of the guest page mapped. > > Signed-off-by: Julien Grall <julien.grall@arm.com> > Reviewed-by: Andrii Anisov <andrii_anisov@epam.com> > > --- > > Changes in v2: > - Add Andrii's reviewed-by > --- > xen/arch/arm/mm.c | 2 +- > xen/arch/arm/p2m.c | 1 + > xen/include/asm-arm/p2m.h | 42 +++++++++++++++++++++++++++++++++++++++--- > 3 files changed, 41 insertions(+), 4 deletions(-) > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > index 7193d83b44..58f7e54640 100644 > --- a/xen/arch/arm/mm.c > +++ b/xen/arch/arm/mm.c > @@ -1267,7 +1267,7 @@ int xenmem_add_to_physmap_one( > } > > mfn = page_to_mfn(page); > - t = p2m_map_foreign_rw; > + t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro; I know there is a p2m_is_ram check close by, but I think it would still be better to do: if (p2mt == p2m_ram_rw) t = p2m_map_foreign_rw; else if (p2mt == p2m_ram_ro) t = p2m_map_foreign_ro; else error to avoid cases where p2mt is something completely different (p2m_mmio_direct_dev for instance) and t gets set to p2m_map_foreign_ro by mistake. > rcu_unlock_domain(od); > break; > diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c > index e0b84a9db5..dea04ef66f 100644 > --- a/xen/arch/arm/p2m.c > +++ b/xen/arch/arm/p2m.c > @@ -477,6 +477,7 @@ static void p2m_set_permission(lpae_t *e, p2m_type_t t, p2m_access_t a) > break; > > case p2m_iommu_map_ro: > + case p2m_map_foreign_ro: > case p2m_grant_map_ro: > case p2m_invalid: > e->p2m.xn = 1; > diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h > index a1aef7b793..6f2728e2bb 100644 > --- a/xen/include/asm-arm/p2m.h > +++ b/xen/include/asm-arm/p2m.h > @@ -116,6 +116,7 @@ typedef enum { > p2m_mmio_direct_nc, /* Read/write mapping of genuine MMIO area non-cacheable */ > p2m_mmio_direct_c, /* Read/write mapping of genuine MMIO area cacheable */ > p2m_map_foreign_rw, /* Read/write RAM pages from foreign domain */ > + p2m_map_foreign_ro, /* Read-only RAM pages from foreign domain */ > p2m_grant_map_rw, /* Read/write grant mapping */ > p2m_grant_map_ro, /* Read-only grant mapping */ > /* The types below are only used to decide the page attribute in the P2M */ > @@ -135,12 +136,16 @@ typedef enum { > #define P2M_GRANT_TYPES (p2m_to_mask(p2m_grant_map_rw) | \ > p2m_to_mask(p2m_grant_map_ro)) > > +/* Foreign mappings types */ > +#define P2M_FOREIGN_TYPES (p2m_to_mask(p2m_map_foreign_rw) | \ > + p2m_to_mask(p2m_map_foreign_ro)) > + > /* Useful predicates */ > #define p2m_is_ram(_t) (p2m_to_mask(_t) & P2M_RAM_TYPES) > -#define p2m_is_foreign(_t) (p2m_to_mask(_t) & p2m_to_mask(p2m_map_foreign_rw)) > +#define p2m_is_foreign(_t) (p2m_to_mask(_t) & P2M_FOREIGN_TYPES) > #define p2m_is_any_ram(_t) (p2m_to_mask(_t) & \ > (P2M_RAM_TYPES | P2M_GRANT_TYPES | \ > - p2m_to_mask(p2m_map_foreign_rw))) > + P2M_FOREIGN_TYPES)) > > /* All common type definitions should live ahead of this inclusion. */ > #ifdef _XEN_P2M_COMMON_H > @@ -295,7 +300,38 @@ struct page_info *p2m_get_page_from_gfn(struct domain *d, gfn_t gfn, > static inline struct page_info *get_page_from_gfn( > struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q) > { > - return p2m_get_page_from_gfn(d, _gfn(gfn), t); > + mfn_t mfn; > + p2m_type_t _t; > + struct page_info *page; > + > + /* > + * Special case for DOMID_XEN as it is the only domain so far that is > + * not auto-translated. > + */ > + if ( unlikely(d != dom_xen) ) Why unlikely? > + return p2m_get_page_from_gfn(d, _gfn(gfn), t); > + > + if ( !t ) > + t = &_t; > + > + *t = p2m_invalid; > + > + /* > + * DOMID_XEN see 1-1 RAM. The p2m_type is based on the type of the ^sees > + * page. > + */ > + mfn = _mfn(gfn); > + page = mfn_to_page(mfn); > + > + if ( !mfn_valid(mfn) || !get_page(page, d) ) > + return NULL; > + > + if ( page->u.inuse.type_info & PGT_writable_page ) > + *t = p2m_ram_rw; > + else > + *t = p2m_ram_ro; > + > + return page; > } > > int get_page_type(struct page_info *page, unsigned long type); > -- > 2.11.0 >
(Sorry for the formatting) On Thu, 20 Dec 2018 at 23:08, Stefano Stabellini <sstabellini@kernel.org> wrote: > On Thu, 20 Dec 2018, Julien Grall wrote: > > Current, foreign mappings can only be read-write. A follow-up patch will > > extend foreign mapping for Xen backend memory (via XEN_DOMID), some of > > that memory should only be read accessible for the mapping domain. > > > > Introduce a new p2m_type to cater read-only foreign mappings. For now, > > the decision between the two foreign mapping type is based on the type > > of the guest page mapped. > > > > Signed-off-by: Julien Grall <julien.grall@arm.com> > > Reviewed-by: Andrii Anisov <andrii_anisov@epam.com> > > > > --- > > > > Changes in v2: > > - Add Andrii's reviewed-by > > --- > > xen/arch/arm/mm.c | 2 +- > > xen/arch/arm/p2m.c | 1 + > > xen/include/asm-arm/p2m.h | 42 > +++++++++++++++++++++++++++++++++++++++--- > > 3 files changed, 41 insertions(+), 4 deletions(-) > > > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > > index 7193d83b44..58f7e54640 100644 > > --- a/xen/arch/arm/mm.c > > +++ b/xen/arch/arm/mm.c > > @@ -1267,7 +1267,7 @@ int xenmem_add_to_physmap_one( > > } > > > > mfn = page_to_mfn(page); > > - t = p2m_map_foreign_rw; > > + t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : > p2m_map_foreign_ro; > > I know there is a p2m_is_ram check close by, but I think it would still > be better to do: > > if (p2mt == p2m_ram_rw) > t = p2m_map_foreign_rw; > else if (p2mt == p2m_ram_ro) > t = p2m_map_foreign_ro; > else > error > > to avoid cases where p2mt is something completely different > (p2m_mmio_direct_dev for instance) and t gets set to p2m_map_foreign_ro > by mistake. The case you suggest is impossible. You can only be here if you manage to get a reference on the page (e.g p2m_foreign or p2m_ram). The check above remove the foreign types. But if you ever get here there are not much harm done as it would be read-only. The extras 5 lines of code are just not worth it. > > > rcu_unlock_domain(od); > > break; > > diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c > > index e0b84a9db5..dea04ef66f 100644 > > --- a/xen/arch/arm/p2m.c > > +++ b/xen/arch/arm/p2m.c > > @@ -477,6 +477,7 @@ static void p2m_set_permission(lpae_t *e, p2m_type_t > t, p2m_access_t a) > > break; > > > > case p2m_iommu_map_ro: > > + case p2m_map_foreign_ro: > > case p2m_grant_map_ro: > > case p2m_invalid: > > e->p2m.xn = 1; > > diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h > > index a1aef7b793..6f2728e2bb 100644 > > --- a/xen/include/asm-arm/p2m.h > > +++ b/xen/include/asm-arm/p2m.h > > @@ -116,6 +116,7 @@ typedef enum { > > p2m_mmio_direct_nc, /* Read/write mapping of genuine MMIO area > non-cacheable */ > > p2m_mmio_direct_c, /* Read/write mapping of genuine MMIO area > cacheable */ > > p2m_map_foreign_rw, /* Read/write RAM pages from foreign domain */ > > + p2m_map_foreign_ro, /* Read-only RAM pages from foreign domain */ > > p2m_grant_map_rw, /* Read/write grant mapping */ > > p2m_grant_map_ro, /* Read-only grant mapping */ > > /* The types below are only used to decide the page attribute in > the P2M */ > > @@ -135,12 +136,16 @@ typedef enum { > > #define P2M_GRANT_TYPES (p2m_to_mask(p2m_grant_map_rw) | \ > > p2m_to_mask(p2m_grant_map_ro)) > > > > +/* Foreign mappings types */ > > +#define P2M_FOREIGN_TYPES (p2m_to_mask(p2m_map_foreign_rw) | \ > > + p2m_to_mask(p2m_map_foreign_ro)) > > + > > /* Useful predicates */ > > #define p2m_is_ram(_t) (p2m_to_mask(_t) & P2M_RAM_TYPES) > > -#define p2m_is_foreign(_t) (p2m_to_mask(_t) & > p2m_to_mask(p2m_map_foreign_rw)) > > +#define p2m_is_foreign(_t) (p2m_to_mask(_t) & P2M_FOREIGN_TYPES) > > #define p2m_is_any_ram(_t) (p2m_to_mask(_t) & \ > > (P2M_RAM_TYPES | P2M_GRANT_TYPES | \ > > - p2m_to_mask(p2m_map_foreign_rw))) > > + P2M_FOREIGN_TYPES)) > > > > /* All common type definitions should live ahead of this inclusion. */ > > #ifdef _XEN_P2M_COMMON_H > > @@ -295,7 +300,38 @@ struct page_info *p2m_get_page_from_gfn(struct > domain *d, gfn_t gfn, > > static inline struct page_info *get_page_from_gfn( > > struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q) > > { > > - return p2m_get_page_from_gfn(d, _gfn(gfn), t); > > + mfn_t mfn; > > + p2m_type_t _t; > > + struct page_info *page; > > + > > + /* > > + * Special case for DOMID_XEN as it is the only domain so far that > is > > + * not auto-translated. > > + */ > > + if ( unlikely(d != dom_xen) ) > > Why unlikely? I got the wrong way around. It should have been likely. > > > + return p2m_get_page_from_gfn(d, _gfn(gfn), t); > > + > > + if ( !t ) > > + t = &_t; > > + > > + *t = p2m_invalid; > > + > > + /* > > + * DOMID_XEN see 1-1 RAM. The p2m_type is based on the type of the > ^sees > > > + * page. > > + */ > > + mfn = _mfn(gfn); > > + page = mfn_to_page(mfn); > > + > > + if ( !mfn_valid(mfn) || !get_page(page, d) ) > > + return NULL; > > + > > + if ( page->u.inuse.type_info & PGT_writable_page ) > > + *t = p2m_ram_rw; > > + else > > + *t = p2m_ram_ro; > > + > > + return page; > > } > > > > int get_page_type(struct page_info *page, unsigned long type); > > -- > > 2.11.0 > > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xenproject.org > https://lists.xenproject.org/mailman/listinfo/xen-devel <div><div dir="auto">(Sorry for the formatting)</div></div><div><br><div class="gmail_quote"><div dir="ltr">On Thu, 20 Dec 2018 at 23:08, Stefano Stabellini <<a href="mailto:sstabellini@kernel.org">sstabellini@kernel.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Thu, 20 Dec 2018, Julien Grall wrote:<br> > Current, foreign mappings can only be read-write. A follow-up patch will<br> > extend foreign mapping for Xen backend memory (via XEN_DOMID), some of<br> > that memory should only be read accessible for the mapping domain.<br> > <br> > Introduce a new p2m_type to cater read-only foreign mappings. For now,<br> > the decision between the two foreign mapping type is based on the type<br> > of the guest page mapped.<br> > <br> > Signed-off-by: Julien Grall <<a href="mailto:julien.grall@arm.com" target="_blank">julien.grall@arm.com</a>><br> > Reviewed-by: Andrii Anisov <<a href="mailto:andrii_anisov@epam.com" target="_blank">andrii_anisov@epam.com</a>><br> > <br> > ---<br> > <br> > Changes in v2:<br> > - Add Andrii's reviewed-by<br> > ---<br> > xen/arch/arm/mm.c | 2 +-<br> > xen/arch/arm/p2m.c | 1 +<br> > xen/include/asm-arm/p2m.h | 42 +++++++++++++++++++++++++++++++++++++++---<br> > 3 files changed, 41 insertions(+), 4 deletions(-)<br> > <br> > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c<br> > index 7193d83b44..58f7e54640 100644<br> > --- a/xen/arch/arm/mm.c<br> > +++ b/xen/arch/arm/mm.c<br> > @@ -1267,7 +1267,7 @@ int xenmem_add_to_physmap_one(<br> > }<br> > <br> > mfn = page_to_mfn(page);<br> > - t = p2m_map_foreign_rw;<br> > + t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro;<br> <br> I know there is a p2m_is_ram check close by, but I think it would still<br> be better to do:<br> <br> if (p2mt == p2m_ram_rw)<br> t = p2m_map_foreign_rw;<br> else if (p2mt == p2m_ram_ro)<br> t = p2m_map_foreign_ro;<br> else<br> error<br> <br> to avoid cases where p2mt is something completely different<br> (p2m_mmio_direct_dev for instance) and t gets set to p2m_map_foreign_ro<br> by mistake.</blockquote><div dir="auto"><br></div><div dir="auto">The case you suggest is impossible. You can only be here if you manage to get a reference on the page (e.g p2m_foreign or p2m_ram).</div><div dir="auto">The check above remove the foreign types. But if you ever get here there are not much harm done as it would be read-only.</div><div dir="auto"><br></div><div dir="auto">The extras 5 lines of code are just not worth it.</div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br> <br> > rcu_unlock_domain(od);<br> > break;<br> > diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c<br> > index e0b84a9db5..dea04ef66f 100644<br> > --- a/xen/arch/arm/p2m.c<br> > +++ b/xen/arch/arm/p2m.c<br> > @@ -477,6 +477,7 @@ static void p2m_set_permission(lpae_t *e, p2m_type_t t, p2m_access_t a)<br> > break;<br> > <br> > case p2m_iommu_map_ro:<br> > + case p2m_map_foreign_ro:<br> > case p2m_grant_map_ro:<br> > case p2m_invalid:<br> > e->p2m.xn = 1;<br> > diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h<br> > index a1aef7b793..6f2728e2bb 100644<br> > --- a/xen/include/asm-arm/p2m.h<br> > +++ b/xen/include/asm-arm/p2m.h<br> > @@ -116,6 +116,7 @@ typedef enum {<br> > p2m_mmio_direct_nc, /* Read/write mapping of genuine MMIO area non-cacheable */<br> > p2m_mmio_direct_c, /* Read/write mapping of genuine MMIO area cacheable */<br> > p2m_map_foreign_rw, /* Read/write RAM pages from foreign domain */<br> > + p2m_map_foreign_ro, /* Read-only RAM pages from foreign domain */<br> > p2m_grant_map_rw, /* Read/write grant mapping */<br> > p2m_grant_map_ro, /* Read-only grant mapping */<br> > /* The types below are only used to decide the page attribute in the P2M */<br> > @@ -135,12 +136,16 @@ typedef enum {<br> > #define P2M_GRANT_TYPES (p2m_to_mask(p2m_grant_map_rw) | \<br> > p2m_to_mask(p2m_grant_map_ro))<br> > <br> > +/* Foreign mappings types */<br> > +#define P2M_FOREIGN_TYPES (p2m_to_mask(p2m_map_foreign_rw) | \<br> > + p2m_to_mask(p2m_map_foreign_ro))<br> > +<br> > /* Useful predicates */<br> > #define p2m_is_ram(_t) (p2m_to_mask(_t) & P2M_RAM_TYPES)<br> > -#define p2m_is_foreign(_t) (p2m_to_mask(_t) & p2m_to_mask(p2m_map_foreign_rw))<br> > +#define p2m_is_foreign(_t) (p2m_to_mask(_t) & P2M_FOREIGN_TYPES)<br> > #define p2m_is_any_ram(_t) (p2m_to_mask(_t) & \<br> > (P2M_RAM_TYPES | P2M_GRANT_TYPES | \<br> > - p2m_to_mask(p2m_map_foreign_rw)))<br> > + P2M_FOREIGN_TYPES))<br> > <br> > /* All common type definitions should live ahead of this inclusion. */<br> > #ifdef _XEN_P2M_COMMON_H<br> > @@ -295,7 +300,38 @@ struct page_info *p2m_get_page_from_gfn(struct domain *d, gfn_t gfn,<br> > static inline struct page_info *get_page_from_gfn(<br> > struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q)<br> > {<br> > - return p2m_get_page_from_gfn(d, _gfn(gfn), t);<br> > + mfn_t mfn;<br> > + p2m_type_t _t;<br> > + struct page_info *page;<br> > +<br> > + /*<br> > + * Special case for DOMID_XEN as it is the only domain so far that is<br> > + * not auto-translated.<br> > + */<br> > + if ( unlikely(d != dom_xen) )<br> <br> Why unlikely?</blockquote><div dir="auto"><br></div><div dir="auto">I got the wrong way around. It should have been likely.</div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br> <br> > + return p2m_get_page_from_gfn(d, _gfn(gfn), t);<br> > +<br> > + if ( !t )<br> > + t = &_t;<br> > +<br> > + *t = p2m_invalid;<br> > +<br> > + /*<br> > + * DOMID_XEN see 1-1 RAM. The p2m_type is based on the type of the<br> ^sees<br> <br> > + * page.<br> > + */<br> > + mfn = _mfn(gfn);<br> > + page = mfn_to_page(mfn);<br> > +<br> > + if ( !mfn_valid(mfn) || !get_page(page, d) )<br> > + return NULL;<br> > +<br> > + if ( page->u.inuse.type_info & PGT_writable_page )<br> > + *t = p2m_ram_rw;<br> > + else<br> > + *t = p2m_ram_ro;<br> > +<br> > + return page;<br> > }<br> > <br> > int get_page_type(struct page_info *page, unsigned long type);<br> > -- <br> > 2.11.0<br> > <br> <br> _______________________________________________<br> Xen-devel mailing list<br> <a href="mailto:Xen-devel@lists.xenproject.org" target="_blank">Xen-devel@lists.xenproject.org</a><br> <a href="https://lists.xenproject.org/mailman/listinfo/xen-devel" rel="noreferrer" target="_blank">https://lists.xenproject.org/mailman/listinfo/xen-devel</a></blockquote></div></div>
On Thu, 20 Dec 2018, Julien Grall wrote: > (Sorry for the formatting) > > On Thu, 20 Dec 2018 at 23:08, Stefano Stabellini <sstabellini@kernel.org> wrote: > On Thu, 20 Dec 2018, Julien Grall wrote: > > Current, foreign mappings can only be read-write. A follow-up patch will > > extend foreign mapping for Xen backend memory (via XEN_DOMID), some of > > that memory should only be read accessible for the mapping domain. > > > > Introduce a new p2m_type to cater read-only foreign mappings. For now, > > the decision between the two foreign mapping type is based on the type > > of the guest page mapped. > > > > Signed-off-by: Julien Grall <julien.grall@arm.com> > > Reviewed-by: Andrii Anisov <andrii_anisov@epam.com> > > > > --- > > > > Changes in v2: > > - Add Andrii's reviewed-by > > --- > > xen/arch/arm/mm.c | 2 +- > > xen/arch/arm/p2m.c | 1 + > > xen/include/asm-arm/p2m.h | 42 +++++++++++++++++++++++++++++++++++++++--- > > 3 files changed, 41 insertions(+), 4 deletions(-) > > > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > > index 7193d83b44..58f7e54640 100644 > > --- a/xen/arch/arm/mm.c > > +++ b/xen/arch/arm/mm.c > > @@ -1267,7 +1267,7 @@ int xenmem_add_to_physmap_one( > > } > > > > mfn = page_to_mfn(page); > > - t = p2m_map_foreign_rw; > > + t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro; > > I know there is a p2m_is_ram check close by, but I think it would still > be better to do: > > if (p2mt == p2m_ram_rw) > t = p2m_map_foreign_rw; > else if (p2mt == p2m_ram_ro) > t = p2m_map_foreign_ro; > else > error > > to avoid cases where p2mt is something completely different > (p2m_mmio_direct_dev for instance) and t gets set to p2m_map_foreign_ro > by mistake. > > > The case you suggest is impossible. You can only be here if you manage to get a reference on the page (e.g p2m_foreign or > p2m_ram). > The check above remove the foreign types. But if you ever get here there are not much harm done as it would be read-only. > > The extras 5 lines of code are just not worth it. I realize the case is impossible today, it was for clarity and for future proof-ness. You can reduce line code count by combining it with the p2m_is_ram check above: diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 49d7a76..01ae2cc 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -1259,7 +1259,9 @@ int xenmem_add_to_physmap_one( return -EINVAL; } - if ( !p2m_is_ram(p2mt) ) + if ( p2m_is_ram(p2mt) ) + t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro; + else { put_page(page); put_pg_owner(od); @@ -1267,7 +1269,6 @@ int xenmem_add_to_physmap_one( } mfn = page_to_mfn(page); - t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro; put_pg_owner(od); break;
Hi, On 20/12/2018 23:35, Stefano Stabellini wrote: > On Thu, 20 Dec 2018, Julien Grall wrote: >> (Sorry for the formatting) >> >> On Thu, 20 Dec 2018 at 23:08, Stefano Stabellini <sstabellini@kernel.org> wrote: >> On Thu, 20 Dec 2018, Julien Grall wrote: >> > Current, foreign mappings can only be read-write. A follow-up patch will >> > extend foreign mapping for Xen backend memory (via XEN_DOMID), some of >> > that memory should only be read accessible for the mapping domain. >> > >> > Introduce a new p2m_type to cater read-only foreign mappings. For now, >> > the decision between the two foreign mapping type is based on the type >> > of the guest page mapped. >> > >> > Signed-off-by: Julien Grall <julien.grall@arm.com> >> > Reviewed-by: Andrii Anisov <andrii_anisov@epam.com> >> > >> > --- >> > >> > Changes in v2: >> > - Add Andrii's reviewed-by >> > --- >> > xen/arch/arm/mm.c | 2 +- >> > xen/arch/arm/p2m.c | 1 + >> > xen/include/asm-arm/p2m.h | 42 +++++++++++++++++++++++++++++++++++++++--- >> > 3 files changed, 41 insertions(+), 4 deletions(-) >> > >> > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c >> > index 7193d83b44..58f7e54640 100644 >> > --- a/xen/arch/arm/mm.c >> > +++ b/xen/arch/arm/mm.c >> > @@ -1267,7 +1267,7 @@ int xenmem_add_to_physmap_one( >> > } >> > >> > mfn = page_to_mfn(page); >> > - t = p2m_map_foreign_rw; >> > + t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro; >> >> I know there is a p2m_is_ram check close by, but I think it would still >> be better to do: >> >> if (p2mt == p2m_ram_rw) >> t = p2m_map_foreign_rw; >> else if (p2mt == p2m_ram_ro) >> t = p2m_map_foreign_ro; >> else >> error >> >> to avoid cases where p2mt is something completely different >> (p2m_mmio_direct_dev for instance) and t gets set to p2m_map_foreign_ro >> by mistake. >> >> >> The case you suggest is impossible. You can only be here if you manage to get a reference on the page (e.g p2m_foreign or >> p2m_ram). >> The check above remove the foreign types. But if you ever get here there are not much harm done as it would be read-only. >> >> The extras 5 lines of code are just not worth it. > > I realize the case is impossible today, it was for clarity and for > future proof-ness. You can reduce line code count by combining it with > the p2m_is_ram check above: > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > index 49d7a76..01ae2cc 100644 > --- a/xen/arch/arm/mm.c > +++ b/xen/arch/arm/mm.c > @@ -1259,7 +1259,9 @@ int xenmem_add_to_physmap_one( > return -EINVAL; > } > > - if ( !p2m_is_ram(p2mt) ) > + if ( p2m_is_ram(p2mt) ) > + t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro; > + else > { > put_page(page); > put_pg_owner(od); > @@ -1267,7 +1269,6 @@ int xenmem_add_to_physmap_one( > } > > mfn = page_to_mfn(page); > - t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro; > > put_pg_owner(od); > break; > That's a better solution. I will update the patch. Cheers,
Hi, On 20/12/2018 19:23, Julien Grall wrote: > Current, foreign mappings can only be read-write. A follow-up patch will > extend foreign mapping for Xen backend memory (via XEN_DOMID), some of > that memory should only be read accessible for the mapping domain. > > Introduce a new p2m_type to cater read-only foreign mappings. For now, > the decision between the two foreign mapping type is based on the type > of the guest page mapped. > > Signed-off-by: Julien Grall <julien.grall@arm.com> > Reviewed-by: Andrii Anisov <andrii_anisov@epam.com> > > --- > > Changes in v2: > - Add Andrii's reviewed-by > --- > xen/arch/arm/mm.c | 2 +- > xen/arch/arm/p2m.c | 1 + > xen/include/asm-arm/p2m.h | 42 +++++++++++++++++++++++++++++++++++++++--- > 3 files changed, 41 insertions(+), 4 deletions(-) > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > index 7193d83b44..58f7e54640 100644 > --- a/xen/arch/arm/mm.c > +++ b/xen/arch/arm/mm.c > @@ -1267,7 +1267,7 @@ int xenmem_add_to_physmap_one( > } > > mfn = page_to_mfn(page); > - t = p2m_map_foreign_rw; > + t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro; > > rcu_unlock_domain(od); > break; > diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c > index e0b84a9db5..dea04ef66f 100644 > --- a/xen/arch/arm/p2m.c > +++ b/xen/arch/arm/p2m.c > @@ -477,6 +477,7 @@ static void p2m_set_permission(lpae_t *e, p2m_type_t t, p2m_access_t a) > break; > > case p2m_iommu_map_ro: > + case p2m_map_foreign_ro: > case p2m_grant_map_ro: > case p2m_invalid: > e->p2m.xn = 1; > diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h > index a1aef7b793..6f2728e2bb 100644 > --- a/xen/include/asm-arm/p2m.h > +++ b/xen/include/asm-arm/p2m.h > @@ -116,6 +116,7 @@ typedef enum { > p2m_mmio_direct_nc, /* Read/write mapping of genuine MMIO area non-cacheable */ > p2m_mmio_direct_c, /* Read/write mapping of genuine MMIO area cacheable */ > p2m_map_foreign_rw, /* Read/write RAM pages from foreign domain */ > + p2m_map_foreign_ro, /* Read-only RAM pages from foreign domain */ > p2m_grant_map_rw, /* Read/write grant mapping */ > p2m_grant_map_ro, /* Read-only grant mapping */ > /* The types below are only used to decide the page attribute in the P2M */ > @@ -135,12 +136,16 @@ typedef enum { > #define P2M_GRANT_TYPES (p2m_to_mask(p2m_grant_map_rw) | \ > p2m_to_mask(p2m_grant_map_ro)) > > +/* Foreign mappings types */ > +#define P2M_FOREIGN_TYPES (p2m_to_mask(p2m_map_foreign_rw) | \ > + p2m_to_mask(p2m_map_foreign_ro)) > + > /* Useful predicates */ > #define p2m_is_ram(_t) (p2m_to_mask(_t) & P2M_RAM_TYPES) > -#define p2m_is_foreign(_t) (p2m_to_mask(_t) & p2m_to_mask(p2m_map_foreign_rw)) > +#define p2m_is_foreign(_t) (p2m_to_mask(_t) & P2M_FOREIGN_TYPES) > #define p2m_is_any_ram(_t) (p2m_to_mask(_t) & \ > (P2M_RAM_TYPES | P2M_GRANT_TYPES | \ > - p2m_to_mask(p2m_map_foreign_rw))) > + P2M_FOREIGN_TYPES)) > > /* All common type definitions should live ahead of this inclusion. */ > #ifdef _XEN_P2M_COMMON_H > @@ -295,7 +300,38 @@ struct page_info *p2m_get_page_from_gfn(struct domain *d, gfn_t gfn, > static inline struct page_info *get_page_from_gfn( > struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q) > { Something has gone wrong with this patch. The chunk below should be in a separate patch. I will split this patch in two. > - return p2m_get_page_from_gfn(d, _gfn(gfn), t); > + mfn_t mfn; > + p2m_type_t _t; > + struct page_info *page; > + > + /* > + * Special case for DOMID_XEN as it is the only domain so far that is > + * not auto-translated. > + */ > + if ( unlikely(d != dom_xen) ) > + return p2m_get_page_from_gfn(d, _gfn(gfn), t); > + > + if ( !t ) > + t = &_t; > + > + *t = p2m_invalid; > + > + /* > + * DOMID_XEN see 1-1 RAM. The p2m_type is based on the type of the > + * page. > + */ > + mfn = _mfn(gfn); > + page = mfn_to_page(mfn); > + > + if ( !mfn_valid(mfn) || !get_page(page, d) ) > + return NULL; > + > + if ( page->u.inuse.type_info & PGT_writable_page ) > + *t = p2m_ram_rw; > + else > + *t = p2m_ram_ro; > + > + return page; > } > > int get_page_type(struct page_info *page, unsigned long type); > Cheers,
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 7193d83b44..58f7e54640 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -1267,7 +1267,7 @@ int xenmem_add_to_physmap_one( } mfn = page_to_mfn(page); - t = p2m_map_foreign_rw; + t = (p2mt == p2m_ram_rw) ? p2m_map_foreign_rw : p2m_map_foreign_ro; rcu_unlock_domain(od); break; diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index e0b84a9db5..dea04ef66f 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -477,6 +477,7 @@ static void p2m_set_permission(lpae_t *e, p2m_type_t t, p2m_access_t a) break; case p2m_iommu_map_ro: + case p2m_map_foreign_ro: case p2m_grant_map_ro: case p2m_invalid: e->p2m.xn = 1; diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h index a1aef7b793..6f2728e2bb 100644 --- a/xen/include/asm-arm/p2m.h +++ b/xen/include/asm-arm/p2m.h @@ -116,6 +116,7 @@ typedef enum { p2m_mmio_direct_nc, /* Read/write mapping of genuine MMIO area non-cacheable */ p2m_mmio_direct_c, /* Read/write mapping of genuine MMIO area cacheable */ p2m_map_foreign_rw, /* Read/write RAM pages from foreign domain */ + p2m_map_foreign_ro, /* Read-only RAM pages from foreign domain */ p2m_grant_map_rw, /* Read/write grant mapping */ p2m_grant_map_ro, /* Read-only grant mapping */ /* The types below are only used to decide the page attribute in the P2M */ @@ -135,12 +136,16 @@ typedef enum { #define P2M_GRANT_TYPES (p2m_to_mask(p2m_grant_map_rw) | \ p2m_to_mask(p2m_grant_map_ro)) +/* Foreign mappings types */ +#define P2M_FOREIGN_TYPES (p2m_to_mask(p2m_map_foreign_rw) | \ + p2m_to_mask(p2m_map_foreign_ro)) + /* Useful predicates */ #define p2m_is_ram(_t) (p2m_to_mask(_t) & P2M_RAM_TYPES) -#define p2m_is_foreign(_t) (p2m_to_mask(_t) & p2m_to_mask(p2m_map_foreign_rw)) +#define p2m_is_foreign(_t) (p2m_to_mask(_t) & P2M_FOREIGN_TYPES) #define p2m_is_any_ram(_t) (p2m_to_mask(_t) & \ (P2M_RAM_TYPES | P2M_GRANT_TYPES | \ - p2m_to_mask(p2m_map_foreign_rw))) + P2M_FOREIGN_TYPES)) /* All common type definitions should live ahead of this inclusion. */ #ifdef _XEN_P2M_COMMON_H @@ -295,7 +300,38 @@ struct page_info *p2m_get_page_from_gfn(struct domain *d, gfn_t gfn, static inline struct page_info *get_page_from_gfn( struct domain *d, unsigned long gfn, p2m_type_t *t, p2m_query_t q) { - return p2m_get_page_from_gfn(d, _gfn(gfn), t); + mfn_t mfn; + p2m_type_t _t; + struct page_info *page; + + /* + * Special case for DOMID_XEN as it is the only domain so far that is + * not auto-translated. + */ + if ( unlikely(d != dom_xen) ) + return p2m_get_page_from_gfn(d, _gfn(gfn), t); + + if ( !t ) + t = &_t; + + *t = p2m_invalid; + + /* + * DOMID_XEN see 1-1 RAM. The p2m_type is based on the type of the + * page. + */ + mfn = _mfn(gfn); + page = mfn_to_page(mfn); + + if ( !mfn_valid(mfn) || !get_page(page, d) ) + return NULL; + + if ( page->u.inuse.type_info & PGT_writable_page ) + *t = p2m_ram_rw; + else + *t = p2m_ram_ro; + + return page; } int get_page_type(struct page_info *page, unsigned long type);