mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86emul: pull permission check ahead for REP INS/OUTS
Based on observations on a fair range of hardware from both primary vendors even zero-iteration-count instances of these insns perform the port related permission checking first. Fixes:fe30060046("x86: Fix emulation of REP prefix") Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> master commit:f41c88a6fcmaster date: 2023-03-30 13:07:16 +0200
This commit is contained in:
1 parent
1df1a2acab
commit
eff203e185
1 file changed
+7
-5
@@ -4249,14 +4249,15 @@ x86_emulate(
|
||||
goto imul;
|
||||
|
||||
case 0x6c ... 0x6d: /* ins %dx,%es:%edi */ {
|
||||
unsigned long nr_reps = get_rep_prefix(false, true);
|
||||
unsigned long nr_reps;
|
||||
unsigned int port = _regs.dx;
|
||||
|
||||
dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
|
||||
dst.mem.seg = x86_seg_es;
|
||||
dst.mem.off = truncate_ea_and_reps(_regs.r(di), nr_reps, dst.bytes);
|
||||
if ( (rc = ioport_access_check(port, dst.bytes, ctxt, ops)) != 0 )
|
||||
goto done;
|
||||
nr_reps = get_rep_prefix(false, true);
|
||||
dst.mem.off = truncate_ea_and_reps(_regs.r(di), nr_reps, dst.bytes);
|
||||
dst.mem.seg = x86_seg_es;
|
||||
/* Try the presumably most efficient approach first. */
|
||||
if ( !ops->rep_ins )
|
||||
nr_reps = 1;
|
||||
@@ -4290,13 +4291,14 @@ x86_emulate(
|
||||
}
|
||||
|
||||
case 0x6e ... 0x6f: /* outs %esi,%dx */ {
|
||||
unsigned long nr_reps = get_rep_prefix(true, false);
|
||||
unsigned long nr_reps;
|
||||
unsigned int port = _regs.dx;
|
||||
|
||||
dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
|
||||
ea.mem.off = truncate_ea_and_reps(_regs.r(si), nr_reps, dst.bytes);
|
||||
if ( (rc = ioport_access_check(port, dst.bytes, ctxt, ops)) != 0 )
|
||||
goto done;
|
||||
nr_reps = get_rep_prefix(true, false);
|
||||
ea.mem.off = truncate_ea_and_reps(_regs.r(si), nr_reps, dst.bytes);
|
||||
/* Try the presumably most efficient approach first. */
|
||||
if ( !ops->rep_outs )
|
||||
nr_reps = 1;
|
||||
|
||||