summary refs log tree commit diff stats
path: root/hw/intc
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2025-05-14 07:16:57 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2025-05-14 07:16:57 -0400
commit864813878951b44e964eb4c012d832fd21f8cc0c (patch)
tree21cdcc42acfd8ecad9170cbaa6671a5fb22b02fa /hw/intc
parentcacb211471e3a4b4abc517bfb2aef7bde5e71eaa (diff)
parenta3d5f62254a48b7c260d5aa7bd8e8467a0bb8ea3 (diff)
downloadfocaccia-qemu-864813878951b44e964eb4c012d832fd21f8cc0c.tar.gz
focaccia-qemu-864813878951b44e964eb4c012d832fd21f8cc0c.zip
Merge tag 'pull-loongarch-20250514' of https://github.com/gaosong715/qemu into staging
pull-loongarch-20250514

# -----BEGIN PGP SIGNATURE-----
#
# iLMEAAEKAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCaCRNgwAKCRBAov/yOSY+
# 343NBACeXLcXkNfPDRsuYC/Z0iYrMO8HuQ6VAcN1f4H+qP6Uo7ywb13GpJTLmewD
# iYmD93qVZBAglSUWhaVzBZbAjGFzZSDLcO0bmfsMvmUaIJfIZkJqRG01shk9iMMR
# zDLEax9udJdhJxBPCINNonXHds4vYKasjUureKd1SJidiBKG4w==
# =wdkQ
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 14 May 2025 04:00:03 EDT
# gpg:                using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF
# gpg: Good signature from "Song Gao <m17746591750@163.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: B8FF 1DA0 D2FD CB2D A09C  6C2C 40A2 FFF2 3926 3EDF

* tag 'pull-loongarch-20250514' of https://github.com/gaosong715/qemu:
  hw/loongarch/boot: Adjust the loading position of the initrd
  hw/intc/loongarch_pch: Merge three memory region into one
  hw/intc/loongarch_pch: Set flexible memory access size with iomem region
  hw/intc/loongarch_pch: Rename memory region iomem32_low with iomem
  hw/intc/loongarch_pch: Use unified trace event for memory region ops
  hw/intc/loongarch_pch: Use generic write callback for iomem8 region
  hw/intc/loongarch_pch: Use generic write callback for iomem32_high region
  hw/intc/loongarch_pch: Use generic write callback for iomem32_low region
  hw/intc/loongarch_pch: Use generic read callback for iomem8 region
  hw/intc/loongarch_pch: Use generic read callback for iomem32_high region
  hw/intc/loongarch_pch: Use generic read callback for iomem32_low region
  hw/intc/loongarch_pch: Discard write operation with ISR register
  hw/intc/loongarch_pch: Use relative address in MemoryRegionOps
  hw/intc/loongarch_pch: Set version information at initial stage
  hw/intc/loongarch_pch: Remove some duplicate macro
  hw/intc/loongarch_pch: Modify register name PCH_PIC_xxx_OFFSET with PCH_PIC_xxx
  hw/intc/loongarch_pch: Modify name of some registers

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/loongarch_pch_pic.c331
-rw-r--r--hw/intc/loongarch_pic_common.c13
-rw-r--r--hw/intc/trace-events8
3 files changed, 125 insertions, 227 deletions
diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c
index 834096265a..cbba2fc284 100644
--- a/hw/intc/loongarch_pch_pic.c
+++ b/hw/intc/loongarch_pch_pic.c
@@ -7,6 +7,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/bitops.h"
+#include "qemu/log.h"
 #include "hw/irq.h"
 #include "hw/intc/loongarch_pch_pic.h"
 #include "trace.h"
@@ -71,285 +72,181 @@ static void pch_pic_irq_handler(void *opaque, int irq, int level)
     pch_pic_update_irq(s, mask, level);
 }
 
