* Will be merged it with virtual IOAPIC logic, since most is the same
*/
+#include <xen/io.h>
#include <xen/types.h>
#include <xen/mm.h>
#include <xen/xmalloc.h>
hwaddr = fix_to_virt(fixmap_idx) + PAGE_OFFSET(address);
- switch ( len )
- {
- case 1:
- *pval = readb(hwaddr);
- break;
-
- case 2:
- *pval = readw(hwaddr);
- break;
-
- case 4:
- *pval = readl(hwaddr);
- break;
-
- case 8:
- *pval = readq(hwaddr);
- break;
-
- default:
- ASSERT_UNREACHABLE();
- break;
- }
+ *pval = read_mmio(hwaddr, len);
}
static void adjacent_write(
hwaddr = fix_to_virt(fixmap_idx) + PAGE_OFFSET(address);
- switch ( len )
- {
- case 1:
- writeb(val, hwaddr);
- break;
-
- case 2:
- writew(val, hwaddr);
- break;
-
- case 4:
- writel(val, hwaddr);
- break;
-
- case 8:
- writeq(val, hwaddr);
- break;
-
- default:
- ASSERT_UNREACHABLE();
- break;
- }
+ write_mmio(hwaddr, val, len);
}
static int cf_check msixtbl_read(
#include <xen/guest_access.h>
#include <xen/hypercall.h>
#include <xen/init.h>
+#include <xen/io.h>
#include <xen/iocap.h>
#include <xen/ioreq.h>
#include <xen/irq.h>
#include <asm/flushtlb.h>
#include <asm/guest.h>
#include <asm/idt.h>
-#include <asm/io.h>
#include <asm/io_apic.h>
#include <asm/ldt.h>
#include <asm/mem_sharing.h>
static void subpage_mmio_write_emulate(
mfn_t mfn,
unsigned int offset,
- const void *data,
+ unsigned long data,
unsigned int len)
{
struct subpage_ro_range *entry;
return;
}
- addr += offset;
- switch ( len )
- {
- case 1:
- writeb(*(const uint8_t*)data, addr);
- break;
- case 2:
- writew(*(const uint16_t*)data, addr);
- break;
- case 4:
- writel(*(const uint32_t*)data, addr);
- break;
- case 8:
- writeq(*(const uint64_t*)data, addr);
- break;
- default:
- /* mmio_ro_emulated_write() already validated the size */
- ASSERT_UNREACHABLE();
+ if ( !write_mmio(addr + offset, data, len) )
goto write_ignored;
- }
}
#ifdef CONFIG_HVM
struct x86_emulate_ctxt *ctxt)
{
struct mmio_ro_emulate_ctxt *mmio_ro_ctxt = ctxt->data;
+ unsigned long data = 0;
/* Only allow naturally-aligned stores at the original %cr2 address. */
if ( ((bytes | offset) & (bytes - 1)) || !bytes ||
return X86EMUL_UNHANDLEABLE;
}
- if ( bytes <= 8 )
+ if ( bytes <= sizeof(data) )
+ {
+ memcpy(&data, p_data, bytes);
subpage_mmio_write_emulate(mmio_ro_ctxt->mfn, PAGE_OFFSET(offset),
- p_data, bytes);
+ data, bytes);
+ }
else if ( subpage_mmio_find_page(mmio_ro_ctxt->mfn) )
gprintk(XENLOG_WARNING,
"unsupported %u-byte write to R/O MMIO 0x%"PRI_mfn"%03lx\n",
* License along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
+#include <xen/io.h>
#include <xen/sched.h>
#include <xen/vpci.h>
return X86EMUL_OKAY;
}
- switch ( len )
- {
- case 1:
- *data = readb(mem + PAGE_OFFSET(addr));
- break;
-
- case 2:
- *data = readw(mem + PAGE_OFFSET(addr));
- break;
-
- case 4:
- *data = readl(mem + PAGE_OFFSET(addr));
- break;
-
- case 8:
- *data = readq(mem + PAGE_OFFSET(addr));
- break;
-
- default:
- ASSERT_UNREACHABLE();
- break;
- }
+ *data = read_mmio(mem + PAGE_OFFSET(addr), len);
spin_unlock(&vpci->lock);
return X86EMUL_OKAY;
return X86EMUL_OKAY;
}
- switch ( len )
- {
- case 1:
- writeb(data, mem + PAGE_OFFSET(addr));
- break;
-
- case 2:
- writew(data, mem + PAGE_OFFSET(addr));
- break;
-
- case 4:
- writel(data, mem + PAGE_OFFSET(addr));
- break;
-
- case 8:
- writeq(data, mem + PAGE_OFFSET(addr));
- break;
-
- default:
- ASSERT_UNREACHABLE();
- break;
- }
+ write_mmio(mem + PAGE_OFFSET(addr), data, len);
spin_unlock(&vpci->lock);
return X86EMUL_OKAY;
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * IO related routines.
+ *
+ * Copyright (c) 2025 Cloud Software Group
+ */
+#ifndef XEN_IO_H
+#define XEN_IO_H
+
+#include <xen/bug.h>
+
+#include <asm/io.h>
+
+static inline unsigned long read_mmio(const volatile void __iomem *mem,
+ unsigned int size)
+{
+ switch ( size )
+ {
+ case 1:
+ return readb(mem);
+
+ case 2:
+ return readw(mem);
+
+ case 4:
+ return readl(mem);
+
+#ifdef CONFIG_64BIT
+ case 8:
+ return readq(mem);
+#endif
+
+ default:
+ ASSERT_UNREACHABLE();
+ return ~0UL;
+ }
+}
+
+static inline bool write_mmio(volatile void __iomem *mem, unsigned long data,
+ unsigned int size)
+{
+ switch ( size )
+ {
+ case 1:
+ writeb(data, mem);
+ break;
+
+ case 2:
+ writew(data, mem);
+ break;
+
+ case 4:
+ writel(data, mem);
+ break;
+
+#ifdef CONFIG_64BIT
+ case 8:
+ writeq(data, mem);
+ break;
+#endif
+
+ default:
+ ASSERT_UNREACHABLE();
+ return false;
+ }
+
+ return true;
+}
+
+#endif /* XEN_IO_H */