From patchwork Wed Nov 10 21:19:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613095 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E39DC433EF for ; Wed, 10 Nov 2021 21:20:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 587E661208 for ; Wed, 10 Nov 2021 21:20:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233446AbhKJVXB (ORCPT ); Wed, 10 Nov 2021 16:23:01 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51162 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233431AbhKJVW6 (ORCPT ); Wed, 10 Nov 2021 16:22:58 -0500 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 15C5EC061767 for ; Wed, 10 Nov 2021 13:20:09 -0800 (PST) Received: by mail-pg1-x549.google.com with SMTP id k22-20020a635a56000000b002df9863aa74so642514pgm.19 for ; Wed, 10 Nov 2021 13:20:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=snzSCWk849MQll6yLKrYuxCyE2OCmcQd3IuDmO+ENMg=; b=EtjOCb18plV0mfDxRroDlrTiBCClhquhMA9uw/kKgourm85G5SnHiYXMkxElwBatYR PFRCedxHSXz7N7sF20OkFGJoeL1Sc8CFVf9z0UQvMnWK52+vPGwEk3LIkOPdZd+9MDgA vo+Xd04bAs1aMNW6i7UH2GqB3nbK5Ylr3Cw6JNmVp01beblj4/+2lr8Aj/Pk86Og2jw5 Ddw/CDxmN9wYiNzp2yNiabvLLGY5KN6X717polSB4L7AQAwHpzJqTiNugoi5Vkbqr6T7 Wx8L67KfS4udWU975Nx9W1N+tDKbFH4f8wv2/+qIguqwy3uFydEqVsgvdTXILwRkjN53 rJgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=snzSCWk849MQll6yLKrYuxCyE2OCmcQd3IuDmO+ENMg=; b=IUPVj/Ru/GtzL71C/YFvupmyWHRWZwyJFrE4aQRqB5iWEvg6tvdMtX1+zUVlcfip9x hakZppP5qiMANbZZRKWtzVIzeXIJ+LvoeZDCfhWhfKkgAvRzwqbRCD1NsiHP0L+DeQbp YjYu26JIqb43BTrl6oaDVHxhxwcxFNFv6hTeZaS+IrpdoQXUHzAfF3pCvnTLi6PKjebe HM3KAA5WNLfAJVrXjnGP7TCQWluMhllYVB6FG/Bn1WRuEU9v1WWsmPS0Sfcye2QC6sQ1 ggakkWa9hiw5xjQ86WrpfVNJtngmPwkkOPDQ//oNYLSgVT9wN1/XarHgK+DaVvIE5ons mLLQ== X-Gm-Message-State: AOAM533PLQNUSnE7A+u8459B2s3JneAm6UQe2fSsz6lH8WLHLXkDpBT3 V6fuzZ5NjpOR2DIcLHBvosxmhzh9TklNf+nP3odj1nqNZl1dpSjzYvAlXTzdsnNLGuuJgzrfK1S hbOSkJr/Dq7Uetj9jbaKxwLD7vAHNSctX3YS7evZbPkdT978QmCw1RGHspIjGWI5OVfCO X-Google-Smtp-Source: ABdhPJyz1645zIeIfF68a4vK7P+qRbezHv8oy0kk3UXwFQBjnZnkLrhdz3THdhSY0lI0gu4onOWIHgcH0HRRqYeW X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a17:902:aa49:b0:142:5a22:428f with SMTP id c9-20020a170902aa4900b001425a22428fmr1970413plr.39.1636579208392; Wed, 10 Nov 2021 13:20:08 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:48 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-2-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 01/14] x86: cleanup handling of 16-byte GDT descriptors From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Look them up using a gdt_entry_t pointer, so that the address of the descriptor is correct even for "odd" selectors (e.g. 0x98). Rename the struct from segment_desc64 to system_desc64, highlighting that it is only used in the case of S=0 (system descriptor). Rename the "limit" bitfield to "limit2", matching the convention used for the various parts of the base field. Signed-off-by: Paolo Bonzini --- lib/x86/desc.h | 4 ++-- x86/svm_tests.c | 12 ++++++------ x86/vmware_backdoors.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/x86/desc.h b/lib/x86/desc.h index a6ffb38..1755486 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -172,7 +172,7 @@ typedef struct { u8 base_high; } gdt_entry_t; -struct segment_desc64 { +struct system_desc64 { uint16_t limit1; uint16_t base1; uint8_t base2; @@ -183,7 +183,7 @@ struct segment_desc64 { uint16_t s:1; uint16_t dpl:2; uint16_t p:1; - uint16_t limit:4; + uint16_t limit2:4; uint16_t avl:1; uint16_t l:1; uint16_t db:1; diff --git a/x86/svm_tests.c b/x86/svm_tests.c index afdd359..2fdb0dc 100644 --- a/x86/svm_tests.c +++ b/x86/svm_tests.c @@ -1876,22 +1876,22 @@ static bool reg_corruption_check(struct svm_test *test) static void get_tss_entry(void *data) { struct descriptor_table_ptr gdt; - struct segment_desc64 *gdt_table; - struct segment_desc64 *tss_entry; + gdt_entry_t *gdt_table; + struct system_desc64 *tss_entry; u16 tr = 0; sgdt(&gdt); tr = str(); - gdt_table = (struct segment_desc64 *) gdt.base; - tss_entry = &gdt_table[tr / sizeof(struct segment_desc64)]; - *((struct segment_desc64 **)data) = tss_entry; + gdt_table = (gdt_entry_t *) gdt.base; + tss_entry = (struct system_desc64 *) &gdt_table[tr / 8]; + *((struct system_desc64 **)data) = tss_entry; } static int orig_cpu_count; static void init_startup_prepare(struct svm_test *test) { - struct segment_desc64 *tss_entry; + struct system_desc64 *tss_entry; int i; on_cpu(1, get_tss_entry, &tss_entry); diff --git a/x86/vmware_backdoors.c b/x86/vmware_backdoors.c index b4902a9..b1433cd 100644 --- a/x86/vmware_backdoors.c +++ b/x86/vmware_backdoors.c @@ -133,8 +133,8 @@ struct fault_test vmware_backdoor_tests[] = { static void set_tss_ioperm(void) { struct descriptor_table_ptr gdt; - struct segment_desc64 *gdt_table; - struct segment_desc64 *tss_entry; + gdt_entry_t *gdt_table; + struct system_desc64 *tss_entry; u16 tr = 0; tss64_t *tss; unsigned char *ioperm_bitmap; @@ -142,8 +142,8 @@ static void set_tss_ioperm(void) sgdt(&gdt); tr = str(); - gdt_table = (struct segment_desc64 *) gdt.base; - tss_entry = &gdt_table[tr / sizeof(struct segment_desc64)]; + gdt_table = (gdt_entry_t *) gdt.base; + tss_entry = (struct system_desc64 *) &gdt_table[tr / 8]; tss_base = ((uint64_t) tss_entry->base1 | ((uint64_t) tss_entry->base2 << 16) | ((uint64_t) tss_entry->base3 << 24) | From patchwork Wed Nov 10 21:19:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613097 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DFB6AC433F5 for ; Wed, 10 Nov 2021 21:20:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C434A611F2 for ; Wed, 10 Nov 2021 21:20:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233445AbhKJVXE (ORCPT ); Wed, 10 Nov 2021 16:23:04 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51172 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233442AbhKJVXA (ORCPT ); Wed, 10 Nov 2021 16:23:00 -0500 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AC1CC061766 for ; Wed, 10 Nov 2021 13:20:11 -0800 (PST) Received: by mail-pg1-x549.google.com with SMTP id e4-20020a630f04000000b002cc40fe16afso2090987pgl.23 for ; Wed, 10 Nov 2021 13:20:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=AZLTHxJn0HLhiHimWkLHNhs7fasAZ14U8RcSe/gnCrg=; b=gqgL1m3nhTAJ92oR8AiaBJv8WXjt6N339BTwWTYY5qclKH2aar13D4rubhmZOHEPf+ boZ/tdCPUk8zpfHg+8/l5ptSgVll2+T4k7f5p8yKwFvTtTrtD71J1yqrpWUAkeMuZUcf Bt/4cQQcl48L680dvaDsS0KR7RQnfXRmrfA2ve7NxLJzb9UrD+x7VmJ8vlbpKdFN7Mib Xit/vXw+8HQw0TDwXEOaP1+2QybfCuJ/bk4m8+djTgilmu8bRK9ze7AUbU7lHisu8pvl c8xhs58fY0Qq7LBqzlvkJzYg+NbvA2MDubFaACjf3DuXom2dLV7l+fWE03vdB3UQxmAl n8KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=AZLTHxJn0HLhiHimWkLHNhs7fasAZ14U8RcSe/gnCrg=; b=X/TbUal2ZQWd+Fs2PhmGFStE+yiALtN6w7UM7yP72npRo5LHpKDDpxE66UD+A/qiXW 4D5woCJ352QPTOsyGNH7Qfqzbe8UDJjJOGhSK+MrhVAkXdRrEjmAjjO3/DY+Y7Uv21sM jy1k21QvL/c78nznKcGrupys45j6dJ4omowBBQc8m5g4wEGu7bYNIgSd3wrkPO2Csyvb V5yGtk3QluQfclwoInZfv9o8mZMBqN92bkTHs5CUsPXAiX+tmE8idrDEo8uhfVjljamu Z8Ou4zNnOZOmOadrQWk1BZUJfo+FyCf7zSAECRtaHOhMw8o3D/lMF0kGtkwCuFJ2vXlK ZJgA== X-Gm-Message-State: AOAM53076qaPuycA/It5m5RKhKLnSJBFIheuIl41XayeIV6atdfnhkx0 3JaQXRyGSaGqZkGtJy37XhZeabkPM2V3iQvYa1ucQos27MwfVzl5ssvJLbsIl92nQYJnrzPi6Iv 3ozo1+w1OWQ6Pkwl7jK0fpyJ3b+xG4Y4M75vAZaG25SR7RqLgYFNYQS0euGlB9i8GkPNM X-Google-Smtp-Source: ABdhPJzIXwZAsauW8Zy1CbClJh4xfq6ZkJ59DoXu2ece3hOH0ioAXzbgHBWglbGDL6FaVUUqnA5A0mhuUIhuk5qR X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a17:902:8e85:b0:142:7621:e3b3 with SMTP id bg5-20020a1709028e8500b001427621e3b3mr1986392plb.84.1636579210768; Wed, 10 Nov 2021 13:20:10 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:49 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-3-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 02/14] x86: fix call to set_gdt_entry From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The low four bits of the fourth argument are unused, make them zero in all the callers. Signed-off-by: Paolo Bonzini --- lib/x86/desc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index e7378c1..b691c9b 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -336,7 +336,7 @@ void setup_tss32(void) tss_intr.ds = tss_intr.es = tss_intr.fs = tss_intr.ss = 0x10; tss_intr.gs = read_gs(); tss_intr.iomap_base = (u16)desc_size; - set_gdt_entry(TSS_INTR, (u32)&tss_intr, desc_size - 1, 0x89, 0x0f); + set_gdt_entry(TSS_INTR, (u32)&tss_intr, desc_size - 1, 0x89, 0); } void set_intr_task_gate(int e, void *fn) From patchwork Wed Nov 10 21:19:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613099 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B6A8C433EF for ; Wed, 10 Nov 2021 21:20:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 54B3261207 for ; Wed, 10 Nov 2021 21:20:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233461AbhKJVXF (ORCPT ); Wed, 10 Nov 2021 16:23:05 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233448AbhKJVXB (ORCPT ); Wed, 10 Nov 2021 16:23:01 -0500 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8B7B8C061767 for ; Wed, 10 Nov 2021 13:20:13 -0800 (PST) Received: by mail-pg1-x54a.google.com with SMTP id i25-20020a631319000000b002cce0a43e94so2182415pgl.0 for ; Wed, 10 Nov 2021 13:20:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=OYAqhY2w+ME/rfsDBI9bkEdCt8BXorqX5vKVexmADCg=; b=fa50fXLugidGg7IlljrqB0sdclm3f3m2kL1FGfN27n1VK3E74cSUqxM+l7BkYgOf/G F3tAHpz89wUc5wv+DScw7uCs9Sp9hkK6p/24HAqrMaGh1jJfOoaR1Tl7fld1P2+VgyEZ 8KPp1pPYPMYVDqdBhCLORlighj9eLcwHhTdNWmhO2U4YLDD3SseB9PGv6k4wUIwJBf3I WI9GYl+2ZCx//DHMo5N57yYkg3kK7oWnejjsxTw69kZJTLRnHLPmbfNBzfvHApABS66q ZhkqvDNuen6VaO+eLnO1QnBklH3TinVYgQ7A1NsQvhsY5n1sScTNVmhPfJMo6RCC4gaa qvrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=OYAqhY2w+ME/rfsDBI9bkEdCt8BXorqX5vKVexmADCg=; b=PeNLFi2bYMjx82kXeXmx0c3GneP4LTlbogtKoBTWRr6KaW4DEB5EHJcSKkjcihtyG4 lw359JkgSk6LbMT7dZYvWW9KSLvzE7ERJ9aloWcdfWoLHeBk+MDMfGo13ngzc6haWJrY s+gHR3bb/pnHRLrmRxxE9qntAmDZRQpsFOdGCq8SCLIzZsn9UXEaqoTawu0xIHGEFksD gMvXyW54n6hM15MQ7KqwOr7ZCrWEIdBN6vswAm7rzZM7uWCZvI/MZLeUT/AX5wtXN6nh 010pg5Zb+Q0ei7J/6zvj4S3d1ujwO6hFf1MviAFRoqjeMJJu/e/UtpYAp24CUTxHigjp 6IyA== X-Gm-Message-State: AOAM530VAZJfmUtisk3BCLUYrLeF6WWo6/dxUhTNPeFlxJCeDy+/r1KZ URQzvEHSzGY9BaVwK6xl0B0zXoY8tjY0MGAP3XZtmo910CUUnG+DSJeUUvlkEXs1uiAU6ecXqmY jce+sMuYjBmvsUZCnT/jN6D8mGrOXB+KC8L9kbz8XV3oxXAzQcJq9IA+UxBc72PDopeRB X-Google-Smtp-Source: ABdhPJxmqL3ZbwwKKf9Z65291K14EtBpzB7ej0Ido6BhPMlBNIrDEfmfTP+1BNWq7xECWpGJqzfD+V2NGFzsXLuu X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a17:90a:e613:: with SMTP id j19mr2401973pjy.182.1636579212932; Wed, 10 Nov 2021 13:20:12 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:50 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-4-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 03/14] unify field names and definitions for GDT descriptors From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Use the same names and definitions (apart from the high base field) for GDT descriptors in both 32-bit and 64-bit code. The next patch will also reuse gdt_entry_t in the 16-byte struct definition, for now some duplication remains. Signed-off-by: Paolo Bonzini --- lib/x86/desc.c | 18 +++++++----------- lib/x86/desc.h | 28 +++++++++++++++++++++------- x86/taskswitch.c | 2 +- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index b691c9b..ba0db65 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -280,22 +280,18 @@ bool exception_rflags_rf(void) static char intr_alt_stack[4096]; #ifndef __x86_64__ -void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran) +void set_gdt_entry(int sel, u32 base, u32 limit, u8 type, u8 flags) { int num = sel >> 3; /* Setup the descriptor base address */ - gdt32[num].base_low = (base & 0xFFFF); - gdt32[num].base_middle = (base >> 16) & 0xFF; - gdt32[num].base_high = (base >> 24) & 0xFF; + gdt32[num].base1 = (base & 0xFFFF); + gdt32[num].base2 = (base >> 16) & 0xFF; + gdt32[num].base3 = (base >> 24) & 0xFF; - /* Setup the descriptor limits */ - gdt32[num].limit_low = (limit & 0xFFFF); - gdt32[num].granularity = ((limit >> 16) & 0x0F); - - /* Finally, set up the granularity and access flags */ - gdt32[num].granularity |= (gran & 0xF0); - gdt32[num].access = access; + /* Setup the descriptor limits, type and flags */ + gdt32[num].limit1 = (limit & 0xFFFF); + gdt32[num].type_limit_flags = ((limit & 0xF0000) >> 8) | ((flags & 0xF0) << 8) | type; } void set_gdt_task_gate(u16 sel, u16 tss_sel) diff --git a/lib/x86/desc.h b/lib/x86/desc.h index 1755486..c339e0e 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -164,14 +164,27 @@ typedef struct { } idt_entry_t; typedef struct { - u16 limit_low; - u16 base_low; - u8 base_middle; - u8 access; - u8 granularity; - u8 base_high; -} gdt_entry_t; + uint16_t limit1; + uint16_t base1; + uint8_t base2; + union { + uint16_t type_limit_flags; /* Type and limit flags */ + struct { + uint16_t type:4; + uint16_t s:1; + uint16_t dpl:2; + uint16_t p:1; + uint16_t limit2:4; + uint16_t avl:1; + uint16_t l:1; + uint16_t db:1; + uint16_t g:1; + } __attribute__((__packed__)); + } __attribute__((__packed__)); + uint8_t base3; +} __attribute__((__packed__)) gdt_entry_t; +#ifdef __x86_64__ struct system_desc64 { uint16_t limit1; uint16_t base1; @@ -194,6 +207,7 @@ struct system_desc64 { uint32_t base4; uint32_t zero; } __attribute__((__packed__)); +#endif #define DESC_BUSY ((uint64_t) 1 << 41) diff --git a/x86/taskswitch.c b/x86/taskswitch.c index 889831e..b6b3451 100644 --- a/x86/taskswitch.c +++ b/x86/taskswitch.c @@ -21,7 +21,7 @@ fault_handler(unsigned long error_code) tss.eip += 2; - gdt32[TSS_MAIN / 8].access &= ~2; + gdt32[TSS_MAIN / 8].type &= ~2; set_gdt_task_gate(TSS_RETURN, tss_intr.prev); } From patchwork Wed Nov 10 21:19:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613101 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F85DC433F5 for ; Wed, 10 Nov 2021 21:20:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E5B0261207 for ; Wed, 10 Nov 2021 21:20:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233473AbhKJVXG (ORCPT ); Wed, 10 Nov 2021 16:23:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51190 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233453AbhKJVXD (ORCPT ); Wed, 10 Nov 2021 16:23:03 -0500 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E0A5AC061766 for ; Wed, 10 Nov 2021 13:20:15 -0800 (PST) Received: by mail-pg1-x54a.google.com with SMTP id z19-20020a630a53000000b002dc2f4542faso2114698pgk.13 for ; Wed, 10 Nov 2021 13:20:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=4WL50j77vhTJcNq8Hhp1UeI24PY+rOpBsAN0R3dl3H8=; b=K0utdhqnxVfIvhE1I9FjHBBwjaI1k2+90+K7hswXLzJ48bBUAaYMuxv7PlfJA8nm40 aakikuLBQnuwgnTfBzuSUizNsyuSY6obxvIW++gtJVBa6W5IXcG2Qruq6dEeWU1twcOF ZHW98hEe81swK+aly6Pbs99M3QeEMCpX3O/E2cSzCra+q8Ie77y281anSdKQ+MFh+HyY 08Vb77ZeDwmfjk+dWwiv/1imE0IgwXHtqZ08isfc4qyoaYjioxS4aJhidHrCRITZdio7 DqVz5d2CGH2HPFzC5hbBfDzLYmvTT660B7LotY6E6e9YUzb5AiXtEooI7BLzB//yw192 Uw8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=4WL50j77vhTJcNq8Hhp1UeI24PY+rOpBsAN0R3dl3H8=; b=igaNloZB/JfDPA6KCpRP5HF8+Z9wJwxVvCy7KrjnYYfHQN0ytl85nkF8/diJYe0C5k tjRRgaEheEtQp1rbEMHKRoaBTseJe57/L5jxQFE7d4ED9oOgeC5nocohJ3Ryr9vWZFcF w1RyC0ynz07lEx6H+FsyhCyktm4Gkmmiy33QWdReISr2iQqpnLWDboLaLwZck81uXl/K oziAsFWtsy397KTXBISXAAfxwlc26f5AIGGNHGOzL23JtOe7xBrIJ4E7lQfOi2r7dGYB X0h24R0ffOoDIouammwCvDXrdHErtCwqo9hmGqu2Ak9FLuHdveTxBfr9VNeKkxX6UkgU t3yA== X-Gm-Message-State: AOAM532LqvOtKpQBAs88EpgAzPDdGJ0j6zdWSvyzUQZ1PPgO0irnya57 2zVFeg9Uj2tC4UjtvkrGvTkZuRmcsAl5BkscBd1ygepw3KO+WqGAAi8aujVtppSdO8eZJPFicfq SjNDPmwxC6omYJx9h1GR8jAqqu3jRi/I+JTm6ShVczAI4Ivbr9W90NGY/LIOKqmPCMqiy X-Google-Smtp-Source: ABdhPJy6928G5xjqPGl5P0SA8KromyLw2a6w1r2xgYqrMm5PjdGGuPkxZPkwZMmdegckHCGW+xIA1XTGSCPwt4jL X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a63:3748:: with SMTP id g8mr1289916pgn.102.1636579215281; Wed, 10 Nov 2021 13:20:15 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:51 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-5-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 04/14] replace tss_descr global with a function From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org tss_descr is declared as a struct descriptor_table_ptr but it is actualy pointing to an _entry_ in the GDT. Also it is different per CPU, but tss_descr does not recognize that. Fix both by reusing the code (already present e.g. in the vmware_backdoors test) that extracts the base from the GDT entry; and also provide a helper to retrieve the limit, which is needed in vmx.c. Signed-off-by: Paolo Bonzini --- lib/x86/desc.c | 32 ++++++++++++++++++++++++++++++++ lib/x86/desc.h | 25 ++++++------------------- x86/cstart64.S | 1 - x86/svm_tests.c | 15 +++------------ x86/taskswitch.c | 2 +- x86/vmware_backdoors.c | 22 ++++++---------------- x86/vmx.c | 9 +++++---- 7 files changed, 53 insertions(+), 53 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index ba0db65..94f0ddb 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -409,3 +409,35 @@ void __set_exception_jmpbuf(jmp_buf *addr) { exception_jmpbuf = addr; } + +gdt_entry_t *get_tss_descr(void) +{ + struct descriptor_table_ptr gdt_ptr; + gdt_entry_t *gdt; + + sgdt(&gdt_ptr); + gdt = (gdt_entry_t *)gdt_ptr.base; + return &gdt[str() / 8]; +} + +unsigned long get_gdt_entry_base(gdt_entry_t *entry) +{ + unsigned long base; + base = entry->base1 | ((u32)entry->base2 << 16) | ((u32)entry->base3 << 24); +#ifdef __x86_64__ + if (!entry->s) { + base |= (u64)((struct system_desc64 *)entry)->base4 << 32; + } +#endif + return base; +} + +unsigned long get_gdt_entry_limit(gdt_entry_t *entry) +{ + unsigned long limit; + limit = entry->limit1 | ((u32)entry->limit2 << 16); + if (entry->g) { + limit = (limit << 12) | 0xFFF; + } + return limit; +} diff --git a/lib/x86/desc.h b/lib/x86/desc.h index c339e0e..51148d1 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -186,30 +186,13 @@ typedef struct { #ifdef __x86_64__ struct system_desc64 { - uint16_t limit1; - uint16_t base1; - uint8_t base2; - union { - uint16_t type_limit_flags; /* Type and limit flags */ - struct { - uint16_t type:4; - uint16_t s:1; - uint16_t dpl:2; - uint16_t p:1; - uint16_t limit2:4; - uint16_t avl:1; - uint16_t l:1; - uint16_t db:1; - uint16_t g:1; - } __attribute__((__packed__)); - } __attribute__((__packed__)); - uint8_t base3; + gdt_entry_t common; uint32_t base4; uint32_t zero; } __attribute__((__packed__)); #endif -#define DESC_BUSY ((uint64_t) 1 << 41) +#define DESC_BUSY 2 extern idt_entry_t boot_idt[256]; @@ -253,4 +236,8 @@ static inline void *get_idt_addr(idt_entry_t *entry) return (void *)addr; } +extern gdt_entry_t *get_tss_descr(void); +extern unsigned long get_gdt_entry_base(gdt_entry_t *entry); +extern unsigned long get_gdt_entry_limit(gdt_entry_t *entry); + #endif diff --git a/x86/cstart64.S b/x86/cstart64.S index 5c6ad38..cf38bae 100644 --- a/x86/cstart64.S +++ b/x86/cstart64.S @@ -4,7 +4,6 @@ .globl boot_idt .globl idt_descr -.globl tss_descr .globl gdt64_desc .globl online_cpus .globl cpu_online_count diff --git a/x86/svm_tests.c b/x86/svm_tests.c index 2fdb0dc..8ad6122 100644 --- a/x86/svm_tests.c +++ b/x86/svm_tests.c @@ -1875,23 +1875,14 @@ static bool reg_corruption_check(struct svm_test *test) static void get_tss_entry(void *data) { - struct descriptor_table_ptr gdt; - gdt_entry_t *gdt_table; - struct system_desc64 *tss_entry; - u16 tr = 0; - - sgdt(&gdt); - tr = str(); - gdt_table = (gdt_entry_t *) gdt.base; - tss_entry = (struct system_desc64 *) &gdt_table[tr / 8]; - *((struct system_desc64 **)data) = tss_entry; + *((gdt_entry_t **)data) = get_tss_descr(); } static int orig_cpu_count; static void init_startup_prepare(struct svm_test *test) { - struct system_desc64 *tss_entry; + gdt_entry_t *tss_entry; int i; on_cpu(1, get_tss_entry, &tss_entry); @@ -1905,7 +1896,7 @@ static void init_startup_prepare(struct svm_test *test) --cpu_online_count; - *(uint64_t *)tss_entry &= ~DESC_BUSY; + tss_entry->type &= ~DESC_BUSY; apic_icr_write(APIC_DEST_PHYSICAL | APIC_DM_STARTUP, id_map[1]); diff --git a/x86/taskswitch.c b/x86/taskswitch.c index b6b3451..0fa818d 100644 --- a/x86/taskswitch.c +++ b/x86/taskswitch.c @@ -21,7 +21,7 @@ fault_handler(unsigned long error_code) tss.eip += 2; - gdt32[TSS_MAIN / 8].type &= ~2; + gdt32[TSS_MAIN / 8].type &= ~DESC_BUSY; set_gdt_task_gate(TSS_RETURN, tss_intr.prev); } diff --git a/x86/vmware_backdoors.c b/x86/vmware_backdoors.c index b1433cd..bc10020 100644 --- a/x86/vmware_backdoors.c +++ b/x86/vmware_backdoors.c @@ -132,23 +132,13 @@ struct fault_test vmware_backdoor_tests[] = { */ static void set_tss_ioperm(void) { - struct descriptor_table_ptr gdt; - gdt_entry_t *gdt_table; - struct system_desc64 *tss_entry; - u16 tr = 0; + gdt_entry_t *tss_entry; tss64_t *tss; unsigned char *ioperm_bitmap; - uint64_t tss_base; - - sgdt(&gdt); - tr = str(); - gdt_table = (gdt_entry_t *) gdt.base; - tss_entry = (struct system_desc64 *) &gdt_table[tr / 8]; - tss_base = ((uint64_t) tss_entry->base1 | - ((uint64_t) tss_entry->base2 << 16) | - ((uint64_t) tss_entry->base3 << 24) | - ((uint64_t) tss_entry->base4 << 32)); - tss = (tss64_t *)tss_base; + u16 tr = str(); + + tss_entry = get_tss_descr(); + tss = (tss64_t *)get_gdt_entry_base(tss_entry); tss->iomap_base = sizeof(*tss); ioperm_bitmap = ((unsigned char *)tss+tss->iomap_base); @@ -157,7 +147,7 @@ static void set_tss_ioperm(void) 1 << (RANDOM_IO_PORT % 8); ioperm_bitmap[VMWARE_BACKDOOR_PORT / 8] |= 1 << (VMWARE_BACKDOOR_PORT % 8); - *(uint64_t *)tss_entry &= ~DESC_BUSY; + tss_entry->type &= ~DESC_BUSY; /* Update TSS */ ltr(tr); diff --git a/x86/vmx.c b/x86/vmx.c index 20dc677..d45c6de 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -75,7 +75,6 @@ union vmx_ept_vpid ept_vpid; extern struct descriptor_table_ptr gdt64_desc; extern struct descriptor_table_ptr idt_descr; -extern struct descriptor_table_ptr tss_descr; extern void *vmx_return; extern void *entry_sysenter; extern void *guest_entry; @@ -1275,7 +1274,7 @@ static void init_vmcs_host(void) vmcs_write(HOST_SEL_FS, KERNEL_DS); vmcs_write(HOST_SEL_GS, KERNEL_DS); vmcs_write(HOST_SEL_TR, TSS_MAIN); - vmcs_write(HOST_BASE_TR, tss_descr.base); + vmcs_write(HOST_BASE_TR, get_gdt_entry_base(get_tss_descr())); vmcs_write(HOST_BASE_GDTR, gdt64_desc.base); vmcs_write(HOST_BASE_IDTR, idt_descr.base); vmcs_write(HOST_BASE_FS, 0); @@ -1291,6 +1290,8 @@ static void init_vmcs_host(void) static void init_vmcs_guest(void) { + gdt_entry_t *tss_descr = get_tss_descr(); + /* 26.3 CHECKING AND LOADING GUEST STATE */ ulong guest_cr0, guest_cr4, guest_cr3; /* 26.3.1.1 */ @@ -1331,7 +1332,7 @@ static void init_vmcs_guest(void) vmcs_write(GUEST_BASE_DS, 0); vmcs_write(GUEST_BASE_FS, 0); vmcs_write(GUEST_BASE_GS, 0); - vmcs_write(GUEST_BASE_TR, tss_descr.base); + vmcs_write(GUEST_BASE_TR, get_gdt_entry_base(tss_descr)); vmcs_write(GUEST_BASE_LDTR, 0); vmcs_write(GUEST_LIMIT_CS, 0xFFFFFFFF); @@ -1341,7 +1342,7 @@ static void init_vmcs_guest(void) vmcs_write(GUEST_LIMIT_FS, 0xFFFFFFFF); vmcs_write(GUEST_LIMIT_GS, 0xFFFFFFFF); vmcs_write(GUEST_LIMIT_LDTR, 0xffff); - vmcs_write(GUEST_LIMIT_TR, tss_descr.limit); + vmcs_write(GUEST_LIMIT_TR, get_gdt_entry_limit(tss_descr)); vmcs_write(GUEST_AR_CS, 0xa09b); vmcs_write(GUEST_AR_DS, 0xc093); From patchwork Wed Nov 10 21:19:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613103 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C4870C433FE for ; Wed, 10 Nov 2021 21:20:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AA63A61207 for ; Wed, 10 Nov 2021 21:20:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233459AbhKJVXH (ORCPT ); Wed, 10 Nov 2021 16:23:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51200 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233448AbhKJVXG (ORCPT ); Wed, 10 Nov 2021 16:23:06 -0500 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2AFFAC061766 for ; Wed, 10 Nov 2021 13:20:18 -0800 (PST) Received: by mail-pg1-x549.google.com with SMTP id h35-20020a63f923000000b002d5262fdfc4so2153500pgi.2 for ; Wed, 10 Nov 2021 13:20:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=tB0hEKl2XjIx6N/+c64vQcumEGJO93RbM+u3u7eeD5U=; b=ZTMvjjof9Ln7Tjrwi7BesRN7JflnzlG16No0XkguMhGW4aRB1N0bXcPzz5WOgsXusu 5TcU0/h303+fkdK+dDkNLpR0kzVIhAXMt+evlOnG2vwiQrDvX1RWUr5rGLs6a22cwJSi /AB1Q88Up2uFfnp2zIElcPCChnGo1YjUVTj5VC6WiAL6C/TTy7cnbO/qNt9td3Eb1KtH KOjRFPZBlSQ0TNgxx7DVvCXp9lNzpTkUoW0nMys2+pK8zFo36TND3EQf9HBsOycEYgSp 4FuuuN4AlJpF9fx86TGeAMFxYpNo+JdDUlD8//xhHLn94/Z4EwTC5yLEA84QNxgLWIW2 Xfng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=tB0hEKl2XjIx6N/+c64vQcumEGJO93RbM+u3u7eeD5U=; b=SUt9V57coIUEq0T3ENJqGs8SGSvhRY8sHLD6lpUvE8oLv9GQmANWJd/bj5gAWPp2Bh tzSyShf40+uK+x2ARTalso/XRJ8doBRqLIlPxY1M37TNPlKbySFQBneSBGCSxhbhH8DK pko5sO8XxKDfftDCdV3z47biu0OfICVq9vf7CrDdLeQ2NM9v4J0S5ascvchIBsBK/m6Q 62MIzPfvqU4HQ/GV/2wDXHuMiAu30LoRukbeluSEC+W4R0zXAXDsUddxX94e/ZCcsYtV QhzfR9akxZIJFnalH7OH4Uiay/43BP5nA3E5WCJK3/R9qVSstFP/dA8JhFwIX9dB+eeh NV6g== X-Gm-Message-State: AOAM530KpBhdKf4DNv86zLkRL3uJ2i/ixGmZQGGb5f+5Mlkw6dQ0CgQO hCMs0DnDdbbV3Ly4BeqeDhK5l2Olz+YwC66C7jaOGFjEJcSBQ3+M1P2KFzbmFlccH8gT/uNs4AY O4mYeotLov/M1dADveURWjYF3JnMnINHluMHe+pRinEAa2LoBey3YdAUK6t6JtrwvlxqI X-Google-Smtp-Source: ABdhPJxOz5ateHVUv4Cqfh5Whz40Y1h8XmYkEZ/eiXhe8hVREB0cRtIt1/DFTskfJQ29070OjniLOaDekF/eONb0 X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a17:903:1110:b0:13f:d1d7:fb5f with SMTP id n16-20020a170903111000b0013fd1d7fb5fmr2045580plh.6.1636579217579; Wed, 10 Nov 2021 13:20:17 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:52 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-6-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 05/14] x86: Move IDT to desc.c From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Move the IDT data structures from x86/cstart.S and x86/cstart64.S to lib/x86/desc.c, so that the follow-up UEFI support commits can reuse these definitions, without re-defining them in UEFI's boot up assembly code. Extracted by a patch by Zixuan Wang and ported to 32-bit too. Signed-off-by: Paolo Bonzini --- lib/x86/desc.c | 10 ++++++++++ x86/cstart.S | 11 ----------- x86/cstart64.S | 14 -------------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index 94f0ddb..2ef5aad 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -3,6 +3,16 @@ #include "processor.h" #include +/* Boot-related data structures */ + +/* IDT and IDT descriptor */ +idt_entry_t boot_idt[256] = {0}; + +struct descriptor_table_ptr idt_descr = { + .limit = sizeof(boot_idt) - 1, + .base = (unsigned long)boot_idt, +}; + #ifndef __x86_64__ __attribute__((regparm(1))) #endif diff --git a/x86/cstart.S b/x86/cstart.S index bcf7218..4461c38 100644 --- a/x86/cstart.S +++ b/x86/cstart.S @@ -1,7 +1,6 @@ #include "apic-defs.h" -.globl boot_idt .global online_cpus ipi_vector = 0x20 @@ -28,12 +27,6 @@ i = 0 i = i + 1 .endr -boot_idt: - .rept 256 - .quad 0 - .endr -end_boot_idt: - .globl gdt32 gdt32: .quad 0 @@ -78,10 +71,6 @@ tss: .endr tss_end: -idt_descr: - .word end_boot_idt - boot_idt - 1 - .long boot_idt - .section .init .code32 diff --git a/x86/cstart64.S b/x86/cstart64.S index cf38bae..b98a0d3 100644 --- a/x86/cstart64.S +++ b/x86/cstart64.S @@ -1,9 +1,6 @@ #include "apic-defs.h" -.globl boot_idt - -.globl idt_descr .globl gdt64_desc .globl online_cpus .globl cpu_online_count @@ -50,13 +47,6 @@ ptl5: .align 4096 -boot_idt: - .rept 256 - .quad 0 - .quad 0 - .endr -end_boot_idt: - gdt64_desc: .word gdt64_end - gdt64 - 1 .quad gdt64 @@ -290,10 +280,6 @@ setup_5level_page_table: lvl5: retq -idt_descr: - .word end_boot_idt - boot_idt - 1 - .quad boot_idt - online_cpus: .fill (max_cpus + 7) / 8, 1, 0 From patchwork Wed Nov 10 21:19:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613105 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB5D8C433EF for ; Wed, 10 Nov 2021 21:20:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D25CB61208 for ; Wed, 10 Nov 2021 21:20:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233469AbhKJVXK (ORCPT ); Wed, 10 Nov 2021 16:23:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51216 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233451AbhKJVXJ (ORCPT ); Wed, 10 Nov 2021 16:23:09 -0500 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CE5F6C061766 for ; Wed, 10 Nov 2021 13:20:20 -0800 (PST) Received: by mail-pg1-x54a.google.com with SMTP id i25-20020a631319000000b002cce0a43e94so2182603pgl.0 for ; Wed, 10 Nov 2021 13:20:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=yaQDhfDTxVkBn2c4lDmED/e+OxEisDXW6FuxukyAWe4=; b=B+AqmLNwuwgrGG/g5IKMB3AsyJvsgiFDRpoAeFAsd7Er21A7WgvgOZLnr9CMsQCpE+ HbVUOttT0hZhXcWsPEMtbIg30Wi/SOtwdjloEHO09rVEq2ETpLWcX13CLaZCwKDPzOG5 Vtsx2KV9fRXA7QGgLTyfTf31dbNT+yS1EHZ2h1wix9EcD6QsBYF07YMa3ST4zumVFnWy uw+f3El49k11AmenBdvkDDylHLyEV/OQ9ddv5gKkhrkP+8E5/S6JjqAK91N1X5rtsy5F wOiHzwcAgZciL+OicguUN+ajOLm2HNxflABk5TRGx5UPS9eVu04FZEntKnd92IK7Rh1f oFFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=yaQDhfDTxVkBn2c4lDmED/e+OxEisDXW6FuxukyAWe4=; b=AFAvJsh6jXjwlfiV0Yj5YGsqIn1c3Su67Ci5QpG5cm0Ll3Q9wUrxnk6p+pYG5OObGg a4lIvodBgKshD0hID65wOl4LEXJW4tfBgav4bEyuraJuembgWRhvfvG8yu7y9pYX4xG7 qRq+5keWoR1uZI3ZYtM0fcY3LxHhmfnkIk0/QAs938DYaPqOXJmyir964/6GIz1PK601 FGA2+YwefjlM7yUNUNdg9N1JxVQFhZyoc/ASDZKib3fGjvphGxUVUJXCdFyE4bHYMPD1 KGgy2k6oU67MdsluAvOkiJFgjDuzLnCDIS/KY4t81ZJqB2tOAgt5o6wUyL5mtr/NbHD7 1ycw== X-Gm-Message-State: AOAM530LfIJJuqyTxg4vyCaWjQQtsShy1wmpofV+Szh+XielDiFGFAS+ hf+6AG54/TlsmM9Qmm4lUL1MZx84yfqC7K+L/NGhgKpZUAqOvAD7bWGczIBBjAt1HhcYHmv25gB MOoPSSvf7beply3uaEEpVXLarvbG2aYaT0Iu6DIpJjhRxSM/pGveKgxY6BRBM0TDo2bia X-Google-Smtp-Source: ABdhPJxwZh4k+mWQE0I9JR46vP1HLvWNaLXNCw7FodHk+skRTlJVxfA2AvOOJlgvVsRZ81ZBIT4JlMhAXVtCySdp X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a05:6a00:2ab:b0:49f:997e:23e2 with SMTP id q11-20020a056a0002ab00b0049f997e23e2mr2057051pfs.22.1636579220158; Wed, 10 Nov 2021 13:20:20 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:53 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-7-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 06/14] x86: unify name of 32-bit and 64-bit GDT From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org There's no need to distinguish gdt32 and gdt64, since the same C functions operate on both and selector numbers are mostly unified between 32- and 64-bit versions. Signed-off-by: Paolo Bonzini --- lib/x86/desc.c | 12 ++++++------ lib/x86/desc.h | 2 +- x86/cstart.S | 20 ++++++++++---------- x86/cstart64.S | 17 +++++++++-------- x86/taskswitch.c | 2 +- x86/vmx.c | 8 ++++---- x86/vmx_tests.c | 4 ++-- 7 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index 2ef5aad..ac167d0 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -292,16 +292,16 @@ static char intr_alt_stack[4096]; #ifndef __x86_64__ void set_gdt_entry(int sel, u32 base, u32 limit, u8 type, u8 flags) { - int num = sel >> 3; + gdt_entry_t *entry = &gdt[sel >> 3]; /* Setup the descriptor base address */ - gdt32[num].base1 = (base & 0xFFFF); - gdt32[num].base2 = (base >> 16) & 0xFF; - gdt32[num].base3 = (base >> 24) & 0xFF; + entry->base1 = (base & 0xFFFF); + entry->base2 = (base >> 16) & 0xFF; + entry->base3 = (base >> 24) & 0xFF; /* Setup the descriptor limits, type and flags */ - gdt32[num].limit1 = (limit & 0xFFFF); - gdt32[num].type_limit_flags = ((limit & 0xF0000) >> 8) | ((flags & 0xF0) << 8) | type; + entry->limit1 = (limit & 0xFFFF); + entry->type_limit_flags = ((limit & 0xF0000) >> 8) | ((flags & 0xF0) << 8) | type; } void set_gdt_task_gate(u16 sel, u16 tss_sel) diff --git a/lib/x86/desc.h b/lib/x86/desc.h index 51148d1..c0817d8 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -197,7 +197,6 @@ struct system_desc64 { extern idt_entry_t boot_idt[256]; #ifndef __x86_64__ -extern gdt_entry_t gdt32[]; extern tss32_t tss; extern tss32_t tss_intr; void set_gdt_task_gate(u16 tss_sel, u16 sel); @@ -207,6 +206,7 @@ void setup_tss32(void); #else extern tss64_t tss; #endif +extern gdt_entry_t gdt[]; unsigned exception_vector(void); int write_cr4_checking(unsigned long val); diff --git a/x86/cstart.S b/x86/cstart.S index 4461c38..5e925d8 100644 --- a/x86/cstart.S +++ b/x86/cstart.S @@ -27,8 +27,8 @@ i = 0 i = i + 1 .endr -.globl gdt32 -gdt32: +.globl gdt +gdt: .quad 0 .quad 0x00cf9b000000ffff // flat 32-bit code segment .quad 0x00cf93000000ffff // flat 32-bit data segment @@ -55,7 +55,7 @@ percpu_descr: .rept max_cpus .quad 0x00cf93000000ffff // 32-bit data segment for perCPU area .endr -gdt32_end: +gdt_end: i = 0 .globl tss @@ -94,7 +94,7 @@ mb_cmdline = 16 mov %al, percpu_descr+4(,%ecx,8) mov %ah, percpu_descr+7(,%ecx,8) - lea percpu_descr-gdt32(,%ecx,8), %eax + lea percpu_descr-gdt(,%ecx,8), %eax mov %ax, %gs .endm @@ -110,7 +110,7 @@ mb_cmdline = 16 .globl start start: - lgdtl gdt32_descr + lgdtl gdt_descr setup_segments mov $stacktop, %esp setup_percpu_area @@ -195,7 +195,7 @@ load_tss: shr $16, %eax mov %al, tss_descr+4(,%ebx,8) mov %ah, tss_descr+7(,%ebx,8) - lea tss_descr-gdt32(,%ebx,8), %eax + lea tss_descr-gdt(,%ebx,8), %eax ltr %ax ret @@ -224,11 +224,11 @@ sipi_entry: mov %cr0, %eax or $1, %eax mov %eax, %cr0 - lgdtl gdt32_descr - sipi_entry + lgdtl gdt_descr - sipi_entry ljmpl $8, $ap_start32 -gdt32_descr: - .word gdt32_end - gdt32 - 1 - .long gdt32 +gdt_descr: + .word gdt_end - gdt - 1 + .long gdt sipi_end: diff --git a/x86/cstart64.S b/x86/cstart64.S index b98a0d3..46b9d9b 100644 --- a/x86/cstart64.S +++ b/x86/cstart64.S @@ -1,7 +1,8 @@ #include "apic-defs.h" -.globl gdt64_desc +.globl gdt +.globl gdt_descr .globl online_cpus .globl cpu_online_count @@ -47,11 +48,11 @@ ptl5: .align 4096 -gdt64_desc: - .word gdt64_end - gdt64 - 1 - .quad gdt64 +gdt_descr: + .word gdt_end - gdt - 1 + .quad gdt -gdt64: +gdt: .quad 0 .quad 0x00af9b000000ffff // 64-bit code segment .quad 0x00cf93000000ffff // 32/64-bit data segment @@ -75,7 +76,7 @@ tss_descr: .quad 0x000089000000ffff // 64-bit avail tss .quad 0 // tss high addr .endr -gdt64_end: +gdt_end: i = 0 .globl tss @@ -162,7 +163,7 @@ switch_to_5level: jmpl $8, $lvl5 prepare_64: - lgdt gdt64_desc + lgdt gdt_descr setup_segments xor %eax, %eax @@ -300,7 +301,7 @@ load_tss: mov %al, tss_descr+7(%rbx) shr $8, %rax mov %eax, tss_descr+8(%rbx) - lea tss_descr-gdt64(%rbx), %rax + lea tss_descr-gdt(%rbx), %rax ltr %ax ret diff --git a/x86/taskswitch.c b/x86/taskswitch.c index 0fa818d..1d6e6e2 100644 --- a/x86/taskswitch.c +++ b/x86/taskswitch.c @@ -21,7 +21,7 @@ fault_handler(unsigned long error_code) tss.eip += 2; - gdt32[TSS_MAIN / 8].type &= ~DESC_BUSY; + gdt[TSS_MAIN / 8].type &= ~DESC_BUSY; set_gdt_task_gate(TSS_RETURN, tss_intr.prev); } diff --git a/x86/vmx.c b/x86/vmx.c index d45c6de..7a2f7a3 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -73,7 +73,7 @@ union vmx_ctrl_msr ctrl_exit_rev; union vmx_ctrl_msr ctrl_enter_rev; union vmx_ept_vpid ept_vpid; -extern struct descriptor_table_ptr gdt64_desc; +extern struct descriptor_table_ptr gdt_descr; extern struct descriptor_table_ptr idt_descr; extern void *vmx_return; extern void *entry_sysenter; @@ -1275,7 +1275,7 @@ static void init_vmcs_host(void) vmcs_write(HOST_SEL_GS, KERNEL_DS); vmcs_write(HOST_SEL_TR, TSS_MAIN); vmcs_write(HOST_BASE_TR, get_gdt_entry_base(get_tss_descr())); - vmcs_write(HOST_BASE_GDTR, gdt64_desc.base); + vmcs_write(HOST_BASE_GDTR, gdt_descr.base); vmcs_write(HOST_BASE_IDTR, idt_descr.base); vmcs_write(HOST_BASE_FS, 0); vmcs_write(HOST_BASE_GS, 0); @@ -1354,9 +1354,9 @@ static void init_vmcs_guest(void) vmcs_write(GUEST_AR_TR, 0x8b); /* 26.3.1.3 */ - vmcs_write(GUEST_BASE_GDTR, gdt64_desc.base); + vmcs_write(GUEST_BASE_GDTR, gdt_descr.base); vmcs_write(GUEST_BASE_IDTR, idt_descr.base); - vmcs_write(GUEST_LIMIT_GDTR, gdt64_desc.limit); + vmcs_write(GUEST_LIMIT_GDTR, gdt_descr.limit); vmcs_write(GUEST_LIMIT_IDTR, idt_descr.limit); /* 26.3.1.4 */ diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index ac2b0b4..9ee6653 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -797,8 +797,8 @@ asm( "insn_wbinvd: wbinvd;ret\n\t" "insn_cpuid: mov $10, %eax; cpuid;ret\n\t" "insn_invd: invd;ret\n\t" - "insn_sgdt: sgdt gdt64_desc;ret\n\t" - "insn_lgdt: lgdt gdt64_desc;ret\n\t" + "insn_sgdt: sgdt gdt_descr;ret\n\t" + "insn_lgdt: lgdt gdt_descr;ret\n\t" "insn_sidt: sidt idt_descr;ret\n\t" "insn_lidt: lidt idt_descr;ret\n\t" "insn_sldt: sldt %ax;ret\n\t" From patchwork Wed Nov 10 21:19:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613107 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E8BD2C433EF for ; Wed, 10 Nov 2021 21:20:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D13E061208 for ; Wed, 10 Nov 2021 21:20:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233453AbhKJVXL (ORCPT ); Wed, 10 Nov 2021 16:23:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51236 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233462AbhKJVXL (ORCPT ); Wed, 10 Nov 2021 16:23:11 -0500 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3297EC061766 for ; Wed, 10 Nov 2021 13:20:23 -0800 (PST) Received: by mail-pj1-x104a.google.com with SMTP id x18-20020a17090a789200b001a7317f995cso1880435pjk.4 for ; Wed, 10 Nov 2021 13:20:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=0Mn3/0vsl/BqcHzl4h7JC934taELWq7FYXUNRPu9fe4=; b=VGLGjfYD/RZA7DWwdCiVpo1kuvYiLVAxgr74Y2PXnz8Sst5Aafg/T66OX1SAxojGFC kO+vXF4+8B14E3aE5eVORO0vq5Kzwt8g3GlqHOpVOfC+PqTCZd0NO34HhbgFm5WudgfI UbVzn2ZGmxEJen2+cK/5W3nKkhlB7D9X8g9Qzov4qfMIh+Gw8xuRVe7JYSql1j7zohOg 8kwwlARnbUdE7nUNA2/eW+3cDTA2rfTeRc9ve8CL/FedXBB8mwEOM24ZzTDJs8NpBXlc OdKnOLw1kbRQ3RRqVM0Gfe7pGC3ALKTfHqLnie/LPnJGU+qYde5Ew4pH0UVufkAEBl0o BoGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=0Mn3/0vsl/BqcHzl4h7JC934taELWq7FYXUNRPu9fe4=; b=3mQ3/KTvkSzlaGBimlPaBpmPzE5009zghtKkuERnXKqxMYP+G2fNGXkQwB3Ch4m6kw J7breFHdOQ/K/dgNjZ+UB93UY1O1Vh+r3XoetTDZSKKVVtBP1ZC6S0bKtt1VTA0K2Yes D1Gv24h4OhWN1HDtUEwmuV7kZ1yx/DZvdqfExa7VJvYGIhC01xnW1mz0YaC0iWnFgP8G pgmfXMcupT01msih/1mf1Xi4aFgmyEDBmu3tN2BvQWj+aXpJqTHOP2LqsyMf7zjuVRbD tdeIGa49tR1qCJccPkLa28sJxJLi4TvVCyTqs/GiAFaGM88OMgdNx8ba8j5NoMBSQ2A2 Ttog== X-Gm-Message-State: AOAM530S4TWJjbWpoYo+mDpOgGNTt1Vok8xWwn3DcdsdjIXI0G8S/zXH wYFHCQdnytfJkHQzyE6Wo5FamiwzKt74/tzsZVpcpQS8tcw3/u09iqEvTPpX/k4MCGsDzCAo1RH rUMKXyvj0RrcXY3HUI+f8xYKNC1PckrgcBGR/HfMg7jpfeck6D/d40v1DmT4JNgdn0z+n X-Google-Smtp-Source: ABdhPJz/KzX2+dGq3iFCuJzmY3Se5ybolVrQyLT5Cj0cvtMnXrPA+uOLG+V+TUENjPYJZcexxhZw5xGbtOVxRwIt X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a17:902:778a:b0:13f:672c:103a with SMTP id o10-20020a170902778a00b0013f672c103amr1965298pll.55.1636579222611; Wed, 10 Nov 2021 13:20:22 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:54 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-8-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 07/14] x86: get rid of ring0stacktop From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The ring3 switch code relied on a special stack page that was used for the ring0 stack during the ring3 part of the test. This special stack page was used if an exception handler ran during the ring3 part of the test. This method is quite complex; it is easier to just use the same stack for the "outer" part of the test and the exception handler. To do so, store esp/rsp in the TSS just before doing the PUSH/IRET sequence. On 64-bit, the TSS can also be used to restore rsp after coming back from ring3. Unifying the three copies of the ring switching code is left as an exercise to the reader. Signed-off-by: Paolo Bonzini [aaron: removed commas after (tss.rsp0) in usermode.c and umips.c] Signed-off-by: Aaron Lewis --- lib/x86/usermode.c | 9 +++++---- x86/access.c | 16 ++++++++-------- x86/cstart.S | 6 +----- x86/cstart64.S | 6 +----- x86/umip.c | 19 ++++++++++++------- 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/lib/x86/usermode.c b/lib/x86/usermode.c index f032523..49b87b2 100644 --- a/lib/x86/usermode.c +++ b/lib/x86/usermode.c @@ -47,8 +47,8 @@ uint64_t run_in_user(usermode_func func, unsigned int fault_vector, } asm volatile ( - /* Backing Up Stack in rdi */ - "mov %%rsp, %%rdi\n\t" + /* Prepare kernel SP for exception handlers */ + "mov %%rsp, %[rsp0]\n\t" /* Load user_ds to DS and ES */ "mov %[user_ds], %%ax\n\t" "mov %%ax, %%ds\n\t" @@ -92,9 +92,10 @@ uint64_t run_in_user(usermode_func func, unsigned int fault_vector, "int %[kernel_entry_vector]\n\t" /* Kernel Mode */ "ret_to_kernel:\n\t" - "mov %%rdi, %%rsp\n\t" + "mov %[rsp0], %%rsp\n\t" : - "+a"(rax) + "+a"(rax), + [rsp0]"=m"(tss.rsp0) : [arg1]"m"(arg1), [arg2]"m"(arg2), diff --git a/x86/access.c b/x86/access.c index 4725bbd..49d31b1 100644 --- a/x86/access.c +++ b/x86/access.c @@ -711,7 +711,7 @@ static int ac_test_do_access(ac_test_t *at) } asm volatile ("mov $fixed1, %%rsi \n\t" - "mov %%rsp, %%rdx \n\t" + "mov %%rsp, %[rsp0] \n\t" "cmp $0, %[user] \n\t" "jz do_access \n\t" "push %%rax; mov %[user_ds], %%ax; mov %%ax, %%ds; pop %%rax \n\t" @@ -734,8 +734,14 @@ static int ac_test_do_access(ac_test_t *at) "done: \n" "fixed1: \n" "int %[kernel_entry_vector] \n\t" + ".section .text.entry \n\t" + "kernel_entry: \n\t" + "mov %[rsp0], %%rsp \n\t" + "jmp back_to_kernel \n\t" + ".section .text \n\t" "back_to_kernel:" - : [reg]"+r"(r), "+a"(fault), "=b"(e), "=&d"(rsp) + : [reg]"+r"(r), "+a"(fault), "=b"(e), "=&d"(rsp), + [rsp0]"=m"(tss.rsp0) : [addr]"r"(at->virt), [write]"r"(F(AC_ACCESS_WRITE)), [user]"r"(F(AC_ACCESS_USER)), @@ -754,12 +760,6 @@ static int ac_test_do_access(ac_test_t *at) "iretq \n\t" ".section .text"); - asm volatile (".section .text.entry \n\t" - "kernel_entry: \n\t" - "mov %rdx, %rsp \n\t" - "jmp back_to_kernel \n\t" - ".section .text"); - ac_test_check(at, &success, fault && !at->expected_fault, "unexpected fault"); ac_test_check(at, &success, !fault && at->expected_fault, diff --git a/x86/cstart.S b/x86/cstart.S index 5e925d8..e9100a4 100644 --- a/x86/cstart.S +++ b/x86/cstart.S @@ -13,10 +13,6 @@ max_cpus = MAX_TEST_CPUS .align 16 stacktop: - . = . + 4096 - .align 16 -ring0stacktop: - .data .align 4096 @@ -62,7 +58,7 @@ i = 0 tss: .rept max_cpus .long 0 - .long ring0stacktop - i * 4096 + .long 0 .long 16 .quad 0, 0 .quad 0, 0, 0, 0, 0, 0, 0, 0 diff --git a/x86/cstart64.S b/x86/cstart64.S index 46b9d9b..18c7457 100644 --- a/x86/cstart64.S +++ b/x86/cstart64.S @@ -16,10 +16,6 @@ max_cpus = MAX_TEST_CPUS .align 16 stacktop: - . = . + 4096 * max_cpus - .align 16 -ring0stacktop: - .data .align 4096 @@ -83,7 +79,7 @@ i = 0 tss: .rept max_cpus .long 0 - .quad ring0stacktop - i * 4096 + .quad 0 .quad 0, 0 .quad 0, 0, 0, 0, 0, 0, 0, 0 .long 0, 0, 0 diff --git a/x86/umip.c b/x86/umip.c index 0fc1f65..1936989 100644 --- a/x86/umip.c +++ b/x86/umip.c @@ -124,7 +124,7 @@ static noinline int do_ring3(void (*fn)(const char *), const char *arg) "mov %%dx, %%es\n\t" "mov %%dx, %%fs\n\t" "mov %%dx, %%gs\n\t" - "mov %%" R "sp, %%" R "cx\n\t" + "mov %%" R "sp, %[sp0]\n\t" /* kernel sp for exception handlers */ "push" W " %%" R "dx \n\t" "lea %[user_stack_top], %%" R "dx \n\t" "push" W " %%" R "dx \n\t" @@ -133,8 +133,6 @@ static noinline int do_ring3(void (*fn)(const char *), const char *arg) "push" W " $1f \n\t" "iret" W "\n" "1: \n\t" - "push %%" R "cx\n\t" /* save kernel SP */ - #ifndef __x86_64__ "push %[arg]\n\t" #endif @@ -142,13 +140,15 @@ static noinline int do_ring3(void (*fn)(const char *), const char *arg) #ifndef __x86_64__ "pop %%ecx\n\t" #endif - - "pop %%" R "cx\n\t" "mov $1f, %%" R "dx\n\t" "int %[kernel_entry_vector]\n\t" ".section .text.entry \n\t" "kernel_entry: \n\t" - "mov %%" R "cx, %%" R "sp \n\t" +#ifdef __x86_64__ + "mov %[sp0], %%" R "sp\n\t" +#else + "add $(5 * " S "), %%esp\n\t" +#endif "mov %[kernel_ds], %%cx\n\t" "mov %%cx, %%ds\n\t" "mov %%cx, %%es\n\t" @@ -157,7 +157,12 @@ static noinline int do_ring3(void (*fn)(const char *), const char *arg) "jmp *%%" R "dx \n\t" ".section .text\n\t" "1:\n\t" - : [ret] "=&a" (ret) + : [ret] "=&a" (ret), +#ifdef __x86_64__ + [sp0] "=m" (tss.rsp0) +#else + [sp0] "=m" (tss.esp0) +#endif : [user_ds] "i" (USER_DS), [user_cs] "i" (USER_CS), [user_stack_top]"m"(user_stack[sizeof(user_stack) - From patchwork Wed Nov 10 21:19:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613109 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C46B5C433F5 for ; Wed, 10 Nov 2021 21:20:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ADE59611F2 for ; Wed, 10 Nov 2021 21:20:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233485AbhKJVXO (ORCPT ); Wed, 10 Nov 2021 16:23:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51252 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233484AbhKJVXN (ORCPT ); Wed, 10 Nov 2021 16:23:13 -0500 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 34DA2C061766 for ; Wed, 10 Nov 2021 13:20:25 -0800 (PST) Received: by mail-pf1-x44a.google.com with SMTP id x14-20020a627c0e000000b0049473df362dso2635137pfc.12 for ; Wed, 10 Nov 2021 13:20:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=WYON61i+BiQGdw3Qu+0D+mgUfA2363/6ERGQ1SkKSaU=; b=B1QT22zlv66BcGokcNmyTkG1UxwMBVfwK3oBntIZA8WlvvGI3yFbW+Inqa8uwMCZk+ xIFSCXT1F44jXYbb/mH9bFARH8GfuDwF7k3w4VJkfdeQam5uHiYwwIf51/KPKsXbPfQ3 LsfIdueIDlCP2qPG0M0Ro+/E0Fa5A4rImWcSruE6BSlgYXJ3iJNvt6zlCcHeV6X8hHlg HOQAdnyEzIhIfj2dLYW+FzfO/Wk7k9rZsB1sc+7SzIMHlosLWRnXyASsmho/BOy37FHs fktswS965XgFySEMsSjBoedFBRR1hzESaTRRqbvAMU0WrtiIw+RHxMLj9o6ZB+2mr3g7 TLiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=WYON61i+BiQGdw3Qu+0D+mgUfA2363/6ERGQ1SkKSaU=; b=hwSGoU/z0f7OYv/iF56wduKVw/3H0AhvUCtG67BC9xxlP0JZ70ugZckS7C61hgyBZd XHrq/WpOb1046vfPApreRiNO14cI4sreq1vBB3zHzJgBXefo0kP2Ngo+pc5kUbqk/JMi jCbtZ3opcVN7H8jbbxKuLo6R/KEXov12ds90SVBpkHlgXlilvmMsTLQghPrV+zemgylr cqAV6ESL7CKuDSUTcjgnPBch7+eMlRHSXbnR8gKM3Xi80Cljq1h6xZ6V9N6Iv1S3qUif yNztwmlAeMKQad8Qam+M2/mmc6ZF6hZftGRh0jzwJ9hFMwQO926mBj40gQbzTGlO8VdG H2Qw== X-Gm-Message-State: AOAM531GJMkzsT3REhcSOCKVHzp6K4G6kslfn8w1pOGtype3OT1GNXdd ajVwNHa0DEOicPtfyr4hq7XZhNbXBCfa0/sJoqye5d6vgzQH6OgmYgL22Xl2zvhGO4SXkD4uroK tQ95YUae/et4gU3NgzVJnFqvFRVspJOmhmxKov5ITccX75DtZ2ytcPiG2AhOi/afqWs7Y X-Google-Smtp-Source: ABdhPJxY9y+aWuKKkkNVlSeWxPxQSp5iD8ktUkikIrsbxjQ/5A23l7yeQJIPqSgX/cNQGdw2elAK2kqhd+DLzTFU X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a17:902:e353:b0:142:d33:9acd with SMTP id p19-20020a170902e35300b001420d339acdmr2028661plc.78.1636579224656; Wed, 10 Nov 2021 13:20:24 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:55 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-9-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 08/14] x86: Move 64-bit GDT and TSS to desc.c From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis , Zixuan Wang Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Move the GDT and TSS data structures from x86/cstart64.S to lib/x86/desc.c, so that the follow-up UEFI support commits can reuse these definitions, without re-defining them in UEFI's boot up assembly code. Signed-off-by: Zixuan Wang Message-Id: <20211004204931.1537823-2-zxwang42@gmail.com> Signed-off-by: Paolo Bonzini --- lib/x86/asm/setup.h | 6 ++++ lib/x86/desc.c | 38 +++++++++++++++++++++-- lib/x86/desc.h | 4 +-- lib/x86/setup.c | 25 +++++++++++++++ lib/x86/usermode.c | 2 +- x86/access.c | 2 +- x86/cstart64.S | 76 +++++---------------------------------------- x86/umip.c | 2 +- 8 files changed, 79 insertions(+), 76 deletions(-) create mode 100644 lib/x86/asm/setup.h diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h new file mode 100644 index 0000000..e3c3bfb --- /dev/null +++ b/lib/x86/asm/setup.h @@ -0,0 +1,6 @@ +#ifndef _X86_ASM_SETUP_H_ +#define _X86_ASM_SETUP_H_ + +unsigned long setup_tss(void); + +#endif /* _X86_ASM_SETUP_H_ */ diff --git a/lib/x86/desc.c b/lib/x86/desc.c index ac167d0..c185c01 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -2,6 +2,7 @@ #include "desc.h" #include "processor.h" #include +#include "apic-defs.h" /* Boot-related data structures */ @@ -13,6 +14,29 @@ struct descriptor_table_ptr idt_descr = { .base = (unsigned long)boot_idt, }; +#ifdef __x86_64__ +/* GDT, TSS and descriptors */ +gdt_entry_t gdt[TSS_MAIN / 8 + MAX_TEST_CPUS * 2] = { + { 0, 0, 0, .type_limit_flags = 0x0000}, /* 0x00 null */ + {0xffff, 0, 0, .type_limit_flags = 0xaf9b}, /* 0x08 64-bit code segment */ + {0xffff, 0, 0, .type_limit_flags = 0xcf93}, /* 0x10 32/64-bit data segment */ + {0xffff, 0, 0, .type_limit_flags = 0xaf1b}, /* 0x18 64-bit code segment, not present */ + {0xffff, 0, 0, .type_limit_flags = 0xcf9b}, /* 0x20 32-bit code segment */ + {0xffff, 0, 0, .type_limit_flags = 0x8f9b}, /* 0x28 16-bit code segment */ + {0xffff, 0, 0, .type_limit_flags = 0x8f93}, /* 0x30 16-bit data segment */ + {0xffff, 0, 0, .type_limit_flags = 0xcffb}, /* 0x38 32-bit code segment (user) */ + {0xffff, 0, 0, .type_limit_flags = 0xcff3}, /* 0x40 32/64-bit data segment (user) */ + {0xffff, 0, 0, .type_limit_flags = 0xaffb}, /* 0x48 64-bit code segment (user) */ +}; + +tss64_t tss[MAX_TEST_CPUS] = {0}; + +struct descriptor_table_ptr gdt_descr = { + .limit = sizeof(gdt) - 1, + .base = (unsigned long)gdt, +}; +#endif + #ifndef __x86_64__ __attribute__((regparm(1))) #endif @@ -289,8 +313,7 @@ bool exception_rflags_rf(void) static char intr_alt_stack[4096]; -#ifndef __x86_64__ -void set_gdt_entry(int sel, u32 base, u32 limit, u8 type, u8 flags) +void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 type, u8 flags) { gdt_entry_t *entry = &gdt[sel >> 3]; @@ -302,8 +325,17 @@ void set_gdt_entry(int sel, u32 base, u32 limit, u8 type, u8 flags) /* Setup the descriptor limits, type and flags */ entry->limit1 = (limit & 0xFFFF); entry->type_limit_flags = ((limit & 0xF0000) >> 8) | ((flags & 0xF0) << 8) | type; + +#ifdef __x86_64__ + if (!entry->s) { + struct system_desc64 *entry16 = (struct system_desc64 *)entry; + entry16->zero = 0; + entry16->base4 = base >> 32; + } +#endif } +#ifndef __x86_64__ void set_gdt_task_gate(u16 sel, u16 tss_sel) { set_gdt_entry(sel, tss_sel, 0, 0x85, 0); // task, present @@ -380,7 +412,7 @@ void set_intr_alt_stack(int e, void *addr) void setup_alt_stack(void) { - tss.ist1 = (u64)intr_alt_stack + 4096; + tss[0].ist1 = (u64)intr_alt_stack + 4096; } #endif diff --git a/lib/x86/desc.h b/lib/x86/desc.h index c0817d8..ddfae04 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -204,7 +204,7 @@ void set_idt_task_gate(int vec, u16 sel); void set_intr_task_gate(int vec, void *fn); void setup_tss32(void); #else -extern tss64_t tss; +extern tss64_t tss[]; #endif extern gdt_entry_t gdt[]; @@ -215,7 +215,7 @@ bool exception_rflags_rf(void); void set_idt_entry(int vec, void *addr, int dpl); void set_idt_sel(int vec, u16 sel); void set_idt_dpl(int vec, u16 dpl); -void set_gdt_entry(int sel, u32 base, u32 limit, u8 access, u8 gran); +void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 access, u8 gran); void set_intr_alt_stack(int e, void *fn); void print_current_tss_info(void); handler handle_exception(u8 v, handler fn); diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 7befe09..ec005b5 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -2,6 +2,7 @@ * Initialize machine setup information * * Copyright (C) 2017, Red Hat Inc, Andrew Jones + * Copyright (C) 2021, Google Inc, Zixuan Wang * * This work is licensed under the terms of the GNU LGPL, version 2. */ @@ -9,6 +10,10 @@ #include "fwcfg.h" #include "alloc_phys.h" #include "argv.h" +#include "desc.h" +#include "apic.h" +#include "apic-defs.h" +#include "asm/setup.h" extern char edata; @@ -97,6 +102,26 @@ void find_highmem(void) phys_alloc_init(best_start, best_end - best_start); } } + +/* Setup TSS for the current processor, and return TSS offset within GDT */ +unsigned long setup_tss(void) +{ + u32 id; + tss64_t *tss_entry; + + id = apic_id(); + + /* Runtime address of current TSS */ + tss_entry = &tss[id]; + + /* Update TSS */ + memset((void *)tss_entry, 0, sizeof(tss64_t)); + + /* Update TSS descriptors; each descriptor takes up 2 entries */ + set_gdt_entry(TSS_MAIN + id * 16, (unsigned long)tss_entry, 0xffff, 0x89, 0); + + return TSS_MAIN + id * 16; +} #endif void setup_multiboot(struct mbi_bootinfo *bi) diff --git a/lib/x86/usermode.c b/lib/x86/usermode.c index 49b87b2..2e77831 100644 --- a/lib/x86/usermode.c +++ b/lib/x86/usermode.c @@ -95,7 +95,7 @@ uint64_t run_in_user(usermode_func func, unsigned int fault_vector, "mov %[rsp0], %%rsp\n\t" : "+a"(rax), - [rsp0]"=m"(tss.rsp0) + [rsp0]"=m"(tss[0].rsp0) : [arg1]"m"(arg1), [arg2]"m"(arg2), diff --git a/x86/access.c b/x86/access.c index 49d31b1..a781a0c 100644 --- a/x86/access.c +++ b/x86/access.c @@ -741,7 +741,7 @@ static int ac_test_do_access(ac_test_t *at) ".section .text \n\t" "back_to_kernel:" : [reg]"+r"(r), "+a"(fault), "=b"(e), "=&d"(rsp), - [rsp0]"=m"(tss.rsp0) + [rsp0]"=m"(tss[0].rsp0) : [addr]"r"(at->virt), [write]"r"(F(AC_ACCESS_WRITE)), [user]"r"(F(AC_ACCESS_USER)), diff --git a/x86/cstart64.S b/x86/cstart64.S index 18c7457..c6daa34 100644 --- a/x86/cstart64.S +++ b/x86/cstart64.S @@ -1,8 +1,6 @@ #include "apic-defs.h" -.globl gdt -.globl gdt_descr .globl online_cpus .globl cpu_online_count @@ -44,49 +42,6 @@ ptl5: .align 4096 -gdt_descr: - .word gdt_end - gdt - 1 - .quad gdt - -gdt: - .quad 0 - .quad 0x00af9b000000ffff // 64-bit code segment - .quad 0x00cf93000000ffff // 32/64-bit data segment - .quad 0x00af1b000000ffff // 64-bit code segment, not present - .quad 0x00cf9b000000ffff // 32-bit code segment - .quad 0x008f9b000000FFFF // 16-bit code segment - .quad 0x008f93000000FFFF // 16-bit data segment - .quad 0x00cffb000000ffff // 32-bit code segment (user) - .quad 0x00cff3000000ffff // 32/64-bit data segment (user) - .quad 0x00affb000000ffff // 64-bit code segment (user) - - .quad 0 // 6 spare selectors - .quad 0 - .quad 0 - .quad 0 - .quad 0 - .quad 0 - -tss_descr: - .rept max_cpus - .quad 0x000089000000ffff // 64-bit avail tss - .quad 0 // tss high addr - .endr -gdt_end: - -i = 0 -.globl tss -tss: - .rept max_cpus - .long 0 - .quad 0 - .quad 0, 0 - .quad 0, 0, 0, 0, 0, 0, 0, 0 - .long 0, 0, 0 -i = i + 1 - .endr -tss_end: - mb_boot_info: .quad 0 pt_root: .quad ptl4 @@ -111,6 +66,12 @@ MSR_GS_BASE = 0xc0000101 wrmsr .endm +.macro load_tss + lidtq idt_descr + call setup_tss + ltr %ax +.endm + .macro setup_segments mov $MSR_GS_BASE, %ecx rdmsr @@ -228,7 +189,7 @@ save_id: ap_start64: call reset_apic - call load_tss + load_tss call enable_apic call save_id call enable_x2apic @@ -241,7 +202,7 @@ ap_start64: start64: call reset_apic - call load_tss + load_tss call mask_pic_interrupts call enable_apic call save_id @@ -280,27 +241,6 @@ lvl5: online_cpus: .fill (max_cpus + 7) / 8, 1, 0 -load_tss: - lidtq idt_descr - mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax - mov (%rax), %eax - shr $24, %eax - mov %eax, %ebx - shl $4, %ebx - mov $((tss_end - tss) / max_cpus), %edx - imul %edx - add $tss, %rax - mov %ax, tss_descr+2(%rbx) - shr $16, %rax - mov %al, tss_descr+4(%rbx) - shr $8, %rax - mov %al, tss_descr+7(%rbx) - shr $8, %rax - mov %eax, tss_descr+8(%rbx) - lea tss_descr-gdt(%rbx), %rax - ltr %ax - ret - ap_init: cld lea sipi_entry, %rsi diff --git a/x86/umip.c b/x86/umip.c index 1936989..0a52342 100644 --- a/x86/umip.c +++ b/x86/umip.c @@ -159,7 +159,7 @@ static noinline int do_ring3(void (*fn)(const char *), const char *arg) "1:\n\t" : [ret] "=&a" (ret), #ifdef __x86_64__ - [sp0] "=m" (tss.rsp0) + [sp0] "=m" (tss[0].rsp0) #else [sp0] "=m" (tss.esp0) #endif From patchwork Wed Nov 10 21:19:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613111 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 746C4C433EF for ; Wed, 10 Nov 2021 21:20:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5BB37611F2 for ; Wed, 10 Nov 2021 21:20:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233488AbhKJVXQ (ORCPT ); Wed, 10 Nov 2021 16:23:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233479AbhKJVXP (ORCPT ); Wed, 10 Nov 2021 16:23:15 -0500 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ACFAFC061767 for ; Wed, 10 Nov 2021 13:20:27 -0800 (PST) Received: by mail-pg1-x549.google.com with SMTP id f7-20020a63f107000000b002db96febb74so2141414pgi.7 for ; Wed, 10 Nov 2021 13:20:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=1WpvXB0uniUiD9TX/k3pJ/CV0aW3BeA8lnHLDvkSFfo=; b=b99CzGQuK3YlEBaWHN1RVgVuX+u9EG/rFuZxVviqaSWUqGBJoeeBp9vLJrzj7+D5EX plnP4aRK2p5LPYnziOy4G4AxpatMKR2Ch5zVVL21KQKR32Qesu6ecZV9IX5Sb6Pp6j/E p8wDPG8xpfEj0pVYGR4QK0LbSxbbFKygsSd/yV29YCnFMkvDJGsXE5Z8S677GvMg2TRn gRCham92vZ7EHitDya/l3V+qkXgrjp/kLHHsgg0EyKX1y4QPuzejZatEtB0mLxKyrtF+ PKXerGuIv/reLYF421vg6xCLJ6A5a1Kxz/V/yrq9H7IOJlvMhw8bfKmUtRUwqSBCv6VS l3mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=1WpvXB0uniUiD9TX/k3pJ/CV0aW3BeA8lnHLDvkSFfo=; b=l30hij/b+10+oJd9+MGshdfBoYgdpahWaxq21BIR9RFC7Q3syDadqsGI6kfPW6faUy jWbjZ1KflVraB3f3gh4y66l83wwt1CYnvzG2J8gkxQa5vjgaSqP+glsysYpCNniIJRlK nhJGzC8GOwe7q53IAg+Lfs9F2DYFuTTcKmtMJe5ci3x46bqFLcAYeWhb3hc0mpS2dX91 P/cKd4p2fSeD05wWKgm+wUfFIEHLgykotdn7iV61LRjoRQxaA8vZHD1SrjUmKjN65c27 ItXxXKAWIfUCyvOK60dhyDgzOogC0cI/Xlck2dXx3V3khWsfsuvhfRvh8CkQaAlRvCBC qVDQ== X-Gm-Message-State: AOAM531hxDYXB14JXVi+O8aiKeNhRLxEczglQn86e1SZ91qUach2Nt6Z cxa1srSEb7BcMUC2ixKqlYVHHobL1WFO1GsNG7J6FIsSBmuezUI4uNpPa9ncSD6FsOrpePscmow Ycd4mf448uehmn64lD5q8svVKA384yu3DXCPMYsV/Y6Xf/zKoh+W6g8aqrJdnY9czOHVH X-Google-Smtp-Source: ABdhPJxHdiVbS0IRrjTL26OOUuHRwy6eLassXrxksjwIfHEduhCIHNEfve42DMdkkxQFLoQdL1FMjwW0FHarJkIk X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:aa7:8081:0:b0:49f:adfd:4be4 with SMTP id v1-20020aa78081000000b0049fadfd4be4mr1943572pff.85.1636579227097; Wed, 10 Nov 2021 13:20:27 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:56 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-10-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 09/14] x86: Move 32-bit GDT and TSS to desc.c From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Move the GDT and TSS data structures from x86/cstart.S to lib/x86/desc.c, for consistency with the 64-bit version. Signed-off-by: Paolo Bonzini --- lib/x86/asm/setup.h | 2 +- lib/x86/desc.c | 22 ++++++++-- lib/x86/desc.h | 2 +- lib/x86/setup.c | 26 +++++++++++- x86/cstart.S | 98 +++++++-------------------------------------- x86/cstart64.S | 1 + x86/smap.c | 2 +- x86/taskswitch.c | 2 +- x86/umip.c | 2 +- 9 files changed, 63 insertions(+), 94 deletions(-) diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h index e3c3bfb..4310132 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -1,6 +1,6 @@ #ifndef _X86_ASM_SETUP_H_ #define _X86_ASM_SETUP_H_ -unsigned long setup_tss(void); +unsigned long setup_tss(u8 *stacktop); #endif /* _X86_ASM_SETUP_H_ */ diff --git a/lib/x86/desc.c b/lib/x86/desc.c index c185c01..16b7256 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -14,8 +14,22 @@ struct descriptor_table_ptr idt_descr = { .base = (unsigned long)boot_idt, }; -#ifdef __x86_64__ +#ifndef __x86_64__ /* GDT, TSS and descriptors */ +gdt_entry_t gdt[TSS_MAIN / 8 + MAX_TEST_CPUS * 2] = { + { 0, 0, 0, .type_limit_flags = 0x0000}, /* 0x00 null */ + {0xffff, 0, 0, .type_limit_flags = 0xcf9b}, /* flat 32-bit code segment */ + {0xffff, 0, 0, .type_limit_flags = 0xcf93}, /* flat 32-bit data segment */ + {0xffff, 0, 0, .type_limit_flags = 0xcf1b}, /* flat 32-bit code segment, not present */ + { 0, 0, 0, .type_limit_flags = 0x0000}, /* TSS for task gates */ + {0xffff, 0, 0, .type_limit_flags = 0x8f9b}, /* 16-bit code segment */ + {0xffff, 0, 0, .type_limit_flags = 0x8f93}, /* 16-bit data segment */ + {0xffff, 0, 0, .type_limit_flags = 0xcffb}, /* 32-bit code segment (user) */ + {0xffff, 0, 0, .type_limit_flags = 0xcff3}, /* 32-bit data segment (user) */ +}; + +tss32_t tss[MAX_TEST_CPUS] = {0}; +#else gdt_entry_t gdt[TSS_MAIN / 8 + MAX_TEST_CPUS * 2] = { { 0, 0, 0, .type_limit_flags = 0x0000}, /* 0x00 null */ {0xffff, 0, 0, .type_limit_flags = 0xaf9b}, /* 0x08 64-bit code segment */ @@ -30,12 +44,12 @@ gdt_entry_t gdt[TSS_MAIN / 8 + MAX_TEST_CPUS * 2] = { }; tss64_t tss[MAX_TEST_CPUS] = {0}; +#endif struct descriptor_table_ptr gdt_descr = { .limit = sizeof(gdt) - 1, .base = (unsigned long)gdt, }; -#endif #ifndef __x86_64__ __attribute__((regparm(1))) @@ -365,7 +379,7 @@ void setup_tss32(void) { u16 desc_size = sizeof(tss32_t); - tss.cr3 = read_cr3(); + tss[0].cr3 = read_cr3(); tss_intr.cr3 = read_cr3(); tss_intr.ss0 = tss_intr.ss1 = tss_intr.ss2 = 0x10; tss_intr.esp = tss_intr.esp0 = tss_intr.esp1 = tss_intr.esp2 = @@ -401,7 +415,7 @@ void print_current_tss_info(void) printf("Unknown TSS %x\n", tr); else printf("TR=%x (%s) Main TSS back link %x. Intr TSS back link %x\n", - tr, tr ? "interrupt" : "main", tss.prev, tss_intr.prev); + tr, tr ? "interrupt" : "main", tss[0].prev, tss_intr.prev); } #else void set_intr_alt_stack(int e, void *addr) diff --git a/lib/x86/desc.h b/lib/x86/desc.h index ddfae04..b65539e 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -197,7 +197,7 @@ struct system_desc64 { extern idt_entry_t boot_idt[256]; #ifndef __x86_64__ -extern tss32_t tss; +extern tss32_t tss[]; extern tss32_t tss_intr; void set_gdt_task_gate(u16 tss_sel, u16 sel); void set_idt_task_gate(int vec, u16 sel); diff --git a/lib/x86/setup.c b/lib/x86/setup.c index ec005b5..9c4393f 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -104,7 +104,7 @@ void find_highmem(void) } /* Setup TSS for the current processor, and return TSS offset within GDT */ -unsigned long setup_tss(void) +unsigned long setup_tss(u8 *stacktop) { u32 id; tss64_t *tss_entry; @@ -122,6 +122,30 @@ unsigned long setup_tss(void) return TSS_MAIN + id * 16; } +#else +/* Setup TSS for the current processor, and return TSS offset within GDT */ +unsigned long setup_tss(u8 *stacktop) +{ + u32 id; + tss32_t *tss_entry; + + id = apic_id(); + + /* Runtime address of current TSS */ + tss_entry = &tss[id]; + + /* Update TSS */ + memset((void *)tss_entry, 0, sizeof(tss32_t)); + tss_entry->ss0 = KERNEL_DS; + + /* Update descriptors for TSS and percpu data segment. */ + set_gdt_entry(TSS_MAIN + id * 8, + (unsigned long)tss_entry, 0xffff, 0x89, 0); + set_gdt_entry(TSS_MAIN + MAX_TEST_CPUS * 8 + id * 8, + (unsigned long)stacktop - 4096, 0xfffff, 0x93, 0xc0); + + return TSS_MAIN + id * 8; +} #endif void setup_multiboot(struct mbi_bootinfo *bi) diff --git a/x86/cstart.S b/x86/cstart.S index e9100a4..2c0eec7 100644 --- a/x86/cstart.S +++ b/x86/cstart.S @@ -23,50 +23,6 @@ i = 0 i = i + 1 .endr -.globl gdt -gdt: - .quad 0 - .quad 0x00cf9b000000ffff // flat 32-bit code segment - .quad 0x00cf93000000ffff // flat 32-bit data segment - .quad 0x00cf1b000000ffff // flat 32-bit code segment, not present - .quad 0 // TSS for task gates - .quad 0x008f9b000000FFFF // 16-bit code segment - .quad 0x008f93000000FFFF // 16-bit data segment - .quad 0x00cffb000000ffff // 32-bit code segment (user) - .quad 0x00cff3000000ffff // 32-bit data segment (user) - .quad 0 // unused - - .quad 0 // 6 spare selectors - .quad 0 - .quad 0 - .quad 0 - .quad 0 - .quad 0 - -tss_descr: - .rept max_cpus - .quad 0x000089000000ffff // 32-bit avail tss - .endr -percpu_descr: - .rept max_cpus - .quad 0x00cf93000000ffff // 32-bit data segment for perCPU area - .endr -gdt_end: - -i = 0 -.globl tss -tss: - .rept max_cpus - .long 0 - .long 0 - .long 16 - .quad 0, 0 - .quad 0, 0, 0, 0, 0, 0, 0, 0 - .long 0, 0, 0 - i = i + 1 - .endr -tss_end: - .section .init .code32 @@ -78,21 +34,14 @@ mb_flags = 0x0 .long mb_magic, mb_flags, 0 - (mb_magic + mb_flags) mb_cmdline = 16 -.macro setup_percpu_area - lea -4096(%esp), %eax - - /* fill GS_BASE in the GDT, do not clobber %ebx (multiboot info) */ - mov (APIC_DEFAULT_PHYS_BASE + APIC_ID), %ecx - shr $24, %ecx - mov %ax, percpu_descr+2(,%ecx,8) - - shr $16, %eax - mov %al, percpu_descr+4(,%ecx,8) - mov %ah, percpu_descr+7(,%ecx,8) - - lea percpu_descr-gdt(,%ecx,8), %eax +.macro setup_tr_and_percpu + lidt idt_descr + push %esp + call setup_tss + addl $4, %esp + ltr %ax + add $(max_cpus * 8), %ax mov %ax, %gs - .endm .macro setup_segments @@ -109,7 +58,6 @@ start: lgdtl gdt_descr setup_segments mov $stacktop, %esp - setup_percpu_area push %ebx call setup_multiboot @@ -147,11 +95,10 @@ ap_start32: setup_segments mov $-4096, %esp lock xaddl %esp, smp_stacktop - setup_percpu_area + setup_tr_and_percpu call prepare_32 call reset_apic call save_id - call load_tss call enable_apic call enable_x2apic sti @@ -162,9 +109,9 @@ ap_start32: jmp 1b start32: + setup_tr_and_percpu call reset_apic call save_id - call load_tss call mask_pic_interrupts call enable_apic call ap_init @@ -177,26 +124,9 @@ start32: push %eax call exit -load_tss: - lidt idt_descr - mov $16, %eax - mov %ax, %ss - mov (APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax - shr $24, %eax - mov %eax, %ebx - mov $((tss_end - tss) / max_cpus), %edx - imul %edx - add $tss, %eax - mov %ax, tss_descr+2(,%ebx,8) - shr $16, %eax - mov %al, tss_descr+4(,%ebx,8) - mov %ah, tss_descr+7(,%ebx,8) - lea tss_descr-gdt(,%ebx,8), %eax - ltr %ax - ret - ap_init: cld + sgdtl ap_gdt_descr // must be close to sipi_entry for real mode access to work lea sipi_entry, %esi xor %edi, %edi mov $(sipi_end - sipi_entry), %ecx @@ -220,11 +150,11 @@ sipi_entry: mov %cr0, %eax or $1, %eax mov %eax, %cr0 - lgdtl gdt_descr - sipi_entry + lgdtl ap_gdt_descr - sipi_entry ljmpl $8, $ap_start32 -gdt_descr: - .word gdt_end - gdt - 1 - .long gdt +ap_gdt_descr: + .word 0 + .long 0 sipi_end: diff --git a/x86/cstart64.S b/x86/cstart64.S index c6daa34..ddb83a0 100644 --- a/x86/cstart64.S +++ b/x86/cstart64.S @@ -68,6 +68,7 @@ MSR_GS_BASE = 0xc0000101 .macro load_tss lidtq idt_descr + movq %rsp, %rdi call setup_tss ltr %ax .endm diff --git a/x86/smap.c b/x86/smap.c index ac2c8d5..c6ddf38 100644 --- a/x86/smap.c +++ b/x86/smap.c @@ -20,7 +20,7 @@ void do_pf_tss(unsigned long error_code) save = test; #ifndef __x86_64__ - tss.eflags |= X86_EFLAGS_AC; + tss[0].eflags |= X86_EFLAGS_AC; #endif } diff --git a/x86/taskswitch.c b/x86/taskswitch.c index 1d6e6e2..0d31149 100644 --- a/x86/taskswitch.c +++ b/x86/taskswitch.c @@ -19,7 +19,7 @@ fault_handler(unsigned long error_code) print_current_tss_info(); printf("error code %lx\n", error_code); - tss.eip += 2; + tss[0].eip += 2; gdt[TSS_MAIN / 8].type &= ~DESC_BUSY; diff --git a/x86/umip.c b/x86/umip.c index 0a52342..af8db59 100644 --- a/x86/umip.c +++ b/x86/umip.c @@ -161,7 +161,7 @@ static noinline int do_ring3(void (*fn)(const char *), const char *arg) #ifdef __x86_64__ [sp0] "=m" (tss[0].rsp0) #else - [sp0] "=m" (tss.esp0) + [sp0] "=m" (tss[0].esp0) #endif : [user_ds] "i" (USER_DS), [user_cs] "i" (USER_CS), From patchwork Wed Nov 10 21:19:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613113 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8CAD0C433F5 for ; Wed, 10 Nov 2021 21:20:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7721761207 for ; Wed, 10 Nov 2021 21:20:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233516AbhKJVXg (ORCPT ); Wed, 10 Nov 2021 16:23:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51354 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233493AbhKJVXd (ORCPT ); Wed, 10 Nov 2021 16:23:33 -0500 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 35101C06120E for ; Wed, 10 Nov 2021 13:20:30 -0800 (PST) Received: by mail-pg1-x549.google.com with SMTP id 76-20020a63054f000000b002c9284978aaso2129078pgf.10 for ; Wed, 10 Nov 2021 13:20:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=NP6FiWe6Se9ZE9bHI8uQWohZGgmsxfNQ6bkZaVjL4lU=; b=i0v/3lqSyF0vUEwy8cpPkl0n2ChZqK90Xw4Cp8jGfRN1xb/dTkjxhyQtVZA70TcHCA 64Jv0rMpNJ09I8Uyq0lLMKdBNSDF+ilWNX7knNVUYV9CeWLF3QPqaHQcK8WAQNJdi2HB jDNJFpqDS5AeSj2PAUS3+RdI3fvn0636YgIBDYBSYsyVtGae0Sp3u3BaIRXKOAxzr6yw ETHTk6mxRg9vdEKI+F6QYhfBxm2KwMV7mo9xl9rqh5p8kmR1x8NNYOCCfrJa7WJq2p7S 4G7AaaXNe8asb+6Zhnwvogzlf9sv6nVFCjOA4NYMxq1IEANv6A3P5x9sAPVGlBDFYONu Sj6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=NP6FiWe6Se9ZE9bHI8uQWohZGgmsxfNQ6bkZaVjL4lU=; b=yBA2VAa9AtI2wh1ZrN6Wk/7IMU4t53VLIUbXmDfB4A8TSBeXEJ9/5LBI8r26U+GEMf G9Kr4c8FJbxyHaIo9etd24wCrXujOBBCCy8Kop0zKbPRHf651I9UXrm1nKVH4RvtH3DO kPjjPbhy6ufPFJ2RPlmd0HA9fkPhyTJKJZ8I6I5ehRZWwT3hAfloX7p65mhTU9GgUQb3 nU1b73tMnp4ZhHFNZTbA+PTbpBptdLeCz0I4XUtDNqfyI+hh+6kqO0o/rI20FedkUzEH gFzRGQy999rg8oq1xNjyLAObuSlpXeNI8MXE0I8LnIqYZlpYIhjiCFebXNIHTDmMTXZo F/Lg== X-Gm-Message-State: AOAM5308iShCXtk6/5jkrJcxhqCnSHPo0o8Nex8Ga0JveN6ymLGdTsMS IJE/aBoBEzci1KvJ15iL2Acgb9948Ne0ygq/OneT0Q+1s3E8Yy220M5BAPCNf9UkLT9J7bVKcLK 1zHqLAtf/0cIGZb14fdlNcE+lW4uUYr6jrFID/DnGqZrD0yrHWWchH276pXMR+VulUjt9 X-Google-Smtp-Source: ABdhPJzVcAj08M6yXfCRF9gly1l8L8KZpSV0bFVbUz7XGCbNx8IKPCUhfjnKY8t72sTViP2jiDbXfCkIf4oVm8UN X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a17:90b:3810:: with SMTP id mq16mr20364953pjb.128.1636579229484; Wed, 10 Nov 2021 13:20:29 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:57 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-11-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 10/14] x86: Look up the PTEs rather than assuming them From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Rather than assuming which PTEs the SMEP test runs on, look them up to ensure they are correct. If this test were to run on a different page table (ie: run in an L2 test) the wrong PTEs would be set. Switch to looking up the PTEs to avoid this from happening. Signed-off-by: Aaron Lewis --- lib/libcflat.h | 1 + lib/x86/vm.c | 21 +++++++++++++++++++++ lib/x86/vm.h | 3 +++ x86/access.c | 26 ++++++++++++++++++-------- x86/cstart64.S | 1 - x86/flat.lds | 1 + 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/lib/libcflat.h b/lib/libcflat.h index 9bb7e08..c1fd31f 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -35,6 +35,7 @@ #define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) #define ALIGN(x, a) __ALIGN((x), (a)) +#define ALIGN_DOWN(x, a) __ALIGN((x) - ((a) - 1), (a)) #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) #define MIN(a, b) ((a) < (b) ? (a) : (b)) diff --git a/lib/x86/vm.c b/lib/x86/vm.c index 5cd2ee4..6a70ef6 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -281,3 +281,24 @@ void force_4k_page(void *addr) if (pte & PT_PAGE_SIZE_MASK) split_large_page(ptep, 2); } + +/* + * Call the callback on each page from virt to virt + len. + */ +void walk_pte(void *virt, size_t len, pte_callback_t callback) +{ + pgd_t *cr3 = current_page_table(); + uintptr_t start = (uintptr_t)virt; + uintptr_t end = (uintptr_t)virt + len; + struct pte_search search; + size_t page_size; + uintptr_t curr; + + for (curr = start; curr < end; curr = ALIGN_DOWN(curr + page_size, page_size)) { + search = find_pte_level(cr3, (void *)curr, 1); + assert(found_leaf_pte(search)); + page_size = 1ul << PGDIR_BITS(search.level); + + callback(search, (void *)curr); + } +} diff --git a/lib/x86/vm.h b/lib/x86/vm.h index d9753c3..4c6dff9 100644 --- a/lib/x86/vm.h +++ b/lib/x86/vm.h @@ -52,4 +52,7 @@ struct vm_vcpu_info { u64 cr0; }; +typedef void (*pte_callback_t)(struct pte_search search, void *va); +void walk_pte(void *virt, size_t len, pte_callback_t callback); + #endif diff --git a/x86/access.c b/x86/access.c index a781a0c..8e3a718 100644 --- a/x86/access.c +++ b/x86/access.c @@ -201,10 +201,24 @@ static void set_cr0_wp(int wp) } } +static void clear_user_mask(struct pte_search search, void *va) +{ + *search.pte &= ~PT_USER_MASK; +} + +static void set_user_mask(struct pte_search search, void *va) +{ + *search.pte |= PT_USER_MASK; + + /* Flush to avoid spurious #PF */ + invlpg(va); +} + static unsigned set_cr4_smep(int smep) { + extern char stext, etext; + size_t len = (size_t)&etext - (size_t)&stext; unsigned long cr4 = shadow_cr4; - extern u64 ptl2[]; unsigned r; cr4 &= ~CR4_SMEP_MASK; @@ -214,14 +228,10 @@ static unsigned set_cr4_smep(int smep) return 0; if (smep) - ptl2[2] &= ~PT_USER_MASK; + walk_pte(&stext, len, clear_user_mask); r = write_cr4_checking(cr4); - if (r || !smep) { - ptl2[2] |= PT_USER_MASK; - - /* Flush to avoid spurious #PF */ - invlpg((void *)(2 << 21)); - } + if (r || !smep) + walk_pte(&stext, len, set_user_mask); if (!r) shadow_cr4 = cr4; return r; diff --git a/x86/cstart64.S b/x86/cstart64.S index ddb83a0..ff79ae7 100644 --- a/x86/cstart64.S +++ b/x86/cstart64.S @@ -17,7 +17,6 @@ stacktop: .data .align 4096 -.globl ptl2 ptl2: i = 0 .rept 512 * 4 diff --git a/x86/flat.lds b/x86/flat.lds index a278b56..337bc44 100644 --- a/x86/flat.lds +++ b/x86/flat.lds @@ -3,6 +3,7 @@ SECTIONS . = 4M + SIZEOF_HEADERS; stext = .; .text : { *(.init) *(.text) *(.text.*) } + etext = .; . = ALIGN(4K); .data : { *(.data) From patchwork Wed Nov 10 21:19:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613115 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AA417C433F5 for ; Wed, 10 Nov 2021 21:20:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9390961208 for ; Wed, 10 Nov 2021 21:20:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233506AbhKJVXl (ORCPT ); Wed, 10 Nov 2021 16:23:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51372 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233405AbhKJVXe (ORCPT ); Wed, 10 Nov 2021 16:23:34 -0500 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8278FC061220 for ; Wed, 10 Nov 2021 13:20:32 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id p12-20020a17090b010c00b001a65bfe8054so1723137pjz.8 for ; Wed, 10 Nov 2021 13:20:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=56RSg2WG+CC/xcFYHTtOxL1OzNea6nTzWtRdveDulCw=; b=FO5xcQdyWC820CBwc57jayjDRNQIae/utOM2q3OH2hR0+uZIVHstFOJvhnR8+frYYi IE8x81BZkkWAFVNe4SrTHTbsv3sU9x/ZUPaO6D1gvt+5wJJEqcd5v1Z97GuOj+8MaefB PvK1LstmK0IqrXoC0rSfP+ecDidj317dXSTr4IxoP4CsqDJGTRqQ1/aEy+fHyOnoW9Kp h0xbAyoGIsv0ySvwx0udYC52k5XFfs5bLGgiTmG5rUTxrnS4cl2MljdqroBcMClaAvrA Ig3zlv2VqlAewW3SnLL6NBG81QP7sICRK4ktfWzNQw/WFT3B8IzPaNAVTw2I05RDtI2M yoTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=56RSg2WG+CC/xcFYHTtOxL1OzNea6nTzWtRdveDulCw=; b=IHLrSPVPwjAFbkQoGyF0l7+LJzRMdmXyuEs5aI6d7OMJ5nj7vrOx8HV96PduLCqLAP ZuAkBpfD4eltnC/lEmmT1EappUWS3kib71P3tqam7kV7+JFFhUyt3TpfCpwRc/5yNwvE 02b2ctstjUcEZgPCGg3/LXftEzqNJr7hi5C9GIZCEZ2HGM9p0GeqEAbOKppZLFTNiHWR dLPw2tkqDXicxT1d/lnn/rHzLAvVQq+rX2xjD/eOE9LGeSeBXyn+4HcnfTTaHWjeEg9F /7jprApCi1du2faJ54dOxO1zMFB5jwoiiL8YCByozNFvPRf6o9yoyDlrmLyLUzL7QuLE 8nCg== X-Gm-Message-State: AOAM532cFtm8b+FeS2t3yNfsKCgtsYUqja2nLqvut2GYmcCytQKfzMad +m5O5RvRr1xerQ4ZCONaZWb1ZnwjuLGun/QUXeMA6VI8E+P82wypIzP/iU3fP7qPfFeot6pGllL wz46YfdOO8xYWCaCSRzRotFGS1UOT44QFbecqpyoeLKT9Kmt0n604SDZuCEdsVMshFKNH X-Google-Smtp-Source: ABdhPJxcO1fuBu/UPCewuL0Mbz7pB8bDEFO9KEOxS4FIlpLdl4p4/fvTXhHgx2kAb6RaqUunbG8J25m81LxW3cxu X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a05:6a00:1254:b0:4a0:3da:3568 with SMTP id u20-20020a056a00125400b004a003da3568mr2013333pfi.57.1636579231899; Wed, 10 Nov 2021 13:20:31 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:58 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-12-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 11/14] x86: Prepare access test for running in L2 From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Move main out of access.c in preparation for running the test in L2. This allows access.c to be used as common code that will be included in a nested tests later in this series. Signed-off-by: Aaron Lewis --- x86/Makefile.common | 2 ++ x86/Makefile.x86_64 | 2 +- x86/access.c | 24 +++--------------------- x86/access.h | 8 ++++++++ x86/access_test.c | 22 ++++++++++++++++++++++ x86/unittests.cfg | 4 ++-- 6 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 x86/access.h create mode 100644 x86/access_test.c diff --git a/x86/Makefile.common b/x86/Makefile.common index 52bb7aa..a665854 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -72,6 +72,8 @@ $(TEST_DIR)/realmode.elf: $(TEST_DIR)/realmode.o $(TEST_DIR)/realmode.o: bits = $(if $(call cc-option,-m16,""),16,32) +$(TEST_DIR)/access_test.elf: $(TEST_DIR)/access.o + $(TEST_DIR)/kvmclock_test.elf: $(TEST_DIR)/kvmclock.o $(TEST_DIR)/hyperv_synic.elf: $(TEST_DIR)/hyperv.o diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64 index 8134952..390d0e9 100644 --- a/x86/Makefile.x86_64 +++ b/x86/Makefile.x86_64 @@ -9,7 +9,7 @@ cflatobjs += lib/x86/setjmp64.o cflatobjs += lib/x86/intel-iommu.o cflatobjs += lib/x86/usermode.o -tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \ +tests = $(TEST_DIR)/access_test.flat $(TEST_DIR)/apic.flat \ $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \ $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \ $(TEST_DIR)/pcid.flat $(TEST_DIR)/debug.flat \ diff --git a/x86/access.c b/x86/access.c index 8e3a718..de6726e 100644 --- a/x86/access.c +++ b/x86/access.c @@ -1,9 +1,9 @@ - #include "libcflat.h" #include "desc.h" #include "processor.h" #include "asm/page.h" #include "x86/vm.h" +#include "access.h" #define smp_id() 0 @@ -14,7 +14,7 @@ static _Bool verbose = false; typedef unsigned long pt_element_t; static int invalid_mask; -static int page_table_levels; +int page_table_levels; #define PT_BASE_ADDR_MASK ((pt_element_t)((((pt_element_t)1 << 36) - 1) & PAGE_MASK)) #define PT_PSE_BASE_ADDR_MASK (PT_BASE_ADDR_MASK & ~(1ull << 21)) @@ -1069,7 +1069,7 @@ const ac_test_fn ac_test_cases[] = check_effective_sp_permissions, }; -static int ac_test_run(void) +int ac_test_run() { ac_test_t at; ac_pool_t pool; @@ -1150,21 +1150,3 @@ static int ac_test_run(void) return successes == tests; } - -int main(void) -{ - int r; - - printf("starting test\n\n"); - page_table_levels = 4; - r = ac_test_run(); - - if (this_cpu_has(X86_FEATURE_LA57)) { - page_table_levels = 5; - printf("starting 5-level paging test.\n\n"); - setup_5level_page_table(); - r = ac_test_run(); - } - - return r ? 0 : 1; -} diff --git a/x86/access.h b/x86/access.h new file mode 100644 index 0000000..4f67b62 --- /dev/null +++ b/x86/access.h @@ -0,0 +1,8 @@ +#ifndef X86_ACCESS_H +#define X86_ACCESS_H + +int ac_test_run(void); + +extern int page_table_levels; + +#endif // X86_ACCESS_H \ No newline at end of file diff --git a/x86/access_test.c b/x86/access_test.c new file mode 100644 index 0000000..497f286 --- /dev/null +++ b/x86/access_test.c @@ -0,0 +1,22 @@ +#include "libcflat.h" +#include "processor.h" +#include "x86/vm.h" +#include "access.h" + +int main(void) +{ + int r; + + printf("starting test\n\n"); + page_table_levels = 4; + r = ac_test_run(); + + if (this_cpu_has(X86_FEATURE_LA57)) { + page_table_levels = 5; + printf("starting 5-level paging test.\n\n"); + setup_5level_page_table(); + r = ac_test_run(); + } + + return r ? 0 : 1; +} diff --git a/x86/unittests.cfg b/x86/unittests.cfg index 3000e53..dbeb8a2 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -114,13 +114,13 @@ groups = vmexit extra_params = -cpu qemu64,+x2apic,+tsc-deadline -append tscdeadline_immed [access] -file = access.flat +file = access_test.flat arch = x86_64 extra_params = -cpu max timeout = 180 [access-reduced-maxphyaddr] -file = access.flat +file = access_test.flat arch = x86_64 extra_params = -cpu IvyBridge,phys-bits=36,host-phys-bits=off timeout = 180 From patchwork Wed Nov 10 21:19:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613119 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D99E1C433EF for ; Wed, 10 Nov 2021 21:20:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BB02F611F2 for ; Wed, 10 Nov 2021 21:20:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233487AbhKJVXm (ORCPT ); Wed, 10 Nov 2021 16:23:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51354 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233490AbhKJVXg (ORCPT ); Wed, 10 Nov 2021 16:23:36 -0500 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5CE02C061766 for ; Wed, 10 Nov 2021 13:20:35 -0800 (PST) Received: by mail-pg1-x54a.google.com with SMTP id w5-20020a654105000000b002692534afceso2139305pgp.8 for ; Wed, 10 Nov 2021 13:20:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=h3spP/vp31gv6EH9eeJCr+gicdzSKq1WmRD/CWJvpPw=; b=QgHYUwUsWz1Zq9or9EO86AThBuYMfz38j4gTTuQ3D1oJnYBe8h0+cU6XIFg8PAyyRO FbXkifjGf8jD0RhSGXqyri6KXqNqdp7PdtL+csl5gyS43zHbBXUku5JC4jZtMw4tV/vg ceBxCZ6BcbMKfvhiYB9vlXhO25TxUtj7/CcduCXz8rtzEp6pffkTXn/Atpi5l0uiiC6P a/r9K6sBYE0m1pw7qqPEV4iDhuyZ5bEYdbRorpJD1yCECmbmrom7hjl6y/hzo2GxHyFC ZYziJt1KdBVSqgIrsKs+QXTnJHJworCUTvtur6HebPFklOsgke2soLcVgtGmSbP5Tffo V/Tw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=h3spP/vp31gv6EH9eeJCr+gicdzSKq1WmRD/CWJvpPw=; b=GOk2IMPZC3zi1Mk52/JVigum0xM6Q6Kmt3uJ2qZL2wKKoYyg6ouaesD8V0t84UwZ8x ObeAIVmkMbcIAVA/ERYkpr757/n0qVxrhQ9WhMrpWQNI2m9VSY4KA/t4oeRWv6TE1jbw Ami8VxIWaWwa3TUaO3p2rfFWZ7PcfNceukN47sJj2T7ROVrfmQ7nFHOcjbOJZbfvJXnp 0nuADSosLr5EMyeMhMbKyYXH3i39A9Z74Gr3l/vXrVAYHuxBE3Wh4RS7svKUkRxlg5A5 8DNGd73CK1lt7kOrcEkDbaGaB0SnOIjBggQUvQ0+BHXh7qGOSg9OsE+tZr0DbXwA7zlp ZcxQ== X-Gm-Message-State: AOAM532ya1Cb+hmVU8KOxSSJIwSVGsArVFuQAfEe9k6hk9uW2cDCFL0W iqdSwO6mET+53LMr0uDUMG2yR/eVdAGz79OG+wknAwG/8tDcrSnS3M8PRwI6/UsFO7HiVutI4qu /xgsWX1De2RSbWWbsMVZgEcEG2FXt5h04wKiVhvYPEjVEiLYOAPHVyyyKVvweGHGNsdhs X-Google-Smtp-Source: ABdhPJycw/K00/FvNWgadpeN2hp8y2rq9jjXkD8In/RVHyJm3R7UFImaxBJdwecyI9k47PN7V8vhmYqE+XxewGj8 X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a17:90a:c3:: with SMTP id v3mr17607pjd.0.1636579234404; Wed, 10 Nov 2021 13:20:34 -0800 (PST) Date: Wed, 10 Nov 2021 21:19:59 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-13-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 12/14] x86: Fix tabs in access.c From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Tabs and spaces in this file are inconsistent and don't follow the coding style. Correct them to adhere to the standard and make it easier to work in this file. No functional change intended. Signed-off-by: Aaron Lewis --- x86/access.c | 1383 +++++++++++++++++++++++++------------------------- 1 file changed, 691 insertions(+), 692 deletions(-) diff --git a/x86/access.c b/x86/access.c index de6726e..f832385 100644 --- a/x86/access.c +++ b/x86/access.c @@ -30,57 +30,57 @@ int page_table_levels; #define PFERR_PK_MASK (1U << 5) #define MSR_EFER 0xc0000080 -#define EFER_NX_MASK (1ull << 11) +#define EFER_NX_MASK (1ull << 11) #define PT_INDEX(address, level) \ - ((address) >> (12 + ((level)-1) * 9)) & 511 + ((address) >> (12 + ((level)-1) * 9)) & 511 /* * page table access check tests */ enum { - AC_PTE_PRESENT_BIT, - AC_PTE_WRITABLE_BIT, - AC_PTE_USER_BIT, - AC_PTE_ACCESSED_BIT, - AC_PTE_DIRTY_BIT, - AC_PTE_NX_BIT, - AC_PTE_BIT51_BIT, - AC_PTE_BIT36_BIT, - - AC_PDE_PRESENT_BIT, - AC_PDE_WRITABLE_BIT, - AC_PDE_USER_BIT, - AC_PDE_ACCESSED_BIT, - AC_PDE_DIRTY_BIT, - AC_PDE_PSE_BIT, - AC_PDE_NX_BIT, - AC_PDE_BIT51_BIT, - AC_PDE_BIT36_BIT, - AC_PDE_BIT13_BIT, - - /* - * special test case to DISABLE writable bit on page directory - * pointer table entry. - */ - AC_PDPTE_NO_WRITABLE_BIT, - - AC_PKU_AD_BIT, - AC_PKU_WD_BIT, - AC_PKU_PKEY_BIT, - - AC_ACCESS_USER_BIT, - AC_ACCESS_WRITE_BIT, - AC_ACCESS_FETCH_BIT, - AC_ACCESS_TWICE_BIT, - - AC_CPU_EFER_NX_BIT, - AC_CPU_CR0_WP_BIT, - AC_CPU_CR4_SMEP_BIT, - AC_CPU_CR4_PKE_BIT, - - NR_AC_FLAGS + AC_PTE_PRESENT_BIT, + AC_PTE_WRITABLE_BIT, + AC_PTE_USER_BIT, + AC_PTE_ACCESSED_BIT, + AC_PTE_DIRTY_BIT, + AC_PTE_NX_BIT, + AC_PTE_BIT51_BIT, + AC_PTE_BIT36_BIT, + + AC_PDE_PRESENT_BIT, + AC_PDE_WRITABLE_BIT, + AC_PDE_USER_BIT, + AC_PDE_ACCESSED_BIT, + AC_PDE_DIRTY_BIT, + AC_PDE_PSE_BIT, + AC_PDE_NX_BIT, + AC_PDE_BIT51_BIT, + AC_PDE_BIT36_BIT, + AC_PDE_BIT13_BIT, + + /* + * special test case to DISABLE writable bit on page directory + * pointer table entry. + */ + AC_PDPTE_NO_WRITABLE_BIT, + + AC_PKU_AD_BIT, + AC_PKU_WD_BIT, + AC_PKU_PKEY_BIT, + + AC_ACCESS_USER_BIT, + AC_ACCESS_WRITE_BIT, + AC_ACCESS_FETCH_BIT, + AC_ACCESS_TWICE_BIT, + + AC_CPU_EFER_NX_BIT, + AC_CPU_CR0_WP_BIT, + AC_CPU_CR4_SMEP_BIT, + AC_CPU_CR4_PKE_BIT, + + NR_AC_FLAGS }; #define AC_PTE_PRESENT_MASK (1 << AC_PTE_PRESENT_BIT) @@ -120,65 +120,65 @@ enum { #define AC_CPU_CR4_PKE_MASK (1 << AC_CPU_CR4_PKE_BIT) const char *ac_names[] = { - [AC_PTE_PRESENT_BIT] = "pte.p", - [AC_PTE_ACCESSED_BIT] = "pte.a", - [AC_PTE_WRITABLE_BIT] = "pte.rw", - [AC_PTE_USER_BIT] = "pte.user", - [AC_PTE_DIRTY_BIT] = "pte.d", - [AC_PTE_NX_BIT] = "pte.nx", - [AC_PTE_BIT51_BIT] = "pte.51", - [AC_PTE_BIT36_BIT] = "pte.36", - [AC_PDE_PRESENT_BIT] = "pde.p", - [AC_PDE_ACCESSED_BIT] = "pde.a", - [AC_PDE_WRITABLE_BIT] = "pde.rw", - [AC_PDE_USER_BIT] = "pde.user", - [AC_PDE_DIRTY_BIT] = "pde.d", - [AC_PDE_PSE_BIT] = "pde.pse", - [AC_PDE_NX_BIT] = "pde.nx", - [AC_PDE_BIT51_BIT] = "pde.51", - [AC_PDE_BIT36_BIT] = "pde.36", - [AC_PDE_BIT13_BIT] = "pde.13", - [AC_PDPTE_NO_WRITABLE_BIT] = "pdpte.ro", - [AC_PKU_AD_BIT] = "pkru.ad", - [AC_PKU_WD_BIT] = "pkru.wd", - [AC_PKU_PKEY_BIT] = "pkey=1", - [AC_ACCESS_WRITE_BIT] = "write", - [AC_ACCESS_USER_BIT] = "user", - [AC_ACCESS_FETCH_BIT] = "fetch", - [AC_ACCESS_TWICE_BIT] = "twice", - [AC_CPU_EFER_NX_BIT] = "efer.nx", - [AC_CPU_CR0_WP_BIT] = "cr0.wp", - [AC_CPU_CR4_SMEP_BIT] = "cr4.smep", - [AC_CPU_CR4_PKE_BIT] = "cr4.pke", + [AC_PTE_PRESENT_BIT] = "pte.p", + [AC_PTE_ACCESSED_BIT] = "pte.a", + [AC_PTE_WRITABLE_BIT] = "pte.rw", + [AC_PTE_USER_BIT] = "pte.user", + [AC_PTE_DIRTY_BIT] = "pte.d", + [AC_PTE_NX_BIT] = "pte.nx", + [AC_PTE_BIT51_BIT] = "pte.51", + [AC_PTE_BIT36_BIT] = "pte.36", + [AC_PDE_PRESENT_BIT] = "pde.p", + [AC_PDE_ACCESSED_BIT] = "pde.a", + [AC_PDE_WRITABLE_BIT] = "pde.rw", + [AC_PDE_USER_BIT] = "pde.user", + [AC_PDE_DIRTY_BIT] = "pde.d", + [AC_PDE_PSE_BIT] = "pde.pse", + [AC_PDE_NX_BIT] = "pde.nx", + [AC_PDE_BIT51_BIT] = "pde.51", + [AC_PDE_BIT36_BIT] = "pde.36", + [AC_PDE_BIT13_BIT] = "pde.13", + [AC_PDPTE_NO_WRITABLE_BIT] = "pdpte.ro", + [AC_PKU_AD_BIT] = "pkru.ad", + [AC_PKU_WD_BIT] = "pkru.wd", + [AC_PKU_PKEY_BIT] = "pkey=1", + [AC_ACCESS_WRITE_BIT] = "write", + [AC_ACCESS_USER_BIT] = "user", + [AC_ACCESS_FETCH_BIT] = "fetch", + [AC_ACCESS_TWICE_BIT] = "twice", + [AC_CPU_EFER_NX_BIT] = "efer.nx", + [AC_CPU_CR0_WP_BIT] = "cr0.wp", + [AC_CPU_CR4_SMEP_BIT] = "cr4.smep", + [AC_CPU_CR4_PKE_BIT] = "cr4.pke", }; static inline void *va(pt_element_t phys) { - return (void *)phys; + return (void *)phys; } typedef struct { - pt_element_t pt_pool; - unsigned pt_pool_size; - unsigned pt_pool_current; + pt_element_t pt_pool; + unsigned pt_pool_size; + unsigned pt_pool_current; } ac_pool_t; typedef struct { - unsigned flags; - void *virt; - pt_element_t phys; - pt_element_t *ptep; - pt_element_t expected_pte; - pt_element_t *pdep; - pt_element_t expected_pde; - pt_element_t ignore_pde; - int expected_fault; - unsigned expected_error; + unsigned flags; + void *virt; + pt_element_t phys; + pt_element_t *ptep; + pt_element_t expected_pte; + pt_element_t *pdep; + pt_element_t expected_pde; + pt_element_t ignore_pde; + int expected_fault; + unsigned expected_error; } ac_test_t; typedef struct { - unsigned short limit; - unsigned long linear_addr; + unsigned short limit; + unsigned long linear_addr; } __attribute__((packed)) descriptor_table_t; @@ -190,15 +190,15 @@ static unsigned long long shadow_efer; static void set_cr0_wp(int wp) { - unsigned long cr0 = shadow_cr0; - - cr0 &= ~CR0_WP_MASK; - if (wp) - cr0 |= CR0_WP_MASK; - if (cr0 != shadow_cr0) { - write_cr0(cr0); - shadow_cr0 = cr0; - } + unsigned long cr0 = shadow_cr0; + + cr0 &= ~CR0_WP_MASK; + if (wp) + cr0 |= CR0_WP_MASK; + if (cr0 != shadow_cr0) { + write_cr0(cr0); + shadow_cr0 = cr0; + } } static void clear_user_mask(struct pte_search search, void *va) @@ -216,404 +216,405 @@ static void set_user_mask(struct pte_search search, void *va) static unsigned set_cr4_smep(int smep) { - extern char stext, etext; - size_t len = (size_t)&etext - (size_t)&stext; - unsigned long cr4 = shadow_cr4; - unsigned r; - - cr4 &= ~CR4_SMEP_MASK; - if (smep) - cr4 |= CR4_SMEP_MASK; - if (cr4 == shadow_cr4) - return 0; - - if (smep) - walk_pte(&stext, len, clear_user_mask); - r = write_cr4_checking(cr4); - if (r || !smep) - walk_pte(&stext, len, set_user_mask); - if (!r) - shadow_cr4 = cr4; - return r; + extern char stext, etext; + size_t len = (size_t)&etext - (size_t)&stext; + unsigned long cr4 = shadow_cr4; + unsigned r; + + cr4 &= ~CR4_SMEP_MASK; + if (smep) + cr4 |= CR4_SMEP_MASK; + if (cr4 == shadow_cr4) + return 0; + + if (smep) + walk_pte(&stext, len, clear_user_mask); + r = write_cr4_checking(cr4); + if (r || !smep) + walk_pte(&stext, len, set_user_mask); + if (!r) + shadow_cr4 = cr4; + return r; } static void set_cr4_pke(int pke) { - unsigned long cr4 = shadow_cr4; - - cr4 &= ~X86_CR4_PKE; - if (pke) - cr4 |= X86_CR4_PKE; - if (cr4 == shadow_cr4) - return; - - /* Check that protection keys do not affect accesses when CR4.PKE=0. */ - if ((shadow_cr4 & X86_CR4_PKE) && !pke) - write_pkru(0xfffffffc); - write_cr4(cr4); - shadow_cr4 = cr4; + unsigned long cr4 = shadow_cr4; + + cr4 &= ~X86_CR4_PKE; + if (pke) + cr4 |= X86_CR4_PKE; + if (cr4 == shadow_cr4) + return; + + /* Check that protection keys do not affect accesses when CR4.PKE=0. */ + if ((shadow_cr4 & X86_CR4_PKE) && !pke) + write_pkru(0xfffffffc); + write_cr4(cr4); + shadow_cr4 = cr4; } static void set_efer_nx(int nx) { - unsigned long long efer = shadow_efer; - - efer &= ~EFER_NX_MASK; - if (nx) - efer |= EFER_NX_MASK; - if (efer != shadow_efer) { - wrmsr(MSR_EFER, efer); - shadow_efer = efer; - } + unsigned long long efer = shadow_efer; + + efer &= ~EFER_NX_MASK; + if (nx) + efer |= EFER_NX_MASK; + if (efer != shadow_efer) { + wrmsr(MSR_EFER, efer); + shadow_efer = efer; + } } static void ac_env_int(ac_pool_t *pool) { - extern char page_fault, kernel_entry; - set_idt_entry(14, &page_fault, 0); - set_idt_entry(0x20, &kernel_entry, 3); + extern char page_fault, kernel_entry; + set_idt_entry(14, &page_fault, 0); + set_idt_entry(0x20, &kernel_entry, 3); - pool->pt_pool = 33 * 1024 * 1024; - pool->pt_pool_size = 120 * 1024 * 1024 - pool->pt_pool; - pool->pt_pool_current = 0; + pool->pt_pool = 33 * 1024 * 1024; + pool->pt_pool_size = 120 * 1024 * 1024 - pool->pt_pool; + pool->pt_pool_current = 0; } static void ac_test_init(ac_test_t *at, void *virt) { - set_efer_nx(1); - set_cr0_wp(1); - at->flags = 0; - at->virt = virt; - at->phys = 32 * 1024 * 1024; + set_efer_nx(1); + set_cr0_wp(1); + at->flags = 0; + at->virt = virt; + at->phys = 32 * 1024 * 1024; } static int ac_test_bump_one(ac_test_t *at) { - at->flags = ((at->flags | invalid_mask) + 1) & ~invalid_mask; - return at->flags < (1 << NR_AC_FLAGS); + at->flags = ((at->flags | invalid_mask) + 1) & ~invalid_mask; + return at->flags < (1 << NR_AC_FLAGS); } #define F(x) ((flags & x##_MASK) != 0) static _Bool ac_test_legal(ac_test_t *at) { - int flags = at->flags; - unsigned reserved; - - if (F(AC_ACCESS_FETCH) && F(AC_ACCESS_WRITE)) - return false; - - /* - * Since we convert current page to kernel page when cr4.smep=1, - * we can't switch to user mode. - */ - if (F(AC_ACCESS_USER) && F(AC_CPU_CR4_SMEP)) - return false; - - /* - * Only test protection key faults if CR4.PKE=1. - */ - if (!F(AC_CPU_CR4_PKE) && - (F(AC_PKU_AD) || F(AC_PKU_WD))) { - return false; - } - - /* - * pde.bit13 checks handling of reserved bits in largepage PDEs. It is - * meaningless if there is a PTE. - */ - if (!F(AC_PDE_PSE) && F(AC_PDE_BIT13)) - return false; - - /* - * Shorten the test by avoiding testing too many reserved bit combinations. - * Skip testing multiple reserved bits to shorten the test. Reserved bit - * page faults are terminal and multiple reserved bits do not affect the - * error code; the odds of a KVM bug are super low, and the odds of actually - * being able to detect a bug are even lower. - */ - reserved = (AC_PDE_BIT51_MASK | AC_PDE_BIT36_MASK | AC_PDE_BIT13_MASK | - AC_PTE_BIT51_MASK | AC_PTE_BIT36_MASK); - if (!F(AC_CPU_EFER_NX)) - reserved |= AC_PDE_NX_MASK | AC_PTE_NX_MASK; - - /* Only test one reserved bit at a time. */ - reserved &= flags; - if (reserved & (reserved - 1)) - return false; - - return true; + int flags = at->flags; + unsigned reserved; + + if (F(AC_ACCESS_FETCH) && F(AC_ACCESS_WRITE)) + return false; + + /* + * Since we convert current page to kernel page when cr4.smep=1, + * we can't switch to user mode. + */ + if (F(AC_ACCESS_USER) && F(AC_CPU_CR4_SMEP)) + return false; + + /* + * Only test protection key faults if CR4.PKE=1. + */ + if (!F(AC_CPU_CR4_PKE) && + (F(AC_PKU_AD) || F(AC_PKU_WD))) { + return false; + } + + /* + * pde.bit13 checks handling of reserved bits in largepage PDEs. It is + * meaningless if there is a PTE. + */ + if (!F(AC_PDE_PSE) && F(AC_PDE_BIT13)) + return false; + + /* + * Shorten the test by avoiding testing too many reserved bit combinations. + * Skip testing multiple reserved bits to shorten the test. Reserved bit + * page faults are terminal and multiple reserved bits do not affect the + * error code; the odds of a KVM bug are super low, and the odds of actually + * being able to detect a bug are even lower. + */ + reserved = (AC_PDE_BIT51_MASK | AC_PDE_BIT36_MASK | AC_PDE_BIT13_MASK | + AC_PTE_BIT51_MASK | AC_PTE_BIT36_MASK); + if (!F(AC_CPU_EFER_NX)) + reserved |= AC_PDE_NX_MASK | AC_PTE_NX_MASK; + + /* Only test one reserved bit at a time. */ + reserved &= flags; + if (reserved & (reserved - 1)) + return false; + + return true; } static int ac_test_bump(ac_test_t *at) { - int ret; + int ret; - ret = ac_test_bump_one(at); - while (ret && !ac_test_legal(at)) ret = ac_test_bump_one(at); - return ret; + while (ret && !ac_test_legal(at)) + ret = ac_test_bump_one(at); + return ret; } static pt_element_t ac_test_alloc_pt(ac_pool_t *pool) { - pt_element_t ret = pool->pt_pool + pool->pt_pool_current; - pool->pt_pool_current += PAGE_SIZE; - memset(va(ret), 0, PAGE_SIZE); - return ret; + pt_element_t ret = pool->pt_pool + pool->pt_pool_current; + pool->pt_pool_current += PAGE_SIZE; + memset(va(ret), 0, PAGE_SIZE); + return ret; } static _Bool ac_test_enough_room(ac_pool_t *pool) { - return pool->pt_pool_current + 5 * PAGE_SIZE <= pool->pt_pool_size; + return pool->pt_pool_current + 5 * PAGE_SIZE <= pool->pt_pool_size; } static void ac_test_reset_pt_pool(ac_pool_t *pool) { - pool->pt_pool_current = 0; + pool->pt_pool_current = 0; } static pt_element_t ac_test_permissions(ac_test_t *at, unsigned flags, - bool writable, bool user, - bool executable) + bool writable, bool user, + bool executable) { - bool kwritable = !F(AC_CPU_CR0_WP) && !F(AC_ACCESS_USER); - pt_element_t expected = 0; - - if (F(AC_ACCESS_USER) && !user) - at->expected_fault = 1; - - if (F(AC_ACCESS_WRITE) && !writable && !kwritable) - at->expected_fault = 1; - - if (F(AC_ACCESS_FETCH) && !executable) - at->expected_fault = 1; - - if (F(AC_ACCESS_FETCH) && user && F(AC_CPU_CR4_SMEP)) - at->expected_fault = 1; - - if (user && !F(AC_ACCESS_FETCH) && F(AC_PKU_PKEY) && F(AC_CPU_CR4_PKE)) { - if (F(AC_PKU_AD)) { - at->expected_fault = 1; - at->expected_error |= PFERR_PK_MASK; - } else if (F(AC_ACCESS_WRITE) && F(AC_PKU_WD) && !kwritable) { - at->expected_fault = 1; - at->expected_error |= PFERR_PK_MASK; - } - } - - if (!at->expected_fault) { - expected |= PT_ACCESSED_MASK; - if (F(AC_ACCESS_WRITE)) - expected |= PT_DIRTY_MASK; - } - - return expected; + bool kwritable = !F(AC_CPU_CR0_WP) && !F(AC_ACCESS_USER); + pt_element_t expected = 0; + + if (F(AC_ACCESS_USER) && !user) + at->expected_fault = 1; + + if (F(AC_ACCESS_WRITE) && !writable && !kwritable) + at->expected_fault = 1; + + if (F(AC_ACCESS_FETCH) && !executable) + at->expected_fault = 1; + + if (F(AC_ACCESS_FETCH) && user && F(AC_CPU_CR4_SMEP)) + at->expected_fault = 1; + + if (user && !F(AC_ACCESS_FETCH) && F(AC_PKU_PKEY) && F(AC_CPU_CR4_PKE)) { + if (F(AC_PKU_AD)) { + at->expected_fault = 1; + at->expected_error |= PFERR_PK_MASK; + } else if (F(AC_ACCESS_WRITE) && F(AC_PKU_WD) && !kwritable) { + at->expected_fault = 1; + at->expected_error |= PFERR_PK_MASK; + } + } + + if (!at->expected_fault) { + expected |= PT_ACCESSED_MASK; + if (F(AC_ACCESS_WRITE)) + expected |= PT_DIRTY_MASK; + } + + return expected; } static void ac_emulate_access(ac_test_t *at, unsigned flags) { - bool pde_valid, pte_valid; - bool user, writable, executable; - - if (F(AC_ACCESS_USER)) - at->expected_error |= PFERR_USER_MASK; - - if (F(AC_ACCESS_WRITE)) - at->expected_error |= PFERR_WRITE_MASK; - - if (F(AC_ACCESS_FETCH)) - at->expected_error |= PFERR_FETCH_MASK; - - if (!F(AC_PDE_ACCESSED)) - at->ignore_pde = PT_ACCESSED_MASK; - - pde_valid = F(AC_PDE_PRESENT) - && !F(AC_PDE_BIT51) && !F(AC_PDE_BIT36) && !F(AC_PDE_BIT13) - && !(F(AC_PDE_NX) && !F(AC_CPU_EFER_NX)); - - if (!pde_valid) { - at->expected_fault = 1; - if (F(AC_PDE_PRESENT)) { - at->expected_error |= PFERR_RESERVED_MASK; - } else { - at->expected_error &= ~PFERR_PRESENT_MASK; - } - goto fault; - } - - writable = !F(AC_PDPTE_NO_WRITABLE) && F(AC_PDE_WRITABLE); - user = F(AC_PDE_USER); - executable = !F(AC_PDE_NX); - - if (F(AC_PDE_PSE)) { - at->expected_pde |= ac_test_permissions(at, flags, writable, user, - executable); - goto no_pte; - } - - at->expected_pde |= PT_ACCESSED_MASK; - - pte_valid = F(AC_PTE_PRESENT) - && !F(AC_PTE_BIT51) && !F(AC_PTE_BIT36) - && !(F(AC_PTE_NX) && !F(AC_CPU_EFER_NX)); - - if (!pte_valid) { - at->expected_fault = 1; - if (F(AC_PTE_PRESENT)) { - at->expected_error |= PFERR_RESERVED_MASK; - } else { - at->expected_error &= ~PFERR_PRESENT_MASK; - } - goto fault; - } - - writable &= F(AC_PTE_WRITABLE); - user &= F(AC_PTE_USER); - executable &= !F(AC_PTE_NX); - - at->expected_pte |= ac_test_permissions(at, flags, writable, user, - executable); + bool pde_valid, pte_valid; + bool user, writable, executable; + + if (F(AC_ACCESS_USER)) + at->expected_error |= PFERR_USER_MASK; + + if (F(AC_ACCESS_WRITE)) + at->expected_error |= PFERR_WRITE_MASK; + + if (F(AC_ACCESS_FETCH)) + at->expected_error |= PFERR_FETCH_MASK; + + if (!F(AC_PDE_ACCESSED)) + at->ignore_pde = PT_ACCESSED_MASK; + + pde_valid = F(AC_PDE_PRESENT) + && !F(AC_PDE_BIT51) && !F(AC_PDE_BIT36) && !F(AC_PDE_BIT13) + && !(F(AC_PDE_NX) && !F(AC_CPU_EFER_NX)); + + if (!pde_valid) { + at->expected_fault = 1; + if (F(AC_PDE_PRESENT)) { + at->expected_error |= PFERR_RESERVED_MASK; + } else { + at->expected_error &= ~PFERR_PRESENT_MASK; + } + goto fault; + } + + writable = !F(AC_PDPTE_NO_WRITABLE) && F(AC_PDE_WRITABLE); + user = F(AC_PDE_USER); + executable = !F(AC_PDE_NX); + + if (F(AC_PDE_PSE)) { + at->expected_pde |= ac_test_permissions(at, flags, writable, + user, executable); + goto no_pte; + } + + at->expected_pde |= PT_ACCESSED_MASK; + + pte_valid = F(AC_PTE_PRESENT) + && !F(AC_PTE_BIT51) && !F(AC_PTE_BIT36) + && !(F(AC_PTE_NX) && !F(AC_CPU_EFER_NX)); + + if (!pte_valid) { + at->expected_fault = 1; + if (F(AC_PTE_PRESENT)) { + at->expected_error |= PFERR_RESERVED_MASK; + } else { + at->expected_error &= ~PFERR_PRESENT_MASK; + } + goto fault; + } + + writable &= F(AC_PTE_WRITABLE); + user &= F(AC_PTE_USER); + executable &= !F(AC_PTE_NX); + + at->expected_pte |= ac_test_permissions(at, flags, writable, user, + executable); no_pte: fault: - if (!at->expected_fault) - at->ignore_pde = 0; - if (!F(AC_CPU_EFER_NX) && !F(AC_CPU_CR4_SMEP)) - at->expected_error &= ~PFERR_FETCH_MASK; + if (!at->expected_fault) + at->ignore_pde = 0; + if (!F(AC_CPU_EFER_NX) && !F(AC_CPU_CR4_SMEP)) + at->expected_error &= ~PFERR_FETCH_MASK; } static void ac_set_expected_status(ac_test_t *at) { - invlpg(at->virt); - - if (at->ptep) - at->expected_pte = *at->ptep; - at->expected_pde = *at->pdep; - at->ignore_pde = 0; - at->expected_fault = 0; - at->expected_error = PFERR_PRESENT_MASK; - - if (at->flags & AC_ACCESS_TWICE_MASK) { - ac_emulate_access(at, at->flags & ~AC_ACCESS_WRITE_MASK - & ~AC_ACCESS_FETCH_MASK & ~AC_ACCESS_USER_MASK); - at->expected_fault = 0; + invlpg(at->virt); + + if (at->ptep) + at->expected_pte = *at->ptep; + at->expected_pde = *at->pdep; + at->ignore_pde = 0; + at->expected_fault = 0; at->expected_error = PFERR_PRESENT_MASK; - at->ignore_pde = 0; - } - ac_emulate_access(at, at->flags); + if (at->flags & AC_ACCESS_TWICE_MASK) { + ac_emulate_access(at, at->flags & + ~AC_ACCESS_WRITE_MASK & + ~AC_ACCESS_FETCH_MASK & + ~AC_ACCESS_USER_MASK); + at->expected_fault = 0; + at->expected_error = PFERR_PRESENT_MASK; + at->ignore_pde = 0; + } + + ac_emulate_access(at, at->flags); } static void __ac_setup_specific_pages(ac_test_t *at, ac_pool_t *pool, bool reuse, u64 pd_page, u64 pt_page) - { - unsigned long root = read_cr3(); - int flags = at->flags; - bool skip = true; - - if (!ac_test_enough_room(pool)) - ac_test_reset_pt_pool(pool); - - at->ptep = 0; - for (int i = page_table_levels; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) { - pt_element_t *vroot = va(root & PT_BASE_ADDR_MASK); - unsigned index = PT_INDEX((unsigned long)at->virt, i); - pt_element_t pte = 0; + unsigned long root = read_cr3(); + int flags = at->flags; + bool skip = true; - /* - * Reuse existing page tables along the path to the test code and data - * (which is in the bottom 2MB). - */ - if (skip && i >= 2 && index == 0) { - goto next; - } - skip = false; - if (reuse && vroot[index]) { - switch (i) { - case 2: - at->pdep = &vroot[index]; - break; - case 1: - at->ptep = &vroot[index]; - break; - } - goto next; - } + if (!ac_test_enough_room(pool)) + ac_test_reset_pt_pool(pool); - switch (i) { - case 5: - case 4: - pte = ac_test_alloc_pt(pool); - pte |= PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK; - break; - case 3: - pte = pd_page ? pd_page : ac_test_alloc_pt(pool); - pte |= PT_PRESENT_MASK | PT_USER_MASK; - if (!F(AC_PDPTE_NO_WRITABLE)) - pte |= PT_WRITABLE_MASK; - break; - case 2: - if (!F(AC_PDE_PSE)) { - pte = pt_page ? pt_page : ac_test_alloc_pt(pool); - /* The protection key is ignored on non-leaf entries. */ - if (F(AC_PKU_PKEY)) - pte |= 2ull << 59; - } else { - pte = at->phys & PT_PSE_BASE_ADDR_MASK; - pte |= PT_PAGE_SIZE_MASK; - if (F(AC_PKU_PKEY)) - pte |= 1ull << 59; - } - if (F(AC_PDE_PRESENT)) - pte |= PT_PRESENT_MASK; - if (F(AC_PDE_WRITABLE)) - pte |= PT_WRITABLE_MASK; - if (F(AC_PDE_USER)) - pte |= PT_USER_MASK; - if (F(AC_PDE_ACCESSED)) - pte |= PT_ACCESSED_MASK; - if (F(AC_PDE_DIRTY)) - pte |= PT_DIRTY_MASK; - if (F(AC_PDE_NX)) - pte |= PT64_NX_MASK; - if (F(AC_PDE_BIT51)) - pte |= 1ull << 51; - if (F(AC_PDE_BIT36)) - pte |= 1ull << 36; - if (F(AC_PDE_BIT13)) - pte |= 1ull << 13; - at->pdep = &vroot[index]; - break; - case 1: - pte = at->phys & PT_BASE_ADDR_MASK; - if (F(AC_PKU_PKEY)) - pte |= 1ull << 59; - if (F(AC_PTE_PRESENT)) - pte |= PT_PRESENT_MASK; - if (F(AC_PTE_WRITABLE)) - pte |= PT_WRITABLE_MASK; - if (F(AC_PTE_USER)) - pte |= PT_USER_MASK; - if (F(AC_PTE_ACCESSED)) - pte |= PT_ACCESSED_MASK; - if (F(AC_PTE_DIRTY)) - pte |= PT_DIRTY_MASK; - if (F(AC_PTE_NX)) - pte |= PT64_NX_MASK; - if (F(AC_PTE_BIT51)) - pte |= 1ull << 51; - if (F(AC_PTE_BIT36)) - pte |= 1ull << 36; - at->ptep = &vroot[index]; - break; - } - vroot[index] = pte; + at->ptep = 0; + for (int i = page_table_levels; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) { + pt_element_t *vroot = va(root & PT_BASE_ADDR_MASK); + unsigned index = PT_INDEX((unsigned long)at->virt, i); + pt_element_t pte = 0; + + /* + * Reuse existing page tables along the path to the test code and data + * (which is in the bottom 2MB). + */ + if (skip && i >= 2 && index == 0) { + goto next; + } + skip = false; + if (reuse && vroot[index]) { + switch (i) { + case 2: + at->pdep = &vroot[index]; + break; + case 1: + at->ptep = &vroot[index]; + break; + } + goto next; + } + + switch (i) { + case 5: + case 4: + pte = ac_test_alloc_pt(pool); + pte |= PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK; + break; + case 3: + pte = pd_page ? pd_page : ac_test_alloc_pt(pool); + pte |= PT_PRESENT_MASK | PT_USER_MASK; + if (!F(AC_PDPTE_NO_WRITABLE)) + pte |= PT_WRITABLE_MASK; + break; + case 2: + if (!F(AC_PDE_PSE)) { + pte = pt_page ? pt_page : ac_test_alloc_pt(pool); + /* The protection key is ignored on non-leaf entries. */ + if (F(AC_PKU_PKEY)) + pte |= 2ull << 59; + } else { + pte = at->phys & PT_PSE_BASE_ADDR_MASK; + pte |= PT_PAGE_SIZE_MASK; + if (F(AC_PKU_PKEY)) + pte |= 1ull << 59; + } + if (F(AC_PDE_PRESENT)) + pte |= PT_PRESENT_MASK; + if (F(AC_PDE_WRITABLE)) + pte |= PT_WRITABLE_MASK; + if (F(AC_PDE_USER)) + pte |= PT_USER_MASK; + if (F(AC_PDE_ACCESSED)) + pte |= PT_ACCESSED_MASK; + if (F(AC_PDE_DIRTY)) + pte |= PT_DIRTY_MASK; + if (F(AC_PDE_NX)) + pte |= PT64_NX_MASK; + if (F(AC_PDE_BIT51)) + pte |= 1ull << 51; + if (F(AC_PDE_BIT36)) + pte |= 1ull << 36; + if (F(AC_PDE_BIT13)) + pte |= 1ull << 13; + at->pdep = &vroot[index]; + break; + case 1: + pte = at->phys & PT_BASE_ADDR_MASK; + if (F(AC_PKU_PKEY)) + pte |= 1ull << 59; + if (F(AC_PTE_PRESENT)) + pte |= PT_PRESENT_MASK; + if (F(AC_PTE_WRITABLE)) + pte |= PT_WRITABLE_MASK; + if (F(AC_PTE_USER)) + pte |= PT_USER_MASK; + if (F(AC_PTE_ACCESSED)) + pte |= PT_ACCESSED_MASK; + if (F(AC_PTE_DIRTY)) + pte |= PT_DIRTY_MASK; + if (F(AC_PTE_NX)) + pte |= PT64_NX_MASK; + if (F(AC_PTE_BIT51)) + pte |= 1ull << 51; + if (F(AC_PTE_BIT36)) + pte |= 1ull << 36; + at->ptep = &vroot[index]; + break; + } + vroot[index] = pte; next: - root = vroot[index]; - } - ac_set_expected_status(at); + root = vroot[index]; + } + ac_set_expected_status(at); } static void ac_test_setup_pte(ac_test_t *at, ac_pool_t *pool) @@ -630,11 +631,11 @@ static void ac_setup_specific_pages(ac_test_t *at, ac_pool_t *pool, static void dump_mapping(ac_test_t *at) { unsigned long root = read_cr3(); - int flags = at->flags; + int flags = at->flags; int i; printf("Dump mapping: address: %p\n", at->virt); - for (i = page_table_levels ; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) { + for (i = page_table_levels; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) { pt_element_t *vroot = va(root & PT_BASE_ADDR_MASK); unsigned index = PT_INDEX((unsigned long)at->virt, i); pt_element_t pte = vroot[index]; @@ -645,168 +646,166 @@ static void dump_mapping(ac_test_t *at) } static void ac_test_check(ac_test_t *at, _Bool *success_ret, _Bool cond, - const char *fmt, ...) + const char *fmt, ...) { - va_list ap; - char buf[500]; + va_list ap; + char buf[500]; - if (!*success_ret) { - return; - } + if (!*success_ret) { + return; + } - if (!cond) { - return; - } + if (!cond) { + return; + } - *success_ret = false; + *success_ret = false; - if (!verbose) { - puts("\n"); - ac_test_show(at); - } + if (!verbose) { + puts("\n"); + ac_test_show(at); + } - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - printf("FAIL: %s\n", buf); - dump_mapping(at); + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + printf("FAIL: %s\n", buf); + dump_mapping(at); } static int pt_match(pt_element_t pte1, pt_element_t pte2, pt_element_t ignore) { - pte1 &= ~ignore; - pte2 &= ~ignore; - return pte1 == pte2; + pte1 &= ~ignore; + pte2 &= ~ignore; + return pte1 == pte2; } static int ac_test_do_access(ac_test_t *at) { - static unsigned unique = 42; - int fault = 0; - unsigned e; - static unsigned char user_stack[4096]; - unsigned long rsp; - _Bool success = true; - int flags = at->flags; - - ++unique; - if (!(unique & 65535)) { - puts("."); - } - - *((unsigned char *)at->phys) = 0xc3; /* ret */ - - unsigned r = unique; - set_cr0_wp(F(AC_CPU_CR0_WP)); - set_efer_nx(F(AC_CPU_EFER_NX)); - set_cr4_pke(F(AC_CPU_CR4_PKE)); - if (F(AC_CPU_CR4_PKE)) { - /* WD2=AD2=1, WD1=F(AC_PKU_WD), AD1=F(AC_PKU_AD) */ - write_pkru(0x30 | (F(AC_PKU_WD) ? 8 : 0) | - (F(AC_PKU_AD) ? 4 : 0)); - } - - set_cr4_smep(F(AC_CPU_CR4_SMEP)); - - if (F(AC_ACCESS_TWICE)) { - asm volatile ( - "mov $fixed2, %%rsi \n\t" - "mov (%[addr]), %[reg] \n\t" - "fixed2:" - : [reg]"=r"(r), [fault]"=a"(fault), "=b"(e) - : [addr]"r"(at->virt) - : "rsi" - ); - fault = 0; - } - - asm volatile ("mov $fixed1, %%rsi \n\t" - "mov %%rsp, %[rsp0] \n\t" - "cmp $0, %[user] \n\t" - "jz do_access \n\t" - "push %%rax; mov %[user_ds], %%ax; mov %%ax, %%ds; pop %%rax \n\t" - "pushq %[user_ds] \n\t" - "pushq %[user_stack_top] \n\t" - "pushfq \n\t" - "pushq %[user_cs] \n\t" - "pushq $do_access \n\t" - "iretq \n" - "do_access: \n\t" - "cmp $0, %[fetch] \n\t" - "jnz 2f \n\t" - "cmp $0, %[write] \n\t" - "jnz 1f \n\t" - "mov (%[addr]), %[reg] \n\t" - "jmp done \n\t" - "1: mov %[reg], (%[addr]) \n\t" - "jmp done \n\t" - "2: call *%[addr] \n\t" - "done: \n" - "fixed1: \n" - "int %[kernel_entry_vector] \n\t" - ".section .text.entry \n\t" - "kernel_entry: \n\t" - "mov %[rsp0], %%rsp \n\t" - "jmp back_to_kernel \n\t" - ".section .text \n\t" - "back_to_kernel:" - : [reg]"+r"(r), "+a"(fault), "=b"(e), "=&d"(rsp), - [rsp0]"=m"(tss[0].rsp0) - : [addr]"r"(at->virt), - [write]"r"(F(AC_ACCESS_WRITE)), - [user]"r"(F(AC_ACCESS_USER)), - [fetch]"r"(F(AC_ACCESS_FETCH)), - [user_ds]"i"(USER_DS), - [user_cs]"i"(USER_CS), - [user_stack_top]"r"(user_stack + sizeof user_stack), - [kernel_entry_vector]"i"(0x20) - : "rsi"); - - asm volatile (".section .text.pf \n\t" - "page_fault: \n\t" - "pop %rbx \n\t" - "mov %rsi, (%rsp) \n\t" - "movl $1, %eax \n\t" - "iretq \n\t" - ".section .text"); - - ac_test_check(at, &success, fault && !at->expected_fault, - "unexpected fault"); - ac_test_check(at, &success, !fault && at->expected_fault, - "unexpected access"); - ac_test_check(at, &success, fault && e != at->expected_error, - "error code %x expected %x", e, at->expected_error); - if (at->ptep) - ac_test_check(at, &success, *at->ptep != at->expected_pte, - "pte %x expected %x", *at->ptep, at->expected_pte); - ac_test_check(at, &success, - !pt_match(*at->pdep, at->expected_pde, at->ignore_pde), - "pde %x expected %x", *at->pdep, at->expected_pde); - - if (success && verbose) { - if (at->expected_fault) { - printf("PASS (%x)\n", at->expected_error); - } else { - printf("PASS\n"); + static unsigned unique = 42; + int fault = 0; + unsigned e; + static unsigned char user_stack[4096]; + unsigned long rsp; + _Bool success = true; + int flags = at->flags; + + ++unique; + if (!(unique & 65535)) { + puts("."); } - } - return success; + + *((unsigned char *)at->phys) = 0xc3; /* ret */ + + unsigned r = unique; + set_cr0_wp(F(AC_CPU_CR0_WP)); + set_efer_nx(F(AC_CPU_EFER_NX)); + set_cr4_pke(F(AC_CPU_CR4_PKE)); + if (F(AC_CPU_CR4_PKE)) { + /* WD2=AD2=1, WD1=F(AC_PKU_WD), AD1=F(AC_PKU_AD) */ + write_pkru(0x30 | (F(AC_PKU_WD) ? 8 : 0) | + (F(AC_PKU_AD) ? 4 : 0)); + } + + set_cr4_smep(F(AC_CPU_CR4_SMEP)); + + if (F(AC_ACCESS_TWICE)) { + asm volatile ("mov $fixed2, %%rsi \n\t" + "mov (%[addr]), %[reg] \n\t" + "fixed2:" + : [reg]"=r"(r), [fault]"=a"(fault), "=b"(e) + : [addr]"r"(at->virt) + : "rsi"); + fault = 0; + } + + asm volatile ("mov $fixed1, %%rsi \n\t" + "mov %%rsp, %[rsp0] \n\t" + "cmp $0, %[user] \n\t" + "jz do_access \n\t" + "push %%rax; mov %[user_ds], %%ax; mov %%ax, %%ds; pop %%rax \n\t" + "pushq %[user_ds] \n\t" + "pushq %[user_stack_top] \n\t" + "pushfq \n\t" + "pushq %[user_cs] \n\t" + "pushq $do_access \n\t" + "iretq \n" + "do_access: \n\t" + "cmp $0, %[fetch] \n\t" + "jnz 2f \n\t" + "cmp $0, %[write] \n\t" + "jnz 1f \n\t" + "mov (%[addr]), %[reg] \n\t" + "jmp done \n\t" + "1: mov %[reg], (%[addr]) \n\t" + "jmp done \n\t" + "2: call *%[addr] \n\t" + "done: \n" + "fixed1: \n" + "int %[kernel_entry_vector] \n\t" + ".section .text.entry \n\t" + "kernel_entry: \n\t" + "mov %[rsp0], %%rsp \n\t" + "jmp back_to_kernel \n\t" + ".section .text \n\t" + "back_to_kernel:" + : [reg]"+r"(r), "+a"(fault), "=b"(e), "=&d"(rsp), + [rsp0]"=m"(tss[0].rsp0) + : [addr]"r"(at->virt), + [write]"r"(F(AC_ACCESS_WRITE)), + [user]"r"(F(AC_ACCESS_USER)), + [fetch]"r"(F(AC_ACCESS_FETCH)), + [user_ds]"i"(USER_DS), + [user_cs]"i"(USER_CS), + [user_stack_top]"r"(user_stack + sizeof user_stack), + [kernel_entry_vector]"i"(0x20) + : "rsi"); + + asm volatile (".section .text.pf \n\t" + "page_fault: \n\t" + "pop %rbx \n\t" + "mov %rsi, (%rsp) \n\t" + "movl $1, %eax \n\t" + "iretq \n\t" + ".section .text"); + + ac_test_check(at, &success, fault && !at->expected_fault, + "unexpected fault"); + ac_test_check(at, &success, !fault && at->expected_fault, + "unexpected access"); + ac_test_check(at, &success, fault && e != at->expected_error, + "error code %x expected %x", e, at->expected_error); + if (at->ptep) + ac_test_check(at, &success, *at->ptep != at->expected_pte, + "pte %x expected %x", *at->ptep, at->expected_pte); + ac_test_check(at, &success, + !pt_match(*at->pdep, at->expected_pde, at->ignore_pde), + "pde %x expected %x", *at->pdep, at->expected_pde); + + if (success && verbose) { + if (at->expected_fault) { + printf("PASS (%x)\n", at->expected_error); + } else { + printf("PASS\n"); + } + } + return success; } static void ac_test_show(ac_test_t *at) { - char line[5000]; - - *line = 0; - strcat(line, "test"); - for (int i = 0; i < NR_AC_FLAGS; ++i) - if (at->flags & (1 << i)) { - strcat(line, " "); - strcat(line, ac_names[i]); - } - - strcat(line, ": "); - printf("%s", line); + char line[5000]; + + *line = 0; + strcat(line, "test"); + for (int i = 0; i < NR_AC_FLAGS; ++i) + if (at->flags & (1 << i)) { + strcat(line, " "); + strcat(line, ac_names[i]); + } + + strcat(line, ": "); + printf("%s", line); } /* @@ -815,36 +814,36 @@ static void ac_test_show(ac_test_t *at) */ static int corrupt_hugepage_triger(ac_pool_t *pool) { - ac_test_t at1, at2; + ac_test_t at1, at2; - ac_test_init(&at1, (void *)(0x123400000000)); - ac_test_init(&at2, (void *)(0x666600000000)); + ac_test_init(&at1, (void *)(0x123400000000)); + ac_test_init(&at2, (void *)(0x666600000000)); - at2.flags = AC_CPU_CR0_WP_MASK | AC_PDE_PSE_MASK | AC_PDE_PRESENT_MASK; - ac_test_setup_pte(&at2, pool); - if (!ac_test_do_access(&at2)) - goto err; + at2.flags = AC_CPU_CR0_WP_MASK | AC_PDE_PSE_MASK | AC_PDE_PRESENT_MASK; + ac_test_setup_pte(&at2, pool); + if (!ac_test_do_access(&at2)) + goto err; - at1.flags = at2.flags | AC_PDE_WRITABLE_MASK; - ac_test_setup_pte(&at1, pool); - if (!ac_test_do_access(&at1)) - goto err; + at1.flags = at2.flags | AC_PDE_WRITABLE_MASK; + ac_test_setup_pte(&at1, pool); + if (!ac_test_do_access(&at1)) + goto err; - at1.flags |= AC_ACCESS_WRITE_MASK; - ac_set_expected_status(&at1); - if (!ac_test_do_access(&at1)) - goto err; + at1.flags |= AC_ACCESS_WRITE_MASK; + ac_set_expected_status(&at1); + if (!ac_test_do_access(&at1)) + goto err; - at2.flags |= AC_ACCESS_WRITE_MASK; - ac_set_expected_status(&at2); - if (!ac_test_do_access(&at2)) - goto err; + at2.flags |= AC_ACCESS_WRITE_MASK; + ac_set_expected_status(&at2); + if (!ac_test_do_access(&at2)) + goto err; - return 1; + return 1; err: - printf("corrupt_hugepage_triger test fail\n"); - return 0; + printf("corrupt_hugepage_triger test fail\n"); + return 0; } /* @@ -861,24 +860,24 @@ static int check_pfec_on_prefetch_pte(ac_pool_t *pool) at1.flags = AC_PDE_PRESENT_MASK | AC_PTE_PRESENT_MASK; ac_setup_specific_pages(&at1, pool, 30 * 1024 * 1024, 30 * 1024 * 1024); - at2.flags = at1.flags | AC_PTE_NX_MASK; + at2.flags = at1.flags | AC_PTE_NX_MASK; ac_setup_specific_pages(&at2, pool, 30 * 1024 * 1024, 30 * 1024 * 1024); if (!ac_test_do_access(&at1)) { printf("%s: prepare fail\n", __FUNCTION__); - goto err; + goto err; } if (!ac_test_do_access(&at2)) { printf("%s: check PFEC on prefetch pte path fail\n", - __FUNCTION__); + __FUNCTION__); goto err; } return 1; err: - return 0; + return 0; } /* @@ -903,14 +902,14 @@ static int check_large_pte_dirty_for_nowp(ac_pool_t *pool) ac_test_init(&at1, (void *)(0x123403000000)); ac_test_init(&at2, (void *)(0x666606000000)); - at2.flags = AC_PDE_PRESENT_MASK | AC_PDE_PSE_MASK; + at2.flags = AC_PDE_PRESENT_MASK | AC_PDE_PSE_MASK; ac_test_setup_pte(&at2, pool); if (!ac_test_do_access(&at2)) { printf("%s: read on the first mapping fail.\n", __FUNCTION__); goto err; } - at1.flags = at2.flags | AC_ACCESS_WRITE_MASK; + at1.flags = at2.flags | AC_ACCESS_WRITE_MASK; ac_test_setup_pte(&at1, pool); if (!ac_test_do_access(&at1)) { printf("%s: write on the second mapping fail.\n", __FUNCTION__); @@ -936,17 +935,17 @@ static int check_smep_andnot_wp(ac_pool_t *pool) int err_prepare_andnot_wp, err_smep_andnot_wp; if (!this_cpu_has(X86_FEATURE_SMEP)) { - return 1; + return 1; } ac_test_init(&at1, (void *)(0x123406001000)); at1.flags = AC_PDE_PRESENT_MASK | AC_PTE_PRESENT_MASK | - AC_PDE_USER_MASK | AC_PTE_USER_MASK | - AC_PDE_ACCESSED_MASK | AC_PTE_ACCESSED_MASK | - AC_CPU_CR4_SMEP_MASK | - AC_CPU_CR0_WP_MASK | - AC_ACCESS_WRITE_MASK; + AC_PDE_USER_MASK | AC_PTE_USER_MASK | + AC_PDE_ACCESSED_MASK | AC_PTE_ACCESSED_MASK | + AC_CPU_CR4_SMEP_MASK | + AC_CPU_CR0_WP_MASK | + AC_ACCESS_WRITE_MASK; ac_test_setup_pte(&at1, pool); /* @@ -960,10 +959,10 @@ static int check_smep_andnot_wp(ac_pool_t *pool) goto clean_up; } - at1.flags &= ~AC_ACCESS_WRITE_MASK; - at1.flags |= AC_ACCESS_FETCH_MASK; - ac_set_expected_status(&at1); - err_smep_andnot_wp = ac_test_do_access(&at1); + at1.flags &= ~AC_ACCESS_WRITE_MASK; + at1.flags |= AC_ACCESS_FETCH_MASK; + ac_set_expected_status(&at1); + err_smep_andnot_wp = ac_test_do_access(&at1); clean_up: set_cr4_smep(0); @@ -1049,14 +1048,14 @@ static int check_effective_sp_permissions(ac_pool_t *pool) static int ac_test_exec(ac_test_t *at, ac_pool_t *pool) { - int r; - - if (verbose) { - ac_test_show(at); - } - ac_test_setup_pte(at, pool); - r = ac_test_do_access(at); - return r; + int r; + + if (verbose) { + ac_test_show(at); + } + ac_test_setup_pte(at, pool); + r = ac_test_do_access(at); + return r; } typedef int (*ac_test_fn)(ac_pool_t *pool); @@ -1071,82 +1070,82 @@ const ac_test_fn ac_test_cases[] = int ac_test_run() { - ac_test_t at; - ac_pool_t pool; - int i, tests, successes; - - printf("run\n"); - tests = successes = 0; - - shadow_cr0 = read_cr0(); - shadow_cr4 = read_cr4(); - shadow_efer = rdmsr(MSR_EFER); - - if (cpuid_maxphyaddr() >= 52) { - invalid_mask |= AC_PDE_BIT51_MASK; - invalid_mask |= AC_PTE_BIT51_MASK; - } - if (cpuid_maxphyaddr() >= 37) { - invalid_mask |= AC_PDE_BIT36_MASK; - invalid_mask |= AC_PTE_BIT36_MASK; - } - - if (this_cpu_has(X86_FEATURE_PKU)) { - set_cr4_pke(1); - set_cr4_pke(0); - /* Now PKRU = 0xFFFFFFFF. */ - } else { - tests++; - if (write_cr4_checking(shadow_cr4 | X86_CR4_PKE) == GP_VECTOR) { - successes++; - invalid_mask |= AC_PKU_AD_MASK; - invalid_mask |= AC_PKU_WD_MASK; - invalid_mask |= AC_PKU_PKEY_MASK; - invalid_mask |= AC_CPU_CR4_PKE_MASK; - printf("CR4.PKE not available, disabling PKE tests\n"); - } else { - printf("Set PKE in CR4 - expect #GP: FAIL!\n"); - set_cr4_pke(0); + ac_test_t at; + ac_pool_t pool; + int i, tests, successes; + + printf("run\n"); + tests = successes = 0; + + shadow_cr0 = read_cr0(); + shadow_cr4 = read_cr4(); + shadow_efer = rdmsr(MSR_EFER); + + if (cpuid_maxphyaddr() >= 52) { + invalid_mask |= AC_PDE_BIT51_MASK; + invalid_mask |= AC_PTE_BIT51_MASK; + } + if (cpuid_maxphyaddr() >= 37) { + invalid_mask |= AC_PDE_BIT36_MASK; + invalid_mask |= AC_PTE_BIT36_MASK; } - } - - if (!this_cpu_has(X86_FEATURE_SMEP)) { - tests++; - if (set_cr4_smep(1) == GP_VECTOR) { - successes++; - invalid_mask |= AC_CPU_CR4_SMEP_MASK; - printf("CR4.SMEP not available, disabling SMEP tests\n"); + + if (this_cpu_has(X86_FEATURE_PKU)) { + set_cr4_pke(1); + set_cr4_pke(0); + /* Now PKRU = 0xFFFFFFFF. */ } else { - printf("Set SMEP in CR4 - expect #GP: FAIL!\n"); - set_cr4_smep(0); + tests++; + if (write_cr4_checking(shadow_cr4 | X86_CR4_PKE) == GP_VECTOR) { + successes++; + invalid_mask |= AC_PKU_AD_MASK; + invalid_mask |= AC_PKU_WD_MASK; + invalid_mask |= AC_PKU_PKEY_MASK; + invalid_mask |= AC_CPU_CR4_PKE_MASK; + printf("CR4.PKE not available, disabling PKE tests\n"); + } else { + printf("Set PKE in CR4 - expect #GP: FAIL!\n"); + set_cr4_pke(0); + } + } + + if (!this_cpu_has(X86_FEATURE_SMEP)) { + tests++; + if (set_cr4_smep(1) == GP_VECTOR) { + successes++; + invalid_mask |= AC_CPU_CR4_SMEP_MASK; + printf("CR4.SMEP not available, disabling SMEP tests\n"); + } else { + printf("Set SMEP in CR4 - expect #GP: FAIL!\n"); + set_cr4_smep(0); + } + } + + /* Toggling LA57 in 64-bit mode (guaranteed for this test) is illegal. */ + if (this_cpu_has(X86_FEATURE_LA57)) { + tests++; + if (write_cr4_checking(shadow_cr4 ^ X86_CR4_LA57) == GP_VECTOR) + successes++; + + /* Force a VM-Exit on KVM, which doesn't intercept LA57 itself. */ + tests++; + if (write_cr4_checking(shadow_cr4 ^ (X86_CR4_LA57 | X86_CR4_PSE)) == GP_VECTOR) + successes++; } - } - - /* Toggling LA57 in 64-bit mode (guaranteed for this test) is illegal. */ - if (this_cpu_has(X86_FEATURE_LA57)) { - tests++; - if (write_cr4_checking(shadow_cr4 ^ X86_CR4_LA57) == GP_VECTOR) - successes++; - - /* Force a VM-Exit on KVM, which doesn't intercept LA57 itself. */ - tests++; - if (write_cr4_checking(shadow_cr4 ^ (X86_CR4_LA57 | X86_CR4_PSE)) == GP_VECTOR) - successes++; - } - - ac_env_int(&pool); - ac_test_init(&at, (void *)(0x123400000000 + 16 * smp_id())); - do { - ++tests; - successes += ac_test_exec(&at, &pool); - } while (ac_test_bump(&at)); - - for (i = 0; i < ARRAY_SIZE(ac_test_cases); i++) { - ++tests; - successes += ac_test_cases[i](&pool); - } - - printf("\n%d tests, %d failures\n", tests, tests - successes); - - return successes == tests; + + ac_env_int(&pool); + ac_test_init(&at, (void *)(0x123400000000 + 16 * smp_id())); + do { + ++tests; + successes += ac_test_exec(&at, &pool); + } while (ac_test_bump(&at)); + + for (i = 0; i < ARRAY_SIZE(ac_test_cases); i++) { + ++tests; + successes += ac_test_cases[i](&pool); + } + + printf("\n%d tests, %d failures\n", tests, tests - successes); + + return successes == tests; } From patchwork Wed Nov 10 21:20:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613117 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B71E5C433F5 for ; Wed, 10 Nov 2021 21:20:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A17D361208 for ; Wed, 10 Nov 2021 21:20:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233511AbhKJVXn (ORCPT ); Wed, 10 Nov 2021 16:23:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51384 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233495AbhKJVXg (ORCPT ); Wed, 10 Nov 2021 16:23:36 -0500 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3FFFEC061226 for ; Wed, 10 Nov 2021 13:20:37 -0800 (PST) Received: by mail-pj1-x104a.google.com with SMTP id p12-20020a17090b010c00b001a65bfe8054so1723219pjz.8 for ; Wed, 10 Nov 2021 13:20:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=JiXicHEorTD0W0ogbHs6tJnf0LcMa3Cy3C2YtlUwBjQ=; b=HRwG4ZjIx3xWJJo4dvUkSljuoPWs7AvFpKsfDZBdie/XltQdzUG/gnh20fCALTdE26 OcMXByYAUp/H83RsPq0Mrpfy8HVWvoA0hYdecG9Uty5oSZRXnHSggT5A/RvTU8ofTgKf WXdIgwx/778sCMAFFEyl4Pb745s+QLUE+rlL+jzHhr01iJkuH/4xTdyQCYJHFiSG5All NOgUx6BAxEWh0v8LSIvPtv+KzdWj5tRqLdbZgnloWWpVmnP1Emw5w+GewpwMqQ6WUES7 uI4bwytM8885lSUQcvaFQpsNjnwILZDw1WC2uBuEPabuz09Vbw0b5h6kNhi/YFolKzfM BXtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=JiXicHEorTD0W0ogbHs6tJnf0LcMa3Cy3C2YtlUwBjQ=; b=DXKdbFtL0ELfRctJEMteMUavPWpBFywGX7aUN292ghu4AYRMcp9Gs51U/+zumJLJW1 8iQh14PtKZkKkgnUdgKFif+pnze1yhKRMLKjICInIRiKv6DwCUXbKYqL9p2Zzooh460w 6K47oADMo5JT9u6PnyXqCjmY8km5ijONBm0/+hU8jPw9vEIZduUcHgVJu59UxqaDjA7M HGpvPJc3ORsJUgqnOAL0VM4AI4tsh77neikwj/xeqU7Rhlr9p3s5SqDFUls5AkYhgvXW qO22yG4+KDuYv7fpSPz5Wf536hPWSaSPdribg18Ae5OEijx0/xIHKH3k/O3frvZl5u0r S/wA== X-Gm-Message-State: AOAM531k4b3257bIiaNQvWOtMEoAP7lU8iG6a8Jh6ZgTlrGlfbn0BmyI CEjG5sYDWLbRGnp6coRJ/ntAPJowXkuWzUtmI4VezmSYSJWWHDXgtZDM71hQQMMlHZl89NdpuQW JiqY70XTW5YYfqiVfkLlxFHHq5uYILXCIVhNwt0cTqkTDq0okSXCmFEb62dbIau566+gK X-Google-Smtp-Source: ABdhPJzN7nSOLibM+XPsF5o01UO1BnBwcmw7LG7bd0pucMtVbhZ7cr6ZaxIMTp4xFIcX7dkly1VMA2BwmrntEmK8 X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a05:6a00:a8b:b0:44d:ef7c:94b9 with SMTP id b11-20020a056a000a8b00b0044def7c94b9mr2112017pfl.36.1636579236669; Wed, 10 Nov 2021 13:20:36 -0800 (PST) Date: Wed, 10 Nov 2021 21:20:00 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-14-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 13/14] x86: Clean up the global, page_table_levels, in access.c From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Remove the global, page table levels, from access.c and store it in the test struct ac_test_t instead. Signed-off-by: Aaron Lewis --- x86/access.c | 50 ++++++++++++++++++++++++----------------------- x86/access.h | 5 +++-- x86/access_test.c | 6 ++---- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/x86/access.c b/x86/access.c index f832385..c5e71db 100644 --- a/x86/access.c +++ b/x86/access.c @@ -14,7 +14,6 @@ static _Bool verbose = false; typedef unsigned long pt_element_t; static int invalid_mask; -int page_table_levels; #define PT_BASE_ADDR_MASK ((pt_element_t)((((pt_element_t)1 << 36) - 1) & PAGE_MASK)) #define PT_PSE_BASE_ADDR_MASK (PT_BASE_ADDR_MASK & ~(1ull << 21)) @@ -174,6 +173,7 @@ typedef struct { pt_element_t ignore_pde; int expected_fault; unsigned expected_error; + int page_table_levels; } ac_test_t; typedef struct { @@ -278,13 +278,14 @@ static void ac_env_int(ac_pool_t *pool) pool->pt_pool_current = 0; } -static void ac_test_init(ac_test_t *at, void *virt) +static void ac_test_init(ac_test_t *at, void *virt, int page_table_levels) { set_efer_nx(1); set_cr0_wp(1); at->flags = 0; at->virt = virt; at->phys = 32 * 1024 * 1024; + at->page_table_levels = page_table_levels; } static int ac_test_bump_one(ac_test_t *at) @@ -518,7 +519,7 @@ static void __ac_setup_specific_pages(ac_test_t *at, ac_pool_t *pool, bool reuse ac_test_reset_pt_pool(pool); at->ptep = 0; - for (int i = page_table_levels; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) { + for (int i = at->page_table_levels; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) { pt_element_t *vroot = va(root & PT_BASE_ADDR_MASK); unsigned index = PT_INDEX((unsigned long)at->virt, i); pt_element_t pte = 0; @@ -635,7 +636,7 @@ static void dump_mapping(ac_test_t *at) int i; printf("Dump mapping: address: %p\n", at->virt); - for (i = page_table_levels; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) { + for (i = at->page_table_levels; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) { pt_element_t *vroot = va(root & PT_BASE_ADDR_MASK); unsigned index = PT_INDEX((unsigned long)at->virt, i); pt_element_t pte = vroot[index]; @@ -812,12 +813,12 @@ static void ac_test_show(ac_test_t *at) * This test case is used to triger the bug which is fixed by * commit e09e90a5 in the kvm tree */ -static int corrupt_hugepage_triger(ac_pool_t *pool) +static int corrupt_hugepage_triger(ac_pool_t *pool, int page_table_levels) { ac_test_t at1, at2; - ac_test_init(&at1, (void *)(0x123400000000)); - ac_test_init(&at2, (void *)(0x666600000000)); + ac_test_init(&at1, (void *)(0x123400000000), page_table_levels); + ac_test_init(&at2, (void *)(0x666600000000), page_table_levels); at2.flags = AC_CPU_CR0_WP_MASK | AC_PDE_PSE_MASK | AC_PDE_PRESENT_MASK; ac_test_setup_pte(&at2, pool); @@ -850,12 +851,12 @@ err: * This test case is used to triger the bug which is fixed by * commit 3ddf6c06e13e in the kvm tree */ -static int check_pfec_on_prefetch_pte(ac_pool_t *pool) +static int check_pfec_on_prefetch_pte(ac_pool_t *pool, int page_table_levels) { ac_test_t at1, at2; - ac_test_init(&at1, (void *)(0x123406001000)); - ac_test_init(&at2, (void *)(0x123406003000)); + ac_test_init(&at1, (void *)(0x123406001000), page_table_levels); + ac_test_init(&at2, (void *)(0x123406003000), page_table_levels); at1.flags = AC_PDE_PRESENT_MASK | AC_PTE_PRESENT_MASK; ac_setup_specific_pages(&at1, pool, 30 * 1024 * 1024, 30 * 1024 * 1024); @@ -895,12 +896,12 @@ err: * * Note: to trigger this bug, hugepage should be disabled on host. */ -static int check_large_pte_dirty_for_nowp(ac_pool_t *pool) +static int check_large_pte_dirty_for_nowp(ac_pool_t *pool, int page_table_levels) { ac_test_t at1, at2; - ac_test_init(&at1, (void *)(0x123403000000)); - ac_test_init(&at2, (void *)(0x666606000000)); + ac_test_init(&at1, (void *)(0x123403000000), page_table_levels); + ac_test_init(&at2, (void *)(0x666606000000), page_table_levels); at2.flags = AC_PDE_PRESENT_MASK | AC_PDE_PSE_MASK; ac_test_setup_pte(&at2, pool); @@ -929,7 +930,7 @@ err: return 0; } -static int check_smep_andnot_wp(ac_pool_t *pool) +static int check_smep_andnot_wp(ac_pool_t *pool, int page_table_levels) { ac_test_t at1; int err_prepare_andnot_wp, err_smep_andnot_wp; @@ -938,7 +939,7 @@ static int check_smep_andnot_wp(ac_pool_t *pool) return 1; } - ac_test_init(&at1, (void *)(0x123406001000)); + ac_test_init(&at1, (void *)(0x123406001000), page_table_levels); at1.flags = AC_PDE_PRESENT_MASK | AC_PTE_PRESENT_MASK | AC_PDE_USER_MASK | AC_PTE_USER_MASK | @@ -979,7 +980,7 @@ err: return 0; } -static int check_effective_sp_permissions(ac_pool_t *pool) +static int check_effective_sp_permissions(ac_pool_t *pool, int page_table_levels) { unsigned long ptr1 = 0x123480000000; unsigned long ptr2 = ptr1 + SZ_2M; @@ -1000,22 +1001,22 @@ static int check_effective_sp_permissions(ac_pool_t *pool) * pud1 and pud2 point to the same pmd page. */ - ac_test_init(&at1, (void *)(ptr1)); + ac_test_init(&at1, (void *)(ptr1), page_table_levels); at1.flags = AC_PDE_PRESENT_MASK | AC_PTE_PRESENT_MASK | AC_PDE_USER_MASK | AC_PTE_USER_MASK | AC_PDE_ACCESSED_MASK | AC_PTE_ACCESSED_MASK | AC_PTE_WRITABLE_MASK | AC_ACCESS_USER_MASK; __ac_setup_specific_pages(&at1, pool, false, pmd, 0); - ac_test_init(&at2, (void *)(ptr2)); + ac_test_init(&at2, (void *)(ptr2), page_table_levels); at2.flags = at1.flags | AC_PDE_WRITABLE_MASK | AC_PTE_DIRTY_MASK | AC_ACCESS_WRITE_MASK; __ac_setup_specific_pages(&at2, pool, true, pmd, 0); - ac_test_init(&at3, (void *)(ptr3)); + ac_test_init(&at3, (void *)(ptr3), page_table_levels); at3.flags = AC_PDPTE_NO_WRITABLE_MASK | at1.flags; __ac_setup_specific_pages(&at3, pool, true, pmd, 0); - ac_test_init(&at4, (void *)(ptr4)); + ac_test_init(&at4, (void *)(ptr4), page_table_levels); at4.flags = AC_PDPTE_NO_WRITABLE_MASK | at2.flags; __ac_setup_specific_pages(&at4, pool, true, pmd, 0); @@ -1058,7 +1059,7 @@ static int ac_test_exec(ac_test_t *at, ac_pool_t *pool) return r; } -typedef int (*ac_test_fn)(ac_pool_t *pool); +typedef int (*ac_test_fn)(ac_pool_t *pool, int page_table_levels); const ac_test_fn ac_test_cases[] = { corrupt_hugepage_triger, @@ -1068,7 +1069,7 @@ const ac_test_fn ac_test_cases[] = check_effective_sp_permissions, }; -int ac_test_run() +int ac_test_run(int page_table_levels) { ac_test_t at; ac_pool_t pool; @@ -1134,7 +1135,8 @@ int ac_test_run() } ac_env_int(&pool); - ac_test_init(&at, (void *)(0x123400000000 + 16 * smp_id())); + ac_test_init(&at, (void *)(0x123400000000 + 16 * smp_id()), + page_table_levels); do { ++tests; successes += ac_test_exec(&at, &pool); @@ -1142,7 +1144,7 @@ int ac_test_run() for (i = 0; i < ARRAY_SIZE(ac_test_cases); i++) { ++tests; - successes += ac_test_cases[i](&pool); + successes += ac_test_cases[i](&pool, page_table_levels); } printf("\n%d tests, %d failures\n", tests, tests - successes); diff --git a/x86/access.h b/x86/access.h index 4f67b62..bcfa7b2 100644 --- a/x86/access.h +++ b/x86/access.h @@ -1,8 +1,9 @@ #ifndef X86_ACCESS_H #define X86_ACCESS_H -int ac_test_run(void); +#define PT_LEVEL_PML4 4 +#define PT_LEVEL_PML5 5 -extern int page_table_levels; +int ac_test_run(int page_table_levels); #endif // X86_ACCESS_H \ No newline at end of file diff --git a/x86/access_test.c b/x86/access_test.c index 497f286..991f333 100644 --- a/x86/access_test.c +++ b/x86/access_test.c @@ -8,14 +8,12 @@ int main(void) int r; printf("starting test\n\n"); - page_table_levels = 4; - r = ac_test_run(); + r = ac_test_run(PT_LEVEL_PML4); if (this_cpu_has(X86_FEATURE_LA57)) { - page_table_levels = 5; printf("starting 5-level paging test.\n\n"); setup_5level_page_table(); - r = ac_test_run(); + r = ac_test_run(PT_LEVEL_PML5); } return r ? 0 : 1; From patchwork Wed Nov 10 21:20:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lewis X-Patchwork-Id: 12613121 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 mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CD865C433EF for ; Wed, 10 Nov 2021 21:20:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B210F611F2 for ; Wed, 10 Nov 2021 21:20:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233520AbhKJVXr (ORCPT ); Wed, 10 Nov 2021 16:23:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51396 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233496AbhKJVXg (ORCPT ); Wed, 10 Nov 2021 16:23:36 -0500 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B402DC061230 for ; Wed, 10 Nov 2021 13:20:39 -0800 (PST) Received: by mail-pg1-x549.google.com with SMTP id v63-20020a632f42000000b002cc65837088so2157447pgv.1 for ; Wed, 10 Nov 2021 13:20:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=NlDToowUudOyKNakNM8rv9+vrJ6Y0uZ/gFEZLkAMb+4=; b=DGbTCaCzcdaTHYDKXNqd7IPLM0VycaoyhS/YNg48aoCd06J7rw+iti0RviugRo2NVS 3jRaHEOJ/BSVFyS7JWHosRYyk6mt6aOIbrGgvhE8zlewlxgg+Tk2+MTtn9By9zrstyEJ SRCA0IDvysR1axUP/BZIJmIHohwMQ3xGXgQzcOScZZx1MiLnddIyuuYHUGZgWk62fFgi vCI+VQGTO6Km8VzfFGeM4T0nYeVHBEi/mEriqYrxCTVhaIGh84zU3yb/ZZ59YhMjcs/k oksmOYfORlZmAgAgvGS3O3Fkzxxaa/bFJc/mmdUOPesGzsg+PsQK4etknn9cV0dUwx65 mGag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=NlDToowUudOyKNakNM8rv9+vrJ6Y0uZ/gFEZLkAMb+4=; b=UZZJETX/eRWdcRjnxaIJDkapp4eV9ZUBGq1458JdHmrRoM/6pqQORFhhjYXHfVjmsY +qVM2dCyuHcC+5G5Ggq9ccnTzz06e60jBLOA5i//BkpUb9CQAEySihzIZMtJhkiTm8Dw y/AWeuBLWq5MoX9fKUujmYET+iQWm85vtVXb389XCz/y1AWr9x44A/3wBqJ5zE7zIbnR kwpvrfiKk4oHxPBYWzFe4SkAvnzydvtTgkwGAU3b1zjA974eXUqTRJDDvnrBYLPZVN4u RaPY4f4I3UV+txsXoDR018/nV1cja0LhsfaQUkbVMJXT+mgWvLsP+dDaS3H0yPGNlqvX 2hnQ== X-Gm-Message-State: AOAM5302yAdhSLqQdLGX/+cgtsMd+axinzW8O0cWY+UKhSYqTSW+xQXs BdQGfVo8rzc0g3sRaHxgoEfXiNgmg5ddhbYLfl1wsUCZ25Q13HHTemXTFQQhO0oBKznVt+LfR9j UFKuS1UYYLaDNlHfzxBTn/iWPPWKbUuOXz5NLqsulzZa9RDcS0S9eqjw8Omqhw2jZmn76 X-Google-Smtp-Source: ABdhPJwn5FfpSg5rHKgry9E8WnfpM8Q0GPpMgxAeNxO7U1ss+7p+s9TBfpO1efTfgksAJX/zqpR/tcjBOITe+7A0 X-Received: from aaronlewis.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2675]) (user=aaronlewis job=sendgmr) by 2002:a17:90b:350c:: with SMTP id ls12mr2317718pjb.197.1636579239141; Wed, 10 Nov 2021 13:20:39 -0800 (PST) Date: Wed, 10 Nov 2021 21:20:01 +0000 In-Reply-To: <20211110212001.3745914-1-aaronlewis@google.com> Message-Id: <20211110212001.3745914-15-aaronlewis@google.com> Mime-Version: 1.0 References: <20211110212001.3745914-1-aaronlewis@google.com> X-Mailer: git-send-email 2.34.0.rc1.387.gb447b232ab-goog Subject: [kvm-unit-tests PATCH 14/14] x86: Add tests that run ac_test_run() in an L2 guest From: Aaron Lewis To: kvm@vger.kernel.org Cc: pbonzini@redhat.com, jmattson@google.com, seanjc@google.com, Aaron Lewis Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Add tests vmx_pf_exception_test and vmx_pf_exception_test_reduced_maxphyaddr to vmx_tests.c. The purpose of these tests are to test the reflection logic in KVM to ensure exceptions are being routed to were they are intended to go. For example, it will test that we are not accidentally reflecting exceptions into L1 when L1 isn't expecting them. Commit 18712c13709d ("KVM: nVMX: Use vmx_need_pf_intercept() when deciding if L0 wants a #PF") fixed an issue related to this which went undetected because there was no testing in place. This adds testing to ensure there is coverage for such issues. Signed-off-by: Aaron Lewis --- x86/Makefile.common | 2 ++ x86/unittests.cfg | 13 ++++++++++++ x86/vmx_tests.c | 49 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/x86/Makefile.common b/x86/Makefile.common index a665854..461de51 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -74,6 +74,8 @@ $(TEST_DIR)/realmode.o: bits = $(if $(call cc-option,-m16,""),16,32) $(TEST_DIR)/access_test.elf: $(TEST_DIR)/access.o +$(TEST_DIR)/vmx.elf: $(TEST_DIR)/access.o + $(TEST_DIR)/kvmclock_test.elf: $(TEST_DIR)/kvmclock.o $(TEST_DIR)/hyperv_synic.elf: $(TEST_DIR)/hyperv.o diff --git a/x86/unittests.cfg b/x86/unittests.cfg index dbeb8a2..4069e4c 100644 --- a/x86/unittests.cfg +++ b/x86/unittests.cfg @@ -347,6 +347,19 @@ extra_params = -cpu max,+vmx -append vmx_vmcs_shadow_test arch = x86_64 groups = vmx +[vmx_pf_exception_test] +file = vmx.flat +extra_params = -cpu max,+vmx -append vmx_pf_exception_test +arch = x86_64 +groups = vmx nested_exception + +[vmx_pf_exception_test_reduced_maxphyaddr] +file = vmx.flat +extra_params = -cpu IvyBridge,phys-bits=36,host-phys-bits=off,+vmx -append vmx_pf_exception_test +arch = x86_64 +groups = vmx nested_exception +check = /sys/module/kvm_intel/parameters/allow_smaller_maxphyaddr=Y + [debug] file = debug.flat arch = x86_64 diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c index 9ee6653..8cf3543 100644 --- a/x86/vmx_tests.c +++ b/x86/vmx_tests.c @@ -20,6 +20,7 @@ #include "alloc_page.h" #include "smp.h" #include "delay.h" +#include "access.h" #define VPID_CAP_INVVPID_TYPES_SHIFT 40 @@ -10658,6 +10659,53 @@ static void atomic_switch_overflow_msrs_test(void) test_skip("Test is only supported on KVM"); } +static void vmx_pf_exception_test_guest(void) +{ + ac_test_run(PT_LEVEL_PML4); +} + +static void vmx_pf_exception_test(void) +{ + u64 efer; + struct cpuid cpuid; + + test_set_guest(vmx_pf_exception_test_guest); + + enter_guest(); + + while (vmcs_read(EXI_REASON) != VMX_VMCALL) { + switch (vmcs_read(EXI_REASON)) { + case VMX_RDMSR: + assert(regs.rcx == MSR_EFER); + efer = vmcs_read(GUEST_EFER); + regs.rdx = efer >> 32; + regs.rax = efer & 0xffffffff; + break; + case VMX_WRMSR: + assert(regs.rcx == MSR_EFER); + efer = regs.rdx << 32 | (regs.rax & 0xffffffff); + vmcs_write(GUEST_EFER, efer); + break; + case VMX_CPUID: + cpuid = (struct cpuid) {0, 0, 0, 0}; + cpuid = raw_cpuid(regs.rax, regs.rcx); + regs.rax = cpuid.a; + regs.rbx = cpuid.b; + regs.rcx = cpuid.c; + regs.rdx = cpuid.d; + break; + default: + assert_msg(false, + "Unexpected exit to L1, exit_reason: %s (0x%lx)", + exit_reason_description(vmcs_read(EXI_REASON)), + vmcs_read(EXI_REASON)); + } + skip_exit_insn(); + enter_guest(); + } + + assert_exit_reason(VMX_VMCALL); +} #define TEST(name) { #name, .v2 = name } /* name/init/guest_main/exit_handler/syscall_handler/guest_regs */ @@ -10763,5 +10811,6 @@ struct vmx_test vmx_tests[] = { TEST(rdtsc_vmexit_diff_test), TEST(vmx_mtf_test), TEST(vmx_mtf_pdpte_test), + TEST(vmx_pf_exception_test), { NULL, NULL, NULL, NULL, NULL, {0} }, };