Mailing List Archive

[PATCH 04/18] xen: Preserve reserved grant entries when switching versions
In order for the toolstack to use reserved grant table entries, the
grant table for a guest must be initialized prior to the guest's boot.
When the guest switches grant table versions (necessary if the guest is
using v2 grant tables, or on kexec if switching grant versions), these
initial grants will be cleared. Instead of clearing them, preserve
the grants across the type change.

Attempting to use or preserve v2-only features such as sub-page grants
will produce invalid v1 grant entries, which (while they will not work)
is not a problem since a guest can always produce such invalid entries.

Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
xen/common/grant_table.c | 38 +++++++++++++++++++++++++++++++-------
1 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 014734d..8d4a4cb 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -2106,6 +2106,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
struct domain *d = current->domain;
struct grant_table *gt = d->grant_table;
struct active_grant_entry *act;
+ grant_entry_v1_t reserved_entries[GNTTAB_NR_RESERVED_ENTRIES];
long res;
int i;

@@ -2126,7 +2127,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
/* (You need to change the version number for e.g. kexec.) */
if ( gt->gt_version != 0 )
{
- for ( i = 0; i < nr_grant_entries(gt); i++ )
+ for ( i = GNTTAB_NR_RESERVED_ENTRIES; i < nr_grant_entries(gt); i++ )
{
act = &active_entry(gt, i);
if ( act->pin != 0 )
@@ -2151,15 +2152,38 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
goto out_unlock;
}

+ /* Preserve the first 8 entries (toolstack reserved grants) */
+ if (gt->gt_version == 1) {
+ memcpy(reserved_entries, gt->shared_v1[0], sizeof(reserved_entries));
+ } else if (gt->gt_version == 2) {
+ for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES && i < nr_grant_entries(gt); i++ )
+ {
+ reserved_entries[i].flags = shared_entry_v2(gt, i).hdr.flags;
+ reserved_entries[i].domid = shared_entry_v2(gt, i).hdr.domid;
+ reserved_entries[i].frame = shared_entry_v2(gt, i).full_page.frame;
+ reserved_entries[i].flags |= status_entry(gt, i);
+ }
+ }
+
if ( op.version < 2 && gt->gt_version == 2 )
gnttab_unpopulate_status_frames(d, gt);

- if ( op.version != gt->gt_version )
- {
- /* Make sure there's no crud left over in the table from the
- old version. */
- for ( i = 0; i < nr_grant_frames(gt); i++ )
- memset(gt->shared_raw[i], 0, PAGE_SIZE);
+ /* Make sure there's no crud left over in the table from the
+ old version. */
+ for ( i = 0; i < nr_grant_frames(gt); i++ )
+ memset(gt->shared_raw[i], 0, PAGE_SIZE);
+
+ /* Restore the first 8 entries (toolstack reserved grants) */
+ if (gt->gt_version != 0 && op.version == 1) {
+ memcpy(gt->shared_v1[0], reserved_entries, sizeof(reserved_entries));
+ } else if (gt->gt_version != 0 && op.version == 2) {
+ for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES; i++ )
+ {
+ status_entry(gt, i) = reserved_entries[i].flags & (GTF_reading|GTF_writing);
+ shared_entry_v2(gt, i).hdr.flags = reserved_entries[i].flags & ~(GTF_reading|GTF_writing);
+ shared_entry_v2(gt, i).hdr.domid = reserved_entries[i].domid;
+ shared_entry_v2(gt, i).full_page.frame = reserved_entries[i].frame;
+ }
}

gt->gt_version = op.version;
--
1.7.7.5


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Re: [PATCH 04/18] xen: Preserve reserved grant entries when switching versions [ In reply to ]
>>> On 11.01.12 at 18:21, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote:
> --- a/xen/common/grant_table.c
> +++ b/xen/common/grant_table.c
> @@ -2106,6 +2106,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> struct domain *d = current->domain;
> struct grant_table *gt = d->grant_table;
> struct active_grant_entry *act;
> + grant_entry_v1_t reserved_entries[GNTTAB_NR_RESERVED_ENTRIES];

How much stack space does this consume? (Or in other words, where
does GNTTAB_NR_RESERVED_ENTRIES get defined? It's not in this
patch, I can't find it in earlier patches, and it also doesn't exist in the
current staging tree.)

Jan

