summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomáš Mózes <tomas.mozes@gmail.com>2024-10-02 07:59:17 +0200
committerTomáš Mózes <tomas.mozes@gmail.com>2024-10-02 07:59:17 +0200
commitbefc038ba7247e93c8b224942fcca2c4a9e32717 (patch)
tree950eaff689ddf97a580c2969891a193643bce8fb /0021-x86-pv-Address-Coverity-complaint-in-check_guest_io_.patch
parentXen 4.18.3-pre-patchset-0 (diff)
downloadxen-upstream-patches-befc038ba7247e93c8b224942fcca2c4a9e32717.tar.gz
xen-upstream-patches-befc038ba7247e93c8b224942fcca2c4a9e32717.tar.bz2
xen-upstream-patches-befc038ba7247e93c8b224942fcca2c4a9e32717.zip
Xen 4.19.1-pre-patchset-04.19.1-pre-patchset-0main
Signed-off-by: Tomáš Mózes <tomas.mozes@gmail.com>
Diffstat (limited to '0021-x86-pv-Address-Coverity-complaint-in-check_guest_io_.patch')
-rw-r--r--0021-x86-pv-Address-Coverity-complaint-in-check_guest_io_.patch112
1 files changed, 112 insertions, 0 deletions
diff --git a/0021-x86-pv-Address-Coverity-complaint-in-check_guest_io_.patch b/0021-x86-pv-Address-Coverity-complaint-in-check_guest_io_.patch
new file mode 100644
index 0000000..b951fb1
--- /dev/null
+++ b/0021-x86-pv-Address-Coverity-complaint-in-check_guest_io_.patch
@@ -0,0 +1,112 @@
+From cb6c3cfc5f8aa8bd8aae1abffea0574b02a04840 Mon Sep 17 00:00:00 2001
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Date: Tue, 24 Sep 2024 14:36:25 +0200
+Subject: [PATCH 21/35] x86/pv: Address Coverity complaint in
+ check_guest_io_breakpoint()
+
+Commit 08aacc392d86 ("x86/emul: Fix misaligned IO breakpoint behaviour in PV
+guests") caused a Coverity INTEGER_OVERFLOW complaint based on the reasoning
+that width could be 0.
+
+It can't, but digging into the code generation, GCC 8 and later (bisected on
+godbolt) choose to emit a CSWITCH lookup table, and because the range (bottom
+2 bits clear), it's a 16-entry lookup table.
+
+So Coverity is understandable, given that GCC did emit a (dead) logic path
+where width stayed 0.
+
+Rewrite the logic. Introduce x86_bp_width() which compiles to a single basic
+block, which replaces the switch() statement. Take the opportunity to also
+make start and width be loop-scope variables.
+
+No practical change, but it should compile better and placate Coverity.
+
+Fixes: 08aacc392d86 ("x86/emul: Fix misaligned IO breakpoint behaviour in PV guests")
+Coverity-ID: 1616152
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+master commit: 6d41a9d8a12ff89adabdc286e63e9391a0481699
+master date: 2024-08-21 23:59:19 +0100
+---
+ xen/arch/x86/include/asm/debugreg.h | 25 +++++++++++++++++++++++++
+ xen/arch/x86/pv/emul-priv-op.c | 21 ++++++---------------
+ 2 files changed, 31 insertions(+), 15 deletions(-)
+
+diff --git a/xen/arch/x86/include/asm/debugreg.h b/xen/arch/x86/include/asm/debugreg.h
+index 6baa725441..23aa592e40 100644
+--- a/xen/arch/x86/include/asm/debugreg.h
++++ b/xen/arch/x86/include/asm/debugreg.h
+@@ -115,4 +115,29 @@ unsigned int x86_adj_dr7_rsvd(const struct cpu_policy *p, unsigned int dr7);
+ unsigned int x86_merge_dr6(const struct cpu_policy *p, unsigned int dr6,
+ unsigned int new);
+
++/*
++ * Calculate the width of a breakpoint from its dr7 encoding.
++ *
++ * The LEN encoding in dr7 is 2 bits wide per breakpoint and encoded as a X-1
++ * (0, 1 and 3) for widths of 1, 2 and 4 respectively in the 32bit days.
++ *
++ * In 64bit, the unused value (2) was given a meaning of width 8, which is
++ * great for efficiency but less great for nicely calculating the width.
++ */
++static inline unsigned int x86_bp_width(unsigned int dr7, unsigned int bp)
++{
++ unsigned int raw = (dr7 >> (DR_CONTROL_SHIFT +
++ DR_CONTROL_SIZE * bp + 2)) & 3;
++
++ /*
++ * If the top bit is set (i.e. we've got an 4 or 8 byte wide breakpoint),
++ * flip the bottom to reverse their order, making them sorted properly.
++ * Then it's a simple shift to calculate the width.
++ */
++ if ( raw & 2 )
++ raw ^= 1;
++
++ return 1U << raw;
++}
++
+ #endif /* _X86_DEBUGREG_H */
+diff --git a/xen/arch/x86/pv/emul-priv-op.c b/xen/arch/x86/pv/emul-priv-op.c
+index 15c83b9d23..b90f745c75 100644
+--- a/xen/arch/x86/pv/emul-priv-op.c
++++ b/xen/arch/x86/pv/emul-priv-op.c
+@@ -323,30 +323,21 @@ static unsigned int check_guest_io_breakpoint(struct vcpu *v,
+ unsigned int port,
+ unsigned int len)
+ {
+- unsigned int width, i, match = 0;
+- unsigned long start;
++ unsigned int i, match = 0;
+
+ if ( !v->arch.pv.dr7_emul || !(v->arch.pv.ctrlreg[4] & X86_CR4_DE) )
+ return 0;
+
+ for ( i = 0; i < 4; i++ )
+ {
++ unsigned long start;
++ unsigned int width;
++
+ if ( !(v->arch.pv.dr7_emul & (3 << (i * DR_ENABLE_SIZE))) )
+ continue;
+
+- start = v->arch.dr[i];
+- width = 0;
+-
+- switch ( (v->arch.dr7 >>
+- (DR_CONTROL_SHIFT + i * DR_CONTROL_SIZE)) & 0xc )
+- {
+- case DR_LEN_1: width = 1; break;
+- case DR_LEN_2: width = 2; break;
+- case DR_LEN_4: width = 4; break;
+- case DR_LEN_8: width = 8; break;
+- }
+-
+- start &= ~(width - 1UL);
++ width = x86_bp_width(v->arch.dr7, i);
++ start = v->arch.dr[i] & ~(width - 1UL);
+
+ if ( (start < (port + len)) && ((start + width) > port) )
+ match |= 1u << i;
+--
+2.46.1
+