File 56d03743-x86-hvm-add-HVM_PARAM_X87_FIP_WIDTH.patch of Package xen.7317
# Commit 5d768fb1f3f7b011e7b6e75909c7f4841730de60
# Date 2016-02-26 12:30:11 +0100
# Author David Vrabel <david.vrabel@citrix.com>
# Committer Jan Beulich <jbeulich@suse.com>
x86/hvm: add HVM_PARAM_X87_FIP_WIDTH
The HVM parameter HVM_PARAM_X87_FIP_WIDTH to allow tools and the guest
to adjust the width of the FIP/FDP registers to be saved/restored by
the hypervisor. This is in case the hypervisor hueristics do not do
the right thing.
Add this parameter to the set saved during domain save/migrate.
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -746,6 +746,7 @@ typedef struct {
uint64_t acpi_ioport_location;
uint64_t viridian;
uint64_t vm_generationid_addr;
+ uint64_t x87_fip_width;
struct toolstack_data_t tdata;
} pagebuf_t;
@@ -996,6 +997,16 @@ static int pagebuf_get_one(xc_interface
DPRINTF("read generation id buffer address");
return pagebuf_get_one(xch, ctx, buf, fd, dom);
+ case XC_SAVE_ID_HVM_X87_FIP_WIDTH:
+ /* Skip padding 4 bytes then read the x87 FIP width. */
+ if ( RDEXACT(fd, &buf->x87_fip_width, sizeof(uint32_t)) ||
+ RDEXACT(fd, &buf->x87_fip_width, sizeof(uint64_t)) )
+ {
+ PERROR("error reading the x87 FIP width");
+ return -1;
+ }
+ return pagebuf_get_one(xch, ctx, buf, fd, dom);
+
default:
if ( (count > MAX_BATCH_SIZE) || (count < 0) ) {
ERROR("Max batch size exceeded (%d). Giving up.", count);
@@ -1754,6 +1765,9 @@ int xc_domain_restore(xc_interface *xch,
if (pagebuf.viridian != 0)
xc_set_hvm_param(xch, dom, HVM_PARAM_VIRIDIAN, 1);
+ if (pagebuf.x87_fip_width != 0)
+ xc_set_hvm_param(xch, dom, HVM_PARAM_X87_FIP_WIDTH,
+ pagebuf.x87_fip_width);
if (pagebuf.acpi_ioport_location == 1) {
DBGPRINTF("Use new firmware ioport from the checkpoint\n");
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -1731,6 +1731,18 @@ int xc_domain_save(xc_interface *xch, in
PERROR("Error when writing the viridian flag");
goto out;
}
+
+ chunk.id = XC_SAVE_ID_HVM_X87_FIP_WIDTH;
+ chunk.data = 0;
+ xc_get_hvm_param(xch, dom, HVM_PARAM_X87_FIP_WIDTH,
+ (unsigned long *)&chunk.data);
+
+ if ( (chunk.data != 0) &&
+ wrexact(io_fd, &chunk, sizeof(chunk)) )
+ {
+ PERROR("Error writing the x87 FIP width");
+ goto out;
+ }
}
if ( callbacks != NULL && callbacks->toolstack_save != NULL )
--- a/tools/libxc/xg_save_restore.h
+++ b/tools/libxc/xg_save_restore.h
@@ -259,6 +259,7 @@
#define XC_SAVE_ID_HVM_ACCESS_RING_PFN -16
#define XC_SAVE_ID_HVM_SHARING_RING_PFN -17
#define XC_SAVE_ID_TOOLSTACK -18 /* Optional toolstack specific info */
+#define XC_SAVE_ID_HVM_X87_FIP_WIDTH -21
/*
** We process save/restore/migrate in batches of pages; the below
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -4245,6 +4245,14 @@ long do_hvm_op(unsigned long op, XEN_GUE
if ( a.value > SHUTDOWN_MAX )
rc = -EINVAL;
break;
+ case HVM_PARAM_X87_FIP_WIDTH:
+ if ( a.value != 0 && a.value != 4 && a.value != 8 )
+ {
+ rc = -EINVAL;
+ break;
+ }
+ d->arch.x87_fip_width = a.value;
+ break;
}
if ( rc == 0 )
@@ -4278,6 +4286,9 @@ long do_hvm_op(unsigned long op, XEN_GUE
case HVM_PARAM_ACPI_S_STATE:
a.value = d->arch.hvm_domain.is_s3_suspended ? 3 : 0;
break;
+ case HVM_PARAM_X87_FIP_WIDTH:
+ a.value = d->arch.x87_fip_width;
+ break;
default:
a.value = d->arch.hvm_domain.params[a.index];
break;
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -145,6 +145,28 @@
/* SHUTDOWN_* action in case of a triple fault */
#define HVM_PARAM_TRIPLE_FAULT_REASON 31
-#define HVM_NR_PARAMS 32
+/*
+ * Size of the x87 FPU FIP/FDP registers that the hypervisor needs to
+ * save/restore. This is a workaround for a hardware limitation that
+ * does not allow the full FIP/FDP and FCS/FDS to be restored.
+ *
+ * Valid values are:
+ *
+ * 8: save/restore 64-bit FIP/FDP and clear FCS/FDS (default if CPU
+ * has FPCSDS feature).
+ *
+ * 4: save/restore 32-bit FIP/FDP, FCS/FDS, and clear upper 32-bits of
+ * FIP/FDP.
+ *
+ * 0: allow hypervisor to choose based on the value of FIP/FDP
+ * (default if CPU does not have FPCSDS).
+ *
+ * If FPCSDS (bit 13 in CPUID leaf 0x7, subleaf 0x0) is set, the CPU
+ * never saves FCS/FDS and this parameter should be left at the
+ * default of 8.
+ */
+#define HVM_PARAM_X87_FIP_WIDTH 36
+
+#define HVM_NR_PARAMS 37
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */