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
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