> long res;
> int i;
>
> @@ -2126,7 +2127,7 @@
> gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> /* (You need to change the version number for e.g. kexec.) */
> if ( gt->gt_version != 0 )
> {
> - for ( i = 0; i < nr_grant_entries(gt); i++ )
> + for ( i = GNTTAB_NR_RESERVED_ENTRIES; i < nr_grant_entries(gt); i++
> )
> {
> act = &active_entry(gt, i);
> if ( act->pin != 0 )
> @@ -2151,15 +2152,38 @@
> gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> goto out_unlock;
> }
>
> + /* Preserve the first 8 entries (toolstack reserved grants) */
> + if (gt->gt_version == 1) {
> + memcpy(reserved_entries, gt->shared_v1[0], sizeof(reserved_entries));
> + } else if (gt->gt_version == 2) {
> + for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES && i <
> nr_grant_entries(gt); i++ )
> + {
> + reserved_entries[i].flags = shared_entry_v2(gt, i).hdr.flags;
> + reserved_entries[i].domid = shared_entry_v2(gt, i).hdr.domid;
> + reserved_entries[i].frame = shared_entry_v2(gt,
> i).full_page.frame;
> + reserved_entries[i].flags |= status_entry(gt, i);
> + }
> + }
> +
> if ( op.version < 2 && gt->gt_version == 2 )
> gnttab_unpopulate_status_frames(d, gt);
>
> - if ( op.version != gt->gt_version )
> - {
> - /* Make sure there's no crud left over in the table from the
> - old version. */
> - for ( i = 0; i < nr_grant_frames(gt); i++ )
> - memset(gt->shared_raw[i], 0, PAGE_SIZE);
> + /* Make sure there's no crud left over in the table from the
> + old version. */
> + for ( i = 0; i < nr_grant_frames(gt); i++ )
> + memset(gt->shared_raw[i], 0, PAGE_SIZE);
> +
> + /* Restore the first 8 entries (toolstack reserved grants) */
> + if (gt->gt_version != 0 && op.version == 1) {
> + memcpy(gt->shared_v1[0], reserved_entries, sizeof(reserved_entries));
> + } else if (gt->gt_version != 0 && op.version == 2) {
> + for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES; i++ )
> + {
> + status_entry(gt, i) = reserved_entries[i].flags &
> (GTF_reading|GTF_writing);
> + shared_entry_v2(gt, i).hdr.flags = reserved_entries[i].flags &
> ~(GTF_reading|GTF_writing);
> + shared_entry_v2(gt, i).hdr.domid = reserved_entries[i].domid;
> + shared_entry_v2(gt, i).full_page.frame =
> reserved_entries[i].frame;
> + }
> }
>
> gt->gt_version = op.version;
> --
> 1.7.7.5
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel




_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Re: [PATCH 04/18] xen: Preserve reserved grant entries when switching versions [ In reply to ]
On Thu, 2012-01-12 at 08:53 +0000, Jan Beulich wrote:
> >>> On 11.01.12 at 18:21, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote:
> > --- a/xen/common/grant_table.c
> > +++ b/xen/common/grant_table.c
> > @@ -2106,6 +2106,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> > struct domain *d = current->domain;
> > struct grant_table *gt = d->grant_table;
> > struct active_grant_entry *act;
> > + grant_entry_v1_t reserved_entries[GNTTAB_NR_RESERVED_ENTRIES];
>
> How much stack space does this consume? (Or in other words, where
> does GNTTAB_NR_RESERVED_ENTRIES get defined? It's not in this
> patch, I can't find it in earlier patches, and it also doesn't exist in the
> current staging tree.)

I could have sworn I'd seen this somewhere but I can't for the life of
me find it now :-/

One place I did find it is in the Linux gnttab driver, but that's not
canonical.

Ian.

