From patchwork Wed Apr 5 16:47:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tim Gardner X-Patchwork-Id: 1765676 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=canonical.com header.i=@canonical.com header.a=rsa-sha256 header.s=20210705 header.b=UTmnXAZW; dkim-atps=neutral Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Ps9Y10H7Fz1yZj for ; Thu, 6 Apr 2023 02:47:47 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1pk6IN-0001uG-Hk; Wed, 05 Apr 2023 16:47:39 +0000 Received: from smtp-relay-internal-0.internal ([10.131.114.225] helo=smtp-relay-internal-0.canonical.com) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1pk6IL-0001to-9n for kernel-team@lists.ubuntu.com; Wed, 05 Apr 2023 16:47:37 +0000 Received: from mail-pl1-f199.google.com (mail-pl1-f199.google.com [209.85.214.199]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id 4B13B3F1EE for ; Wed, 5 Apr 2023 16:47:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1680713256; bh=DzFnDTAjSgmvl+zyMeH3hQaBU2KrkIZ5wOiIvxqz0Nk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UTmnXAZWqthN5+eW20HqlSgU98wEqWrb7YJmFgolsvNIsawLCpjiRz3e0OdxUZKK/ U7dHzjHPxxdib+dXiIDIf8iaww1gQYh6Z1p1iSoTaG6/qfH9qrndFHeZK7q9KKtFrs fUNdG46K9KF1HptNhnsgqPzrKF5iPQ+FvqZ1ZPf3liEhAWEnAz4FaPUeeInsaZ8tCS A9sDEa56N/l5399gJwB/NMUO55tj7q4gvT0rDnanzbXUUOmO7CVGBRNUojeUJync0W G19P/MahrTQP2wIO9p/gfD/AcVW6wakCmZiT3mlLy6Ac8pcHHNCkq+SKb0gOQwZNGw zP0cgE+SSOODg== Received: by mail-pl1-f199.google.com with SMTP id d2-20020a170902cec200b001a1e8390831so21109884plg.5 for ; Wed, 05 Apr 2023 09:47:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680713254; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DzFnDTAjSgmvl+zyMeH3hQaBU2KrkIZ5wOiIvxqz0Nk=; b=PXDFdZLRU3yXycNZjs8aBuGxbJXJIjyxo7M5ZyYtvHZf/4ayJaPzhs/ZBFsQ6p4qdm zQPrCKVXmm/4DkPr4Ebi5O8wkwgrCisfS1Po4vGDuvgIa4RY/DT2ohMdglPjBElLJovy saa99PBwgN9B7ZPmgRl3TL5lDJ4c2gg8Zcco6OZj8kZwF7bTGVgd3BHWrZlhQKpVcWqR 2H9bkGue/hMAPrPFgTmFBdk8xn8gJXUQVW8ARFFqhROTXq8c4AldURfP2RG7cx9Zac3G /pR8JDuhmEUtgCSI+1dWnXiCXik+/8dOVJFc0Bjbgkpgb0tKUx58cnrVMVFPDVhLehWX AbPw== X-Gm-Message-State: AAQBX9erlu1BPwkKmACVar6XDtC6RjjR1KvlFQFBg5gXQl8keR2q6As5 8iUX2VindMETdLtYpOca+nnL/KwniJ4FDXjzd6MqZwQMYighdRHx5aQZTTexvp3jaUjOevPNBRl OxejVY7QsWK0dvePYLcoACXbtzbmK/PVZoEscrEIaXzMurOSFzw== X-Received: by 2002:a17:903:41ca:b0:19a:839f:435 with SMTP id u10-20020a17090341ca00b0019a839f0435mr3391227ple.3.1680713253843; Wed, 05 Apr 2023 09:47:33 -0700 (PDT) X-Google-Smtp-Source: AKy350a4v4HL+yEXMgHzi2qhK+8p/uMi8ManPF5NBfCfLGnjpePjT6TICS5y9L7HCrNq/jO+udrM4Q== X-Received: by 2002:a17:903:41ca:b0:19a:839f:435 with SMTP id u10-20020a17090341ca00b0019a839f0435mr3391215ple.3.1680713253511; Wed, 05 Apr 2023 09:47:33 -0700 (PDT) Received: from smtp.gmail.com ([69.163.84.166]) by smtp.gmail.com with ESMTPSA id on13-20020a17090b1d0d00b0023493354f37sm1622119pjb.26.2023.04.05.09.47.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 09:47:33 -0700 (PDT) From: Tim Gardner To: kernel-team@lists.ubuntu.com Subject: [PATCH][jammy/linux-azure] x86/ioremap: Add hypervisor callback for private MMIO mapping in coco VM Date: Wed, 5 Apr 2023 10:47:28 -0600 Message-Id: <20230405164729.1280155-2-tim.gardner@canonical.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230405164729.1280155-1-tim.gardner@canonical.com> References: <20230405164729.1280155-1-tim.gardner@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Michael Kelley BugLink: https://bugs.launchpad.net/bugs/2015369 Current code always maps MMIO devices as shared (decrypted) in a confidential computing VM. But Hyper-V guest VMs on AMD SEV-SNP with vTOM use a paravisor running in VMPL0 to emulate some devices, such as the IO-APIC and TPM. In such a case, the device must be accessed as private (encrypted) because the paravisor emulates the device at an address below vTOM, where all accesses are encrypted. Add a new hypervisor callback to determine if an MMIO address should be mapped private. The callback allows hypervisor-specific code to handle any quirks, the use of a paravisor, etc. in determining whether a mapping must be private. If the callback is not used by a hypervisor, default to returning "false", which is consistent with normal coco VM behavior. Use this callback as another special case to check for when doing ioremap(). Just checking the starting address is sufficient as an ioremap range must be all private or all shared. Also make the callback in early boot IO-APIC mapping code that uses the fixmap. [ bp: Touchups. ] Signed-off-by: Michael Kelley Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/1678329614-3482-2-git-send-email-mikelley@microsoft.com (backported from commit 88e378d400fa0544d51cf62037e7774d8a4b4379 linux-next) [rtg - context adjustment, replace calls to set_fixmap_nocache() with io_apic_set_fixmap()] Signed-off-by: Tim Gardner --- arch/x86/include/asm/x86_init.h | 4 ++++ arch/x86/kernel/apic/io_apic.c | 23 +++++++++++++++++++++-- arch/x86/kernel/x86_init.c | 3 +++ arch/x86/mm/ioremap.c | 5 +++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 5c69f7eb5d47..6d3ec719abee 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -244,11 +244,15 @@ struct x86_legacy_features { * VMMCALL under SEV-ES. Needs to return 'false' * if the checks fail. Called from the #VC * exception handler. + * @is_private_mmio: For CoCo VMs, must map MMIO address as private. + * Used when device is emulated by a paravisor + * layer in the VM context. */ struct x86_hyper_runtime { void (*pin_vcpu)(int cpu); void (*sev_es_hcall_prepare)(struct ghcb *ghcb, struct pt_regs *regs); bool (*sev_es_hcall_finish)(struct ghcb *ghcb, struct pt_regs *regs); + bool (*is_private_mmio)(u64 addr); }; /** diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index c1bb384935b0..d0d7b8432509 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -65,6 +65,7 @@ #include #include #include +#include #define for_each_ioapic(idx) \ for ((idx) = 0; (idx) < nr_ioapics; (idx)++) @@ -2677,6 +2678,24 @@ static struct resource * __init ioapic_setup_resources(void) return res; } +static void io_apic_set_fixmap(enum fixed_addresses idx, phys_addr_t phys) +{ + pgprot_t flags = FIXMAP_PAGE_NOCACHE; + + /* + * Ensure fixmaps for IO-APIC MMIO respect memory encryption pgprot + * bits, just like normal ioremap(): + */ + if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) { + if (x86_platform.hyper.is_private_mmio(phys)) + flags = pgprot_encrypted(flags); + else + flags = pgprot_decrypted(flags); + } + + __set_fixmap(idx, phys, flags); +} + void __init io_apic_init_mappings(void) { unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; @@ -2709,7 +2728,7 @@ void __init io_apic_init_mappings(void) __func__, PAGE_SIZE, PAGE_SIZE); ioapic_phys = __pa(ioapic_phys); } - set_fixmap_nocache(idx, ioapic_phys); + io_apic_set_fixmap(idx, ioapic_phys); apic_printk(APIC_VERBOSE, "mapped IOAPIC to %08lx (%08lx)\n", __fix_to_virt(idx) + (ioapic_phys & ~PAGE_MASK), ioapic_phys); @@ -2838,7 +2857,7 @@ int mp_register_ioapic(int id, u32 address, u32 gsi_base, ioapics[idx].mp_config.flags = MPC_APIC_USABLE; ioapics[idx].mp_config.apicaddr = address; - set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); + io_apic_set_fixmap(FIX_IO_APIC_BASE_0 + idx, address); if (bad_ioapic_register(idx)) { clear_fixmap(FIX_IO_APIC_BASE_0 + idx); return -ENODEV; diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 8b395821cb8d..e1c28902d062 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -129,6 +129,8 @@ struct x86_cpuinit_ops x86_cpuinit = { static void default_nmi_init(void) { }; +static bool is_private_mmio_noop(u64 addr) {return false; } + struct x86_platform_ops x86_platform __ro_after_init = { .calibrate_cpu = native_calibrate_cpu_early, .calibrate_tsc = native_calibrate_tsc, @@ -141,6 +143,7 @@ struct x86_platform_ops x86_platform __ro_after_init = { .save_sched_clock_state = tsc_save_sched_clock_state, .restore_sched_clock_state = tsc_restore_sched_clock_state, .hyper.pin_vcpu = x86_op_int_noop, + .hyper.is_private_mmio = is_private_mmio_noop, }; EXPORT_SYMBOL_GPL(x86_platform); diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 58c2fcfa9774..e87b4df0dc4f 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -115,6 +115,11 @@ static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *des if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) return; + if (x86_platform.hyper.is_private_mmio(addr)) { + desc->flags |= IORES_MAP_ENCRYPTED; + return; + } + if (!IS_ENABLED(CONFIG_EFI)) return;