From: "Michael S. Tsirkin" <mst@redhat.com>
To: zhaoguohan@kylinos.cn
Cc: bp@alien8.de, dave.hansen@linux.intel.com, eperezma@redhat.com,
hpa@zytor.com, jasowang@redhat.com, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org, mingo@redhat.com,
netdev@vger.kernel.org, tglx@kernel.org,
virtualization@lists.linux.dev, x86@kernel.org
Subject: Re: [PATCH RFC] vhost: set dirty log bits without pinning pages on x86
Date: Fri, 13 Nov 2026 08:51:38 -0500 [thread overview]
Message-ID: <20261113083351-mutt-send-email-mst@kernel.org> (raw)
In-Reply-To: <20261113012937.40818-1-zhaoguohan@kylinos.cn>
On Fri, Nov 13, 2026 at 09:29:37AM +0800, zhaoguohan@kylinos.cn wrote:
> On Thu, Nov 12, 2026 at 05:53:47AM -0500, Michael S. Tsirkin wrote:
> > vhost had a TODO to replace page pinning with a version
> > of set_bit that works on userspace memory, since forever.
> >
> > It is really best to avoid GUP on fast path entirely.
> > Implement set_user_bit and use it in vhost, to do just that.
> [...]
> > lightly tested. pls test and resubmit with your tool.
>
> Thanks, this is much simpler than my version. Two comments on
> set_bit_user() before I resubmit:
>
> > + int __err = 0; \
> > + __uaccess_begin(); \
> > + asm volatile("\n" \
> > + "1: " LOCK_PREFIX "orb %[mask], %[ptr]\n" \
> > + "2:\n" \
> > + _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, \
> > + %[errout]) \
> > + : [errout] "=r" (__err), \
> > + [ptr] "+m" (*(u8 __user *)(addr)) \
>
> errout is only written on the fixup path, so it needs "+r", as in
> __try_cmpxchg_user_asm(). With "=r" gcc drops the initialisation; here
> (gcc 13.3, x86_64_defconfig) it even shares a register with mask:
>
> 1a3: lock or %dl,(%rax)
> 1a9: test %edx,%edx
> 1ab: jne 1bd <log_write+0x5d>
> ...
> 1bd: mov $0xfffffff2,%eax
>
> so every call returns -EFAULT, and log_write() stops after the first
> page.
>
> > + __uaccess_begin(); \
>
> No access_ok() here. vhost checks the log range when it is set up and
> I couldn't find a way around that, but GUP used to reject kernel
> addresses by itself. user_access_begin() would keep the check (and the
> nospec barrier) local. Something like this, build-tested on x86_64 and
> i386 only:
>
> diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
> --- a/arch/x86/include/asm/uaccess.h
> +++ b/arch/x86/include/asm/uaccess.h
> @@ -597,19 +597,23 @@ _label: \
> /* set_bit() on a byte of user memory; returns -EFAULT on fault. */
> #define set_bit_user(nr, addr) \
> ({ \
> - int __err = 0; \
> - __uaccess_begin(); \
> - asm volatile("\n" \
> - "1: " LOCK_PREFIX "orb %[mask], %[ptr]\n" \
> - "2:\n" \
> - _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, \
> - %[errout]) \
> - : [errout] "=r" (__err), \
> - [ptr] "+m" (*(u8 __user *)(addr)) \
> - : [mask] "q" ((unsigned char)BIT(nr)) \
> - : "memory", "cc"); \
> - __uaccess_end(); \
> - __err ? -EFAULT : 0; \
> + u8 __user *__p = (addr); \
> + int __err = -EFAULT; \
> + if (user_access_begin(__p, sizeof(*__p))) { \
> + __err = 0; \
> + asm volatile("\n" \
> + "1: " LOCK_PREFIX "orb %[mask], %[ptr]\n" \
> + "2:\n" \
> + _ASM_EXTABLE_TYPE_REG(1b, 2b, \
> + EX_TYPE_EFAULT_REG, \
> + %[errout]) \
> + : [errout] "+r" (__err), \
> + [ptr] "+m" (*__p) \
> + : [mask] "q" ((unsigned char)BIT(nr)) \
> + : "memory", "cc"); \
> + user_access_end(); \
> + } \
> + __err; \
> })
>
> /*
>
> If this looks right, I'll fold it in, run my test in a VM and resubmit
> with the test as a second patch.
>
> Thanks,
> Khan
So, you were right, it's better to check access. But I don't like
paying nospec. Let's use the modern scoped accessors?
Like this maybe? Very lightly tested, no time today, sorry.
If you want to use it:
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 3a0dd3c2b233e..0bffa43e02179 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -594,6 +594,28 @@ _label: \
__ret; \
})
+/* set_bit() on a byte of user memory; returns -EFAULT on fault. */
+#define set_bit_user(nr, addr) \
+({ \
+ int __err = -EFAULT; \
+ u8 __user *__p = (addr); \
+ scoped_user_rw_access(__p, efault) { \
+ __err = 0; \
+ asm volatile("\n" \
+ "1: " LOCK_PREFIX "orb %[mask], %[ptr]\n" \
+ "2:\n" \
+ _ASM_EXTABLE_TYPE_REG(1b, 2b, \
+ EX_TYPE_EFAULT_REG, \
+ %[errout]) \
+ : [errout] "+r" (__err), \
+ [ptr] "+m" (*__p) \
+ : [mask] "q" ((unsigned char)BIT(nr)) \
+ : "memory", "cc"); \
+ } \
+efault: \
+ __err; \
+})
+
/*
* We want the unsafe accessors to always be inlined and use
* the error labels - thus the macro games.
prev parent reply other threads:[~2026-11-13 13:51 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 10:53 Michael S. Tsirkin
2026-11-13 1:29 ` zhaoguohan
2026-11-13 5:47 ` Michael S. Tsirkin
2026-11-13 6:09 ` Michael S. Tsirkin
2026-11-13 13:51 ` Michael S. Tsirkin [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=20261113083351-mutt-send-email-mst@kernel.org \
--to=mst@redhat.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=eperezma@redhat.com \
--cc=hpa@zytor.com \
--cc=jasowang@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=tglx@kernel.org \
--cc=virtualization@lists.linux.dev \
--cc=x86@kernel.org \
--cc=zhaoguohan@kylinos.cn \
/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
all inboxes | Powered by JetHome®