Received: by 2002:a25:e74b:0:0:0:0:0 with SMTP id e72csp1703997ybh; Tue, 14 Jul 2020 05:17:05 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxZ/q2g2qSeXTurugVVOIIXzlzOr8E26kHCUcT/uEyoohofJciN34zYVbf8ttR+gxNW82j+ X-Received: by 2002:a17:906:ca43:: with SMTP id jx3mr4103044ejb.208.1594729025336; Tue, 14 Jul 2020 05:17:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1594729025; cv=none; d=google.com; s=arc-20160816; b=Tm6UQRYN9gZ/59cnijEjojUozl3zMkGpZUiQDjA1ddv1bT6GyJXefbPdHvLVV3Di+s CXiy6woNE73dM4Yo4MBvlDhDIkHEZ23hN+4EBjCkwuZ/32GKktSUNMmWARvG0jKDDNEE dPZhuNCjF6oa0l62YLE5dEp/4wNxBucdRxZ1wTKuozTyNIUEshRyVNMB8E1L4STAWEP6 x7kAhmNEtExXd2ApUWLIA47tSyBfJnd9UY7oDDcMuzGhDzbGpbiBcRqpq3VXpJXxfmEo 3DA1g4FKOp774YcmPSnYO3xMNGoNQuPCZuIhIEP1vkLz0B9O/1eHIrj2B2QuNzoDbCN0 xs8A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=uFn/XiV+1xwLx+tWhAIppf7vAPMmLlZXlWZmcRY4i1s=; b=BS/aXjSHfnwGeq3RbtlPqeRqpJC0bJsRAN8zBS294Ae2CiC+QLtpzf72Pl9GwQ0XO7 U4sk8zS6k6nwqyIbBd8OQAMkiqVWXQtMb1QNAgamnm0V18e+flpjld9R4WmGKbztLg6o VD54swSQhhSVTLcLYuNzQaPEH+RYISJzjr5F3mfQmqS9pyvF/A9librTDabKPjXNlmNI QbMeOKUG1iQzDuFJ7qepwVLWBJiaD4mDCUO8yU3HqtCfm0sU1B2ubGqWPCT0Q1B09Dpo M72zXOKWP2wOP5l8QYK/7ZbGauVZ0XFrgv333ILnUwYMkFQ4BZgkQHOdPvBsjHBEj8li wOpQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=8bytes.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id h5si10864314eji.26.2020.07.14.05.16.40; Tue, 14 Jul 2020 05:17:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=8bytes.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728855AbgGNMNZ (ORCPT + 99 others); Tue, 14 Jul 2020 08:13:25 -0400 Received: from 8bytes.org ([81.169.241.247]:52886 "EHLO theia.8bytes.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728480AbgGNMLI (ORCPT ); Tue, 14 Jul 2020 08:11:08 -0400 Received: from cap.home.8bytes.org (p5b006776.dip0.t-ipconnect.de [91.0.103.118]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by theia.8bytes.org (Postfix) with ESMTPSA id DDB69FC2; Tue, 14 Jul 2020 14:11:02 +0200 (CEST) From: Joerg Roedel To: x86@kernel.org Cc: Joerg Roedel , Joerg Roedel , Tom Lendacky , hpa@zytor.com, Andy Lutomirski , Dave Hansen , Peter Zijlstra , Jiri Slaby , Dan Williams , Juergen Gross , Kees Cook , David Rientjes , Cfir Cohen , Erdem Aktas , Masami Hiramatsu , Mike Stunes , Sean Christopherson , Martin Radev , linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org Subject: [PATCH v4 54/75] x86/sev-es: Handle DR7 read/write events Date: Tue, 14 Jul 2020 14:08:56 +0200 Message-Id: <20200714120917.11253-55-joro@8bytes.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200714120917.11253-1-joro@8bytes.org> References: <20200714120917.11253-1-joro@8bytes.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tom Lendacky Add code to handle #VC exceptions on DR7 register reads and writes. This is needed early because show_regs() reads DR7 to print it out. Under SEV-ES there is currently no support for saving/restoring the DRx registers, but software expects to be able to write to the DR7 register. For now, cache the value written to DR7 and return it on read attempts, but do not touch the real hardware DR7. Signed-off-by: Tom Lendacky [ jroedel@suse.de: - Adapt to #VC handling framework - Support early usage ] Co-developed-by: Joerg Roedel Signed-off-by: Joerg Roedel --- arch/x86/kernel/sev-es.c | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c index cbe158091f18..09738d6fe55e 100644 --- a/arch/x86/kernel/sev-es.c +++ b/arch/x86/kernel/sev-es.c @@ -28,6 +28,8 @@ #include #include +#define DR7_RESET_VALUE 0x400 + /* For early boot hypervisor communication in SEV-ES enabled guests */ static struct ghcb boot_ghcb_page __bss_decrypted __aligned(PAGE_SIZE); @@ -75,6 +77,13 @@ struct sev_es_runtime_data { */ bool ghcb_active; bool backup_ghcb_active; + + /* + * Cached DR7 value - write it on DR7 writes and return it on reads. + * That value will never make it to the real hardware DR7 as debugging + * is currently unsupported in SEV-ES guests. + */ + unsigned long dr7; }; struct ghcb_state { @@ -527,6 +536,21 @@ static long *vc_insn_get_reg(struct es_em_ctxt *ctxt) return reg_array + offset; } +static long *vc_insn_get_rm(struct es_em_ctxt *ctxt) +{ + long *reg_array; + int offset; + + reg_array = (long *)ctxt->regs; + offset = insn_get_modrm_rm_off(&ctxt->insn, ctxt->regs); + + if (offset < 0) + return NULL; + + offset /= sizeof(long); + + return reg_array + offset; +} static enum es_result vc_do_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt, unsigned int bytes, bool read) { @@ -774,6 +798,61 @@ static enum es_result vc_handle_mmio(struct ghcb *ghcb, return ret; } +static enum es_result vc_handle_dr7_write(struct ghcb *ghcb, + struct es_em_ctxt *ctxt) +{ + struct sev_es_runtime_data *data = this_cpu_read(runtime_data); + long val, *reg = vc_insn_get_rm(ctxt); + enum es_result ret; + + if (!reg) + return ES_DECODE_FAILED; + + val = *reg; + + /* Upper 32 bits must be written as zeroes */ + if (val >> 32) { + ctxt->fi.vector = X86_TRAP_GP; + ctxt->fi.error_code = 0; + return ES_EXCEPTION; + } + + /* Clear out other reserved bits and set bit 10 */ + val = (val & 0xffff23ffL) | BIT(10); + + /* Early non-zero writes to DR7 are not supported */ + if (!data && (val & ~DR7_RESET_VALUE)) + return ES_UNSUPPORTED; + + /* Using a value of 0 for ExitInfo1 means RAX holds the value */ + ghcb_set_rax(ghcb, val); + ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_WRITE_DR7, 0, 0); + if (ret != ES_OK) + return ret; + + if (data) + data->dr7 = val; + + return ES_OK; +} + +static enum es_result vc_handle_dr7_read(struct ghcb *ghcb, + struct es_em_ctxt *ctxt) +{ + struct sev_es_runtime_data *data = this_cpu_read(runtime_data); + long *reg = vc_insn_get_rm(ctxt); + + if (!reg) + return ES_DECODE_FAILED; + + if (data) + *reg = data->dr7; + else + *reg = DR7_RESET_VALUE; + + return ES_OK; +} + static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt, struct ghcb *ghcb, unsigned long exit_code) @@ -781,6 +860,12 @@ static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt, enum es_result result; switch (exit_code) { + case SVM_EXIT_READ_DR7: + result = vc_handle_dr7_read(ghcb, ctxt); + break; + case SVM_EXIT_WRITE_DR7: + result = vc_handle_dr7_write(ghcb, ctxt); + break; case SVM_EXIT_CPUID: result = vc_handle_cpuid(ghcb, ctxt); break; -- 2.27.0