-static uint64_t loongarch_pch_pic_low_readw(void *opaque, hwaddr addr,
-                                            unsigned size)
+static uint64_t pch_pic_read(void *opaque, hwaddr addr, uint64_t field_mask)
 {
     LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
     uint64_t val = 0;
-    uint32_t offset = addr & 0xfff;
+    uint32_t offset;
 
-    switch (offset) {
-    case PCH_PIC_INT_ID_LO:
-        val = PCH_PIC_INT_ID_VAL;
+    offset = addr & 7;
+    addr -= offset;
+    switch (addr) {
+    case PCH_PIC_INT_ID:
+        val = s->id.data;
         break;
-    case PCH_PIC_INT_ID_HI:
-        /*
-         * With 7A1000 manual
-         *   bit  0-15 pch irqchip version
-         *   bit 16-31 irq number supported with pch irqchip
-         */
-        val = deposit32(PCH_PIC_INT_ID_VER, 16, 16, s->irq_num - 1);
+    case PCH_PIC_INT_MASK:
+        val = s->int_mask;
         break;
-    case PCH_PIC_INT_MASK_LO:
-        val = (uint32_t)s->int_mask;
+    case PCH_PIC_INT_EDGE:
+        val = s->intedge;
         break;
-    case PCH_PIC_INT_MASK_HI:
-        val = s->int_mask >> 32;
+    case PCH_PIC_HTMSI_EN:
+        val = s->htmsi_en;
         break;
-    case PCH_PIC_INT_EDGE_LO:
-        val = (uint32_t)s->intedge;
+    case PCH_PIC_AUTO_CTRL0:
+    case PCH_PIC_AUTO_CTRL1:
+        /* PCH PIC connect to EXTIOI always, discard auto_ctrl access */
         break;
-    case PCH_PIC_INT_EDGE_HI:
-        val = s->intedge >> 32;
+    case PCH_PIC_INT_STATUS:
+        val = s->intisr & (~s->int_mask);
         break;
-    case PCH_PIC_HTMSI_EN_LO:
-        val = (uint32_t)s->htmsi_en;
+    case PCH_PIC_INT_POL:
+        val = s->int_polarity;
         break;
-    case PCH_PIC_HTMSI_EN_HI:
-        val = s->htmsi_en >> 32;
+    case PCH_PIC_HTMSI_VEC ... PCH_PIC_HTMSI_VEC_END:
+        val = *(uint64_t *)(s->htmsi_vector + addr - PCH_PIC_HTMSI_VEC);
         break;
-    case PCH_PIC_AUTO_CTRL0_LO:
-    case PCH_PIC_AUTO_CTRL0_HI:
-    case PCH_PIC_AUTO_CTRL1_LO:
-    case PCH_PIC_AUTO_CTRL1_HI:
+    case PCH_PIC_ROUTE_ENTRY ... PCH_PIC_ROUTE_ENTRY_END:
+        val = *(uint64_t *)(s->route_entry + addr - PCH_PIC_ROUTE_ENTRY);
         break;
     default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "pch_pic_read: Bad address 0x%"PRIx64"\n", addr);
         break;
     }
 
-    trace_loongarch_pch_pic_low_readw(size, addr, val);
-    return val;
+    return (val >> (offset * 8)) & field_mask;
 }
 