>
> Jan
>
> > long res;
> > int i;
> >
> > @@ -2126,7 +2127,7 @@
> > gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> > /* (You need to change the version number for e.g. kexec.) */
> > if ( gt->gt_version != 0 )
> > {
> > - for ( i = 0; i < nr_grant_entries(gt); i++ )
> > + for ( i = GNTTAB_NR_RESERVED_ENTRIES; i < nr_grant_entries(gt); i++
> > )
> > {
> > act = &active_entry(gt, i);
> > if ( act->pin != 0 )
> > @@ -2151,15 +2152,38 @@
> > gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> > goto out_unlock;
> > }
> >
> > + /* Preserve the first 8 entries (toolstack reserved grants) */
> > + if (gt->gt_version == 1) {
> > + memcpy(reserved_entries, gt->shared_v1[0], sizeof(reserved_entries));
> > + } else if (gt->gt_version == 2) {
> > + for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES && i <
> > nr_grant_entries(gt); i++ )
> > + {
> > + reserved_entries[i].flags = shared_entry_v2(gt, i).hdr.flags;
> > + reserved_entries[i].domid = shared_entry_v2(gt, i).hdr.domid;
> > + reserved_entries[i].frame = shared_entry_v2(gt,
> > i).full_page.frame;
> > + reserved_entries[i].flags |= status_entry(gt, i);
> > + }
> > + }
> > +
> > if ( op.version < 2 && gt->gt_version == 2 )
> > gnttab_unpopulate_status_frames(d, gt);
> >
> > - if ( op.version != gt->gt_version )
> > - {
> > - /* Make sure there's no crud left over in the table from the
> > - old version. */
> > - for ( i = 0; i < nr_grant_frames(gt); i++ )
> > - memset(gt->shared_raw[i], 0, PAGE_SIZE);
> > + /* Make sure there's no crud left over in the table from the
> > + old version. */
> > + for ( i = 0; i < nr_grant_frames(gt); i++ )
> > + memset(gt->shared_raw[i], 0, PAGE_SIZE);
> > +
> > + /* Restore the first 8 entries (toolstack reserved grants) */
> > + if (gt->gt_version != 0 && op.version == 1) {
> > + memcpy(gt->shared_v1[0], reserved_entries, sizeof(reserved_entries));
> > + } else if (gt->gt_version != 0 && op.version == 2) {
> > + for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES; i++ )
> > + {
> > + status_entry(gt, i) = reserved_entries[i].flags &
> > (GTF_reading|GTF_writing);
> > + shared_entry_v2(gt, i).hdr.flags = reserved_entries[i].flags &
> > ~(GTF_reading|GTF_writing);
> > + shared_entry_v2(gt, i).hdr.domid = reserved_entries[i].domid;
> > + shared_entry_v2(gt, i).full_page.frame =
> > reserved_entries[i].frame;
> > + }
> > }
> >
> > gt->gt_version = op.version;
> > --
> > 1.7.7.5
> >
> >
> > _______________________________________________
> > Xen-devel mailing list
> > Xen-devel@lists.xensource.com
> > http://lists.xensource.com/xen-devel
>
>
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Re: [PATCH 04/18] xen: Preserve reserved grant entries when switching versions [ In reply to ]
On Thu, 2012-01-12 at 09:49 +0000, Ian Campbell wrote:
> On Thu, 2012-01-12 at 08:53 +0000, Jan Beulich wrote:
> > >>> On 11.01.12 at 18:21, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote:
> > > --- a/xen/common/grant_table.c
> > > +++ b/xen/common/grant_table.c
> > > @@ -2106,6 +2106,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> > > struct domain *d = current->domain;
> > > struct grant_table *gt = d->grant_table;
> > > struct active_grant_entry *act;
> > > + grant_entry_v1_t reserved_entries[GNTTAB_NR_RESERVED_ENTRIES];
> >
> > How much stack space does this consume? (Or in other words, where
> > does GNTTAB_NR_RESERVED_ENTRIES get defined? It's not in this
> > patch, I can't find it in earlier patches, and it also doesn't exist in the
> > current staging tree.)
>
> I could have sworn I'd seen this somewhere but I can't for the life of
> me find it now :-/

Found it in patch #6.

+/* External tools reserve first few grant table entries. */
+#define GNTTAB_NR_RESERVED_ENTRIES 8
+#define GNTTAB_RESERVED_CONSOLE 0
+#define GNTTAB_RESERVED_XENSTORE 1
+/* (the next 6 are reserved for future use) */

These patches need to be reordered to make sure each step builds.

Ian.

