70 lines
3.1 KiB
Diff
70 lines
3.1 KiB
Diff
|
References: bnc#882089
|
||
|
|
||
|
# Commit 401d5c5cc5a780cad160aa0e3c282c11ac11dd0c
|
||
|
# Date 2014-08-28 16:03:26 +0200
|
||
|
# Author Tamas K Lengyel <tamas.lengyel@zentific.com>
|
||
|
# Committer Jan Beulich <jbeulich@suse.com>
|
||
|
x86/hvm: treat non-instruction fetch nested page faults also as read violations
|
||
|
|
||
|
As pointed out by Jan Beulich in
|
||
|
http://lists.xen.org/archives/html/xen-devel/2014-08/msg01269.html:
|
||
|
"Read-modify-write instructions absolutely need to be treated as read
|
||
|
accesses, yet hardware doesn't guarantee to tell us so (they may
|
||
|
surface as just write accesses)." This patch addresses the issue in
|
||
|
both the VMX and the SVM side.
|
||
|
|
||
|
VMX: Treat all write data access violations also as read violations (in
|
||
|
addition to those that were already reported as read violations).
|
||
|
SVM: Refine the meaning of read data access violations to distinguish
|
||
|
between read/write and instruction fetch access violations.
|
||
|
|
||
|
With this patch both VMX and SVM specific nested page fault handling code reports violations the same way, thus abstracting the hardware specific behaviour from the layers above.
|
||
|
|
||
|
Suggested-by: Jan Beulich <JBeulich@suse.com>
|
||
|
Signed-off-by: Tamas K Lengyel <tamas.lengyel@zentific.com>
|
||
|
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
|
||
|
Reviewed-by: Tim Deegan <tim@xen.org>
|
||
|
|
||
|
--- a/xen/arch/x86/hvm/svm/svm.c
|
||
|
+++ b/xen/arch/x86/hvm/svm/svm.c
|
||
|
@@ -1298,8 +1298,13 @@ static void svm_do_nested_pgfault(struct
|
||
|
p2m_access_t p2ma;
|
||
|
struct p2m_domain *p2m = NULL;
|
||
|
|
||
|
+ /*
|
||
|
+ * Since HW doesn't explicitly provide a read access bit and we need to
|
||
|
+ * somehow describe read-modify-write instructions we will conservatively
|
||
|
+ * set read_access for all memory accesses that are not instruction fetches.
|
||
|
+ */
|
||
|
struct npfec npfec = {
|
||
|
- .read_access = 1, /* All NPFs count as reads */
|
||
|
+ .read_access = !(pfec & PFEC_insn_fetch),
|
||
|
.write_access = !!(pfec & PFEC_write_access),
|
||
|
.insn_fetch = !!(pfec & PFEC_insn_fetch)
|
||
|
};
|
||
|
--- a/xen/arch/x86/hvm/vmx/vmx.c
|
||
|
+++ b/xen/arch/x86/hvm/vmx/vmx.c
|
||
|
@@ -2278,8 +2278,21 @@ static void ept_handle_violation(unsigne
|
||
|
p2m_type_t p2mt;
|
||
|
int ret;
|
||
|
struct domain *d = current->domain;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * We treat all write violations also as read violations.
|
||
|
+ * The reason why this is required is the following warning:
|
||
|
+ * "An EPT violation that occurs during as a result of execution of a
|
||
|
+ * read-modify-write operation sets bit 1 (data write). Whether it also
|
||
|
+ * sets bit 0 (data read) is implementation-specific and, for a given
|
||
|
+ * implementation, may differ for different kinds of read-modify-write
|
||
|
+ * operations."
|
||
|
+ * - Intel(R) 64 and IA-32 Architectures Software Developer's Manual
|
||
|
+ * Volume 3C: System Programming Guide, Part 3
|
||
|
+ */
|
||
|
struct npfec npfec = {
|
||
|
- .read_access = !!(qualification & EPT_READ_VIOLATION),
|
||
|
+ .read_access = !!(qualification & EPT_READ_VIOLATION) ||
|
||
|
+ !!(qualification & EPT_WRITE_VIOLATION),
|
||
|
.write_access = !!(qualification & EPT_WRITE_VIOLATION),
|
||
|
.insn_fetch = !!(qualification & EPT_EXEC_VIOLATION)
|
||
|
};
|