Skip to content

Commit 88e378d

Browse files
kelleymhbp3tk0v
authored andcommitted
x86/ioremap: Add hypervisor callback for private MMIO mapping in coco VM
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 <mikelley@microsoft.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/r/1678329614-3482-2-git-send-email-mikelley@microsoft.com
1 parent 0144e3b commit 88e378d

4 files changed

Lines changed: 19 additions & 2 deletions

File tree

arch/x86/include/asm/x86_init.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,11 +259,15 @@ struct x86_legacy_features {
259259
* VMMCALL under SEV-ES. Needs to return 'false'
260260
* if the checks fail. Called from the #VC
261261
* exception handler.
262+
* @is_private_mmio: For CoCo VMs, must map MMIO address as private.
263+
* Used when device is emulated by a paravisor
264+
* layer in the VM context.
262265
*/
263266
struct x86_hyper_runtime {
264267
void (*pin_vcpu)(int cpu);
265268
void (*sev_es_hcall_prepare)(struct ghcb *ghcb, struct pt_regs *regs);
266269
bool (*sev_es_hcall_finish)(struct ghcb *ghcb, struct pt_regs *regs);
270+
bool (*is_private_mmio)(u64 addr);
267271
};
268272

269273
/**

arch/x86/kernel/apic/io_apic.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
#include <asm/hw_irq.h>
6767
#include <asm/apic.h>
6868
#include <asm/pgtable.h>
69+
#include <asm/x86_init.h>
6970

7071
#define for_each_ioapic(idx) \
7172
for ((idx) = 0; (idx) < nr_ioapics; (idx)++)
@@ -2680,10 +2681,15 @@ static void io_apic_set_fixmap(enum fixed_addresses idx, phys_addr_t phys)
26802681
pgprot_t flags = FIXMAP_PAGE_NOCACHE;
26812682

26822683
/*
2683-
* Ensure fixmaps for IOAPIC MMIO respect memory encryption pgprot
2684+
* Ensure fixmaps for IO-APIC MMIO respect memory encryption pgprot
26842685
* bits, just like normal ioremap():
26852686
*/
2686-
flags = pgprot_decrypted(flags);
2687+
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
2688+
if (x86_platform.hyper.is_private_mmio(phys))
2689+
flags = pgprot_encrypted(flags);
2690+
else
2691+
flags = pgprot_decrypted(flags);
2692+
}
26872693

26882694
__set_fixmap(idx, phys, flags);
26892695
}

arch/x86/kernel/x86_init.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ static void enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool
134134
static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return false; }
135135
static bool enc_tlb_flush_required_noop(bool enc) { return false; }
136136
static bool enc_cache_flush_required_noop(void) { return false; }
137+
static bool is_private_mmio_noop(u64 addr) {return false; }
137138

138139
struct x86_platform_ops x86_platform __ro_after_init = {
139140
.calibrate_cpu = native_calibrate_cpu_early,
@@ -149,6 +150,7 @@ struct x86_platform_ops x86_platform __ro_after_init = {
149150
.realmode_reserve = reserve_real_mode,
150151
.realmode_init = init_real_mode,
151152
.hyper.pin_vcpu = x86_op_int_noop,
153+
.hyper.is_private_mmio = is_private_mmio_noop,
152154

153155
.guest = {
154156
.enc_status_change_prepare = enc_status_change_prepare_noop,

arch/x86/mm/ioremap.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *des
116116
if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
117117
return;
118118

119+
if (x86_platform.hyper.is_private_mmio(addr)) {
120+
desc->flags |= IORES_MAP_ENCRYPTED;
121+
return;
122+
}
123+
119124
if (!IS_ENABLED(CONFIG_EFI))
120125
return;
121126

0 commit comments

Comments
 (0)