>
> One place I did find it is in the Linux gnttab driver, but that's not
> canonical.
>
> Ian.
>
> >
> > Jan
> >
> > > long res;
> > > int i;
> > >
> > > @@ -2126,7 +2127,7 @@
> > > gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> > > /* (You need to change the version number for e.g. kexec.) */
> > > if ( gt->gt_version != 0 )
> > > {
> > > - for ( i = 0; i < nr_grant_entries(gt); i++ )
> > > + for ( i = GNTTAB_NR_RESERVED_ENTRIES; i < nr_grant_entries(gt); i++
> > > )
> > > {
> > > act = &active_entry(gt, i);
> > > if ( act->pin != 0 )
> > > @@ -2151,15 +2152,38 @@
> > > gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> > > goto out_unlock;
> > > }
> > >
> > > + /* Preserve the first 8 entries (toolstack reserved grants) */
> > > + if (gt->gt_version == 1) {
> > > + memcpy(reserved_entries, gt->shared_v1[0], sizeof(reserved_entries));
> > > + } else if (gt->gt_version == 2) {
> > > + for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES && i <
> > > nr_grant_entries(gt); i++ )
> > > + {
> > > + reserved_entries[i].flags = shared_entry_v2(gt, i).hdr.flags;
> > > + reserved_entries[i].domid = shared_entry_v2(gt, i).hdr.domid;
> > > + reserved_entries[i].frame = shared_entry_v2(gt,
> > > i).full_page.frame;
> > > + reserved_entries[i].flags |= status_entry(gt, i);
> > > + }
> > > + }
> > > +
> > > if ( op.version < 2 && gt->gt_version == 2 )
> > > gnttab_unpopulate_status_frames(d, gt);
> > >
> > > - if ( op.version != gt->gt_version )
> > > - {
> > > - /* Make sure there's no crud left over in the table from the
> > > - old version. */
> > > - for ( i = 0; i < nr_grant_frames(gt); i++ )
> > > - memset(gt->shared_raw[i], 0, PAGE_SIZE);
> > > + /* Make sure there's no crud left over in the table from the
> > > + old version. */
> > > + for ( i = 0; i < nr_grant_frames(gt); i++ )
> > > + memset(gt->shared_raw[i], 0, PAGE_SIZE);
> > > +
> > > + /* Restore the first 8 entries (toolstack reserved grants) */
> > > + if (gt->gt_version != 0 && op.version == 1) {
> > > + memcpy(gt->shared_v1[0], reserved_entries, sizeof(reserved_entries));
> > > + } else if (gt->gt_version != 0 && op.version == 2) {
> > > + for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES; i++ )
> > > + {
> > > + status_entry(gt, i) = reserved_entries[i].flags &
> > > (GTF_reading|GTF_writing);
> > > + shared_entry_v2(gt, i).hdr.flags = reserved_entries[i].flags &
> > > ~(GTF_reading|GTF_writing);
> > > + shared_entry_v2(gt, i).hdr.domid = reserved_entries[i].domid;
> > > + shared_entry_v2(gt, i).full_page.frame =
> > > reserved_entries[i].frame;
> > > + }
> > > }
> > >
> > > gt->gt_version = op.version;
> > > --
> > > 1.7.7.5
> > >
> > >
> > > _______________________________________________
> > > Xen-devel mailing list
> > > Xen-devel@lists.xensource.com
> > > http://lists.xensource.com/xen-devel
> >
> >
> >
> >
> > _______________________________________________
> > Xen-devel mailing list
> > Xen-devel@lists.xensource.com
> > http://lists.xensource.com/xen-devel
>
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
[PATCH 04/18] xen: Preserve reserved grant entries when switching versions [ In reply to ]
In order for the toolstack to use reserved grant table entries, the
grant table for a guest must be initialized prior to the guest's boot.
When the guest switches grant table versions (necessary if the guest is
using v2 grant tables, or on kexec if switching grant versions), these
initial grants will be cleared. Instead of clearing them, preserve
the grants across the type change.

Attempting to use or preserve v2-only features such as sub-page grants
will produce invalid v1 grant entries, which (while they will not work)
is not a problem since a guest can always produce such invalid entries.

Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
xen/common/grant_table.c | 38 +++++++++++++++++++++++++++++++-------
xen/include/public/grant_table.h | 6 ++++++
2 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 014734d..8d4a4cb 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -2106,6 +2106,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
struct domain *d = current->domain;
struct grant_table *gt = d->grant_table;
struct active_grant_entry *act;
+ grant_entry_v1_t reserved_entries[GNTTAB_NR_RESERVED_ENTRIES];
long res;
int i;

