From: Alexey Gladkov <legion@kernel.org>
To: linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev
Cc: "Alexey Gladkov (Intel)" <legion@kernel.org>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
"H. Peter Anvin" <hpa@zytor.com>,
"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>,
Andrew Morton <akpm@linux-foundation.org>,
Yuan Yao <yuan.yao@intel.com>,
Geert Uytterhoeven <geert@linux-m68k.org>,
Yuntao Wang <ytcoode@gmail.com>, Kai Huang <kai.huang@intel.com>,
Baoquan He <bhe@redhat.com>, Oleg Nesterov <oleg@redhat.com>,
cho@microsoft.com, decui@microsoft.com,
John.Starks@microsoft.com
Subject: [PATCH v7 6/6] x86/tdx: Implement MOVS for MMIO
Date: Fri, 13 Sep 2024 19:06:01 +0200 [thread overview]
Message-ID: <6f901828e66b30d7aff5c64dd7c57f2cf922be7e.1726237595.git.legion@kernel.org> (raw)
In-Reply-To: <cover.1726237595.git.legion@kernel.org>
From: "Alexey Gladkov (Intel)" <legion@kernel.org>
Add emulation of the MOVS instruction on MMIO regions. MOVS emulation
consists of dividing it into a series of read and write operations,
which in turn will be validated separately.
This implementation is based on the same principle as in SEV. It splits
MOVS into separate read and write operations, which in turn can cause
nested #VEs depending on which of the arguments caused the first #VE.
The difference with the SEV implementation is the execution context. SEV
code is executed in atomic context. Exception handler in TDX is executed
with interrupts enabled. That's why the approach to locking is
different. In TDX, mmap_lock is taken to verify and emulate the
instruction.
Another difference is how the read and write instructions are executed
for MOVS emulation. While in SEV each read/write operation returns to
user space, in TDX these operations are performed from the kernel
context.
It may be possible to achieve more code reuse at this point,
but it would require confirmation from SEV that such a thing wouldn't
break anything.
Reviewed-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Alexey Gladkov (Intel) <legion@kernel.org>
---
arch/x86/coco/tdx/tdx.c | 82 ++++++++++++++++++++++++++++----
arch/x86/include/asm/processor.h | 1 +
2 files changed, 75 insertions(+), 8 deletions(-)
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index dffc343e64d7..151e63083a13 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -514,6 +514,60 @@ static int decode_insn_struct(struct insn *insn, struct pt_regs *regs)
return 0;
}
+static int handle_mmio_movs(struct insn *insn, struct pt_regs *regs, int size, struct ve_info *ve)
+{
+ unsigned long ds_base, es_base;
+ unsigned char *src, *dst;
+ unsigned char buffer[8];
+ int off, ret;
+ bool rep;
+
+ /*
+ * The in-kernel code must use a special API that does not use MOVS.
+ * If the MOVS instruction is received from in-kernel, then something
+ * is broken.
+ */
+ if (WARN_ON_ONCE(!user_mode(regs)))
+ return -EFAULT;
+
+ ds_base = insn_get_seg_base(regs, INAT_SEG_REG_DS);
+ es_base = insn_get_seg_base(regs, INAT_SEG_REG_ES);
+
+ if (ds_base == -1L || es_base == -1L)
+ return -EINVAL;
+
+ current->thread.in_mmio_emul = 1;
+
+ rep = insn_has_rep_prefix(insn);
+
+ do {
+ src = ds_base + (unsigned char *) regs->si;
+ dst = es_base + (unsigned char *) regs->di;
+
+ ret = __get_iomem(src, buffer, size);
+ if (ret)
+ goto out;
+
+ ret = __put_iomem(dst, buffer, size);
+ if (ret)
+ goto out;
+
+ off = (regs->flags & X86_EFLAGS_DF) ? -size : size;
+
+ regs->si += off;
+ regs->di += off;
+
+ if (rep)
+ regs->cx -= 1;
+ } while (rep || regs->cx > 0);
+
+ ret = insn->length;
+out:
+ current->thread.in_mmio_emul = 0;
+
+ return ret;
+}
+
static int handle_mmio_write(struct insn *insn, enum insn_mmio_type mmio, int size,
struct pt_regs *regs, struct ve_info *ve)
{
@@ -535,9 +589,8 @@ static int handle_mmio_write(struct insn *insn, enum insn_mmio_type mmio, int si
return insn->length;
case INSN_MMIO_MOVS:
/*
- * MMIO was accessed with an instruction that could not be
- * decoded or handled properly. It was likely not using io.h
- * helpers or accessed MMIO accidentally.
+ * MOVS is processed through higher level emulation which breaks
+ * this instruction into a sequence of reads and writes.
*/
return -EINVAL;
default:
@@ -596,6 +649,7 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
{
enum insn_mmio_type mmio;
struct insn insn = {};
+ int need_validation;
unsigned long vaddr;
int size, ret;
@@ -607,14 +661,27 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
if (WARN_ON_ONCE(mmio == INSN_MMIO_DECODE_FAILED))
return -EINVAL;
+ if (mmio == INSN_MMIO_MOVS)
+ return handle_mmio_movs(&insn, regs, size, ve);
+
+ need_validation = user_mode(regs);
+
if (!user_mode(regs) && !fault_in_kernel_space(ve->gla)) {
- WARN_ONCE(1, "Access to userspace address is not supported");
- return -EINVAL;
+ /*
+ * Access from kernel to userspace addresses is not allowed
+ * unless it is a nested exception during MOVS emulation.
+ */
+ if (!current->thread.in_mmio_emul || !current->mm) {
+ WARN_ONCE(1, "Access to userspace address is not supported");
+ return -EINVAL;
+ }
+
+ need_validation = 1;
}
vaddr = (unsigned long)insn_get_addr_ref(&insn, regs);
- if (user_mode(regs)) {
+ if (need_validation) {
if (mmap_read_lock_killable(current->mm))
return -EINTR;
@@ -640,7 +707,6 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
switch (mmio) {
case INSN_MMIO_WRITE:
case INSN_MMIO_WRITE_IMM:
- case INSN_MMIO_MOVS:
ret = handle_mmio_write(&insn, mmio, size, regs, ve);
break;
case INSN_MMIO_READ:
@@ -661,7 +727,7 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
ret = -EINVAL;
}
unlock:
- if (user_mode(regs))
+ if (need_validation)
mmap_read_unlock(current->mm);
return ret;
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index a75a07f4931f..57605b11b06c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -486,6 +486,7 @@ struct thread_struct {
unsigned long iopl_emul;
unsigned int iopl_warn:1;
+ unsigned int in_mmio_emul:1;
/*
* Protection Keys Register for Userspace. Loaded immediately on
--
2.46.0
prev parent reply other threads:[~2024-09-13 17:06 UTC|newest]
Thread overview: 109+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-30 17:35 [PATCH v1 0/4] x86/tdx: Allow MMIO instructions from userspace Alexey Gladkov (Intel)
2024-07-30 17:35 ` [PATCH v1 1/4] x86/tdx: Split MMIO read and write operations Alexey Gladkov (Intel)
2024-07-30 18:31 ` Thomas Gleixner
2024-08-05 12:48 ` Alexey Gladkov
2024-07-30 17:35 ` [PATCH v1 2/4] x86/tdx: Add validation of userspace MMIO instructions Alexey Gladkov (Intel)
2024-07-30 18:34 ` Thomas Gleixner
2024-08-02 7:41 ` Kirill A. Shutemov
2024-08-05 12:50 ` Alexey Gladkov
2024-07-30 17:35 ` [PATCH v1 3/4] x86/tdx: Allow MMIO from userspace Alexey Gladkov (Intel)
2024-07-30 18:36 ` Thomas Gleixner
2024-07-30 17:35 ` [PATCH v1 4/4] x86/tdx: Implement movs for MMIO Alexey Gladkov (Intel)
2024-07-30 18:41 ` Thomas Gleixner
2024-08-05 12:51 ` Alexey Gladkov
2024-08-05 13:29 ` [PATCH v2 0/5] x86/tdx: Allow MMIO instructions from userspace Alexey Gladkov (Intel)
2024-08-05 13:29 ` [PATCH v2 1/5] x86/tdx: Split MMIO read and write operations Alexey Gladkov (Intel)
2024-08-05 13:29 ` [PATCH v2 2/5] x86/tdx: Add validation of userspace MMIO instructions Alexey Gladkov (Intel)
2024-08-05 22:40 ` Edgecombe, Rick P
2024-08-06 7:18 ` kirill.shutemov
2024-08-06 11:11 ` Alexey Gladkov
2024-08-06 11:41 ` Reshetova, Elena
2024-08-08 15:56 ` Alexey Gladkov
2024-08-08 15:53 ` Alexey Gladkov
2024-08-08 15:42 ` [PATCH v3 6/7] x86/tdx: Add a restriction on access to MMIO address Alexey Gladkov (Intel)
2024-08-08 15:42 ` [PATCH v3 7/7] x86/tdx: Avoid crossing the page boundary Alexey Gladkov (Intel)
2024-08-05 13:29 ` [PATCH v2 3/5] x86/tdx: Allow MMIO from userspace Alexey Gladkov (Intel)
2024-08-05 13:29 ` [PATCH v2 4/5] x86/tdx: Move MMIO helpers to common library Alexey Gladkov (Intel)
2024-08-05 13:29 ` [PATCH v2 5/5] x86/tdx: Implement movs for MMIO Alexey Gladkov (Intel)
2024-08-08 13:48 ` Tom Lendacky
2024-08-08 15:42 ` Alexey Gladkov
2024-08-08 16:53 ` Alexey Gladkov
2024-08-16 13:43 ` [PATCH v3 00/10] x86/tdx: Allow MMIO instructions from userspace Alexey Gladkov
2024-08-16 13:43 ` [PATCH v3 01/10] x86/tdx: Split MMIO read and write operations Alexey Gladkov
2024-08-19 10:19 ` Kirill A. Shutemov
2024-08-16 13:43 ` [PATCH v3 02/10] x86/tdx: Add validation of userspace MMIO instructions Alexey Gladkov
2024-08-19 10:39 ` Kirill A. Shutemov
2024-08-19 11:48 ` Alexey Gladkov
2024-08-19 12:07 ` Kirill A. Shutemov
2024-08-19 12:39 ` Alexey Gladkov
2024-08-16 13:43 ` [PATCH v3 03/10] x86/tdx: Allow MMIO from userspace Alexey Gladkov
2024-08-19 10:46 ` Kirill A. Shutemov
2024-08-19 11:50 ` Alexey Gladkov
2024-08-16 13:43 ` [PATCH v3 04/10] x86/insn: Read and decode insn without crossing the page boundary Alexey Gladkov
2024-08-17 3:28 ` kernel test robot
2024-08-19 10:48 ` Kirill A. Shutemov
2024-08-19 11:56 ` Alexey Gladkov
2024-08-19 12:08 ` Kirill A. Shutemov
2024-08-16 13:43 ` [PATCH v3 05/10] x86/tdx: Avoid " Alexey Gladkov
2024-08-16 13:43 ` [PATCH v3 06/10] x86/sev: " Alexey Gladkov
2024-08-16 13:43 ` [PATCH v3 07/10] x86/umip: " Alexey Gladkov
2024-08-16 13:43 ` [PATCH v3 08/10] x86/tdx: Add a restriction on access to MMIO address Alexey Gladkov
2024-08-16 13:43 ` [PATCH v3 09/10] x86/tdx: Move MMIO helpers to common library Alexey Gladkov
2024-08-16 13:44 ` [PATCH v3 10/10] x86/tdx: Implement movs for MMIO Alexey Gladkov
2024-08-21 14:24 ` [PATCH v4 0/6] x86/tdx: Allow MMIO instructions from userspace Alexey Gladkov
2024-08-21 14:24 ` [PATCH v4 1/6] x86/tdx: Split MMIO read and write operations Alexey Gladkov
2024-08-21 14:24 ` [PATCH v4 2/6] x86/tdx: Add validation of userspace MMIO instructions Alexey Gladkov
2024-08-22 7:16 ` Kirill A. Shutemov
2024-08-21 14:24 ` [PATCH v4 3/6] x86/tdx: Allow MMIO from userspace Alexey Gladkov
2024-08-22 7:18 ` Kirill A. Shutemov
2024-08-21 14:24 ` [PATCH v4 4/6] x86/tdx: Add a restriction on access to MMIO address Alexey Gladkov
2024-08-22 8:18 ` Kirill A. Shutemov
2024-08-21 14:24 ` [PATCH v4 5/6] x86/tdx: Move MMIO helpers to common library Alexey Gladkov
2024-08-22 8:23 ` Kirill A. Shutemov
2024-08-21 14:24 ` [PATCH v4 6/6] x86/tdx: Implement movs for MMIO Alexey Gladkov
2024-08-22 8:28 ` Kirill A. Shutemov
2024-08-24 16:57 ` Alexey Gladkov
2024-08-28 10:44 ` [PATCH v5 0/6] x86/tdx: Allow MMIO instructions from userspace Alexey Gladkov
2024-08-28 10:44 ` [PATCH v5 1/6] x86/tdx: Split MMIO read and write operations Alexey Gladkov
2024-08-28 10:44 ` [PATCH v5 2/6] x86/tdx: Add validation of userspace MMIO instructions Alexey Gladkov
2024-08-28 10:44 ` [PATCH v5 3/6] x86/tdx: Allow MMIO from userspace Alexey Gladkov
2024-08-28 10:44 ` [PATCH v5 4/6] x86/tdx: Add a restriction on access to MMIO address Alexey Gladkov
2024-08-29 12:30 ` Kirill A. Shutemov
2024-08-28 10:44 ` [PATCH v5 5/6] x86/tdx: Move MMIO helpers to common library Alexey Gladkov
2024-08-28 10:44 ` [PATCH v5 6/6] x86/tdx: Implement MOVS for MMIO Alexey Gladkov
2024-08-29 12:44 ` Kirill A. Shutemov
2024-08-29 18:40 ` Alexey Gladkov
2024-09-09 9:17 ` Kirill A. Shutemov
2024-09-06 11:49 ` [PATCH v6 0/6] x86/tdx: Allow MMIO instructions from userspace Alexey Gladkov
2024-09-06 11:49 ` [PATCH v6 1/6] x86/tdx: Fix "in-kernel MMIO" check Alexey Gladkov
2024-09-10 19:54 ` Dave Hansen
2024-09-11 12:08 ` Alexey Gladkov
2024-09-11 13:03 ` Kirill A. Shutemov
2024-09-10 19:59 ` Kirill A. Shutemov
2024-09-06 11:50 ` [PATCH v6 2/6] x86/tdx: Split MMIO read and write operations Alexey Gladkov
2024-09-06 11:50 ` [PATCH v6 3/6] x86/tdx: Add validation of userspace MMIO instructions Alexey Gladkov
2024-09-06 11:50 ` [PATCH v6 4/6] x86/tdx: Allow MMIO from userspace Alexey Gladkov
2024-09-06 11:50 ` [PATCH v6 5/6] x86/tdx: Move MMIO helpers to common library Alexey Gladkov
2024-09-09 9:19 ` Kirill A. Shutemov
2024-09-06 11:50 ` [PATCH v6 6/6] x86/tdx: Implement MOVS for MMIO Alexey Gladkov
2024-09-09 9:24 ` Kirill A. Shutemov
2024-09-06 16:19 ` [PATCH v6 0/6] x86/tdx: Allow MMIO instructions from userspace Dave Hansen
2024-09-06 21:13 ` Sean Christopherson
2024-09-11 15:38 ` Dave Hansen
2024-09-11 16:19 ` Sean Christopherson
2024-09-12 9:45 ` Kirill A. Shutemov
2024-09-12 15:49 ` Dave Hansen
2024-09-13 15:53 ` Kirill A. Shutemov
2024-09-13 16:01 ` Dave Hansen
2024-09-13 16:28 ` Sean Christopherson
2024-09-13 16:47 ` Dave Hansen
2024-09-13 17:39 ` Sean Christopherson
2024-09-13 17:05 ` [PATCH v7 " Alexey Gladkov
2024-09-13 17:05 ` [PATCH v7 1/6] x86/tdx: Fix "in-kernel MMIO" check Alexey Gladkov
2024-09-13 17:18 ` Dave Hansen
2024-09-13 17:23 ` Dave Hansen
2024-09-13 17:05 ` [PATCH v7 2/6] x86/tdx: Split MMIO read and write operations Alexey Gladkov
2024-09-13 17:05 ` [PATCH v7 3/6] x86/tdx: Add validation of userspace MMIO instructions Alexey Gladkov
2024-09-13 17:05 ` [PATCH v7 4/6] x86/tdx: Allow MMIO from userspace Alexey Gladkov
2024-09-13 17:06 ` [PATCH v7 5/6] x86/tdx: Move MMIO helpers to common library Alexey Gladkov
2024-09-13 17:06 ` Alexey Gladkov [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6f901828e66b30d7aff5c64dd7c57f2cf922be7e.1726237595.git.legion@kernel.org \
--to=legion@kernel.org \
--cc=John.Starks@microsoft.com \
--cc=akpm@linux-foundation.org \
--cc=bhe@redhat.com \
--cc=bp@alien8.de \
--cc=cho@microsoft.com \
--cc=dave.hansen@linux.intel.com \
--cc=decui@microsoft.com \
--cc=geert@linux-m68k.org \
--cc=hpa@zytor.com \
--cc=kai.huang@intel.com \
--cc=kirill.shutemov@linux.intel.com \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=oleg@redhat.com \
--cc=tglx@linutronix.de \
--cc=ytcoode@gmail.com \
--cc=yuan.yao@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).