[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v12 3/6] lib/arm: Add I/O memory copy helpers


  • To: Jan Beulich <jbeulich@xxxxxxxx>
  • From: Oleksii Moisieiev <Oleksii_Moisieiev@xxxxxxxx>
  • Date: Fri, 11 Sep 2026 13:06:13 +0000
  • Accept-language: en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=epam.com; dmarc=pass action=none header.from=epam.com; dkim=pass header.d=epam.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=5K3Fakczljm9GzsN8TcPKbpUXzJbqrxJZwgis0B6h4U=; b=QUX8HkviCcTdXy4MD7BVUjB6U0Cdoq+5ig/NnmYaK2iISVdpNOqdvobKQsLqwPsiHBQ0Olj6WNlxMdaILx7pRE1Tc119LCEC7pOF3dlo353/hYq/0FjYY0i2xBFFvNWvLGI2MOiE1yqrNebxuMITCt54MmqGbXYi/mhxVb7Ohwuy7121luFcQ22Kq7u3QxBnCnZD9Qp1D7Tk8rzS1pS+FhQhth/PnTjxA/Zy0gtK6EfjWix4qdNEUnwxS66NBbUeFJdlyAyVQ/2ry8cQ+9JwpBr1ZnHd7o7RAK8S7kmjR7u0ZWXTocUFrQ+U3QhoYzPZwZTRgm3pko1jnhmfAWc/KA==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=nCLyb7EfYRMwUG5suVHV5oosogepWIqrUaC3Hu8DHWX0Upt6ri0B9xzxKKo9HNOL8UswCZBF89+rnZdPt2iG8M7PX9zWq3o3taBV0Nl4YftWxQhKjFwPB2k7gbF+1Ron+6HvuQbuH2bLOOaqXQYrUJfc2ODOtUQHkSxpMhmtF4Jr9xV5gGWulM9NCVZhRYYggE9Q9w24GUpScgNXY5ZJskEqJRT/U6Jnp/NHIb+LYTXaTj404653O7CG9BH4yBaMPkW4yxjzOSvfIwuFmUbDZkHMg/6ucGbMRaAe9OH3QWrkl/zpxpKoeI28V1twhA/govrSRw4xn9VwbiMvaFawpA==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=epam.com header.i="@epam.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:x-ms-exchange-senderadcheck"
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=epam.com;
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Anthony PERARD <anthony.perard@xxxxxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Juergen Gross <jgross@xxxxxxxx>, Julien Grall <julien@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Roger Pau Monné <roger@xxxxxxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>, Grygorii Strashko <grygorii_strashko@xxxxxxxx>, "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • Delivery-date: Fri, 11 Sep 2026 13:06:22 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHdQb7XwQvbnxLqDEGK19PLXXgae7bJAQCAgABYGQA=
  • Thread-topic: [PATCH v12 3/6] lib/arm: Add I/O memory copy helpers

Hi Jan,

Thank you for quick response. please see below.