@@ -2126,7 +2127,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
/* (You need to change the version number for e.g. kexec.) */
if ( gt->gt_version != 0 )
{
- for ( i = 0; i < nr_grant_entries(gt); i++ )
+ for ( i = GNTTAB_NR_RESERVED_ENTRIES; i < nr_grant_entries(gt); i++ )
{
act = &active_entry(gt, i);
if ( act->pin != 0 )
@@ -2151,15 +2152,38 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
goto out_unlock;
}

+ /* Preserve the first 8 entries (toolstack reserved grants) */
+ if (gt->gt_version == 1) {
+ memcpy(reserved_entries, gt->shared_v1[0], sizeof(reserved_entries));
+ } else if (gt->gt_version == 2) {
+ for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES && i < nr_grant_entries(gt); i++ )
+ {
+ reserved_entries[i].flags = shared_entry_v2(gt, i).hdr.flags;
+ reserved_entries[i].domid = shared_entry_v2(gt, i).hdr.domid;
+ reserved_entries[i].frame = shared_entry_v2(gt, i).full_page.frame;
+ reserved_entries[i].flags |= status_entry(gt, i);
+ }
+ }
+
if ( op.version < 2 && gt->gt_version == 2 )
gnttab_unpopulate_status_frames(d, gt);

- if ( op.version != gt->gt_version )
- {
- /* Make sure there's no crud left over in the table from the
- old version. */
- for ( i = 0; i < nr_grant_frames(gt); i++ )
- memset(gt->shared_raw[i], 0, PAGE_SIZE);
+ /* Make sure there's no crud left over in the table from the
+ old version. */
+ for ( i = 0; i < nr_grant_frames(gt); i++ )
+ memset(gt->shared_raw[i], 0, PAGE_SIZE);
+
+ /* Restore the first 8 entries (toolstack reserved grants) */
+ if (gt->gt_version != 0 && op.version == 1) {
+ memcpy(gt->shared_v1[0], reserved_entries, sizeof(reserved_entries));
+ } else if (gt->gt_version != 0 && op.version == 2) {
+ for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES; i++ )
+ {
+ status_entry(gt, i) = reserved_entries[i].flags & (GTF_reading|GTF_writing);
+ shared_entry_v2(gt, i).hdr.flags = reserved_entries[i].flags & ~(GTF_reading|GTF_writing);
+ shared_entry_v2(gt, i).hdr.domid = reserved_entries[i].domid;
+ shared_entry_v2(gt, i).full_page.frame = reserved_entries[i].frame;
+ }
}

gt->gt_version = op.version;
diff --git a/xen/include/public/grant_table.h b/xen/include/public/grant_table.h
index 0bf20bc..36d1ac7 100644
--- a/xen/include/public/grant_table.h
+++ b/xen/include/public/grant_table.h
@@ -117,6 +117,12 @@ struct grant_entry_v1 {
};
typedef struct grant_entry_v1 grant_entry_v1_t;

+/* External tools reserve first few grant table entries. */
+#define GNTTAB_NR_RESERVED_ENTRIES 8
+#define GNTTAB_RESERVED_CONSOLE 0
+#define GNTTAB_RESERVED_XENSTORE 1
+/* (the next 6 are reserved for future use) */
+
/*
* Type of grant entry.
* GTF_invalid: This grant entry grants no privileges.
--
1.7.7.5


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Re: [PATCH 04/18] xen: Preserve reserved grant entries when switching versions [ In reply to ]
>>> On 13.01.12 at 00:35, Daniel De Graaf <dgdegra@tycho.nsa.gov> wrote:
> --- a/xen/include/public/grant_table.h
> +++ b/xen/include/public/grant_table.h
> @@ -117,6 +117,12 @@ struct grant_entry_v1 {
> };
> typedef struct grant_entry_v1 grant_entry_v1_t;
>
> +/* External tools reserve first few grant table entries. */

This reads as if they must not be used (but could without taking extra
care) by other than the tools themselves, which would be an
incompatible change. As my understanding is that the change is
backwards compatible, I would suggest adjusting the comment.

Jan

