[PATCH v2 3/3] xen/vpci: msix: move read/write call to MSI-X PBA entry to arch file

Rahul Singh posted 3 patches 2 years, 9 months ago
[PATCH v2 3/3] xen/vpci: msix: move read/write call to MSI-X PBA entry to arch file
Posted by Rahul Singh 2 years, 9 months ago
{read,write}{l,q} function argument is different for ARM and x86.
ARM {read,wrie}(l,q} function argument is pointer whereas X86
{read,wrie}(l,q} function argument is address itself.

{read,write}{l,q} is only used in common file to access the MSI-X PBA
structure. To avoid impacting other x86 code and to make the code common
move the read/write call to MSI-X PBA to arch specific file.

Signed-off-by: Rahul Singh <rahul.singh@arm.com>
---
Changes since v1:
 - Added in this version
---
 xen/arch/x86/hvm/vmsi.c | 47 +++++++++++++++++++++++++++++++++++++++++
 xen/drivers/vpci/msix.c | 43 ++-----------------------------------
 xen/include/xen/vpci.h  |  6 ++++++
 3 files changed, 55 insertions(+), 41 deletions(-)

diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
index 761ce674d7..f124a1d07d 100644
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -1033,4 +1033,51 @@ void vpci_msix_arch_register(struct vpci_msix *msix, struct domain *d)
 
     list_add(&msix->next, &d->arch.hvm.msix_tables);
 }
+
+bool vpci_msix_arch_pba_read(unsigned long addr, unsigned int len,
+                             unsigned long *data)
+{
+    /*
+     * Access to PBA.
+     *
+     * TODO: note that this relies on having the PBA identity mapped to the
+     * guest address space. If this changes the address will need to be
+     * translated.
+     */
+    switch ( len )
+    {
+    case 4:
+        *data = readl(addr);
+        break;
+
+    case 8:
+        *data = readq(addr);
+        break;
+
+    default:
+        ASSERT_UNREACHABLE();
+        break;
+    }
+
+    return true;
+}
+
+void vpci_msix_arch_pba_write(unsigned long addr, unsigned int len,
+                              unsigned long data)
+{
+    switch ( len )
+    {
+    case 4:
+        writel(data, addr);
+        break;
+
+    case 8:
+        writeq(data, addr);
+        break;
+
+    default:
+        ASSERT_UNREACHABLE();
+        break;
+    }
+}
 #endif /* CONFIG_HAS_VPCI */