On 11/09/2026 10:50, Jan Beulich wrote:
> On 11.09.2026 09:26, Oleksii Moisieiev wrote:
>> Introduce memcpy_fromio() and memcpy_toio() helpers to copy between
>> regular memory and MMIO space on Arm. The generic prototypes live in
>> io.h so other architectures can provide their own implementations.
>>
>> These helpers handle alignment safely by using ordered byte accesses for
>> any leading/trailing unaligned bytes and ordered 32-bit accesses for the
>> aligned bulk transfer.
> That's over-simplifying things (just like code comments do). If source
> and destination are equally misaligned modulo 4, what is said is true. If
> they are differently misaligned, the entire copy will be done byte-wise.
> Which can easily be a problem when 4-byte accesses are required for
> particular MMIO locations (which may e.g. actually represent device
> registers).
>
> As said on earlier versions: I think you either want to get misalignment
> handling right for all possible cases, or you want to demand aligned
> incoming pointers.
>
> (Ftaod, using byte accesses for two or three leading / trailing misaligned
> bytes can be equally wrong, when the MMIO location accessed wants to be
> accessed with a 16-bit load/store, for being e.g. a 16-bit device register.
> Similarly using 32-bit loads/stores can be wrong in the general case. IOW
> while some of that is said to a certain degree, I think there are
> unmentioned further constraints on when these functions may safely be
> used. For example "devices that tolerate 8-bit and 32-bit accesses" is
> still ambiguous as to what exactly it means. Not the least because
> "tolerate" doesn't mean "work correctly with".)
>
>> Using the ordered `readb/readl` and
>> `writeb/writel` accessors avoids unintended endianness conversion while
>> respecting device ordering requirements on ARM32/ARM64 hardware that may
>> not support 64-bit MMIO atomically.
> I'm having trouble making sense of this part. Why's endianness of concern
> here? The accessors used don't care about endianness at all, and what may
> have (wrongly) been used in earlier versions shouldn't matter here (or it
> would need calling out which other accessors would be wrong to use).
This is the leftover from v7 where __raw_write/__raw_read were used. 
readl()/writel() include little endian conversion through their relaxed 
variants.
https://patchew.org/Xen/cover.1768415200.git.oleksii._5Fmoisieiev@xxxxxxxx/d166348530b9229673e1a6e3b29ff4ee9123ab2f.1768415200.git.oleksii._5Fmoisieiev@xxxxxxxx/

I will remove the claim that ordered accessors avoid endianness conversion.

>> --- a/xen/include/xen/io.h
>> +++ b/xen/include/xen/io.h
>> @@ -67,4 +67,14 @@ static inline bool write_mmio(volatile void __iomem *mem, 
>> unsigned long data,
>>       return true;
>>   }
>>   
>> +/*
>> + * Copy between regular memory and MMIO space.  Implementations are
>> + * architecture-specific and must use appropriate MMIO accessors for
>> + * their memory and I/O models.
>> + */
>> +void memcpy_fromio(void *to, const volatile void __iomem *from,
>> +                   size_t count);
>> +void memcpy_toio(volatile void __iomem *to, const void *from,
>> +                 size_t count);
> For somebody wanting to use these functions and merely looking here, how
> would they know of all the constraints? That is implementations are not
> merely arch-specific, they may also impose arch-specific constraints.
>
> Jan
You are right about the alignment handling. Advancing both pointers by
the same amount preserves their relative alignment, so they never become
aligned together if their offsets modulo four differ. In that case the
current implementation copies the whole range using byte accesses.

I propose to handle arbitrary RAM alignment by aligning only the I/O
pointer, then using put_unaligned_le32()/get_unaligned_le32() on the
Normal-memory side of the word transfers. All I/O accesses would still
use readb/readl or writeb/writel. This would make the I/O access widths
independent of the RAM pointer's alignment. In particular, an aligned
I/O address and a length divisible by four would produce only 32-bit
I/O accesses, even with an unaligned RAM buffer.

So the changes for memcpy_toio will look like:

void memcpy_toio(volatile void __iomem *to, const void *from,
                  size_t count)
  {
-    while ( count && (!IS_ALIGNED((unsigned long)to, 4) ||
-                      !IS_ALIGNED((unsigned long)from, 4)) )
+    while ( count && !IS_ALIGNED((unsigned long)to, 4) )
      {
          writeb(*(const uint8_t *)from, to);
          from++;
@@ -29,7 +22,7 @@

      while ( count >= 4 )
      {
-        writel(*(const uint32_t *)from, to);
+        writel(get_unaligned_le32(from), to);
          from += 4;
          to += 4;
          count -= 4;

This does not make the helpers suitable for arbitrary device registers.
I will describe them as copying a byte sequence to/from a memory-like
I/O region. The region must support byte accesses at every byte address
and aligned 32-bit accesses with equivalent byte-storage semantics.
The implementation uses byte accesses to align the I/O pointer.

And also I will document the Arm requirements next to the declarations
in xen/io.h as you suggested.


What do you think about this approach?

Oleksii.

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.