> +#define GNTTAB_NR_RESERVED_ENTRIES 8
> +#define GNTTAB_RESERVED_CONSOLE 0
> +#define GNTTAB_RESERVED_XENSTORE 1
> +/* (the next 6 are reserved for future use) */
> +
> /*
> * Type of grant entry.
> * GTF_invalid: This grant entry grants no privileges.



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
Re: [PATCH 04/18] xen: Preserve reserved grant entries when switching versions [ In reply to ]
On Thu, 2012-01-12 at 23:35 +0000, Daniel De Graaf wrote:
> In order for the toolstack to use reserved grant table entries, the
> grant table for a guest must be initialized prior to the guest's boot.
> When the guest switches grant table versions (necessary if the guest is
> using v2 grant tables, or on kexec if switching grant versions), these
> initial grants will be cleared. Instead of clearing them, preserve
> the grants across the type change.
>
> Attempting to use or preserve v2-only features such as sub-page grants
> will produce invalid v1 grant entries, which (while they will not work)
> is not a problem since a guest can always produce such invalid entries.

Would it be better to explicitly clear such entries? Perhaps we should
even warn since it is effectively disallowed for the toolstack to use v2
features in the reserved entries.

> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> ---
> xen/common/grant_table.c | 38 +++++++++++++++++++++++++++++++-------
> xen/include/public/grant_table.h | 6 ++++++
> 2 files changed, 37 insertions(+), 7 deletions(-)
>
> diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
> index 014734d..8d4a4cb 100644
> --- a/xen/common/grant_table.c
> +++ b/xen/common/grant_table.c
> @@ -2106,6 +2106,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> struct domain *d = current->domain;
> struct grant_table *gt = d->grant_table;
> struct active_grant_entry *act;
> + grant_entry_v1_t reserved_entries[GNTTAB_NR_RESERVED_ENTRIES];
> long res;
> int i;
>
> @@ -2126,7 +2127,7 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> /* (You need to change the version number for e.g. kexec.) */
> if ( gt->gt_version != 0 )
> {
> - for ( i = 0; i < nr_grant_entries(gt); i++ )
> + for ( i = GNTTAB_NR_RESERVED_ENTRIES; i < nr_grant_entries(gt); i++ )
> {
> act = &active_entry(gt, i);
> if ( act->pin != 0 )
> @@ -2151,15 +2152,38 @@ gnttab_set_version(XEN_GUEST_HANDLE(gnttab_set_version_t uop))
> goto out_unlock;
> }
>
> + /* Preserve the first 8 entries (toolstack reserved grants) */
> + if (gt->gt_version == 1) {
> + memcpy(reserved_entries, gt->shared_v1[0], sizeof(reserved_entries));
> + } else if (gt->gt_version == 2) {
> + for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES && i < nr_grant_entries(gt); i++ )
> + {
> + reserved_entries[i].flags = shared_entry_v2(gt, i).hdr.flags;
> + reserved_entries[i].domid = shared_entry_v2(gt, i).hdr.domid;
> + reserved_entries[i].frame = shared_entry_v2(gt, i).full_page.frame;
> + reserved_entries[i].flags |= status_entry(gt, i);
> + }
> + }
> +
> if ( op.version < 2 && gt->gt_version == 2 )
> gnttab_unpopulate_status_frames(d, gt);
>
> - if ( op.version != gt->gt_version )
> - {
> - /* Make sure there's no crud left over in the table from the
> - old version. */
> - for ( i = 0; i < nr_grant_frames(gt); i++ )
> - memset(gt->shared_raw[i], 0, PAGE_SIZE);
> + /* Make sure there's no crud left over in the table from the
> + old version. */
> + for ( i = 0; i < nr_grant_frames(gt); i++ )
> + memset(gt->shared_raw[i], 0, PAGE_SIZE);
> +
> + /* Restore the first 8 entries (toolstack reserved grants) */
> + if (gt->gt_version != 0 && op.version == 1) {
> + memcpy(gt->shared_v1[0], reserved_entries, sizeof(reserved_entries));
> + } else if (gt->gt_version != 0 && op.version == 2) {
> + for ( i = 0; i < GNTTAB_NR_RESERVED_ENTRIES; i++ )
> + {
> + status_entry(gt, i) = reserved_entries[i].flags & (GTF_reading|GTF_writing);
> + shared_entry_v2(gt, i).hdr.flags = reserved_entries[i].flags & ~(GTF_reading|GTF_writing);
> + shared_entry_v2(gt, i).hdr.domid = reserved_entries[i].domid;
> + shared_entry_v2(gt, i).full_page.frame = reserved_entries[i].frame;
> + }
> }
>
> gt->gt_version = op.version;
> diff --git a/xen/include/public/grant_table.h b/xen/include/public/grant_table.h
> index 0bf20bc..36d1ac7 100644
> --- a/xen/include/public/grant_table.h
> +++ b/xen/include/public/grant_table.h
> @@ -117,6 +117,12 @@ struct grant_entry_v1 {
> };
> typedef struct grant_entry_v1 grant_entry_v1_t;
>
> +/* External tools reserve first few grant table entries. */
> +#define GNTTAB_NR_RESERVED_ENTRIES 8
> +#define GNTTAB_RESERVED_CONSOLE 0
> +#define GNTTAB_RESERVED_XENSTORE 1
> +/* (the next 6 are reserved for future use) */
> +
> /*
> * Type of grant entry.
> * GTF_invalid: This grant entry grants no privileges.



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel