From 11e261ada41190562de10f2830e518c674cd574b Mon Sep 17 00:00:00 2001
From: Alexander Boettcher <alexander.boettcher@genode-labs.com>
Date: Wed, 28 Oct 2020 22:08:31 +0100
Subject: [PATCH] platform_drv(x86): use 32bit writes for MSI-X

Fixes #3927
---
 repos/os/src/drivers/platform/spec/x86/pci_device.cc   | 10 ++++++----
 .../drivers/platform/spec/x86/pci_device_component.h   |  4 +++-
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device.cc b/repos/os/src/drivers/platform/spec/x86/pci_device.cc
index 529d9d403c..668bae1026 100644
--- a/repos/os/src/drivers/platform/spec/x86/pci_device.cc
+++ b/repos/os/src/drivers/platform/spec/x86/pci_device.cc
@@ -297,15 +297,17 @@ bool Platform::Device_component::_setup_msix(Genode::uint16_t const msix_cap)
 			struct Msi_entry : public Mmio {
 				Msi_entry(addr_t const base) : Mmio(base) { }
 
-				struct Address : Register<0x0, 64> { };
-				struct Value   : Register<0x8, 32> { };
-				struct Vector  : Register<0xc, 32> {
+				struct Address_low  : Register<0x0, 32> { };
+				struct Address_high : Register<0x4, 32> { };
+				struct Value        : Register<0x8, 32> { };
+				struct Vector       : Register<0xc, 32> {
 					struct Mask : Bitfield <0, 1> { };
 				};
 			} msi_entry_0 (msix_table);
 
 			/* setup first msi-x table entry */
-			msi_entry_0.write<Msi_entry::Address>(msi_address & ~(0x3UL));
+			msi_entry_0.write<Msi_entry::Address_low>(msi_address & ~(0x3UL));
+			msi_entry_0.write<Msi_entry::Address_high>(sizeof(msi_address) == 4 ? 0 : msi_address >> 32);
 			msi_entry_0.write<Msi_entry::Value>(msi_value);
 			msi_entry_0.write<Msi_entry::Vector::Mask>(0);
 
diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h
index d1e8735ef0..c5766d74a5 100644
--- a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h
+++ b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h
@@ -260,7 +260,9 @@ class Platform::Device_component : public  Genode::Rpc_object<Platform::Device>,
 			/* requested io_mem not allocated by Pci::Resource - try direct */
 			Io_mem io_mem(_env, msix_table_phys, msix_table_size, false);
 			Attached_dataspace mem_io(_env.rm(), io_mem.dataspace());
-			Genode::addr_t const msix_table = reinterpret_cast<addr_t>(mem_io.local_addr<void>());
+			addr_t const offset = msix_table_phys & 0xfffull;
+			addr_t const msix_table = reinterpret_cast<addr_t>(mem_io.local_addr<void>()) + offset;
+
 			fn(msix_table);
 		};