From patchwork Tue Apr 3 15:36:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 894657 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=web.de Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40FtXT0lFSz9s0q for ; Wed, 4 Apr 2018 01:38:17 +1000 (AEST) Received: from localhost ([::1]:43562 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f3O0l-0000p4-4v for incoming@patchwork.ozlabs.org; Tue, 03 Apr 2018 11:38:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38191) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f3NzA-0008Sw-EU for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f3Nz7-00089R-7i for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:36 -0400 Received: from mout.web.de ([212.227.15.4]:37331) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1f3Nz6-000898-Ui for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:33 -0400 Received: from md1f2u6c.ww002.siemens.net ([92.77.50.102]) by smtp.web.de (mrweb004 [213.165.67.108]) with ESMTPSA (Nemesis) id 0LclHj-1ed9VH25hv-00k7tQ; Tue, 03 Apr 2018 17:36:24 +0200 From: Jan Kiszka To: qemu-devel , Paolo Bonzini , Richard Henderson , Eduardo Habkost Date: Tue, 3 Apr 2018 17:36:11 +0200 Message-Id: X-Mailer: git-send-email 2.13.6 In-Reply-To: References: In-Reply-To: References: X-Provags-ID: V03:K0:PrbzBDj66ovhyEaFR0ut4GjZ+9sen0VtMZNolgBZhn0CVCkxo9e 3D8pjMFqATtTW/Nl9gGB1ATjNiNx9Sxy36fiKQuTFiCKAPncRhHI9Hq4G9FcMClVLZJl1+w s+gcSg4ExTue8MjnfoaDsGOYU4Sl0be3TPGpL09GyDtqKWhXy5AWc2Slad3gJ8rQMZHbbYB brP3XjRIUa2J+yI8LOVBA== X-UI-Out-Filterresults: notjunk:1; V01:K0:qTxX9H+DBtU=:xRv0NNESfOx5L2Y8INyLjg A9RNZOozMU7V9+hCS2i8rQySqKGQQrJ06EXH/PsGiFDS5hAznIy/XaBM4pSWreE5KVQtwJe49 dI2/n5+ZhLkWBH9ZHlaClAR//M79H8CBWp7M/D/GKdPfAuCc2WDVwknRmeSIXnybTjPxrYZZV LtZpDgllW2AzE7qWev5wVc1Xkd5HVDSaGG3P4gDzzqkM2P7FNJ1rav9ELsJ8QzKajtaT04EnX LetCiMkufySTa2IXs9HBCrAv6LWFpsnV/Z65U/01fe6eNgfIS6wKTHhdZ5kdAhtVEMosxQd6y d/2M0gJuuNi45BlP7W8nIVr95MxBaxy/sRmxbrzpdRCkL/DzhVnQgbdtsN6sZlI5YUvT0iRbk ZZ8XMAqvygwxYqvb6twNFhgCwJBHmJ0J7nm044enZQkw5FUeS/6KEkP+6hwFZjFpnhc2rKLoh rbBd474MCxdeI9+1DWCXB8Y02rhm7W3eyXaKBGldfFqOh6Ax5kzt3k+ioiBUGl6IHtdiSpSlF Df3+qkwV7MispQnu5TQHduN74JEsIVSOt3BTQIp02IV7WlDdjmpZrqdqcNQ1/wlpWKgawZmo6 fZk0hHGjfRAfLcojjrPkhaE6JNObITTbXbM+n/XMfYYaKHTH/M9tRqHCLnUbobOFzIXUN2aVB +AT3rtWzak7nKHHSj8b102glJL50q0bvp5us0P3ZQlFyUxLMErZ7XwWWcBUNtftlTEMgLvwO9 s9AzD6RcgdfQg+x4Mlv2o/e2Ix32pKbUT22LHOckRBfQKh2Ec7tKcHmJf3cPN6uGZIKvsYAv9 Ulyk70NHkczqztmDJB2qaLkOUe0yg== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.15.4 Subject: [Qemu-devel] [PATCH v2 1/4] target-i386: Add NMI interception to SVM X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Valentine Sinitsyn Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Jan Kiszka Check for SVM interception prior to injecting an NMI. Tested via the Jailhouse hypervisor. Signed-off-by: Jan Kiszka --- target/i386/seg_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c index 600a4d7586..00301a0c04 100644 --- a/target/i386/seg_helper.c +++ b/target/i386/seg_helper.c @@ -1337,6 +1337,7 @@ bool x86_cpu_exec_interrupt(CPUState *cs, int interrupt_request) ret = true; } else if ((interrupt_request & CPU_INTERRUPT_NMI) && !(env->hflags2 & HF2_NMI_MASK)) { + cpu_svm_check_intercept_param(env, SVM_EXIT_NMI, 0, 0); cs->interrupt_request &= ~CPU_INTERRUPT_NMI; env->hflags2 |= HF2_NMI_MASK; do_interrupt_x86_hardirq(env, EXCP02_NMI, 1); From patchwork Tue Apr 3 15:36:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 894659 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=web.de Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40FtbR63g1z9ryk for ; Wed, 4 Apr 2018 01:40:51 +1000 (AEST) Received: from localhost ([::1]:43696 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f3O3F-0002yg-Rl for incoming@patchwork.ozlabs.org; Tue, 03 Apr 2018 11:40:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38221) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f3NzD-0008Vo-QV for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f3NzD-0008CR-0f for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:39 -0400 Received: from mout.web.de ([212.227.15.3]:42819) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1f3NzC-0008B9-OQ for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:38 -0400 Received: from md1f2u6c.ww002.siemens.net ([92.77.50.102]) by smtp.web.de (mrweb004 [213.165.67.108]) with ESMTPSA (Nemesis) id 0MGlGr-1fGKGf364v-00DWAA; Tue, 03 Apr 2018 17:36:24 +0200 From: Jan Kiszka To: qemu-devel , Paolo Bonzini , Richard Henderson , Eduardo Habkost Date: Tue, 3 Apr 2018 17:36:12 +0200 Message-Id: <37939b244dda0e9cccf96ce50f2b15df1e48315d.1522769774.git.jan.kiszka@web.de> X-Mailer: git-send-email 2.13.6 In-Reply-To: References: In-Reply-To: References: X-Provags-ID: V03:K0:LjEpBn2awL6G8jtLrMVgG99aD2PWx4NaCaqDjRUUdA/rJPCPIdG XhjxxfLIFDR2SuF9gxVTJ6CCpn1UVhac7eYmpMdE1fArNV5tXqawNBcs123cKqHSQLX+VUA /Zb8HLi5aGP17zr3M+2TKr8SfCSb/NXDZBM8BF7xBBhxGf1puW/K7UyKZpfr5/5kQwOzsd1 XrUNJAzR/DfLEcpb+GcQw== X-UI-Out-Filterresults: notjunk:1; V01:K0:iCugiP1hCC8=:I8wFIy+OhFoAS9q1han0RN nb9r+2zrHoggj369tZrIYJmwot20KV4own2iBqp73yNYrqvqP67OxCBIqCfDpDlO0Sx6UgmLf Trc9zHK5JuYVa6DwDVHV2sDPmONaox5pZLhVbHeCiYM/wi66QClpQMS1v52tQ4TGzxeqfjBTO 6K7DtBUZJQIwLo5lRkrNEqrvDbrPHqjrOCpIx+pkzW2d3nD2dC+wNwmvuHIqG0utsD2WhBodQ JFBRGoa/WM1IC8my7KDiJekzDBSUBjxhR7LdJFjvntPTZ55abOWJPbdLeJTpyu3XnwO0R0Ehf CMj1RcDDXN6wXZ0RtnWGArWh0NY8TjMIr7fKZoQtvgm5aTl56SR5fexVD3u/bCmtPhPXGPY2x PXi5IdHq5/+eRIzxLGlEdPrIg5ZO6RG+1SWBvtcygTpZ9rIurEIh/NDW0wtiKLFFhrlejG3vO gQjynGp+rYB+A4R8xTCMKR9DnpJQmCNP19DZSZMnvVdDyh8LrndCIVuBr76oEwSjy8KayqpKR wMk7rBiqRS4E4SB/hdsg4eROH2bSG8XTDCH92NlWOQfd/wyWWjaem9H5cj0kXtOgkACBO14zr skVvh7Y/kVdjJVfAS3TQtO/A5gXTEfY0RCdfXJwYfeiobQj9xEGrIjuAZXUj3I8qHFa0kTom0 FW1fZZwB5kqRayRDA5O1lmmdBcQGrASpyK8e7OUOTcCtNX1vHrhPkD9824mo4rrTzHipyadMb jtH0K9kQToW2C1uYlLk5IywIeguH7h28GquHLY3UXWnEs67r3RfYGreZWkIB4/tmS8GY7grA3 fMumyTpEx08m52KBttxApvwTDLWMg== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.15.3 Subject: [Qemu-devel] [PATCH v2 2/4] target-i386: Allow interrupt injection after STGI X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Valentine Sinitsyn Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Jan Kiszka We need to terminate the translation block after STGI so that pending interrupts can be injected. This fixes pending NMI injection for Jailhouse which uses "stgi; clgi" to open a brief injection window. Signed-off-by: Jan Kiszka --- target/i386/translate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/i386/translate.c b/target/i386/translate.c index 0135415d92..71d97876c7 100644 --- a/target/i386/translate.c +++ b/target/i386/translate.c @@ -7450,8 +7450,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; } gen_update_cc_op(s); - gen_jmp_im(pc_start - s->cs_base); gen_helper_stgi(cpu_env); + gen_jmp_im(s->pc - s->cs_base); + gen_eob(s); break; case 0xdd: /* CLGI */ From patchwork Tue Apr 3 15:36:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 894662 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=web.de Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40Ftf80s8Zz9s0b for ; Wed, 4 Apr 2018 01:43:12 +1000 (AEST) Received: from localhost ([::1]:43830 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f3O5W-0004sv-7F for incoming@patchwork.ozlabs.org; Tue, 03 Apr 2018 11:43:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38241) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f3NzF-00004x-Gq for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f3NzE-0008Db-PL for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:41 -0400 Received: from mout.web.de ([212.227.15.4]:45141) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1f3NzE-0008Cl-CB for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:40 -0400 Received: from md1f2u6c.ww002.siemens.net ([92.77.50.102]) by smtp.web.de (mrweb004 [213.165.67.108]) with ESMTPSA (Nemesis) id 0MBY4U-1fClN042Pm-00AW1h; Tue, 03 Apr 2018 17:36:25 +0200 From: Jan Kiszka To: qemu-devel , Paolo Bonzini , Richard Henderson , Eduardo Habkost Date: Tue, 3 Apr 2018 17:36:13 +0200 Message-Id: <6f4d44ffde55d074cbceb48309c1678600abad2f.1522769774.git.jan.kiszka@web.de> X-Mailer: git-send-email 2.13.6 In-Reply-To: References: In-Reply-To: References: X-Provags-ID: V03:K0:ajZfQ68Md/SYlFv6OBljw63/lUJjHyv8CUKmfOSy5z6cXUwOog7 tqkfDIele7BO/tpTSNZibnxR5zUUfF1NEBRmbVIMvF0d96hFnVSOZODlgaAboHDKUxTLo3n 3YIFIV2r4luLmIQVLNxY5PiPErQ5S6xXDo0F4kJAEcqDx3BybZV2Y1pr/Ny1K345qHCwD99 Lh55v1kxuByCLv76xJR8g== X-UI-Out-Filterresults: notjunk:1; V01:K0:OcHhzKLc1vQ=:LacfRIz4lFoBe6lZGL+VLU tLxWyzdMd43SKhWP5GLTBhxm9179KboYa6RlHYZIL7NDXiADgTtut0BmFKodDMot/M5yY5CAh OY7glXNcds0My5IAhvyRFyTZjYOWgeaoUDElPnD7vZZgucEmmSyJ2+OeMV8xSkJb3DPRqDLhf fRCNBosOF/PwVd2cMFI7m+l+ghObpCx3ZIBeWWILYwUB2zANziUCt999k2/VcXNdks4xzyA9W wWtAYcBMquXUtIzIDu/eTOU7mtBdH+SIpVuhZc7wXg2ngYfHHUbJsHh/tXquX3+TXQD6gV+WG yKhcKLqlsTTy7t5/W/utQ2q9aXYKtaJw4Ujan2qOGpNmMJoidNmlNXMkQJJ2KG+ya47SGRL2c LjXe9qtFFzZ9Y0lNUVO/Lym28zHXyR36e3eMl0XsiU1i1FP8c/T/klORT7hBHZQopTOLg+y1o n6HVHRcWwsdCahdb8AFMxOyvlyVTi19N3lxIpLsi8ljPkS2PotyLTuc0oHsf9+zlBNiJb0tFW a1gK8CHi4EqvtE8uZYDoqMbLCEdtmF96SgTYj5KgNec/PkhS3Doekh9U2qA+5yxmrAWgWgX3X mo71/F9t05Gtl6GMgYqaerz+/0a6msQtLHfhnbqt0CPsNFlX/Y+JSRVILGtWozirsW5clfeW5 neanx/aW8oQKIsPMoJruJjlddPdJixlGhcwZhXzbggg71Tu21XNSYE5AkrrDnBvV/ypbEXOVo uQHXsRV6of2xCAFqhNW2Lp2OA2rwKuU4SRkoQhOk7xdYXTKyNdZbcT6jSsa5egGeOXQ/6KvVc uj4nexzurYMiFGUE6vloBCQYOHHTQ== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.15.4 Subject: [Qemu-devel] [PATCH v2 3/4] target-i386: Mark cpu_vmexit noreturn X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Valentine Sinitsyn Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Jan Kiszka It calls cpu_loop_exit in system emulation mode (and should never be called in user emulation mode). Signed-off-by: Jan Kiszka --- target/i386/cpu.h | 4 ++-- target/i386/svm_helper.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 78db1b833a..d711634c2f 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1764,8 +1764,8 @@ void helper_lock_init(void); /* svm_helper.c */ void cpu_svm_check_intercept_param(CPUX86State *env1, uint32_t type, uint64_t param, uintptr_t retaddr); -void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1, - uintptr_t retaddr); +void QEMU_NORETURN cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, + uint64_t exit_info_1, uintptr_t retaddr); void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1); /* seg_helper.c */ diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c index 303106981c..e3288955f1 100644 --- a/target/i386/svm_helper.c +++ b/target/i386/svm_helper.c @@ -62,6 +62,7 @@ void helper_invlpga(CPUX86State *env, int aflag) void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1, uintptr_t retaddr) { + assert(0); } void helper_svm_check_intercept_param(CPUX86State *env, uint32_t type, From patchwork Tue Apr 3 15:36:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 894656 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=web.de Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40FtX10Mwhz9ryk for ; Wed, 4 Apr 2018 01:37:53 +1000 (AEST) Received: from localhost ([::1]:43400 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f3O0M-0000Ep-GB for incoming@patchwork.ozlabs.org; Tue, 03 Apr 2018 11:37:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38295) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f3NzK-00008v-9k for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f3NzH-0008Eo-0D for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:46 -0400 Received: from mout.web.de ([212.227.15.3]:43777) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1f3NzG-0008E8-Hj for qemu-devel@nongnu.org; Tue, 03 Apr 2018 11:36:42 -0400 Received: from md1f2u6c.ww002.siemens.net ([92.77.50.102]) by smtp.web.de (mrweb004 [213.165.67.108]) with ESMTPSA (Nemesis) id 0LfVe5-1ejBNA0pez-00p2lq; Tue, 03 Apr 2018 17:36:25 +0200 From: Jan Kiszka To: qemu-devel , Paolo Bonzini , Richard Henderson , Eduardo Habkost Date: Tue, 3 Apr 2018 17:36:14 +0200 Message-Id: X-Mailer: git-send-email 2.13.6 In-Reply-To: References: In-Reply-To: References: X-Provags-ID: V03:K0:xpWkMqnBSVi+v/7P2wIAXpahXs2NvJRizu2DVxkZnT5ITA6/EGv 5VfE+vtoxx2OVFO3XyJ9SY26UQteSWZgJgTOKQZoHynMziBr6aLaoKdluPncPxXaNhSfLDx LhbgT/dUB+pwG5ialCR483ux1NovO7moUeiMllnJqz42Tm3h4Bo4iQYfp+LBmJtpMjyx8QX MMCiDeOUQBT3T5uoFLNuw== X-UI-Out-Filterresults: notjunk:1; V01:K0:o40QmPh772M=:HhYi4y2Hv2OOlhnwMmBT00 ozT0pLTBZURV1dCfopYe4D7zT7sRFG1fcdItGg+s/itQ4X8WoFnB2CoXajw1fXiH7ck1rQuZk 3TmcfKf746g5+kYxLw9Eu6okU8CAajln7gaCxtNeV0jBZMdqJh63ag0selhA5JTODnOkYW82w IbCvM4OzXxPlt9sy1s+7SrsFpeqtU6wZokE2uZMtyZ/w64DFruHVw8rMZ8trKk6xjn703jRhh dWg8F7etO6hpACNJJI4P4E6gfPq9sjIFKehb5a27g9Ph78QNa2gu+Y5Ep/iNl2wWOhGPgetKb HIY0YcSqxT6G8SV9vCa3PMKskrRjn+E0r6dUlppxlq7trPM9gF9MPCDctXEqfsfpm6ZSXpptm fcoGXa9eWjF8pPXfSqQDEkeOxyDbd/DzXFAWpPIO2XoRB6zSHcJYAgTBpSks6VHkqRETKUax2 0tCURQX0d0UVeyzeTH6FPzyayiy+PL0TRzPB7RBMm/USal8Gb3dl0F+SpPFNzkCmATG9wPO5s PCpAvOeE1E7Vk1eDMU/zuvlN/lM+JAPcwH/HBOGDvcjbMNv0lzxvY4AJWDi9X68ZY0em4gy7M CWh816I52S2twYrc6JwhV9oqJkon1YW7erd4IYLWNdQz2pkpAKewBC43+2ZpFht8kdmIQ6vP/ 4iy159LREA5YTzXea3RFje7lBRFkN9NnsqJEUcQfth5EJlW4aRNW4d6vdGdViBAdrVPe6Fzlb tu0JFDc6VaER9XmkiS1fBBtDnPCPGqsMCF0gM26dQRVlkEKWV6du2nmEEMKYVq/SeyyG08PZG Lriwv8L5MMp6FYWjWo6QLh+y9r0qg== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.15.3 Subject: [Qemu-devel] [PATCH v2 4/4] target-i386: Add NPT support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Valentine Sinitsyn Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Jan Kiszka This implements NPT suport for SVM by hooking into x86_cpu_handle_mmu_fault where it reads the stage-1 page table. Whether we need to perform this 2nd stage translation, and how, is decided during vmrun and stored in hflags as well as nested_cr3 and nested_pg_mode. As get_hphys performs a direct cpu_vmexit in case of NPT faults, we need retaddr in that function. To avoid changing the signature of cpu_handle_mmu_fault, this passes the value from tlb_fill to get_hphys via the CPU state. This was tested successfully via the Jailhouse hypervisor. Signed-off-by: Jan Kiszka --- target/i386/cpu.c | 2 +- target/i386/cpu.h | 6 ++ target/i386/excp_helper.c | 216 +++++++++++++++++++++++++++++++++++++++++++++- target/i386/mem_helper.c | 6 +- target/i386/svm.h | 14 +++ target/i386/svm_helper.c | 22 +++++ 6 files changed, 260 insertions(+), 6 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 555ae79d29..0d14254ca1 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -261,7 +261,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, #define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \ CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A) #define TCG_EXT4_FEATURES 0 -#define TCG_SVM_FEATURES 0 +#define TCG_SVM_FEATURES CPUID_SVM_NPT #define TCG_KVM_FEATURES 0 #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \ CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \ diff --git a/target/i386/cpu.h b/target/i386/cpu.h index d711634c2f..106a70e1cf 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -177,6 +177,7 @@ typedef enum X86Seg { #define HF_IOBPT_SHIFT 24 /* an io breakpoint enabled */ #define HF_MPX_EN_SHIFT 25 /* MPX Enabled (CR4+XCR0+BNDCFGx) */ #define HF_MPX_IU_SHIFT 26 /* BND registers in-use */ +#define HF_NPT_SHIFT 27 /* Nested Paging enabled */ #define HF_CPL_MASK (3 << HF_CPL_SHIFT) #define HF_INHIBIT_IRQ_MASK (1 << HF_INHIBIT_IRQ_SHIFT) @@ -202,6 +203,7 @@ typedef enum X86Seg { #define HF_IOBPT_MASK (1 << HF_IOBPT_SHIFT) #define HF_MPX_EN_MASK (1 << HF_MPX_EN_SHIFT) #define HF_MPX_IU_MASK (1 << HF_MPX_IU_SHIFT) +#define HF_NPT_MASK (1 << HF_NPT_SHIFT) /* hflags2 */ @@ -1201,12 +1203,16 @@ typedef struct CPUX86State { uint16_t intercept_dr_read; uint16_t intercept_dr_write; uint32_t intercept_exceptions; + uint64_t nested_cr3; + uint32_t nested_pg_mode; uint8_t v_tpr; /* KVM states, automatically cleared on reset */ uint8_t nmi_injected; uint8_t nmi_pending; + uintptr_t retaddr; + /* Fields up to this point are cleared by a CPU reset */ struct {} end_reset_fields; diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c index cb4d1b7d33..e3bb59284f 100644 --- a/target/i386/excp_helper.c +++ b/target/i386/excp_helper.c @@ -157,6 +157,209 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, #else +static hwaddr get_hphys(CPUState *cs, hwaddr gphys, MMUAccessType access_type, + int *prot) +{ + CPUX86State *env = &X86_CPU(cs)->env; + uint64_t rsvd_mask = PG_HI_RSVD_MASK; + uint64_t ptep, pte; + uint64_t exit_info_1 = 0; + target_ulong pde_addr, pte_addr; + uint32_t page_offset; + int page_size; + + if (likely(!(env->hflags & HF_NPT_MASK))) { + return gphys; + } + + if (!(env->nested_pg_mode & SVM_NPT_NXE)) { + rsvd_mask |= PG_NX_MASK; + } + + if (env->nested_pg_mode & SVM_NPT_PAE) { + uint64_t pde, pdpe; + target_ulong pdpe_addr; + +#ifdef TARGET_X86_64 + if (env->nested_pg_mode & SVM_NPT_LMA) { + uint64_t pml5e; + uint64_t pml4e_addr, pml4e; + + pml5e = env->nested_cr3; + ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK; + + pml4e_addr = (pml5e & PG_ADDRESS_MASK) + + (((gphys >> 39) & 0x1ff) << 3); + pml4e = x86_ldq_phys(cs, pml4e_addr); + if (!(pml4e & PG_PRESENT_MASK)) { + goto do_fault; + } + if (pml4e & (rsvd_mask | PG_PSE_MASK)) { + goto do_fault_rsvd; + } + if (!(pml4e & PG_ACCESSED_MASK)) { + pml4e |= PG_ACCESSED_MASK; + x86_stl_phys_notdirty(cs, pml4e_addr, pml4e); + } + ptep &= pml4e ^ PG_NX_MASK; + pdpe_addr = (pml4e & PG_ADDRESS_MASK) + + (((gphys >> 30) & 0x1ff) << 3); + pdpe = x86_ldq_phys(cs, pdpe_addr); + if (!(pdpe & PG_PRESENT_MASK)) { + goto do_fault; + } + if (pdpe & rsvd_mask) { + goto do_fault_rsvd; + } + ptep &= pdpe ^ PG_NX_MASK; + if (!(pdpe & PG_ACCESSED_MASK)) { + pdpe |= PG_ACCESSED_MASK; + x86_stl_phys_notdirty(cs, pdpe_addr, pdpe); + } + if (pdpe & PG_PSE_MASK) { + /* 1 GB page */ + page_size = 1024 * 1024 * 1024; + pte_addr = pdpe_addr; + pte = pdpe; + goto do_check_protect; + } + } else +#endif + { + pdpe_addr = (env->nested_cr3 & ~0x1f) + ((gphys >> 27) & 0x18); + pdpe = x86_ldq_phys(cs, pdpe_addr); + if (!(pdpe & PG_PRESENT_MASK)) { + goto do_fault; + } + rsvd_mask |= PG_HI_USER_MASK; + if (pdpe & (rsvd_mask | PG_NX_MASK)) { + goto do_fault_rsvd; + } + ptep = PG_NX_MASK | PG_USER_MASK | PG_RW_MASK; + } + + pde_addr = (pdpe & PG_ADDRESS_MASK) + (((gphys >> 21) & 0x1ff) << 3); + pde = x86_ldq_phys(cs, pde_addr); + if (!(pde & PG_PRESENT_MASK)) { + goto do_fault; + } + if (pde & rsvd_mask) { + goto do_fault_rsvd; + } + ptep &= pde ^ PG_NX_MASK; + if (pde & PG_PSE_MASK) { + /* 2 MB page */ + page_size = 2048 * 1024; + pte_addr = pde_addr; + pte = pde; + goto do_check_protect; + } + /* 4 KB page */ + if (!(pde & PG_ACCESSED_MASK)) { + pde |= PG_ACCESSED_MASK; + x86_stl_phys_notdirty(cs, pde_addr, pde); + } + pte_addr = (pde & PG_ADDRESS_MASK) + (((gphys >> 12) & 0x1ff) << 3); + pte = x86_ldq_phys(cs, pte_addr); + if (!(pte & PG_PRESENT_MASK)) { + goto do_fault; + } + if (pte & rsvd_mask) { + goto do_fault_rsvd; + } + /* combine pde and pte nx, user and rw protections */ + ptep &= pte ^ PG_NX_MASK; + page_size = 4096; + } else { + uint32_t pde; + + /* page directory entry */ + pde_addr = (env->nested_cr3 & ~0xfff) + ((gphys >> 20) & 0xffc); + pde = x86_ldl_phys(cs, pde_addr); + if (!(pde & PG_PRESENT_MASK)) { + goto do_fault; + } + ptep = pde | PG_NX_MASK; + + /* if PSE bit is set, then we use a 4MB page */ + if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { + page_size = 4096 * 1024; + pte_addr = pde_addr; + + /* Bits 20-13 provide bits 39-32 of the address, bit 21 is reserved. + * Leave bits 20-13 in place for setting accessed/dirty bits below. + */ + pte = pde | ((pde & 0x1fe000LL) << (32 - 13)); + rsvd_mask = 0x200000; + goto do_check_protect_pse36; + } + + if (!(pde & PG_ACCESSED_MASK)) { + pde |= PG_ACCESSED_MASK; + x86_stl_phys_notdirty(cs, pde_addr, pde); + } + + /* page directory entry */ + pte_addr = (pde & ~0xfff) + ((gphys >> 10) & 0xffc); + pte = x86_ldl_phys(cs, pte_addr); + if (!(pte & PG_PRESENT_MASK)) { + goto do_fault; + } + /* combine pde and pte user and rw protections */ + ptep &= pte | PG_NX_MASK; + page_size = 4096; + rsvd_mask = 0; + } + + do_check_protect: + rsvd_mask |= (page_size - 1) & PG_ADDRESS_MASK & ~PG_PSE_PAT_MASK; + do_check_protect_pse36: + if (pte & rsvd_mask) { + goto do_fault_rsvd; + } + ptep ^= PG_NX_MASK; + + if (!(ptep & PG_USER_MASK)) { + goto do_fault_protect; + } + if (ptep & PG_NX_MASK) { + if (access_type == MMU_INST_FETCH) { + goto do_fault_protect; + } + *prot &= ~PAGE_EXEC; + } + if (!(ptep & PG_RW_MASK)) { + if (access_type == MMU_DATA_STORE) { + goto do_fault_protect; + } + *prot &= ~PAGE_WRITE; + } + + pte &= PG_ADDRESS_MASK & ~(page_size - 1); + page_offset = gphys & (page_size - 1); + return pte + page_offset; + + do_fault_rsvd: + exit_info_1 |= SVM_NPTEXIT_RSVD; + do_fault_protect: + exit_info_1 |= SVM_NPTEXIT_P; + do_fault: + x86_stq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2), + gphys); + exit_info_1 |= SVM_NPTEXIT_US; + if (access_type == MMU_DATA_STORE) { + exit_info_1 |= SVM_NPTEXIT_RW; + } else if (access_type == MMU_INST_FETCH) { + exit_info_1 |= SVM_NPTEXIT_ID; + } + if (prot) { + exit_info_1 |= SVM_NPTEXIT_GPA; + } else { /* page table access */ + exit_info_1 |= SVM_NPTEXIT_GPT; + } + cpu_vmexit(env, SVM_EXIT_NPF, exit_info_1, env->retaddr); +} + /* return value: * -1 = cannot handle fault * 0 = nothing more to do @@ -224,6 +427,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, if (la57) { pml5e_addr = ((env->cr[3] & ~0xfff) + (((addr >> 48) & 0x1ff) << 3)) & a20_mask; + pml5e_addr = get_hphys(cs, pml5e_addr, MMU_DATA_STORE, NULL); pml5e = x86_ldq_phys(cs, pml5e_addr); if (!(pml5e & PG_PRESENT_MASK)) { goto do_fault; @@ -243,6 +447,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, pml4e_addr = ((pml5e & PG_ADDRESS_MASK) + (((addr >> 39) & 0x1ff) << 3)) & a20_mask; + pml4e_addr = get_hphys(cs, pml4e_addr, MMU_DATA_STORE, false); pml4e = x86_ldq_phys(cs, pml4e_addr); if (!(pml4e & PG_PRESENT_MASK)) { goto do_fault; @@ -257,6 +462,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, ptep &= pml4e ^ PG_NX_MASK; pdpe_addr = ((pml4e & PG_ADDRESS_MASK) + (((addr >> 30) & 0x1ff) << 3)) & a20_mask; + pdpe_addr = get_hphys(cs, pdpe_addr, MMU_DATA_STORE, NULL); pdpe = x86_ldq_phys(cs, pdpe_addr); if (!(pdpe & PG_PRESENT_MASK)) { goto do_fault; @@ -282,6 +488,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, /* XXX: load them when cr3 is loaded ? */ pdpe_addr = ((env->cr[3] & ~0x1f) + ((addr >> 27) & 0x18)) & a20_mask; + pdpe_addr = get_hphys(cs, pdpe_addr, MMU_DATA_STORE, false); pdpe = x86_ldq_phys(cs, pdpe_addr); if (!(pdpe & PG_PRESENT_MASK)) { goto do_fault; @@ -295,6 +502,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, pde_addr = ((pdpe & PG_ADDRESS_MASK) + (((addr >> 21) & 0x1ff) << 3)) & a20_mask; + pde_addr = get_hphys(cs, pde_addr, MMU_DATA_STORE, NULL); pde = x86_ldq_phys(cs, pde_addr); if (!(pde & PG_PRESENT_MASK)) { goto do_fault; @@ -317,6 +525,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, } pte_addr = ((pde & PG_ADDRESS_MASK) + (((addr >> 12) & 0x1ff) << 3)) & a20_mask; + pte_addr = get_hphys(cs, pte_addr, MMU_DATA_STORE, NULL); pte = x86_ldq_phys(cs, pte_addr); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; @@ -333,6 +542,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, /* page directory entry */ pde_addr = ((env->cr[3] & ~0xfff) + ((addr >> 20) & 0xffc)) & a20_mask; + pde_addr = get_hphys(cs, pde_addr, MMU_DATA_STORE, NULL); pde = x86_ldl_phys(cs, pde_addr); if (!(pde & PG_PRESENT_MASK)) { goto do_fault; @@ -360,6 +570,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, int size, /* page directory entry */ pte_addr = ((pde & ~0xfff) + ((addr >> 10) & 0xffc)) & a20_mask; + pte_addr = get_hphys(cs, pte_addr, MMU_DATA_STORE, NULL); pte = x86_ldl_phys(cs, pte_addr); if (!(pte & PG_PRESENT_MASK)) { goto do_fault; @@ -442,12 +653,13 @@ do_check_protect_pse36: /* align to page_size */ pte &= PG_ADDRESS_MASK & ~(page_size - 1); + page_offset = addr & (page_size - 1); + paddr = get_hphys(cs, pte + page_offset, is_write1, &prot); /* Even if 4MB pages, we map only one 4KB page in the cache to avoid filling it too fast */ vaddr = addr & TARGET_PAGE_MASK; - page_offset = vaddr & (page_size - 1); - paddr = pte + page_offset; + paddr &= TARGET_PAGE_MASK; assert(prot & (1 << is_write1)); tlb_set_page_with_attrs(cs, vaddr, paddr, cpu_get_mem_attrs(env), diff --git a/target/i386/mem_helper.c b/target/i386/mem_helper.c index a8ae694a9c..30c26b9d9c 100644 --- a/target/i386/mem_helper.c +++ b/target/i386/mem_helper.c @@ -202,13 +202,13 @@ void helper_boundl(CPUX86State *env, target_ulong a0, int v) void tlb_fill(CPUState *cs, target_ulong addr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; int ret; + env->retaddr = retaddr; ret = x86_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx); if (ret) { - X86CPU *cpu = X86_CPU(cs); - CPUX86State *env = &cpu->env; - raise_exception_err_ra(env, cs->exception_index, env->error_code, retaddr); } } diff --git a/target/i386/svm.h b/target/i386/svm.h index 922c8fd39c..23a3a040b8 100644 --- a/target/i386/svm.h +++ b/target/i386/svm.h @@ -130,6 +130,20 @@ #define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) /* TS and MP */ +#define SVM_NPT_ENABLED (1 << 0) + +#define SVM_NPT_PAE (1 << 0) +#define SVM_NPT_LMA (1 << 1) +#define SVM_NPT_NXE (1 << 2) + +#define SVM_NPTEXIT_P (1ULL << 0) +#define SVM_NPTEXIT_RW (1ULL << 1) +#define SVM_NPTEXIT_US (1ULL << 2) +#define SVM_NPTEXIT_RSVD (1ULL << 3) +#define SVM_NPTEXIT_ID (1ULL << 4) +#define SVM_NPTEXIT_GPA (1ULL << 32) +#define SVM_NPTEXIT_GPT (1ULL << 33) + struct QEMU_PACKED vmcb_control_area { uint16_t intercept_cr_read; uint16_t intercept_cr_write; diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c index e3288955f1..209881cf16 100644 --- a/target/i386/svm_helper.c +++ b/target/i386/svm_helper.c @@ -124,6 +124,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) { CPUState *cs = CPU(x86_env_get_cpu(env)); target_ulong addr; + uint64_t nested_ctl; uint32_t event_inj; uint32_t int_ctl; @@ -206,6 +207,26 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) control.intercept_exceptions )); + nested_ctl = x86_ldq_phys(cs, env->vm_vmcb + offsetof(struct vmcb, + control.nested_ctl)); + if (nested_ctl & SVM_NPT_ENABLED) { + env->nested_cr3 = x86_ldq_phys(cs, + env->vm_vmcb + offsetof(struct vmcb, + control.nested_cr3)); + env->hflags |= HF_NPT_MASK; + + env->nested_pg_mode = 0; + if (env->cr[4] & CR4_PAE_MASK) { + env->nested_pg_mode |= SVM_NPT_PAE; + } + if (env->hflags & HF_LMA_MASK) { + env->nested_pg_mode |= SVM_NPT_LMA; + } + if (env->efer & MSR_EFER_NXE) { + env->nested_pg_mode |= SVM_NPT_NXE; + } + } + /* enable intercepts */ env->hflags |= HF_SVMI_MASK; @@ -616,6 +637,7 @@ void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) x86_stl_phys(cs, env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0); } + env->hflags &= ~HF_NPT_MASK; /* Save the VM state in the vmcb */ svm_save_seg(env, env->vm_vmcb + offsetof(struct vmcb, save.es),