Re: [PATCH v2 7/8] KVM: x86 emulator: SSE support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Mar 29, 2011 at 5:54 AM, Avi Kivity <avi@xxxxxxxxxx> wrote:
> Add support for marking an instruction as SSE, switching registers used
> to the SSE register file.

Avi,

So this change will only support XMM register as its destination not
memory, right? I am seeing the mmio size in qemu is still 8 bytes.

Do we need to support memory destination and update qemu as well?

Thanks,
CJ

>
> Signed-off-by: Avi Kivity <avi@xxxxxxxxxx>
> ---
>  arch/x86/include/asm/kvm_emulate.h |    6 ++-
>  arch/x86/kvm/emulate.c             |  102 ++++++++++++++++++++++++++++++++++-
>  2 files changed, 104 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
> index 4c0e682..48693f0 100644
> --- a/arch/x86/include/asm/kvm_emulate.h
> +++ b/arch/x86/include/asm/kvm_emulate.h
> @@ -162,9 +162,11 @@ struct x86_emulate_ops {
>        void (*put_fpu)(struct x86_emulate_ctxt *ctxt); /* reenables preempt */
>  };
>
> +typedef u32 __attribute__((vector_size(16))) sse128_t;
> +
>  /* Type, address-of, and value of an instruction's operand. */
>  struct operand {
> -       enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type;
> +       enum { OP_REG, OP_MEM, OP_IMM, OP_XMM, OP_NONE } type;
>        unsigned int bytes;
>        union {
>                unsigned long orig_val;
> @@ -176,11 +178,13 @@ struct operand {
>                        ulong ea;
>                        unsigned seg;
>                } mem;
> +               unsigned xmm;
>        } addr;
>        union {
>                unsigned long val;
>                u64 val64;
>                char valptr[sizeof(unsigned long) + 2];
> +               sse128_t vec_val;
>        };
>  };
>
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index 458faea..7b7d96a 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -76,6 +76,7 @@
>  #define Group       (1<<14)     /* Bits 3:5 of modrm byte extend opcode */
>  #define GroupDual   (1<<15)     /* Alternate decoding of mod == 3 */
>  #define Prefix      (1<<16)     /* Instruction varies with 66/f2/f3 prefix */
> +#define Sse         (1<<17)     /* SSE Vector instruction */
>  /* Misc flags */
>  #define VendorSpecific (1<<22) /* Vendor specific instruction */
>  #define NoAccess    (1<<23) /* Don't access memory (lea/invlpg/verr etc) */
> @@ -505,6 +506,11 @@ static int emulate_de(struct x86_emulate_ctxt *ctxt)
>        return emulate_exception(ctxt, DE_VECTOR, 0, false);
>  }
>
> +static int emulate_nm(struct x86_emulate_ctxt *ctxt)
> +{
> +       return emulate_exception(ctxt, NM_VECTOR, 0, false);
> +}
> +
>  static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
>                              struct x86_emulate_ops *ops,
>                              unsigned long eip, u8 *dest)
> @@ -632,7 +638,63 @@ static void fetch_register_operand(struct operand *op)
>        }
>  }
>
> -static void decode_register_operand(struct operand *op,
> +static void read_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data, int reg)
> +{
> +       ctxt->ops->get_fpu(ctxt);
> +       switch (reg) {
> +       case 0: asm("movdqu %%xmm0, %0" : "=m"(*data)); break;
> +       case 1: asm("movdqu %%xmm1, %0" : "=m"(*data)); break;
> +       case 2: asm("movdqu %%xmm2, %0" : "=m"(*data)); break;
> +       case 3: asm("movdqu %%xmm3, %0" : "=m"(*data)); break;
> +       case 4: asm("movdqu %%xmm4, %0" : "=m"(*data)); break;
> +       case 5: asm("movdqu %%xmm5, %0" : "=m"(*data)); break;
> +       case 6: asm("movdqu %%xmm6, %0" : "=m"(*data)); break;
> +       case 7: asm("movdqu %%xmm7, %0" : "=m"(*data)); break;
> +#ifdef CONFIG_X86_64
> +       case 8: asm("movdqu %%xmm8, %0" : "=m"(*data)); break;
> +       case 9: asm("movdqu %%xmm9, %0" : "=m"(*data)); break;
> +       case 10: asm("movdqu %%xmm10, %0" : "=m"(*data)); break;
> +       case 11: asm("movdqu %%xmm11, %0" : "=m"(*data)); break;
> +       case 12: asm("movdqu %%xmm12, %0" : "=m"(*data)); break;
> +       case 13: asm("movdqu %%xmm13, %0" : "=m"(*data)); break;
> +       case 14: asm("movdqu %%xmm14, %0" : "=m"(*data)); break;
> +       case 15: asm("movdqu %%xmm15, %0" : "=m"(*data)); break;
> +#endif
> +       default: BUG();
> +       }
> +       ctxt->ops->put_fpu(ctxt);
> +}
> +
> +static void write_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data,
> +                         int reg)
> +{
> +       ctxt->ops->get_fpu(ctxt);
> +       switch (reg) {
> +       case 0: asm("movdqu %0, %%xmm0" : : "m"(*data)); break;
> +       case 1: asm("movdqu %0, %%xmm1" : : "m"(*data)); break;
> +       case 2: asm("movdqu %0, %%xmm2" : : "m"(*data)); break;
> +       case 3: asm("movdqu %0, %%xmm3" : : "m"(*data)); break;
> +       case 4: asm("movdqu %0, %%xmm4" : : "m"(*data)); break;
> +       case 5: asm("movdqu %0, %%xmm5" : : "m"(*data)); break;
> +       case 6: asm("movdqu %0, %%xmm6" : : "m"(*data)); break;
> +       case 7: asm("movdqu %0, %%xmm7" : : "m"(*data)); break;
> +#ifdef CONFIG_X86_64
> +       case 8: asm("movdqu %0, %%xmm8" : : "m"(*data)); break;
> +       case 9: asm("movdqu %0, %%xmm9" : : "m"(*data)); break;
> +       case 10: asm("movdqu %0, %%xmm10" : : "m"(*data)); break;
> +       case 11: asm("movdqu %0, %%xmm11" : : "m"(*data)); break;
> +       case 12: asm("movdqu %0, %%xmm12" : : "m"(*data)); break;
> +       case 13: asm("movdqu %0, %%xmm13" : : "m"(*data)); break;
> +       case 14: asm("movdqu %0, %%xmm14" : : "m"(*data)); break;
> +       case 15: asm("movdqu %0, %%xmm15" : : "m"(*data)); break;
> +#endif
> +       default: BUG();
> +       }
> +       ctxt->ops->put_fpu(ctxt);
> +}
> +
> +static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
> +                                   struct operand *op,
>                                    struct decode_cache *c,
>                                    int inhibit_bytereg)
>  {
> @@ -641,6 +703,15 @@ static void decode_register_operand(struct operand *op,
>
>        if (!(c->d & ModRM))
>                reg = (c->b & 7) | ((c->rex_prefix & 1) << 3);
> +
> +       if (c->d & Sse) {
> +               op->type = OP_XMM;
> +               op->bytes = 16;
> +               op->addr.xmm = reg;
> +               read_sse_reg(ctxt, &op->vec_val, reg);
> +               return;
> +       }
> +
>        op->type = OP_REG;
>        if ((c->d & ByteOp) && !inhibit_bytereg) {
>                op->addr.reg = decode_register(reg, c->regs, highbyte_regs);
> @@ -680,6 +751,13 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
>                op->bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
>                op->addr.reg = decode_register(c->modrm_rm,
>                                               c->regs, c->d & ByteOp);
> +               if (c->d & Sse) {
> +                       op->type = OP_XMM;
> +                       op->bytes = 16;
> +                       op->addr.xmm = c->modrm_rm;
> +                       read_sse_reg(ctxt, &op->vec_val, c->modrm_rm);
> +                       return rc;
> +               }
>                fetch_register_operand(op);
>                return rc;
>        }
> @@ -1107,6 +1185,9 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt,
>                if (rc != X86EMUL_CONTINUE)
>                        return rc;
>                break;
> +       case OP_XMM:
> +               write_sse_reg(ctxt, &c->dst.vec_val, c->dst.addr.xmm);
> +               break;
>        case OP_NONE:
>                /* no writeback */
>                break;
> @@ -2785,6 +2866,9 @@ done_prefixes:
>                        c->op_bytes = 4;
>        }
>
> +       if (c->d & Sse)
> +               c->op_bytes = 16;
> +
>        /* ModRM and SIB bytes. */
>        if (c->d & ModRM) {
>                rc = decode_modrm(ctxt, ops, &memop);
> @@ -2814,7 +2898,7 @@ done_prefixes:
>        case SrcNone:
>                break;
>        case SrcReg:
> -               decode_register_operand(&c->src, c, 0);
> +               decode_register_operand(ctxt, &c->src, c, 0);
>                break;
>        case SrcMem16:
>                memop.bytes = 2;
> @@ -2905,7 +2989,7 @@ done_prefixes:
>        /* Decode and fetch the destination operand: register or memory. */
>        switch (c->d & DstMask) {
>        case DstReg:
> -               decode_register_operand(&c->dst, c,
> +               decode_register_operand(ctxt, &c->dst, c,
>                         c->twobyte && (c->b == 0xb6 || c->b == 0xb7));
>                break;
>        case DstImmUByte:
> @@ -3001,6 +3085,18 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
>                goto done;
>        }
>
> +       if ((c->d & Sse)
> +           && ((ops->get_cr(0, ctxt->vcpu) & X86_CR0_EM)
> +               || !(ops->get_cr(4, ctxt->vcpu) & X86_CR4_OSFXSR))) {
> +               rc = emulate_ud(ctxt);
> +               goto done;
> +       }
> +
> +       if ((c->d & Sse) && (ops->get_cr(0, ctxt->vcpu) & X86_CR0_TS)) {
> +               rc = emulate_nm(ctxt);
> +               goto done;
> +       }
> +
>        /* Privileged instruction can be executed only in CPL=0 */
>        if ((c->d & Priv) && ops->cpl(ctxt->vcpu)) {
>                rc = emulate_gp(ctxt, 0);
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux