Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1620622 > unrolled thread
| Started by | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| First post | 2017-04-10 21:00 +0200 |
| Last post | 2017-04-11 00:50 +0200 |
| Articles | 7 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
RE: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-04-10 21:00 +0200
Re: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions Dan Williams <dan.j.williams@intel.com> - 2017-04-10 23:20 +0200
RE: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-04-10 23:30 +0200
Re: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions Dan Williams <dan.j.williams@intel.com> - 2017-04-10 23:40 +0200
RE: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-04-10 23:50 +0200
Re: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions Dan Williams <dan.j.williams@intel.com> - 2017-04-11 00:20 +0200
RE: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions "Kani, Toshimitsu" <toshi.kani@hpe.com> - 2017-04-11 00:50 +0200
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-04-10 21:00 +0200 |
| Subject | RE: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions |
| Message-ID | <tuMHE-4zk-13@gated-at.bofh.it> |
> Subject: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-
> bypass assumptions
>
> Before we rework the "pmem api" to stop abusing __copy_user_nocache()
> for memcpy_to_pmem() we need to fix cases where we may strand dirty data
> in the cpu cache. The problem occurs when copy_from_iter_pmem() is used
> for arbitrary data transfers from userspace. There is no guarantee that
> these transfers, performed by dax_iomap_actor(), will have aligned
> destinations or aligned transfer lengths. Backstop the usage
> __copy_user_nocache() with explicit cache management in these unaligned
> cases.
>
> Yes, copy_from_iter_pmem() is now too big for an inline, but addressing
> that is saved for a later patch that moves the entirety of the "pmem
> api" into the pmem driver directly.
:
> ---
> v2: Change the condition for flushing the last cacheline of the
> destination from 8-byte to 4-byte misalignment (Toshi)
:
> arch/x86/include/asm/pmem.h | 41 ++++++++++++++++++++++++++++++----
:
> @@ -94,7 +86,34 @@ static inline size_t arch_copy_from_iter_pmem(void
> *addr, size_t bytes,
> /* TODO: skip the write-back by always using non-temporal stores */
> len = copy_from_iter_nocache(addr, bytes, i);
>
> - if (__iter_needs_pmem_wb(i))
> + /*
> + * In the iovec case on x86_64 copy_from_iter_nocache() uses
> + * non-temporal stores for the bulk of the transfer, but we need
> + * to manually flush if the transfer is unaligned. In the
> + * non-iovec case the entire destination needs to be flushed.
> + */
> + if (iter_is_iovec(i)) {
> + unsigned long dest = (unsigned long) addr;
> +
> + /*
> + * If the destination is not 8-byte aligned then
> + * __copy_user_nocache (on x86_64) uses cached copies
> + */
> + if (dest & 8) {
> + arch_wb_cache_pmem(addr, 1);
> + dest = ALIGN(dest, 8);
> + }
> +
> + /*
> + * If the remaining transfer length, after accounting
> + * for destination alignment, is not 4-byte aligned
> + * then __copy_user_nocache() falls back to cached
> + * copies for the trailing bytes in the final cacheline
> + * of the transfer.
> + */
> + if ((bytes - (dest - (unsigned long) addr)) & 4)
> + arch_wb_cache_pmem(addr + bytes - 1, 1);
> + } else
> arch_wb_cache_pmem(addr, bytes);
>
> return len;
Thanks for the update. I think the alignment check should be based on
the following note in copy_user_nocache.
* Note: Cached memory copy is used when destination or size is not
* naturally aligned. That is:
* - Require 8-byte alignment when size is 8 bytes or larger.
* - Require 4-byte alignment when size is 4 bytes.
So, I think the code may be something like this. I also made the following changes:
- Mask with 7, not 8.
- ALIGN with cacheline size, instead of 8.
- Add (bytes > flushed) test since calculation with unsigned long still results in a negative
value (as a positive value).
if (bytes < 8) {
if ((dest & 3) || (bytes != 4))
arch_wb_cache_pmem(addr, 1);
} else {
if (dest & 7) {
dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
arch_wb_cache_pmem(addr, 1);
}
flushed = dest - (unsigned long) addr;
if ((bytes > flushed) && ((bytes - flushed) & 7))
arch_wb_cache_pmem(addr + bytes - 1, 1);
}
Thanks,
-Toshi
[toc] | [next] | [standalone]
| From | Dan Williams <dan.j.williams@intel.com> |
|---|---|
| Date | 2017-04-10 23:20 +0200 |
| Subject | Re: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions |
| Message-ID | <tuOT8-6cJ-5@gated-at.bofh.it> |
| In reply to | #1620622 |
On Mon, Apr 10, 2017 at 11:53 AM, Kani, Toshimitsu <toshi.kani@hpe.com> wrote:
>> Subject: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-
>> bypass assumptions
>>
>> Before we rework the "pmem api" to stop abusing __copy_user_nocache()
>> for memcpy_to_pmem() we need to fix cases where we may strand dirty data
>> in the cpu cache. The problem occurs when copy_from_iter_pmem() is used
>> for arbitrary data transfers from userspace. There is no guarantee that
>> these transfers, performed by dax_iomap_actor(), will have aligned
>> destinations or aligned transfer lengths. Backstop the usage
>> __copy_user_nocache() with explicit cache management in these unaligned
>> cases.
>>
>> Yes, copy_from_iter_pmem() is now too big for an inline, but addressing
>> that is saved for a later patch that moves the entirety of the "pmem
>> api" into the pmem driver directly.
> :
>> ---
>> v2: Change the condition for flushing the last cacheline of the
>> destination from 8-byte to 4-byte misalignment (Toshi)
> :
>> arch/x86/include/asm/pmem.h | 41 ++++++++++++++++++++++++++++++----
> :
>> @@ -94,7 +86,34 @@ static inline size_t arch_copy_from_iter_pmem(void
>> *addr, size_t bytes,
>> /* TODO: skip the write-back by always using non-temporal stores */
>> len = copy_from_iter_nocache(addr, bytes, i);
>>
>> -if (__iter_needs_pmem_wb(i))
>> +/*
>> + * In the iovec case on x86_64 copy_from_iter_nocache() uses
>> + * non-temporal stores for the bulk of the transfer, but we need
>> + * to manually flush if the transfer is unaligned. In the
>> + * non-iovec case the entire destination needs to be flushed.
>> + */
>> +if (iter_is_iovec(i)) {
>> +unsigned long dest = (unsigned long) addr;
>> +
>> +/*
>> + * If the destination is not 8-byte aligned then
>> + * __copy_user_nocache (on x86_64) uses cached copies
>> + */
>> +if (dest & 8) {
>> +arch_wb_cache_pmem(addr, 1);
>> +dest = ALIGN(dest, 8);
>> +}
>> +
>> +/*
>> + * If the remaining transfer length, after accounting
>> + * for destination alignment, is not 4-byte aligned
>> + * then __copy_user_nocache() falls back to cached
>> + * copies for the trailing bytes in the final cacheline
>> + * of the transfer.
>> + */
>> +if ((bytes - (dest - (unsigned long) addr)) & 4)
>> +arch_wb_cache_pmem(addr + bytes - 1, 1);
>> +} else
>> arch_wb_cache_pmem(addr, bytes);
>>
>> return len;
>
> Thanks for the update. I think the alignment check should be based on
> the following note in copy_user_nocache.
>
> * Note: Cached memory copy is used when destination or size is not
> * naturally aligned. That is:
> * - Require 8-byte alignment when size is 8 bytes or larger.
> * - Require 4-byte alignment when size is 4 bytes.
>
> So, I think the code may be something like this. I also made the following changes:
Thanks!
> - Mask with 7, not 8.
Yes, good catch.
> - ALIGN with cacheline size, instead of 8.
> - Add (bytes > flushed) test since calculation with unsigned long still results in a negative
> value (as a positive value).
>
> if (bytes < 8) {
> if ((dest & 3) || (bytes != 4))
> arch_wb_cache_pmem(addr, 1);
> } else {
> if (dest & 7) {
> dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
Why align the destination to the next cacheline? As far as I can see
the ALIGN_DESTINATION macro in arch/x86/include/asm/asm.h only aligns
to the next 8-byte boundary.
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-04-10 23:30 +0200 |
| Message-ID | <tuP2O-6g5-9@gated-at.bofh.it> |
| In reply to | #1620738 |
> > Thanks for the update. I think the alignment check should be based on
> > the following note in copy_user_nocache.
> >
> > * Note: Cached memory copy is used when destination or size is not
> > * naturally aligned. That is:
> > * - Require 8-byte alignment when size is 8 bytes or larger.
> > * - Require 4-byte alignment when size is 4 bytes.
> >
> > So, I think the code may be something like this. I also made the following
> changes:
>
> Thanks!
>
> > - Mask with 7, not 8.
>
> Yes, good catch.
>
> > - ALIGN with cacheline size, instead of 8.
> > - Add (bytes > flushed) test since calculation with unsigned long still results
> in a negative
> > value (as a positive value).
> >
> > if (bytes < 8) {
> > if ((dest & 3) || (bytes != 4))
> > arch_wb_cache_pmem(addr, 1);
> > } else {
> > if (dest & 7) {
> > dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
>
> Why align the destination to the next cacheline? As far as I can see
> the ALIGN_DESTINATION macro in arch/x86/include/asm/asm.h only aligns
> to the next 8-byte boundary.
The clflush here flushes for the cacheline size. So, we do not need to flush
the same cacheline again when the unaligned tail is in the same line.
Thanks,
-Toshi
[toc] | [prev] | [next] | [standalone]
| From | Dan Williams <dan.j.williams@intel.com> |
|---|---|
| Date | 2017-04-10 23:40 +0200 |
| Subject | Re: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions |
| Message-ID | <tuPcu-6jI-3@gated-at.bofh.it> |
| In reply to | #1620741 |
On Mon, Apr 10, 2017 at 2:28 PM, Kani, Toshimitsu <toshi.kani@hpe.com> wrote:
>> > Thanks for the update. I think the alignment check should be based on
>> > the following note in copy_user_nocache.
>> >
>> > * Note: Cached memory copy is used when destination or size is not
>> > * naturally aligned. That is:
>> > * - Require 8-byte alignment when size is 8 bytes or larger.
>> > * - Require 4-byte alignment when size is 4 bytes.
>> >
>> > So, I think the code may be something like this. I also made the following
>> changes:
>>
>> Thanks!
>>
>> > - Mask with 7, not 8.
>>
>> Yes, good catch.
>>
>> > - ALIGN with cacheline size, instead of 8.
>> > - Add (bytes > flushed) test since calculation with unsigned long still results
>> in a negative
>> > value (as a positive value).
>> >
>> > if (bytes < 8) {
>> > if ((dest & 3) || (bytes != 4))
>> > arch_wb_cache_pmem(addr, 1);
>> > } else {
>> > if (dest & 7) {
>> > dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
>>
>> Why align the destination to the next cacheline? As far as I can see
>> the ALIGN_DESTINATION macro in arch/x86/include/asm/asm.h only aligns
>> to the next 8-byte boundary.
>
> The clflush here flushes for the cacheline size. So, we do not need to flush
> the same cacheline again when the unaligned tail is in the same line.
Ok, makes sense. Last question, can't we reduce the check to be:
if ((bytes > flushed) && ((bytes - flushed) & 3))
...since if 'bytes' was 4-byte aligned we would have performed
non-temporal stores.
Can I add your Signed-off-by: on v3?
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-04-10 23:50 +0200 |
| Message-ID | <tuPma-6ni-21@gated-at.bofh.it> |
| In reply to | #1620745 |
> On Mon, Apr 10, 2017 at 2:28 PM, Kani, Toshimitsu <toshi.kani@hpe.com>
> wrote:
> >> > Thanks for the update. I think the alignment check should be based on
> >> > the following note in copy_user_nocache.
> >> >
> >> > * Note: Cached memory copy is used when destination or size is not
> >> > * naturally aligned. That is:
> >> > * - Require 8-byte alignment when size is 8 bytes or larger.
> >> > * - Require 4-byte alignment when size is 4 bytes.
> >> >
> >> > So, I think the code may be something like this. I also made the following
> >> changes:
> >>
> >> Thanks!
> >>
> >> > - Mask with 7, not 8.
> >>
> >> Yes, good catch.
> >>
> >> > - ALIGN with cacheline size, instead of 8.
> >> > - Add (bytes > flushed) test since calculation with unsigned long still
> results
> >> in a negative
> >> > value (as a positive value).
> >> >
> >> > if (bytes < 8) {
> >> > if ((dest & 3) || (bytes != 4))
> >> > arch_wb_cache_pmem(addr, 1);
> >> > } else {
> >> > if (dest & 7) {
> >> > dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
> >>
> >> Why align the destination to the next cacheline? As far as I can see
> >> the ALIGN_DESTINATION macro in arch/x86/include/asm/asm.h only aligns
> >> to the next 8-byte boundary.
> >
> > The clflush here flushes for the cacheline size. So, we do not need to flush
> > the same cacheline again when the unaligned tail is in the same line.
>
> Ok, makes sense. Last question, can't we reduce the check to be:
>
> if ((bytes > flushed) && ((bytes - flushed) & 3))
>
> ...since if 'bytes' was 4-byte aligned we would have performed
> non-temporal stores.
That is not documented behavior of copy_user_nocache, but as long as the pmem
version of copy_user_nocache follows the same implemented behavior, yes, that
works.
> Can I add your Signed-off-by: on v3?
Sure.
Thanks,
-Toshi
[toc] | [prev] | [next] | [standalone]
| From | Dan Williams <dan.j.williams@intel.com> |
|---|---|
| Date | 2017-04-11 00:20 +0200 |
| Subject | Re: [PATCH v2] x86, pmem: fix broken __copy_user_nocache cache-bypass assumptions |
| Message-ID | <tuPPc-6MT-11@gated-at.bofh.it> |
| In reply to | #1620751 |
On Mon, Apr 10, 2017 at 2:45 PM, Kani, Toshimitsu <toshi.kani@hpe.com> wrote:
>> On Mon, Apr 10, 2017 at 2:28 PM, Kani, Toshimitsu <toshi.kani@hpe.com>
>> wrote:
>> >> > Thanks for the update. I think the alignment check should be based on
>> >> > the following note in copy_user_nocache.
>> >> >
>> >> > * Note: Cached memory copy is used when destination or size is not
>> >> > * naturally aligned. That is:
>> >> > * - Require 8-byte alignment when size is 8 bytes or larger.
>> >> > * - Require 4-byte alignment when size is 4 bytes.
>> >> >
>> >> > So, I think the code may be something like this. I also made the following
>> >> changes:
>> >>
>> >> Thanks!
>> >>
>> >> > - Mask with 7, not 8.
>> >>
>> >> Yes, good catch.
>> >>
>> >> > - ALIGN with cacheline size, instead of 8.
>> >> > - Add (bytes > flushed) test since calculation with unsigned long still
>> results
>> >> in a negative
>> >> > value (as a positive value).
>> >> >
>> >> > if (bytes < 8) {
>> >> > if ((dest & 3) || (bytes != 4))
>> >> > arch_wb_cache_pmem(addr, 1);
>> >> > } else {
>> >> > if (dest & 7) {
>> >> > dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
>> >>
>> >> Why align the destination to the next cacheline? As far as I can see
>> >> the ALIGN_DESTINATION macro in arch/x86/include/asm/asm.h only aligns
>> >> to the next 8-byte boundary.
>> >
>> > The clflush here flushes for the cacheline size. So, we do not need to flush
>> > the same cacheline again when the unaligned tail is in the same line.
>>
>> Ok, makes sense. Last question, can't we reduce the check to be:
>>
>> if ((bytes > flushed) && ((bytes - flushed) & 3))
>>
>> ...since if 'bytes' was 4-byte aligned we would have performed
>> non-temporal stores.
>
> That is not documented behavior of copy_user_nocache, but as long as the pmem
> version of copy_user_nocache follows the same implemented behavior, yes, that
> works.
Hmm, sorry this comment confuses me, I'm only referring to the current
version of __copy_user_nocache not the new pmem version. The way I
read the current code we only ever jump to the cached copy loop
(.L_1b_cache_copy_loop) if the trailing byte-count is 4-byte
misaligned.
[toc] | [prev] | [next] | [standalone]
| From | "Kani, Toshimitsu" <toshi.kani@hpe.com> |
|---|---|
| Date | 2017-04-11 00:50 +0200 |
| Message-ID | <tuQid-6Xw-5@gated-at.bofh.it> |
| In reply to | #1620761 |
> >> > The clflush here flushes for the cacheline size. So, we do not need to > flush > >> > the same cacheline again when the unaligned tail is in the same line. > >> > >> Ok, makes sense. Last question, can't we reduce the check to be: > >> > >> if ((bytes > flushed) && ((bytes - flushed) & 3)) > >> > >> ...since if 'bytes' was 4-byte aligned we would have performed > >> non-temporal stores. > > > > That is not documented behavior of copy_user_nocache, but as long as the > pmem > > version of copy_user_nocache follows the same implemented behavior, yes, > that > > works. > > Hmm, sorry this comment confuses me, I'm only referring to the current > version of __copy_user_nocache not the new pmem version. The way I > read the current code we only ever jump to the cached copy loop > (.L_1b_cache_copy_loop) if the trailing byte-count is 4-byte > misaligned. Yes, you are right and that's how the code is implemented. I added this trailing 4-byte handling for the >=8B case, which is shared with <8B case, since it was easy to do. But I considered it a bonus. This function also needs to handle 4B-aligned destination if it is to state that it handles 4B alignment for the >=8B case as well. Otherwise, it's inconsistent. Since I did not see much point of supporting such case, I simply documented in the Note that 8 byte alignment is required for the >=8B case. Thanks, -Toshi
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web