On 02/11/2014 10:54, Nadav Amit wrote:
> In one occassion, decode_modrm uses the rm field after it is extended with
> REX.B to determine the addressing mode. Doing so causes it not to read the
> offset for rip-relative addressing.
> 
> This patch uses the value after masking instead.
> 
> Signed-off-by: Nadav Amit <na...@cs.technion.ac.il>
> ---
>  arch/x86/kvm/emulate.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index 4b3fa70..efe7239 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -1209,7 +1209,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
>               }
>               switch (ctxt->modrm_mod) {
>               case 0:
> -                     if (ctxt->modrm_rm == 5)
> +                     if ((ctxt->modrm_rm & 7) == 5)
>                               modrm_ea += insn_fetch(s32, ctxt);
>                       break;
>               case 1:
> 

We can do instead:

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 05ea85ff39c6..a4703eb9c1ed 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1223,6 +1223,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
                        if (index_reg != 4)
                                modrm_ea += reg_read(ctxt, index_reg) << scale;
                } else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) {
+                       modrm_ea += insn_fetch(s32, ctxt);
                        if (ctxt->mode == X86EMUL_MODE_PROT64)
                                ctxt->rip_relative = 1;
                } else {
@@ -1231,10 +1232,6 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
                        adjust_modrm_seg(ctxt, base_reg);
                }
                switch (ctxt->modrm_mod) {
-               case 0:
-                       if ((ctxt->modrm_rm & 7) == 5)
-                               modrm_ea += insn_fetch(s32, ctxt);
-                       break;
                case 1:
                        modrm_ea += insn_fetch(s8, ctxt);
                        break;

which matches what we already do to handle the case where REX.B is
ignored for MOD=00, RM=0100:

                        if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)

I'll write a testcase, too.

Paolo
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to