diff --git a/xen/drivers/vpci/msix.c b/xen/drivers/vpci/msix.c
index 5b315757ef..b6720f1a1a 100644
--- a/xen/drivers/vpci/msix.c
+++ b/xen/drivers/vpci/msix.c
@@ -170,31 +170,7 @@ bool vpci_msix_read(struct vpci_msix *msix, unsigned long addr,
         return true;
 
     if ( VMSIX_ADDR_IN_RANGE(addr, msix->pdev->vpci, VPCI_MSIX_PBA) )
-    {
-        /*
-         * Access to PBA.
-         *
-         * TODO: note that this relies on having the PBA identity mapped to the
-         * guest address space. If this changes the address will need to be
-         * translated.
-         */
-        switch ( len )
-        {
-        case 4:
-            *data = readl(addr);
-            break;
-
-        case 8:
-            *data = readq(addr);
-            break;
-
-        default:
-            ASSERT_UNREACHABLE();
-            break;
-        }
-
-        return true;
-    }
+        return vpci_msix_arch_pba_read(addr, len, data);
 
     spin_lock(&msix->pdev->vpci->lock);
     entry = get_entry(msix, addr);
@@ -247,22 +223,7 @@ bool vpci_msix_write(struct vpci_msix *msix, unsigned long addr,
     {
         /* Ignore writes to PBA for DomUs, it's behavior is undefined. */
         if ( is_hardware_domain(d) )
-        {
-            switch ( len )
-            {
-            case 4:
-                writel(data, addr);
-                break;
-
-            case 8:
-                writeq(data, addr);
-                break;
-
-            default:
-                ASSERT_UNREACHABLE();
-                break;
-            }
-        }
+            vpci_msix_arch_pba_write(addr, len, data);
 
         return true;
     }
diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h
index 1c36845abf..a61daf9d53 100644
--- a/xen/include/xen/vpci.h
+++ b/xen/include/xen/vpci.h
@@ -231,6 +231,12 @@ bool vpci_msix_write(struct vpci_msix *msix, unsigned long addr,
 bool vpci_msix_read(struct vpci_msix *msix, unsigned long addr,
                     unsigned int len, unsigned long *data);
 
+bool vpci_msix_arch_pba_read(unsigned long addr, unsigned int len,
+                             unsigned long *data);
+
+void vpci_msix_arch_pba_write(unsigned long addr, unsigned int len,
+                              unsigned long data);
+
 #endif /* __XEN__ */
 
 #else /* !CONFIG_HAS_VPCI */
-- 
2.25.1


Re: [PATCH v2 3/3] xen/vpci: msix: move read/write call to MSI-X PBA entry to arch file
Posted by Jan Beulich 2 years, 9 months ago
On 15.02.2022 16:25, Rahul Singh wrote:
> {read,write}{l,q} function argument is different for ARM and x86.
> ARM {read,wrie}(l,q} function argument is pointer whereas X86
> {read,wrie}(l,q} function argument is address itself.

I'm afraid I don't follow: x86 has

#define readl(x) (*(volatile uint32_t *)(x))
#define readq(x) (*(volatile uint64_t *)(x))

That's no different from Arm64:

#define readl(c)                ({ u32 __v = readl_relaxed(c); __iormb(); __v; })

#define readl_relaxed(c)        ({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; })

static inline u32 __raw_readl(const volatile void __iomem *addr)

The difference is whether the address is expressed as a pointer, or
_may_ also be expressed as unsigned long. IOW the x86 variant is
perfectly fine to be passed e.g. a void * (preferably qualified
appropriately). The conversion from unsigned long to a pointer type
is actually expressed ...

> @@ -170,31 +170,7 @@ bool vpci_msix_read(struct vpci_msix *msix, unsigned long addr,
>          return true;
>  
>      if ( VMSIX_ADDR_IN_RANGE(addr, msix->pdev->vpci, VPCI_MSIX_PBA) )
> -    {
> -        /*
> -         * Access to PBA.
> -         *
> -         * TODO: note that this relies on having the PBA identity mapped to the
> -         * guest address space. If this changes the address will need to be
> -         * translated.
> -         */
> -        switch ( len )
> -        {
> -        case 4:
> -            *data = readl(addr);
> -            break;
> -
> -        case 8:
> -            *data = readq(addr);
> -            break;
> -
> -        default:
> -            ASSERT_UNREACHABLE();
> -            break;
> -        }

... in the comment ahead of this switch() (and the assumption is likely
wrong for DomU).

But then, Roger: What "identity mapped" is meant here? Surely not GVA ->
GPA, but rather GPA -> HPA? The address here is a guest physical one,
but read{l,q}() act on (host) virtual addresses. This would have been
easier to notice as wrong if read{l,q}() weren't allowing unsigned long
arguments to be passed to them.

Jan


Re: [PATCH v2 3/3] xen/vpci: msix: move read/write call to MSI-X PBA entry to arch file
Posted by Roger Pau Monné 2 years, 9 months ago
On Tue, Feb 15, 2022 at 03:25:18PM +0000, Rahul Singh wrote:
> {read,write}{l,q} function argument is different for ARM and x86.
> ARM {read,wrie}(l,q} function argument is pointer whereas X86
> {read,wrie}(l,q} function argument is address itself.
> 
> {read,write}{l,q} is only used in common file to access the MSI-X PBA
> structure. To avoid impacting other x86 code and to make the code common
> move the read/write call to MSI-X PBA to arch specific file.

I think we agreed where going to unify {read,write}{l,q} so they could
be used in arch-agnostic code?

Thanks, Roger.

Re: [PATCH v2 3/3] xen/vpci: msix: move read/write call to MSI-X PBA entry to arch file
Posted by Rahul Singh 2 years, 9 months ago
Hi Roger,

> On 25 Feb 2022, at 8:20 am, Roger Pau Monné <roger.pau@citrix.com> wrote:
> 
> On Tue, Feb 15, 2022 at 03:25:18PM +0000, Rahul Singh wrote:
>> {read,write}{l,q} function argument is different for ARM and x86.
>> ARM {read,wrie}(l,q} function argument is pointer whereas X86
>> {read,wrie}(l,q} function argument is address itself.
>> 
>> {read,write}{l,q} is only used in common file to access the MSI-X PBA
>> structure. To avoid impacting other x86 code and to make the code common
>> move the read/write call to MSI-X PBA to arch specific file.
> 
> I think we agreed where going to unify {read,write}{l,q} so they could
> be used in arch-agnostic code?

We agreed to modify the vPCI MSIx code to use a pointer, but that not 
helped me to make code arch-agnostic. I decided to move the PBA handling code to an 
arch-specific file to make the code usable.

Thanks for the series  "vpci/msix: fix PBA acceses” series that will help to use the 
code for ARM arch also without any modification to {read,write}{l,q} .

Regards,
Rahul
> 
> Thanks, Roger.
>