{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
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
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.
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.
>
© 2016 - 2026 Red Hat, Inc.