From patchwork Wed Jun 21 14:33:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasant Karasulli X-Patchwork-Id: 13287412 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 85587EB64D7 for ; Wed, 21 Jun 2023 14:34:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231449AbjFUOeJ (ORCPT ); Wed, 21 Jun 2023 10:34:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229950AbjFUOd7 (ORCPT ); Wed, 21 Jun 2023 10:33:59 -0400 Received: from smtp-out2.suse.de (smtp-out2.suse.de [IPv6:2001:67c:2178:6::1d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6510910E6 for ; Wed, 21 Jun 2023 07:33:58 -0700 (PDT) Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out2.suse.de (Postfix) with ESMTP id 1DE471FEBB; Wed, 21 Jun 2023 14:33:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1687358037; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=C+vTkOQhxhhZSmYwG9dsjhuIod1bY+TLalNC41sGdlY=; b=xZYB/nht8rdlOhrhiLIZkmxeP7K3u6BV5bxFel3WuvouFJFZBS17H6tr8GICDZkHpG6FMo pPIdRWLwfxsmNtjDoUh8g9uz5DSW7EdglSFufI9GQZEHEYCuyVnmj9ez3IQohIRgYJyQT7 mdspoeaUVJIRNd7EnGvTJPToWXrqERE= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1687358037; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=C+vTkOQhxhhZSmYwG9dsjhuIod1bY+TLalNC41sGdlY=; b=7PAdwzZndakpGsqH//ZM/2VEudl6+UEp3bBWNZefByywVyYVzwlB4+Nk6JKZFotvXVUMe5 HaV5hUKTHQ4amMDg== Received: from vasant-suse.fritz.box (unknown [10.163.24.134]) by relay2.suse.de (Postfix) with ESMTP id A8DA42C143; Wed, 21 Jun 2023 14:33:56 +0000 (UTC) From: Vasant Karasulli To: kvm@vger.kernel.org, pbonzini@redhat.com Cc: Thomas.Lendacky@amd.com, drjones@redhat.com, erdemaktas@google.com, marcorr@google.com, rientjes@google.com, seanjc@google.com, zxwang42@gmail.com, papaluri@amd.com, Vasant Karasulli , Varad Gautam Subject: [kvm-unit-tests PATCH v4 10/11] x86: AMD SEV-ES: Handle IOIO #VC Date: Wed, 21 Jun 2023 16:33:24 +0200 Message-Id: <20230621143325.25933-11-vkarasulli@suse.de> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230621143325.25933-1-vkarasulli@suse.de> References: <20230621143325.25933-1-vkarasulli@suse.de> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Using Linux's IOIO #VC processing logic. Signed-off-by: Varad Gautam Signed-off-by: Vasant Karasulli Reviewed-by: Marc Orr --- lib/x86/amd_sev_vc.c | 169 +++++++++++++++++++++++++++++++++++++++++++ lib/x86/processor.h | 7 ++ 2 files changed, 176 insertions(+) -- 2.34.1 diff --git a/lib/x86/amd_sev_vc.c b/lib/x86/amd_sev_vc.c index f6ddfad..e8fc042 100644 --- a/lib/x86/amd_sev_vc.c +++ b/lib/x86/amd_sev_vc.c @@ -171,6 +171,172 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) return ret; } +#define IOIO_TYPE_STR BIT(2) +#define IOIO_TYPE_IN 1 +#define IOIO_TYPE_INS (IOIO_TYPE_IN | IOIO_TYPE_STR) +#define IOIO_TYPE_OUT 0 +#define IOIO_TYPE_OUTS (IOIO_TYPE_OUT | IOIO_TYPE_STR) + +#define IOIO_REP BIT(3) + +#define IOIO_ADDR_64 BIT(9) +#define IOIO_ADDR_32 BIT(8) +#define IOIO_ADDR_16 BIT(7) + +#define IOIO_DATA_32 BIT(6) +#define IOIO_DATA_16 BIT(5) +#define IOIO_DATA_8 BIT(4) + +#define IOIO_SEG_ES (0 << 10) +#define IOIO_SEG_DS (3 << 10) + +/** + * insn_has_rep_prefix() - Determine if instruction has a REP prefix + * @insn: Instruction containing the prefix to inspect + * + * Returns: + * + * 1 if the instruction has a REP prefix, 0 if not. + */ +static int insn_has_rep_prefix(struct insn *insn) +{ + insn_byte_t p; + int i; + + insn_get_prefixes(insn); + + for_each_insn_prefix(insn, i, p) { + if (p == 0xf2 || p == 0xf3) + return 1; + } + + return 0; +} + +static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) +{ + struct insn *insn = &ctxt->insn; + *exitinfo = 0; + + switch (insn->opcode.bytes[0]) { + /* INS opcodes */ + case 0x6c: + case 0x6d: + *exitinfo |= IOIO_TYPE_INS; + *exitinfo |= IOIO_SEG_ES; + *exitinfo |= (ctxt->regs->rdx & 0xffff) << 16; + break; + + /* OUTS opcodes */ + case 0x6e: + case 0x6f: + *exitinfo |= IOIO_TYPE_OUTS; + *exitinfo |= IOIO_SEG_DS; + *exitinfo |= (ctxt->regs->rdx & 0xffff) << 16; + break; + + /* IN immediate opcodes */ + case 0xe4: + case 0xe5: + *exitinfo |= IOIO_TYPE_IN; + *exitinfo |= (u8)insn->immediate.value << 16; + break; + + /* OUT immediate opcodes */ + case 0xe6: + case 0xe7: + *exitinfo |= IOIO_TYPE_OUT; + *exitinfo |= (u8)insn->immediate.value << 16; + break; + + /* IN register opcodes */ + case 0xec: + case 0xed: + *exitinfo |= IOIO_TYPE_IN; + *exitinfo |= (ctxt->regs->rdx & 0xffff) << 16; + break; + + /* OUT register opcodes */ + case 0xee: + case 0xef: + *exitinfo |= IOIO_TYPE_OUT; + *exitinfo |= (ctxt->regs->rdx & 0xffff) << 16; + break; + + default: + return ES_DECODE_FAILED; + } + + switch (insn->opcode.bytes[0]) { + case 0x6c: + case 0x6e: + case 0xe4: + case 0xe6: + case 0xec: + case 0xee: + /* Single byte opcodes */ + *exitinfo |= IOIO_DATA_8; + break; + default: + /* Length determined by instruction parsing */ + *exitinfo |= (insn->opnd_bytes == 2) ? IOIO_DATA_16 + : IOIO_DATA_32; + } + switch (insn->addr_bytes) { + case 2: + *exitinfo |= IOIO_ADDR_16; + break; + case 4: + *exitinfo |= IOIO_ADDR_32; + break; + case 8: + *exitinfo |= IOIO_ADDR_64; + break; + } + + if (insn_has_rep_prefix(insn)) + *exitinfo |= IOIO_REP; + + return ES_OK; +} + +static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt) +{ + struct ex_regs *regs = ctxt->regs; + u64 exit_info_1; + enum es_result ret; + + ret = vc_ioio_exitinfo(ctxt, &exit_info_1); + if (ret != ES_OK) + return ret; + + if (exit_info_1 & IOIO_TYPE_STR) { + ret = ES_VMM_ERROR; + } else { + /* IN/OUT into/from rAX */ + + int bits = (exit_info_1 & 0x70) >> 1; + u64 rax = 0; + + if (!(exit_info_1 & IOIO_TYPE_IN)) + rax = lower_bits(regs->rax, bits); + + ghcb_set_rax(ghcb, rax); + + ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_IOIO, exit_info_1, 0); + if (ret != ES_OK) + return ret; + + if (exit_info_1 & IOIO_TYPE_IN) { + if (!ghcb_rax_is_valid(ghcb)) + return ES_VMM_ERROR; + regs->rax = lower_bits(ghcb->save.rax, bits); + } + } + + return ret; +} + static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt, struct ghcb *ghcb, unsigned long exit_code) @@ -184,6 +350,9 @@ static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt, case SVM_EXIT_MSR: result = vc_handle_msr(ghcb, ctxt); break; + case SVM_EXIT_IOIO: + result = vc_handle_ioio(ghcb, ctxt); + break; default: /* * Unexpected #VC exception diff --git a/lib/x86/processor.h b/lib/x86/processor.h index dc66ba2..8d27dcc 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -808,6 +808,13 @@ static inline int test_bit(int nr, const volatile unsigned long *addr) return (*word & mask) != 0; } +static inline u64 lower_bits(u64 val, unsigned int bits) +{ + u64 mask = (1ULL << bits) - 1; + + return (val & mask); +} + static inline void flush_tlb(void) { ulong cr4;