-static uint64_t get_writew_val(uint64_t value, uint32_t target, bool hi)
-{
-    uint64_t mask = 0xffffffff00000000;
-    uint64_t data = target;
-
-    return hi ? (value & ~mask) | (data << 32) : (value & mask) | data;
-}
-
-static void loongarch_pch_pic_low_writew(void *opaque, hwaddr addr,
-                                         uint64_t value, unsigned size)
+static void pch_pic_write(void *opaque, hwaddr addr, uint64_t value,
+                          uint64_t field_mask)
 {
     LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
-    uint32_t offset, old_valid, data = (uint32_t)value;
-    uint64_t old, int_mask;
-    offset = addr & 0xfff;
-
-    trace_loongarch_pch_pic_low_writew(size, addr, data);
-
-    switch (offset) {
-    case PCH_PIC_INT_MASK_LO:
+    uint32_t offset;
+    uint64_t old, mask, data, *ptemp;
+
+    offset = addr & 7;
+    addr -= offset;
+    mask = field_mask << (offset * 8);
+    data = (value & field_mask) << (offset * 8);
+    switch (addr) {
+    case PCH_PIC_INT_MASK:
         old = s->int_mask;
-        s->int_mask = get_writew_val(old, data, 0);
-        old_valid = (uint32_t)old;
-        if (old_valid & ~data) {
-            pch_pic_update_irq(s, (old_valid & ~data), 1);
+        s->int_mask = (old & ~mask) | data;
+        if (old & ~data) {
+            pch_pic_update_irq(s, old & ~data, 1);
         }
-        if (~old_valid & data) {
-            pch_pic_update_irq(s, (~old_valid & data), 0);
-        }
-        break;
-    case PCH_PIC_INT_MASK_HI:
-        old = s->int_mask;
-        s->int_mask = get_writew_val(old, data, 1);
-        old_valid = (uint32_t)(old >> 32);
-        int_mask = old_valid & ~data;
-        if (int_mask) {
-            pch_pic_update_irq(s, int_mask << 32, 1);
-        }
-        int_mask = ~old_valid & data;
-        if (int_mask) {
-            pch_pic_update_irq(s, int_mask << 32, 0);
+
+        if (~old & data) {
+            pch_pic_update_irq(s, ~old & data, 0);
         }
         break;
-    case PCH_PIC_INT_EDGE_LO:
-        s->intedge = get_writew_val(s->intedge, data, 0);
-        break;
-    case PCH_PIC_INT_EDGE_HI:
-        s->intedge = get_writew_val(s->intedge, data, 1);
+    case PCH_PIC_INT_EDGE:
+        s->intedge = (s->intedge & ~mask) | data;
         break;
-    case PCH_PIC_INT_CLEAR_LO:
+    case PCH_PIC_INT_CLEAR:
         if (s->intedge & data) {
-            s->intirr &= (~data);
+            s->intirr &= ~data;
             pch_pic_update_irq(s, data, 0);
-            s->intisr &= (~data);
+            s->intisr &= ~data;
         }
         break;
-    case PCH_PIC_INT_CLEAR_HI:
-        value <<= 32;
-        if (s->intedge & value) {
-            s->intirr &= (~value);
-            pch_pic_update_irq(s, value, 0);
-            s->intisr &= (~value);
-        }
+    case PCH_PIC_HTMSI_EN:
+        s->htmsi_en = (s->htmsi_en & ~mask) | data;
+        break;
+    case PCH_PIC_AUTO_CTRL0:
+    case PCH_PIC_AUTO_CTRL1:
+        /* Discard auto_ctrl access */
         break;
-    case PCH_PIC_HTMSI_EN_LO:
-        s->htmsi_en = get_writew_val(s->htmsi_en, data, 0);
+    case PCH_PIC_INT_POL:
+        s->int_polarity = (s->int_polarity & ~mask) | data;
         break;
-    case PCH_PIC_HTMSI_EN_HI:
-        s->htmsi_en = get_writew_val(s->htmsi_en, data, 1);
+    case PCH_PIC_HTMSI_VEC ... PCH_PIC_HTMSI_VEC_END:
+        ptemp = (uint64_t *)(s->htmsi_vector + addr - PCH_PIC_HTMSI_VEC);
+        *ptemp = (*ptemp & ~mask) | data;
         break;
-    case PCH_PIC_AUTO_CTRL0_LO:
-    case PCH_PIC_AUTO_CTRL0_HI:
-    case PCH_PIC_AUTO_CTRL1_LO:
-    case PCH_PIC_AUTO_CTRL1_HI:
+    case PCH_PIC_ROUTE_ENTRY ... PCH_PIC_ROUTE_ENTRY_END:
+        ptemp = (uint64_t *)(s->route_entry + addr - PCH_PIC_ROUTE_ENTRY);
+        *ptemp = (*ptemp & ~mask) | data;
         break;
     default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "pch_pic_write: Bad address 0x%"PRIx64"\n", addr);
         break;
     }
 }
 
-static uint64_t loongarch_pch_pic_high_readw(void *opaque, hwaddr addr,
-                                        unsigned size)
+static uint64_t loongarch_pch_pic_read(void *opaque, hwaddr addr,
+                                       unsigned size)
 {
-    LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
     uint64_t val = 0;
-    uint32_t offset = addr & 0xfff;
 
-    switch (offset) {
-    case STATUS_LO_START:
-        val = (uint32_t)(s->intisr & (~s->int_mask));
+    switch (size) {
+    case 1:
+        val = pch_pic_read(opaque, addr, UCHAR_MAX);
         break;
-    case STATUS_HI_START:
-        val = (s->intisr & (~s->int_mask)) >> 32;
+    case 2:
+        val = pch_pic_read(opaque, addr, USHRT_MAX);
         break;
-    case POL_LO_START:
-        val = (uint32_t)s->int_polarity;
+    case 4:
+        val = pch_pic_read(opaque, addr, UINT_MAX);
         break;
-    case POL_HI_START:
-        val = s->int_polarity >> 32;
+    case 8:
+        val = pch_pic_read(opaque, addr, UINT64_MAX);
         break;
     default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "loongarch_pch_pic_read: Bad size %d\n", size);
         break;
     }
 
-    trace_loongarch_pch_pic_high_readw(size, addr, val);
+    trace_loongarch_pch_pic_read(size, addr, val);
     return val;
 }
 
-static void loongarch_pch_pic_high_writew(void *opaque, hwaddr addr,
-                                     uint64_t value, unsigned size)
+static void loongarch_pch_pic_write(void *opaque, hwaddr addr,
+                                    uint64_t value, unsigned size)
 {
-    LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
-    uint32_t offset, data = (uint32_t)value;
-    offset = addr & 0xfff;
-
-    trace_loongarch_pch_pic_high_writew(size, addr, data);
+    trace_loongarch_pch_pic_write(size, addr, value);
 
-    switch (offset) {
-    case STATUS_LO_START:
-        s->intisr = get_writew_val(s->intisr, data, 0);
-        break;
-    case STATUS_HI_START:
-        s->intisr = get_writew_val(s->intisr, data, 1);
-        break;
-    case POL_LO_START:
-        s->int_polarity = get_writew_val(s->int_polarity, data, 0);
-        break;
-    case POL_HI_START:
-        s->int_polarity = get_writew_val(s->int_polarity, data, 1);
-        break;
-    default:
-        break;
-    }
-}
-
-static uint64_t loongarch_pch_pic_readb(void *opaque, hwaddr addr,
-                                        unsigned size)
-{
-    LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
-    uint64_t val = 0;
-    uint32_t offset = (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET;
-    int64_t offset_tmp;
-
-    switch (offset) {
-    case PCH_PIC_HTMSI_VEC_OFFSET ... PCH_PIC_HTMSI_VEC_END:
-        offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET;
-        if (offset_tmp >= 0 && offset_tmp < 64) {
-            val = s->htmsi_vector[offset_tmp];
-        }
+    switch (size) {
+    case 1:
+        pch_pic_write(opaque, addr, value, UCHAR_MAX);
         break;
-    case PCH_PIC_ROUTE_ENTRY_OFFSET ... PCH_PIC_ROUTE_ENTRY_END:
-        offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET;
-        if (offset_tmp >= 0 && offset_tmp < 64) {
-            val = s->route_entry[offset_tmp];
-        }
+    case 2:
+        pch_pic_write(opaque, addr, value, USHRT_MAX);
         break;
-    default:
         break;
-    }
-
-    trace_loongarch_pch_pic_readb(size, addr, val);
-    return val;
-}
-
-static void loongarch_pch_pic_writeb(void *opaque, hwaddr addr,
-                                     uint64_t data, unsigned size)
-{
-    LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
-    int32_t offset_tmp;
-    uint32_t offset = (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET;
-
-    trace_loongarch_pch_pic_writeb(size, addr, data);
-
-    switch (offset) {
-    case PCH_PIC_HTMSI_VEC_OFFSET ... PCH_PIC_HTMSI_VEC_END:
-        offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET;
-        if (offset_tmp >= 0 && offset_tmp < 64) {
-            s->htmsi_vector[offset_tmp] = (uint8_t)(data & 0xff);
-        }
+    case 4:
+        pch_pic_write(opaque, addr, value, UINT_MAX);
         break;
-    case PCH_PIC_ROUTE_ENTRY_OFFSET ... PCH_PIC_ROUTE_ENTRY_END:
-        offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET;
-        if (offset_tmp >= 0 && offset_tmp < 64) {
-            s->route_entry[offset_tmp] = (uint8_t)(data & 0xff);
-        }
+    case 8:
+        pch_pic_write(opaque, addr, value, UINT64_MAX);
         break;
     default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "loongarch_pch_pic_write: Bad size %d\n", size);
         break;
     }
 }
 
-static const MemoryRegionOps loongarch_pch_pic_reg32_low_ops = {
-    .read = loongarch_pch_pic_low_readw,
-    .write = loongarch_pch_pic_low_writew,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 8,
-    },
-    .impl = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static const MemoryRegionOps loongarch_pch_pic_reg32_high_ops = {
-    .read = loongarch_pch_pic_high_readw,
-    .write = loongarch_pch_pic_high_writew,
-    .valid = {
-        .min_access_size = 4,
-        .max_access_size = 8,
-    },
-    .impl = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-static const MemoryRegionOps loongarch_pch_pic_reg8_ops = {
-    .read = loongarch_pch_pic_readb,
-    .write = loongarch_pch_pic_writeb,
+static const MemoryRegionOps loongarch_pch_pic_ops = {
+    .read = loongarch_pch_pic_read,
+    .write = loongarch_pch_pic_write,
     .valid = {
         .min_access_size = 1,
-        .max_access_size = 1,
+        .max_access_size = 8,
+        /*
+         * PCH PIC device would not work correctly if the guest was doing
+         * unaligned access. This might not be a limitation on the real
+         * device but in practice there is no reason for a guest to access
+         * this device unaligned.
+         */
+        .unaligned = false,
     },
     .impl = {
         .min_access_size = 1,
-        .max_access_size = 1,
+        .max_access_size = 8,
     },
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
@@ -378,18 +275,10 @@ static void loongarch_pic_realize(DeviceState *dev, Error **errp)
 
     qdev_init_gpio_out(dev, s->parent_irq, s->irq_num);
     qdev_init_gpio_in(dev, pch_pic_irq_handler, s->irq_num);
-    memory_region_init_io(&s->iomem32_low, OBJECT(dev),
-                          &loongarch_pch_pic_reg32_low_ops,
-                          s, PCH_PIC_NAME(.reg32_part1), 0x100);
-    memory_region_init_io(&s->iomem8, OBJECT(dev), &loongarch_pch_pic_reg8_ops,
-                          s, PCH_PIC_NAME(.reg8), 0x2a0);
-    memory_region_init_io(&s->iomem32_high, OBJECT(dev),
-                          &loongarch_pch_pic_reg32_high_ops,
-                          s, PCH_PIC_NAME(.reg32_part2), 0xc60);
-    sysbus_init_mmio(sbd, &s->iomem32_low);
-    sysbus_init_mmio(sbd, &s->iomem8);
-    sysbus_init_mmio(sbd, &s->iomem32_high);
-
+    memory_region_init_io(&s->iomem, OBJECT(dev),
+                          &loongarch_pch_pic_ops,
+                          s, TYPE_LOONGARCH_PIC, VIRT_PCH_REG_SIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
 }
 
 static void loongarch_pic_class_init(ObjectClass *klass, const void *data)
diff --git a/hw/intc/loongarch_pic_common.c b/hw/intc/loongarch_pic_common.c
index 6dccacc741..de170501cf 100644
--- a/hw/intc/loongarch_pic_common.c
+++ b/hw/intc/loongarch_pic_common.c
@@ -49,6 +49,19 @@ static void loongarch_pic_common_reset_hold(Object *obj, ResetType type)
     LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(obj);
     int i;
 
+    /*
+     * With Loongson 7A1000 user manual
+     * Chapter 5.2 "Description of Interrupt-related Registers"
+     *
+     * Interrupt controller identification register 1
+     *   Bit 24-31 Interrupt Controller ID
+     * Interrupt controller identification register 2
+     *   Bit  0-7  Interrupt Controller version number
+     *   Bit 16-23 The number of interrupt sources supported
+     */
+    s->id.desc.id = PCH_PIC_INT_ID_VAL;
+    s->id.desc.version = PCH_PIC_INT_ID_VER;
+    s->id.desc.irq_num = s->irq_num - 1;
     s->int_mask = UINT64_MAX;
     s->htmsi_en = 0x0;
     s->intedge  = 0x0;
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 0ba9a02e73..334aa6a97b 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -314,12 +314,8 @@ loongson_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x
 loongson_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
 # loongarch_pch_pic.c
 loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d"
-loongarch_pch_pic_low_readw(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
-loongarch_pch_pic_low_writew(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
-loongarch_pch_pic_high_readw(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
-loongarch_pch_pic_high_writew(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
-loongarch_pch_pic_readb(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
-loongarch_pch_pic_writeb(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
+loongarch_pch_pic_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
+loongarch_pch_pic_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
 
 # loongarch_pch_msi.c
 loongarch_msi_set_irq(int irq_num) "set msi irq %d"