diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f9920f1341c8d..09973d0d8fb53 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -869,6 +869,7 @@ config INTEL_TDX_GUEST select ARCH_HAS_CC_PLATFORM select X86_MEM_ENCRYPT select X86_MCE + select IOMAP_IND_MMIO help Support running as a guest under Intel TDX. Without this support, the guest kernel can not boot or run under TDX. diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index c4f1936868cc8..c5e546d4b124c 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -480,6 +480,102 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve) return insn.length; } +static unsigned long tdx_virt_mmio(int size, bool write, unsigned long vaddr, + unsigned long* val) +{ + pte_t* pte; + int level; + + pte = lookup_address(vaddr, &level); + if (!pte) + return -EIO; + + return write ? + mmio_write(size, + (pte_pfn(*pte) << PAGE_SHIFT) + + (vaddr & ~page_level_mask(level)), + *val) : + mmio_read(size, + (pte_pfn(*pte) << PAGE_SHIFT) + + (vaddr & ~page_level_mask(level)), + val); +} + +static unsigned char tdx_mmio_readb(void __iomem* addr) +{ + unsigned long val; + + if (tdx_virt_mmio(1, false, (unsigned long)addr, &val)) + return 0xff; + return val; +} + +static unsigned short tdx_mmio_readw(void __iomem* addr) +{ + unsigned long val; + + if (tdx_virt_mmio(2, false, (unsigned long)addr, &val)) + return 0xffff; + return val; +} + +static unsigned int tdx_mmio_readl(void __iomem* addr) +{ + unsigned long val; + + if (tdx_virt_mmio(4, false, (unsigned long)addr, &val)) + return 0xffffffff; + return val; +} + +unsigned long tdx_mmio_readq(void __iomem* addr) +{ + unsigned long val; + + if (tdx_virt_mmio(8, false, (unsigned long)addr, &val)) + return 0xffffffffffffffff; + return val; +} + +static void tdx_mmio_writeb(unsigned char v, void __iomem* addr) +{ + unsigned long val = v; + + tdx_virt_mmio(1, true, (unsigned long)addr, &val); +} + +static void tdx_mmio_writew(unsigned short v, void __iomem* addr) +{ + unsigned long val = v; + + tdx_virt_mmio(2, true, (unsigned long)addr, &val); +} + +static void tdx_mmio_writel(unsigned int v, void __iomem* addr) +{ + unsigned long val = v; + + tdx_virt_mmio(4, true, (unsigned long)addr, &val); +} + +static void tdx_mmio_writeq(unsigned long v, void __iomem* addr) +{ + unsigned long val = v; + + tdx_virt_mmio(8, true, (unsigned long)addr, &val); +} + +static const struct iomap_mmio tdx_iomap_mmio = { + .ireadb = tdx_mmio_readb, + .ireadw = tdx_mmio_readw, + .ireadl = tdx_mmio_readl, + .ireadq = tdx_mmio_readq, + .iwriteb = tdx_mmio_writeb, + .iwritew = tdx_mmio_writew, + .iwritel = tdx_mmio_writel, + .iwriteq = tdx_mmio_writeq, +}; + static bool handle_in(struct pt_regs *regs, int size, int port) { struct tdx_hypercall_args args = { @@ -817,6 +913,8 @@ void __init tdx_early_init(void) */ random_enable_trust_cpu(); + iomap_mmio = &tdx_iomap_mmio; + /* * Make sure there is a panic if something goes wrong, * just in case it's some kind of host attack.