Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging

virtio,pci,pc: features, fixes

intel_iommu:
    SVM support
vhost:
    support for indirect descriptors in shadow virtqueue
vhost-user:
    vhost-user-spi support
    vhost-user-blk inflight migration support
    vhost-user-blk inflight migration support

misc fixes in pci, vhost, virtio, acpi, cxl
cleanups in acpi/ghes

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# -----BEGIN PGP SIGNATURE-----
#
# iQFDBAABCgAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmmEa9APHG1zdEByZWRo
# YXQuY29tAAoJECgfDbjSjVRpqj8H/iBqAHZSTmAdBJgoLnmgoTLB01J9aUTrQU2H
# BHKyrd+G3m54pwjgUNN5ieZARtlXscigf6fr0Gq2wrc8/kV/O5G5jViw9+1Bo8nW
# OkLDW45nDzZGhap4oUedV+PJ3fCuW2fC8Jyb1n8OGlkadbhq0NU6GtqiEx6/7QIh
# hk5WUDE/3LH4cTp8qNtr0/nYfM4FZk2sjq7aRyg4cz/uC7rIAFRq7BCZ/dfRqMh/
# T+rLnizSSAg9PFMd8slWqoxOGF9NzT9LIoDSkAlso1L9lUekUSNoUblhlWDrRlLn
# DEEqqGCVounfBzA95WrTRmvWs6JodppjjAjI0M4isrMKGXXg8dg=
# =HdgY
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu Feb  5 10:07:12 2026 GMT
# gpg:                using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469
# gpg:                issuer "mst@redhat.com"
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full]
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>" [full]
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu: (38 commits)
  hw/cxl: Take into account how many media operations are requested for param check
  hw/cxl: Check for overflow on santize media as both base and offset 64bit.
  vhost-user-blk: support inter-host inflight migration
  vhost: add vmstate for inflight region with inner buffer
  vmstate: introduce VMSTATE_VBUFFER_UINT64
  vhost-user: introduce protocol feature for skip drain on GET_VRING_BASE
  vhost-user.rst: specify vhost-user back-end action on GET_VRING_BASE
  virtio-gpu: use consistent error checking for virtio_gpu_create_mapping_iov
  virtio-gpu: fix error handling in virgl_cmd_resource_create_blob
  virtio-pmem: ignore empty queue notifications
  virtio-gpu-virgl: correct parent for blob memory region
  MAINTAINERS: Update VIOT maintainer
  cryptodev-builtin: Limit the maximum size
  hw/virtio/virtio-crypto: verify asym request size
  virtio-spi: Add vhost-user-spi device support
  standard-headers: Update virtio_spi.h from Linux v6.18-rc3
  q35: Fix migration of SMRAM state
  pcie_sriov: Fix PCI_SRIOV_* accesses in pcie_sriov_pf_exit()
  virtio: Fix crash when sriov-pf is set for non-PCI-Express device
  virtio-dmabuf: Ensure UUID persistence for hash table insertion
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/MAINTAINERS b/MAINTAINERS
index ebd27cd..65ac60b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1249,11 +1249,13 @@
 F: include/hw/net/ftgmac100.h
 F: docs/system/arm/aspeed.rst
 F: docs/system/arm/fby35.rst
+F: docs/specs/aspeed*
 F: tests/functional/*/*aspeed*
 F: tests/*/*aspeed*
 F: tests/*/*ast2700*
 F: hw/arm/fby35.c
 F: pc-bios/ast27x0_bootrom.bin
+F: roms/vbootrom
 
 NRF51
 M: Joel Stanley <joel@jms.id.au>
diff --git a/backends/igvm-cfg.c b/backends/igvm-cfg.c
index d00acf3..64589ca 100644
--- a/backends/igvm-cfg.c
+++ b/backends/igvm-cfg.c
@@ -11,9 +11,15 @@
 
 #include "qemu/osdep.h"
 
-#include "system/igvm-cfg.h"
 #include "system/igvm.h"
+#include "system/igvm-cfg.h"
+#include "system/igvm-internal.h"
+#include "system/reset.h"
 #include "qom/object_interfaces.h"
+#include "hw/core/qdev.h"
+#include "hw/core/boards.h"
+
+#include "trace.h"
 
 static char *get_igvm(Object *obj, Error **errp)
 {
@@ -28,24 +34,78 @@
     igvm->filename = g_strdup(value);
 }
 
+static ResettableState *igvm_reset_state(Object *obj)
+{
+    IgvmCfg *igvm = IGVM_CFG(obj);
+    return &igvm->reset_state;
+}
+
+static void igvm_reset_enter(Object *obj, ResetType type)
+{
+    trace_igvm_reset_enter(type);
+}
+
+static void igvm_reset_hold(Object *obj, ResetType type)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+    IgvmCfg *igvm = IGVM_CFG(obj);
+
+    trace_igvm_reset_hold(type);
+
+    qigvm_process_file(igvm, ms, false, &error_fatal);
+}
+
+static void igvm_reset_exit(Object *obj, ResetType type)
+{
+    trace_igvm_reset_exit(type);
+}
+
+static void igvm_complete(UserCreatable *uc, Error **errp)
+{
+    IgvmCfg *igvm = IGVM_CFG(uc);
+
+    igvm->file = qigvm_file_init(igvm->filename, errp);
+}
+
 OBJECT_DEFINE_TYPE_WITH_INTERFACES(IgvmCfg, igvm_cfg, IGVM_CFG, OBJECT,
-                                   { TYPE_USER_CREATABLE }, { NULL })
+                                   { TYPE_USER_CREATABLE },
+                                   { TYPE_RESETTABLE_INTERFACE },
+                                   { NULL })
 
 static void igvm_cfg_class_init(ObjectClass *oc, const void *data)
 {
     IgvmCfgClass *igvmc = IGVM_CFG_CLASS(oc);
+    ResettableClass *rc = RESETTABLE_CLASS(oc);
+    UserCreatableClass *uc = USER_CREATABLE_CLASS(oc);
 
     object_class_property_add_str(oc, "file", get_igvm, set_igvm);
     object_class_property_set_description(oc, "file",
                                           "Set the IGVM filename to use");
 
     igvmc->process = qigvm_process_file;
+
+    rc->get_state = igvm_reset_state;
+    rc->phases.enter = igvm_reset_enter;
+    rc->phases.hold = igvm_reset_hold;
+    rc->phases.exit = igvm_reset_exit;
+
+    uc->complete = igvm_complete;
 }
 
 static void igvm_cfg_init(Object *obj)
 {
+    IgvmCfg *igvm = IGVM_CFG(obj);
+
+    igvm->file = -1;
+    qemu_register_resettable(obj);
 }
 
 static void igvm_cfg_finalize(Object *obj)
 {
+    IgvmCfg *igvm = IGVM_CFG(obj);
+
+    qemu_unregister_resettable(obj);
+    if (igvm->file >= 0) {
+        igvm_free(igvm->file);
+    }
 }
diff --git a/backends/igvm.c b/backends/igvm.c
index 905bd8d..b01a19b 100644
--- a/backends/igvm.c
+++ b/backends/igvm.c
@@ -12,21 +12,20 @@
 #include "qemu/osdep.h"
 
 #include "qapi/error.h"
+#include "qemu/error-report.h"
 #include "qemu/target-info-qapi.h"
 #include "system/igvm.h"
+#include "system/igvm-cfg.h"
+#include "system/igvm-internal.h"
 #include "system/memory.h"
 #include "system/address-spaces.h"
 #include "hw/core/cpu.h"
 
+#include "trace.h"
+
 #include <igvm/igvm.h>
 #include <igvm/igvm_defs.h>
 
-typedef struct QIgvmParameterData {
-    QTAILQ_ENTRY(QIgvmParameterData) next;
-    uint8_t *data;
-    uint32_t size;
-    uint32_t index;
-} QIgvmParameterData;
 
 /*
  * Some directives are specific to particular confidential computing platforms.
@@ -62,36 +61,19 @@
 
 #define IGVM_SEV_ID_BLOCK_VERSION 1
 
-/*
- * QIgvm contains the information required during processing
- * of a single IGVM file.
- */
-typedef struct QIgvm {
-    IgvmHandle file;
-    ConfidentialGuestSupport *cgs;
-    ConfidentialGuestSupportClass *cgsc;
-    uint32_t compatibility_mask;
-    unsigned current_header_index;
-    QTAILQ_HEAD(, QIgvmParameterData) parameter_data;
-    IgvmPlatformType platform_type;
-
-    /*
-     * SEV-SNP platforms can contain an ID block and authentication
-     * that should be verified by the guest.
-     */
-    struct sev_id_block *id_block;
-    struct sev_id_authentication *id_auth;
-
-    /* Define the guest policy for SEV guests */
-    uint64_t sev_policy;
-
-    /* These variables keep track of contiguous page regions */
-    IGVM_VHS_PAGE_DATA region_prev_page_data;
-    uint64_t region_start;
-    unsigned region_start_index;
-    unsigned region_last_index;
-    unsigned region_page_count;
-} QIgvm;
+QIgvmParameterData*
+qigvm_find_param_entry(QIgvm *igvm, uint32_t parameter_area_index)
+{
+    QIgvmParameterData *param_entry;
+    QTAILQ_FOREACH(param_entry, &igvm->parameter_data, next)
+    {
+        if (param_entry->index == parameter_area_index) {
+            return param_entry;
+        }
+    }
+    warn_report("IGVM: No parameter area for index %u", parameter_area_index);
+    return NULL;
+}
 
 static int qigvm_directive_page_data(QIgvm *ctx, const uint8_t *header_data,
                                      Error **errp);
@@ -146,6 +128,8 @@
       qigvm_directive_snp_id_block },
     { IGVM_VHT_GUEST_POLICY, IGVM_HEADER_SECTION_INITIALIZATION,
       qigvm_initialization_guest_policy },
+    { IGVM_VHT_MADT, IGVM_HEADER_SECTION_DIRECTIVE,
+      qigvm_directive_madt },
 };
 
 static int qigvm_handler(QIgvm *ctx, uint32_t type, Error **errp)
@@ -220,7 +204,8 @@
         g_autofree char *region_name =
             g_strdup_printf("igvm.%X", region_identifier);
         igvm_pages = g_new0(MemoryRegion, 1);
-        if (ctx->cgs && ctx->cgs->require_guest_memfd) {
+        if (ctx->machine_state->cgs &&
+            ctx->machine_state->cgs->require_guest_memfd) {
             if (!memory_region_init_ram_guest_memfd(igvm_pages, NULL,
                                                     region_name, size, errp)) {
                 return NULL;
@@ -340,7 +325,7 @@
      * If a confidential guest support object is provided then use it to set the
      * guest state.
      */
-    if (ctx->cgs) {
+    if (ctx->machine_state->cgs) {
         cgs_page_type =
             qigvm_type_to_cgs_type(page_type, flags->unmeasured, zero);
         if (cgs_page_type < 0) {
@@ -442,7 +427,7 @@
 
     data = (uint8_t *)igvm_get_buffer(ctx->file, data_handle);
 
-    if (ctx->cgs) {
+    if (ctx->machine_state->cgs) {
         result = ctx->cgsc->set_guest_state(
             vp_context->gpa, data, igvm_get_buffer_size(ctx->file, data_handle),
             CGS_PAGE_TYPE_VMSA, vp_context->vp_index, errp);
@@ -494,31 +479,31 @@
         return 0;
     }
 
-    QTAILQ_FOREACH(param_entry, &ctx->parameter_data, next)
-    {
-        if (param_entry->index == param->parameter_area_index) {
-            region = qigvm_prepare_memory(ctx, param->gpa, param_entry->size,
-                                          ctx->current_header_index, errp);
-            if (!region) {
-                return -1;
-            }
-            memcpy(region, param_entry->data, param_entry->size);
-            g_free(param_entry->data);
-            param_entry->data = NULL;
+    param_entry = qigvm_find_param_entry(ctx, param->parameter_area_index);
+    if (param_entry == NULL) {
+        return 0;
+    }
 
-            /*
-             * If a confidential guest support object is provided then use it to
-             * set the guest state.
-             */
-            if (ctx->cgs) {
-                result = ctx->cgsc->set_guest_state(param->gpa, region,
-                                                    param_entry->size,
-                                                    CGS_PAGE_TYPE_UNMEASURED, 0,
-                                                    errp);
-                if (result < 0) {
-                    return -1;
-                }
-            }
+    region = qigvm_prepare_memory(ctx, param->gpa, param_entry->size,
+                                    ctx->current_header_index, errp);
+    if (!region) {
+        return -1;
+    }
+    memcpy(region, param_entry->data, param_entry->size);
+    g_free(param_entry->data);
+    param_entry->data = NULL;
+
+    /*
+     * If a confidential guest support object is provided then use it to
+     * set the guest state.
+     */
+    if (ctx->machine_state->cgs) {
+        result = ctx->cgsc->set_guest_state(param->gpa, region,
+                                            param_entry->size,
+                                            CGS_PAGE_TYPE_UNMEASURED, 0,
+                                            errp);
+        if (result < 0) {
+            return -1;
         }
     }
     return 0;
@@ -553,7 +538,7 @@
     ConfidentialGuestMemoryMapEntry cgmm_entry;
     int retval = 0;
 
-    if (ctx->cgs && ctx->cgsc->get_mem_map_entry) {
+    if (ctx->machine_state->cgs && ctx->cgsc->get_mem_map_entry) {
         get_mem_map_entry = ctx->cgsc->get_mem_map_entry;
 
     } else if (target_arch() == SYS_EMU_TARGET_X86_64) {
@@ -567,58 +552,54 @@
     }
 
     /* Find the parameter area that should hold the memory map */
-    QTAILQ_FOREACH(param_entry, &ctx->parameter_data, next)
-    {
-        if (param_entry->index == param->parameter_area_index) {
-            max_entry_count =
-                param_entry->size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
-            mm_entry = (IGVM_VHS_MEMORY_MAP_ENTRY *)param_entry->data;
+    param_entry = qigvm_find_param_entry(ctx, param->parameter_area_index);
+    if (param_entry == NULL) {
+        return 0;
+    }
 
-            retval = get_mem_map_entry(entry, &cgmm_entry, errp);
-            while (retval == 0) {
-                if (entry >= max_entry_count) {
-                    error_setg(
-                        errp,
-                        "IGVM: guest memory map size exceeds parameter area defined in IGVM file");
-                    return -1;
-                }
-                mm_entry[entry].starting_gpa_page_number = cgmm_entry.gpa >> 12;
-                mm_entry[entry].number_of_pages = cgmm_entry.size >> 12;
+    max_entry_count = param_entry->size / sizeof(IGVM_VHS_MEMORY_MAP_ENTRY);
+    mm_entry = (IGVM_VHS_MEMORY_MAP_ENTRY *)param_entry->data;
 
-                switch (cgmm_entry.type) {
-                case CGS_MEM_RAM:
-                    mm_entry[entry].entry_type =
-                        IGVM_MEMORY_MAP_ENTRY_TYPE_MEMORY;
-                    break;
-                case CGS_MEM_RESERVED:
-                    mm_entry[entry].entry_type =
-                        IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
-                    break;
-                case CGS_MEM_ACPI:
-                    mm_entry[entry].entry_type =
-                        IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
-                    break;
-                case CGS_MEM_NVS:
-                    mm_entry[entry].entry_type =
-                        IGVM_MEMORY_MAP_ENTRY_TYPE_PERSISTENT;
-                    break;
-                case CGS_MEM_UNUSABLE:
-                    mm_entry[entry].entry_type =
-                        IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
-                    break;
-                }
-                retval = get_mem_map_entry(++entry, &cgmm_entry, errp);
-            }
-            if (retval < 0) {
-                return retval;
-            }
-            /* The entries need to be sorted */
-            qsort(mm_entry, entry, sizeof(IGVM_VHS_MEMORY_MAP_ENTRY),
-                  qigvm_cmp_mm_entry);
+    retval = get_mem_map_entry(entry, &cgmm_entry, errp);
+    while (retval == 0) {
+        if (entry >= max_entry_count) {
+            error_setg(
+                errp,
+                "IGVM: guest memory map size exceeds parameter area defined "
+                "in IGVM file");
+            return -1;
+        }
+        mm_entry[entry].starting_gpa_page_number = cgmm_entry.gpa >> 12;
+        mm_entry[entry].number_of_pages = cgmm_entry.size >> 12;
 
+        switch (cgmm_entry.type) {
+        case CGS_MEM_RAM:
+            mm_entry[entry].entry_type = IGVM_MEMORY_MAP_ENTRY_TYPE_MEMORY;
+            break;
+        case CGS_MEM_RESERVED:
+            mm_entry[entry].entry_type =
+                IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
+            break;
+        case CGS_MEM_ACPI:
+            mm_entry[entry].entry_type =
+                IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
+            break;
+        case CGS_MEM_NVS:
+            mm_entry[entry].entry_type = IGVM_MEMORY_MAP_ENTRY_TYPE_PERSISTENT;
+            break;
+        case CGS_MEM_UNUSABLE:
+            mm_entry[entry].entry_type =
+                IGVM_MEMORY_MAP_ENTRY_TYPE_PLATFORM_RESERVED;
             break;
         }
+        retval = get_mem_map_entry(++entry, &cgmm_entry, errp);
     }
+    if (retval < 0) {
+        return retval;
+    }
+    /* The entries need to be sorted */
+    qsort(mm_entry, entry, sizeof(IGVM_VHS_MEMORY_MAP_ENTRY),
+          qigvm_cmp_mm_entry);
     return 0;
 }
 
@@ -630,18 +611,18 @@
     uint32_t *vp_count;
     CPUState *cpu;
 
-    QTAILQ_FOREACH(param_entry, &ctx->parameter_data, next)
-    {
-        if (param_entry->index == param->parameter_area_index) {
-            vp_count = (uint32_t *)(param_entry->data + param->byte_offset);
-            *vp_count = 0;
-            CPU_FOREACH(cpu)
-            {
-                (*vp_count)++;
-            }
-            break;
-        }
+    param_entry = qigvm_find_param_entry(ctx, param->parameter_area_index);
+    if (param_entry == NULL) {
+        return 0;
     }
+
+    vp_count = (uint32_t *)(param_entry->data + param->byte_offset);
+    *vp_count = 0;
+    CPU_FOREACH(cpu)
+    {
+        (*vp_count)++;
+    }
+
     return 0;
 }
 
@@ -653,15 +634,15 @@
     QIgvmParameterData *param_entry;
     IgvmEnvironmentInfo *environmental_state;
 
-    QTAILQ_FOREACH(param_entry, &ctx->parameter_data, next)
-    {
-        if (param_entry->index == param->parameter_area_index) {
-            environmental_state =
-                (IgvmEnvironmentInfo *)(param_entry->data + param->byte_offset);
-            environmental_state->memory_is_shared = 1;
-            break;
-        }
+    param_entry = qigvm_find_param_entry(ctx, param->parameter_area_index);
+    if (param_entry == NULL) {
+        return 0;
     }
+
+    environmental_state =
+        (IgvmEnvironmentInfo *)(param_entry->data + param->byte_offset);
+    environmental_state->memory_is_shared = 1;
+
     return 0;
 }
 
@@ -683,7 +664,7 @@
     if (!region) {
         return -1;
     }
-    if (ctx->cgs) {
+    if (ctx->machine_state->cgs) {
         result =
             ctx->cgsc->set_guest_state(mem->gpa, region, mem->number_of_bytes,
                                        CGS_PAGE_TYPE_REQUIRED_MEMORY, 0, errp);
@@ -801,14 +782,14 @@
                                                 sizeof(
                                                     IGVM_VHS_VARIABLE_HEADER));
             if ((platform->platform_type == IGVM_PLATFORM_TYPE_SEV_ES) &&
-                ctx->cgs) {
+                ctx->machine_state->cgs) {
                 if (ctx->cgsc->check_support(
                         CGS_PLATFORM_SEV_ES, platform->platform_version,
                         platform->highest_vtl, platform->shared_gpa_boundary)) {
                     compatibility_mask_sev_es = platform->compatibility_mask;
                 }
             } else if ((platform->platform_type == IGVM_PLATFORM_TYPE_SEV) &&
-                       ctx->cgs) {
+                       ctx->machine_state->cgs) {
                 if (ctx->cgsc->check_support(
                         CGS_PLATFORM_SEV, platform->platform_version,
                         platform->highest_vtl, platform->shared_gpa_boundary)) {
@@ -816,7 +797,7 @@
                 }
             } else if ((platform->platform_type ==
                         IGVM_PLATFORM_TYPE_SEV_SNP) &&
-                       ctx->cgs) {
+                       ctx->machine_state->cgs) {
                 if (ctx->cgsc->check_support(
                         CGS_PLATFORM_SEV_SNP, platform->platform_version,
                         platform->highest_vtl, platform->shared_gpa_boundary)) {
@@ -867,7 +848,7 @@
     return 0;
 }
 
-static IgvmHandle qigvm_file_init(char *filename, Error **errp)
+IgvmHandle qigvm_file_init(char *filename, Error **errp)
 {
     IgvmHandle igvm;
     g_autofree uint8_t *buf = NULL;
@@ -884,10 +865,12 @@
         error_setg(errp, "Unable to parse IGVM file %s: %d", filename, igvm);
         return -1;
     }
+
+    trace_igvm_file_loaded(filename, igvm);
     return igvm;
 }
 
-int qigvm_process_file(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
+int qigvm_process_file(IgvmCfg *cfg, MachineState *machine_state,
                        bool onlyVpContext, Error **errp)
 {
     int32_t header_count;
@@ -896,18 +879,23 @@
     QIgvm ctx;
 
     memset(&ctx, 0, sizeof(ctx));
-    ctx.file = qigvm_file_init(cfg->filename, errp);
-    if (ctx.file < 0) {
+    if (cfg->file < 0) {
+        error_setg(errp, "No IGVM file loaded.");
         return -1;
     }
+    ctx.file = cfg->file;
+    trace_igvm_process_file(cfg->file, onlyVpContext);
+
+    ctx.machine_state = machine_state;
 
     /*
      * The ConfidentialGuestSupport object is optional and allows a confidential
      * guest platform to perform extra processing, such as page measurement, on
      * IGVM directives.
      */
-    ctx.cgs = cgs;
-    ctx.cgsc = cgs ? CONFIDENTIAL_GUEST_SUPPORT_GET_CLASS(cgs) : NULL;
+    ctx.cgsc = machine_state->cgs ?
+                   CONFIDENTIAL_GUEST_SUPPORT_GET_CLASS(machine_state->cgs) :
+                   NULL;
 
     /*
      * Check that the IGVM file provides configuration for the current
@@ -990,7 +978,5 @@
     g_free(ctx.id_auth);
 
 cleanup:
-    igvm_free(ctx.file);
-
     return retval;
 }
diff --git a/backends/trace-events b/backends/trace-events
index 14a7ecf..8dc64a2 100644
--- a/backends/trace-events
+++ b/backends/trace-events
@@ -23,3 +23,10 @@
 iommufd_backend_invalidate_cache(int iommufd, uint32_t id, uint32_t data_type, uint32_t entry_len, uint32_t entry_num, uint32_t done_num, uint64_t data_ptr, int ret) " iommufd=%d id=%u data_type=%u entry_len=%u entry_num=%u done_num=%u data_ptr=0x%"PRIx64" (%d)"
 iommufd_backend_alloc_viommu(int iommufd, uint32_t dev_id, uint32_t type, uint32_t hwpt_id, uint32_t viommu_id, int ret) " iommufd=%d type=%u dev_id=%u hwpt_id=%u viommu_id=%u (%d)"
 iommufd_backend_alloc_vdev(int iommufd, uint32_t dev_id, uint32_t viommu_id, uint64_t virt_id, uint32_t vdev_id, int ret) " iommufd=%d dev_id=%u viommu_id=%u virt_id=0x%"PRIx64" vdev_id=%u (%d)"
+
+# igvm-cfg.c
+igvm_reset_enter(int type) "type=%u"
+igvm_reset_hold(int type) "type=%u"
+igvm_reset_exit(int type) "type=%u"
+igvm_file_loaded(const char *fn, int32_t handle) "fn=%s, handle=0x%x"
+igvm_process_file(int32_t handle, bool context_only) "handle=0x%x context-only=%d"
diff --git a/disas/riscv.c b/disas/riscv.c
index 85cd2a9..6f26674 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -5409,7 +5409,7 @@
 /* disassemble instruction */
 
 static GString *disasm_inst(rv_isa isa, uint64_t pc, rv_inst inst,
-                            RISCVCPUConfig *cfg)
+                            const RISCVCPUConfig *cfg)
 {
     rv_decode dec = { 0 };
     dec.pc = pc;
@@ -5509,7 +5509,8 @@
     }
 
     g_autoptr(GString) str =
-        disasm_inst(isa, memaddr, inst, (RISCVCPUConfig *)info->target_info);
+        disasm_inst(isa, memaddr, inst,
+                    (const RISCVCPUConfig *)info->target_info);
     (*info->fprintf_func)(info->stream, "%s", str->str);
 
     return len;
diff --git a/disas/riscv.h b/disas/riscv.h
index d211700..379e642 100644
--- a/disas/riscv.h
+++ b/disas/riscv.h
@@ -189,7 +189,7 @@
 } rv_opcode_data;
 
 typedef struct {
-    RISCVCPUConfig *cfg;
+    const RISCVCPUConfig *cfg;
     uint64_t  pc;
     uint64_t  inst;
     const rv_opcode_data *opcode_data;
diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst
index 97e14b7..d0054a7 100644
--- a/docs/system/arm/aspeed.rst
+++ b/docs/system/arm/aspeed.rst
@@ -350,11 +350,9 @@
 .. code-block:: bash
 
   IMGDIR=ast2700-default
-  UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin)
 
   $ qemu-system-aarch64 -M ast2700-evb \
-       -device loader,force-raw=on,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin \
-       -device loader,force-raw=on,addr=$((0x400000000 + ${UBOOT_SIZE})),file=${IMGDIR}/u-boot.dtb \
+       -device loader,force-raw=on,addr=0x400000000,file=${IMGDIR}/u-boot.bin \
        -device loader,force-raw=on,addr=0x430000000,file=${IMGDIR}/bl31.bin \
        -device loader,force-raw=on,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin \
        -device loader,cpu-num=0,addr=0x430000000 \
@@ -409,11 +407,9 @@
 .. code-block:: bash
 
   IMGDIR=ast2700-default
-  UBOOT_SIZE=$(stat --format=%s -L ${IMGDIR}/u-boot-nodtb.bin)
 
   $ qemu-system-aarch64 -M ast2700fc \
-       -device loader,force-raw=on,addr=0x400000000,file=${IMGDIR}/u-boot-nodtb.bin \
-       -device loader,force-raw=on,addr=$((0x400000000 + ${UBOOT_SIZE})),file=${IMGDIR}/u-boot.dtb \
+       -device loader,force-raw=on,addr=0x400000000,file=${IMGDIR}/u-boot.bin \
        -device loader,force-raw=on,addr=0x430000000,file=${IMGDIR}/bl31.bin \
        -device loader,force-raw=on,addr=0x430080000,file=${IMGDIR}/optee/tee-raw.bin \
        -device loader,cpu-num=0,addr=0x430000000 \
diff --git a/docs/system/igvm.rst b/docs/system/igvm.rst
index 79508d9..9db8ae4 100644
--- a/docs/system/igvm.rst
+++ b/docs/system/igvm.rst
@@ -166,8 +166,8 @@
 ----------
 
 [1] AMD64 Architecture Programmer's Manual, Volume 2: System Programming
-  Rev 3.41
-  https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24593.pdf
+  Rev 3.43
+  https://docs.amd.com/v/u/en-US/24593_3.43
 
 [2] ``buildigvm`` - A tool to build example IGVM files containing OVMF firmware
-  https://github.com/roy-hopkins/buildigvm
\ No newline at end of file
+  https://gitlab.com/qemu-project/buildigvm
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index dad4cfc..ea1c415 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -22,6 +22,7 @@
 #include "qemu/osdep.h"
 #include <glib/gprintf.h>
 #include "hw/acpi/aml-build.h"
+#include "hw/acpi/acpi.h"
 #include "qemu/bswap.h"
 #include "qemu/bitops.h"
 #include "system/numa.h"
@@ -1741,6 +1742,7 @@
     uint32_t table_len = desc->array->len - desc->table_offset;
     uint32_t table_len_le = cpu_to_le32(table_len);
     gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
+    uint8_t *table;
 
     /* patch "Length" field that has been reserved by acpi_table_begin()
      * to the actual length, i.e. accumulated table length from
@@ -1748,8 +1750,14 @@
      */
     memcpy(len_ptr, &table_len_le, sizeof table_len_le);
 
-    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
-        desc->table_offset, table_len, desc->table_offset + checksum_offset);
+    if (linker != NULL) {
+        bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
+                                        desc->table_offset, table_len,
+                                        desc->table_offset + checksum_offset);
+    } else {
+        table = (uint8_t *) &desc->array->data[desc->table_offset];
+        table[checksum_offset] = acpi_checksum(table, table_len);
+    }
 }
 
 void *acpi_data_push(GArray *table_data, unsigned size)
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index d9979b0..6b65e58 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -83,7 +83,10 @@
     return true;
 }
 
-static int acpi_checksum(const uint8_t *data, int len)
+/* Calculate the ACPI checksum value so that if used in the corresponding
+ * header field, the ACPI checksum verification will be successful.
+ */
+int acpi_checksum(const uint8_t *data, int len)
 {
     int sum, i;
     sum = 0;
diff --git a/hw/adc/aspeed_adc.c b/hw/adc/aspeed_adc.c
index fd3af30..3cc75bb 100644
--- a/hw/adc/aspeed_adc.c
+++ b/hw/adc/aspeed_adc.c
@@ -228,7 +228,8 @@
         qemu_log_mask(LOG_UNIMP, "%s: engine[%u]: "
                       "0x%" HWADDR_PRIx " 0x%" PRIx64 "\n",
                       __func__, s->engine_id, addr, value);
-        break;
+        /* Do not update the regs[] array */
+        return;
     }
 
     s->regs[reg] = value;
diff --git a/hw/arm/aspeed_ast1700.c b/hw/arm/aspeed_ast1700.c
new file mode 100644
index 0000000..e90302c
--- /dev/null
+++ b/hw/arm/aspeed_ast1700.c
@@ -0,0 +1,276 @@
+/*
+ * ASPEED AST1700 IO Expander
+ *
+ * Copyright (C) 2025 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "hw/core/boards.h"
+#include "qom/object.h"
+#include "qapi/error.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/arm/aspeed_ast1700.h"
+
+#define AST2700_SOC_LTPI_SIZE        0x01000000
+#define AST1700_SOC_SRAM_SIZE        0x00040000
+#define AST1700_SOC_I3C_SIZE         0x00010000
+
+enum {
+    ASPEED_AST1700_DEV_SPI0,
+    ASPEED_AST1700_DEV_PWM,
+    ASPEED_AST1700_DEV_SRAM,
+    ASPEED_AST1700_DEV_ADC,
+    ASPEED_AST1700_DEV_SCU,
+    ASPEED_AST1700_DEV_GPIO,
+    ASPEED_AST1700_DEV_SGPIOM0,
+    ASPEED_AST1700_DEV_SGPIOM1,
+    ASPEED_AST1700_DEV_I2C,
+    ASPEED_AST1700_DEV_I3C,
+    ASPEED_AST1700_DEV_UART12,
+    ASPEED_AST1700_DEV_LTPI_CTRL,
+    ASPEED_AST1700_DEV_WDT,
+    ASPEED_AST1700_DEV_SPI0_MEM,
+};
+
+static const hwaddr aspeed_ast1700_io_memmap[] = {
+    [ASPEED_AST1700_DEV_SPI0]      =  0x00030000,
+    [ASPEED_AST1700_DEV_PWM]       =  0x000C0000,
+    [ASPEED_AST1700_DEV_SRAM]      =  0x00BC0000,
+    [ASPEED_AST1700_DEV_ADC]       =  0x00C00000,
+    [ASPEED_AST1700_DEV_SCU]       =  0x00C02000,
+    [ASPEED_AST1700_DEV_GPIO]      =  0x00C0B000,
+    [ASPEED_AST1700_DEV_SGPIOM0]   =  0x00C0C000,
+    [ASPEED_AST1700_DEV_SGPIOM1]   =  0x00C0D000,
+    [ASPEED_AST1700_DEV_I2C]       =  0x00C0F000,
+    [ASPEED_AST1700_DEV_I3C]       =  0x00C20000,
+    [ASPEED_AST1700_DEV_UART12]    =  0x00C33B00,
+    [ASPEED_AST1700_DEV_LTPI_CTRL] =  0x00C34000,
+    [ASPEED_AST1700_DEV_WDT]       =  0x00C37000,
+    [ASPEED_AST1700_DEV_SPI0_MEM]  =  0x04000000,
+};
+
+static void aspeed_ast1700_realize(DeviceState *dev, Error **errp)
+{
+    AspeedAST1700SoCState *s = ASPEED_AST1700(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    char dev_name[32];
+
+    if (!s->dram_mr) {
+        error_setg(errp, TYPE_ASPEED_AST1700 ": 'dram' link not set");
+        return;
+    }
+
+    /* Occupy memory space for all controllers in AST1700 */
+    memory_region_init(&s->iomem, OBJECT(s), TYPE_ASPEED_AST1700,
+                       AST2700_SOC_LTPI_SIZE);
+    sysbus_init_mmio(sbd, &s->iomem);
+
+    /* SRAM */
+    snprintf(dev_name, sizeof(dev_name), "aspeed.ioexp-sram.%d", s->board_idx);
+    memory_region_init_ram(&s->sram, OBJECT(s), dev_name,
+                           AST1700_SOC_SRAM_SIZE, errp);
+    memory_region_add_subregion(&s->iomem,
+                            aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SRAM],
+                            &s->sram);
+
+    /* UART */
+    qdev_prop_set_uint8(DEVICE(&s->uart), "regshift", 2);
+    qdev_prop_set_uint32(DEVICE(&s->uart), "baudbase", 38400);
+    qdev_prop_set_uint8(DEVICE(&s->uart), "endianness", DEVICE_LITTLE_ENDIAN);
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->uart), errp)) {
+        return;
+    }
+    memory_region_add_subregion(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_UART12],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart), 0));
+
+    /* SPI */
+    object_property_set_link(OBJECT(&s->spi), "dram",
+                             OBJECT(s->dram_mr), errp);
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi), errp)) {
+        return;
+    }
+    memory_region_add_subregion(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SPI0],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->spi), 0));
+
+    memory_region_add_subregion(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SPI0_MEM],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->spi), 1));
+
+    /* ADC */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) {
+        return;
+    }
+    memory_region_add_subregion(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_ADC],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->adc), 0));
+
+    /* SCU */
+    qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
+                         s->silicon_rev);
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
+        return;
+    }
+    memory_region_add_subregion(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SCU],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->scu), 0));
+
+    /* GPIO */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
+        return;
+    }
+    memory_region_add_subregion(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_GPIO],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0));
+
+    /* I2C */
+    snprintf(dev_name, sizeof(dev_name), "ioexp%d", s->board_idx);
+    qdev_prop_set_string(DEVICE(&s->i2c), "bus-label", dev_name);
+
+    object_property_set_link(OBJECT(&s->i2c), "dram",
+                             OBJECT(s->dram_mr), errp);
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->i2c), errp)) {
+        return;
+    }
+    memory_region_add_subregion(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_I2C],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i2c), 0));
+
+    /* PWM */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->pwm), errp)) {
+        return;
+    }
+    memory_region_add_subregion(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_PWM],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->pwm), 0));
+
+    /* LTPI controller */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&s->ltpi), errp)) {
+        return;
+    }
+    memory_region_add_subregion(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_LTPI_CTRL],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ltpi), 0));
+
+    /* SGPIOM */
+    for (int i = 0; i < AST1700_SGPIO_NUM; i++) {
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->sgpiom[i]), errp)) {
+            return;
+        }
+        memory_region_add_subregion(&s->iomem,
+                    aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_SGPIOM0 + i],
+                    sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sgpiom[i]), 0));
+    }
+
+    /* WDT */
+    for (int i = 0; i < AST1700_WDT_NUM; i++) {
+        AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
+        hwaddr wdt_offset = aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_WDT] +
+                            i * awc->iosize;
+
+        object_property_set_link(OBJECT(&s->wdt[i]), "scu", OBJECT(&s->scu),
+                                 errp);
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->wdt[i]), errp)) {
+            return;
+        }
+        memory_region_add_subregion(&s->iomem,
+                        wdt_offset,
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->wdt[i]), 0));
+    }
+
+    /* I3C */
+    qdev_prop_set_string(DEVICE(&s->i3c), "name", "ioexp-i3c");
+    qdev_prop_set_uint64(DEVICE(&s->i3c), "size", AST1700_SOC_I3C_SIZE);
+    sysbus_realize(SYS_BUS_DEVICE(&s->i3c), errp);
+    memory_region_add_subregion_overlap(&s->iomem,
+                        aspeed_ast1700_io_memmap[ASPEED_AST1700_DEV_I3C],
+                        sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->i3c), 0),
+                        -1000);
+}
+
+static void aspeed_ast1700_instance_init(Object *obj)
+{
+    AspeedAST1700SoCState *s = ASPEED_AST1700(obj);
+
+    /* UART */
+    object_initialize_child(obj, "uart", &s->uart,
+                            TYPE_SERIAL_MM);
+
+    /* SPI */
+    object_initialize_child(obj, "ioexp-spi", &s->spi,
+                            "aspeed.spi0-ast2700");
+
+    /* ADC */
+    object_initialize_child(obj, "ioexp-adc", &s->adc,
+                            "aspeed.adc-ast2700");
+
+    /* SCU */
+    object_initialize_child(obj, "ioexp-scu", &s->scu,
+                            TYPE_ASPEED_2700_SCU);
+
+    /* GPIO */
+    object_initialize_child(obj, "ioexp-gpio", &s->gpio,
+                            "aspeed.gpio-ast2700");
+
+    /* I2C */
+    object_initialize_child(obj, "ioexp-i2c", &s->i2c,
+                            "aspeed.i2c-ast2700");
+
+    /* PWM */
+    object_initialize_child(obj, "pwm", &s->pwm, TYPE_ASPEED_PWM);
+
+    /* LTPI controller */
+    object_initialize_child(obj, "ltpi-ctrl",
+                            &s->ltpi, TYPE_ASPEED_LTPI);
+
+    /* SGPIOM */
+    for (int i = 0; i < AST1700_SGPIO_NUM; i++) {
+        object_initialize_child(obj, "ioexp-sgpiom[*]", &s->sgpiom[i],
+                                "aspeed.sgpio-ast2700");
+    }
+
+    /* WDT */
+    for (int i = 0; i < AST1700_WDT_NUM; i++) {
+        object_initialize_child(obj, "ioexp-wdt[*]",
+                                &s->wdt[i], "aspeed.wdt-ast2700");
+    }
+
+    /* I3C */
+    object_initialize_child(obj, "ioexp-i3c", &s->i3c,
+                            TYPE_UNIMPLEMENTED_DEVICE);
+
+    return;
+}
+
+static const Property aspeed_ast1700_props[] = {
+    DEFINE_PROP_UINT8("board-idx", AspeedAST1700SoCState, board_idx, 0),
+    DEFINE_PROP_UINT32("silicon-rev", AspeedAST1700SoCState, silicon_rev, 0),
+    DEFINE_PROP_LINK("dram", AspeedAST1700SoCState, dram_mr,
+                     TYPE_MEMORY_REGION, MemoryRegion *),
+};
+
+static void aspeed_ast1700_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = aspeed_ast1700_realize;
+    device_class_set_props(dc, aspeed_ast1700_props);
+}
+
+static const TypeInfo aspeed_ast1700_info = {
+    .name          = TYPE_ASPEED_AST1700,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AspeedAST1700SoCState),
+    .class_init    = aspeed_ast1700_class_init,
+    .instance_init = aspeed_ast1700_instance_init,
+};
+
+static void aspeed_ast1700_register_types(void)
+{
+    type_register_static(&aspeed_ast1700_info);
+}
+
+type_init(aspeed_ast1700_register_types);
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
index 4c5a42e..efb1d8c 100644
--- a/hw/arm/aspeed_ast2600.c
+++ b/hw/arm/aspeed_ast2600.c
@@ -81,7 +81,7 @@
     [ASPEED_DEV_FSI1]      = 0x1E79B000,
     [ASPEED_DEV_FSI2]      = 0x1E79B100,
     [ASPEED_DEV_I3C]       = 0x1E7A0000,
-    [ASPEED_DEV_PCIE_MMIO1] = 0x70000000,
+    [ASPEED_DEV_PCIE_MMIO1] = 0x60000000,
     [ASPEED_DEV_SDRAM]     = 0x80000000,
 };
 
@@ -303,14 +303,14 @@
  *
  * Model scope / limitations:
  *   - Firmware supports RC_H only; this QEMU model does not support RC_L.
- *   - RC_H uses PHY1 and the MMIO window [0x70000000, 0x80000000]
+ *   - RC_H uses PHY1 and the MMIO window [0x60000000, 0x80000000]
  *     (aka MMIO1).
  *
  * Indexing convention (this model):
  *   - Expose a single logical instance at index 0.
  *   - pcie[0] -> hardware RC_H (PCIe1)
  *   - phy[0]  -> hardware PHY1
- *   - mmio.0 -> guest address range MMIO1: 0x70000000-0x80000000
+ *   - mmio.0 -> guest address range MMIO1: 0x60000000-0x80000000
  *   - RC_L / PCIe0 is not created and mapped.
  */
 static bool aspeed_soc_ast2600_pcie_realize(DeviceState *dev, Error **errp)
@@ -346,7 +346,7 @@
     memory_region_init_alias(&s->pcie_mmio_alias[0], OBJECT(&s->pcie[0].rc),
                              "aspeed.pcie-mmio", mmio_mr,
                              sc->memmap[ASPEED_DEV_PCIE_MMIO1],
-                             0x10000000);
+                             0x20000000);
     memory_region_add_subregion(s->memory,
                                 sc->memmap[ASPEED_DEV_PCIE_MMIO1],
                                 &s->pcie_mmio_alias[0]);
diff --git a/hw/arm/aspeed_ast2600_catalina.c b/hw/arm/aspeed_ast2600_catalina.c
index 4edb30b..65495a5 100644
--- a/hw/arm/aspeed_ast2600_catalina.c
+++ b/hw/arm/aspeed_ast2600_catalina.c
@@ -480,7 +480,7 @@
     /* i2c0mux1ch1 */
     /* io_expander7 - pca9535@20 */
     i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 1),
-                            TYPE_PCA9552, 0x20);
+                            TYPE_PCA9535, 0x20);
     /* eeprom@50 */
     at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 1), 0x50, 8 * KiB,
                           gb200io_eeprom, gb200io_eeprom_len);
@@ -497,7 +497,7 @@
     /* i2c0mux4ch1 */
     /* io_expander8 - pca9535@21 */
     i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 1),
-                            TYPE_PCA9552, 0x21);
+                            TYPE_PCA9535, 0x21);
     /* eeprom@50 */
     at24c_eeprom_init_rom(pca954x_i2c_get_bus(i2c_mux, 1), 0x50, 8 * KiB,
                           gb200io_eeprom, gb200io_eeprom_len);
diff --git a/hw/arm/aspeed_ast27x0-ssp.c b/hw/arm/aspeed_ast27x0-ssp.c
index cee937b..9b12ba6 100644
--- a/hw/arm/aspeed_ast27x0-ssp.c
+++ b/hw/arm/aspeed_ast27x0-ssp.c
@@ -23,15 +23,15 @@
     [ASPEED_DEV_SRAM]      =  0x70000000,
     [ASPEED_DEV_INTC]      =  0x72100000,
     [ASPEED_DEV_SCU]       =  0x72C02000,
+    [ASPEED_DEV_TIMER1]    =  0x72C10000,
+    [ASPEED_DEV_UART4]     =  0x72C1A000,
+    [ASPEED_DEV_IPC0]      =  0x72C1C000,
     [ASPEED_DEV_SCUIO]     =  0x74C02000,
+    [ASPEED_DEV_INTCIO]    =  0x74C18000,
     [ASPEED_DEV_UART0]     =  0x74C33000,
     [ASPEED_DEV_UART1]     =  0x74C33100,
     [ASPEED_DEV_UART2]     =  0x74C33200,
     [ASPEED_DEV_UART3]     =  0x74C33300,
-    [ASPEED_DEV_UART4]     =  0x72C1A000,
-    [ASPEED_DEV_INTCIO]    =  0x74C18000,
-    [ASPEED_DEV_IPC0]      =  0x72C1C000,
-    [ASPEED_DEV_IPC1]      =  0x74C39000,
     [ASPEED_DEV_UART5]     =  0x74C33400,
     [ASPEED_DEV_UART6]     =  0x74C33500,
     [ASPEED_DEV_UART7]     =  0x74C33600,
@@ -40,16 +40,17 @@
     [ASPEED_DEV_UART10]    =  0x74C33900,
     [ASPEED_DEV_UART11]    =  0x74C33A00,
     [ASPEED_DEV_UART12]    =  0x74C33B00,
-    [ASPEED_DEV_TIMER1]    =  0x72C10000,
+    [ASPEED_DEV_IPC1]      =  0x74C39000,
 };
 
 static const int aspeed_soc_ast27x0ssp_irqmap[] = {
+    [ASPEED_DEV_UART4]     = 8,
     [ASPEED_DEV_SCU]       = 12,
+    [ASPEED_DEV_TIMER1]    = 16,
     [ASPEED_DEV_UART0]     = 164,
     [ASPEED_DEV_UART1]     = 164,
     [ASPEED_DEV_UART2]     = 164,
     [ASPEED_DEV_UART3]     = 164,
-    [ASPEED_DEV_UART4]     = 8,
     [ASPEED_DEV_UART5]     = 164,
     [ASPEED_DEV_UART6]     = 164,
     [ASPEED_DEV_UART7]     = 164,
@@ -58,7 +59,6 @@
     [ASPEED_DEV_UART10]    = 164,
     [ASPEED_DEV_UART11]    = 164,
     [ASPEED_DEV_UART12]    = 164,
-    [ASPEED_DEV_TIMER1]    = 16,
 };
 
 /* SSPINT 164 */
diff --git a/hw/arm/aspeed_ast27x0-tsp.c b/hw/arm/aspeed_ast27x0-tsp.c
index 9c11c01..e39d1dc 100644
--- a/hw/arm/aspeed_ast27x0-tsp.c
+++ b/hw/arm/aspeed_ast27x0-tsp.c
@@ -23,15 +23,15 @@
     [ASPEED_DEV_SRAM]      =  0x70000000,
     [ASPEED_DEV_INTC]      =  0x72100000,
     [ASPEED_DEV_SCU]       =  0x72C02000,
+    [ASPEED_DEV_TIMER1]    =  0x72C10000,
+    [ASPEED_DEV_UART4]     =  0x72C1A000,
+    [ASPEED_DEV_IPC0]      =  0x72C1C000,
     [ASPEED_DEV_SCUIO]     =  0x74C02000,
+    [ASPEED_DEV_INTCIO]    =  0x74C18000,
     [ASPEED_DEV_UART0]     =  0x74C33000,
     [ASPEED_DEV_UART1]     =  0x74C33100,
     [ASPEED_DEV_UART2]     =  0x74C33200,
     [ASPEED_DEV_UART3]     =  0x74C33300,
-    [ASPEED_DEV_UART4]     =  0x72C1A000,
-    [ASPEED_DEV_INTCIO]    =  0x74C18000,
-    [ASPEED_DEV_IPC0]      =  0x72C1C000,
-    [ASPEED_DEV_IPC1]      =  0x74C39000,
     [ASPEED_DEV_UART5]     =  0x74C33400,
     [ASPEED_DEV_UART6]     =  0x74C33500,
     [ASPEED_DEV_UART7]     =  0x74C33600,
@@ -40,16 +40,17 @@
     [ASPEED_DEV_UART10]    =  0x74C33900,
     [ASPEED_DEV_UART11]    =  0x74C33A00,
     [ASPEED_DEV_UART12]    =  0x74C33B00,
-    [ASPEED_DEV_TIMER1]    =  0x72C10000,
+    [ASPEED_DEV_IPC1]      =  0x74C39000,
 };
 
 static const int aspeed_soc_ast27x0tsp_irqmap[] = {
+    [ASPEED_DEV_UART4]     = 8,
     [ASPEED_DEV_SCU]       = 12,
+    [ASPEED_DEV_TIMER1]    = 16,
     [ASPEED_DEV_UART0]     = 164,
     [ASPEED_DEV_UART1]     = 164,
     [ASPEED_DEV_UART2]     = 164,
     [ASPEED_DEV_UART3]     = 164,
-    [ASPEED_DEV_UART4]     = 8,
     [ASPEED_DEV_UART5]     = 164,
     [ASPEED_DEV_UART6]     = 164,
     [ASPEED_DEV_UART7]     = 164,
@@ -58,7 +59,6 @@
     [ASPEED_DEV_UART10]    = 164,
     [ASPEED_DEV_UART11]    = 164,
     [ASPEED_DEV_UART12]    = 164,
-    [ASPEED_DEV_TIMER1]    = 16,
 };
 
 /* TSPINT 164 */
diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c
index d17f446..61790ea 100644
--- a/hw/arm/aspeed_ast27x0.c
+++ b/hw/arm/aspeed_ast27x0.c
@@ -26,7 +26,6 @@
 #define AST2700_SOC_IO_SIZE          0x00FE0000
 #define AST2700_SOC_IOMEM_SIZE       0x01000000
 #define AST2700_SOC_DPMCU_SIZE       0x00040000
-#define AST2700_SOC_LTPI_SIZE        0x01000000
 
 static const hwaddr aspeed_soc_ast2700_memmap[] = {
     [ASPEED_DEV_VBOOTROM]  =  0x00000000,
@@ -88,8 +87,13 @@
     [ASPEED_DEV_UART10]    =  0x14C33900,
     [ASPEED_DEV_UART11]    =  0x14C33A00,
     [ASPEED_DEV_UART12]    =  0x14C33B00,
+    [ASPEED_DEV_LTPI_CTRL1] =  0x14C34000,
+    [ASPEED_DEV_LTPI_CTRL2] =  0x14C35000,
     [ASPEED_DEV_WDT]       =  0x14C37000,
-    [ASPEED_DEV_LTPI]      =  0x30000000,
+    [ASPEED_DEV_LTPI_IO0]  =  0x30000000,
+    [ASPEED_DEV_IOEXP0_INTCIO] = 0x30C18000,
+    [ASPEED_DEV_LTPI_IO1]  =  0x50000000,
+    [ASPEED_DEV_IOEXP1_INTCIO] = 0x50C18000,
     [ASPEED_DEV_PCIE_MMIO0] = 0x60000000,
     [ASPEED_DEV_PCIE_MMIO1] = 0x80000000,
     [ASPEED_DEV_PCIE_MMIO2] = 0xA0000000,
@@ -149,8 +153,14 @@
     [ASPEED_DEV_ETH1]      = 196,
     [ASPEED_DEV_ETH2]      = 196,
     [ASPEED_DEV_ETH3]      = 196,
+    [ASPEED_DEV_EHCI3]     = 196,
+    [ASPEED_DEV_EHCI4]     = 196,
     [ASPEED_DEV_PECI]      = 197,
     [ASPEED_DEV_SDHCI]     = 197,
+    [ASPEED_DEV_IOEXP0_I2C] = 198,
+    [ASPEED_DEV_IOEXP0_I3C] = 199,
+    [ASPEED_DEV_IOEXP1_I2C] = 200,
+    [ASPEED_DEV_IOEXP1_I3C] = 201,
 };
 
 /* GICINT 192 */
@@ -207,6 +217,30 @@
     [ASPEED_DEV_PECI]      = 4,
 };
 
+/* Primary AST1700 Interrupts */
+/* A1: GICINT 198 */
+static const int ast2700_gic198_intcmap[] = {
+    [ASPEED_DEV_IOEXP0_I2C]       = 0, /* 0 - 15 */
+};
+
+/* Primary AST1700 Interrupts */
+/* A1: GINTC 199 */
+static const int ast2700_gic199_intcmap[] = {
+    [ASPEED_DEV_IOEXP0_I3C]       = 0, /* 0 - 15 */
+};
+
+/* Secondary AST1700 Interrupts */
+/* A1: GINTC 200 */
+static const int ast2700_gic200_intcmap[] = {
+    [ASPEED_DEV_IOEXP1_I2C]       = 0, /* 0 - 15 */
+};
+
+/* Secondary AST1700 Interrupts */
+/* A1: GINTC 201 */
+static const int ast2700_gic201_intcmap[] = {
+    [ASPEED_DEV_IOEXP1_I3C]       = 0, /* 0 - 15 */
+};
+
 /* GICINT 192 ~ 201 */
 struct gic_intc_irq_info {
     int irq;
@@ -222,10 +256,10 @@
     {195, 1, 3, ast2700_gic195_intcmap},
     {196, 1, 4, ast2700_gic196_intcmap},
     {197, 1, 5, ast2700_gic197_intcmap},
-    {198, 1, 6, NULL},
-    {199, 1, 7, NULL},
-    {200, 1, 8, NULL},
-    {201, 1, 9, NULL},
+    {198, 2, 0, ast2700_gic198_intcmap},
+    {199, 2, 1, ast2700_gic199_intcmap},
+    {200, 3, 0, ast2700_gic200_intcmap},
+    {201, 3, 1, ast2700_gic201_intcmap},
 };
 
 static qemu_irq aspeed_soc_ast2700_get_irq(AspeedSoCState *s, int dev)
@@ -257,14 +291,23 @@
     int or_idx;
     int idx;
     int i;
+    OrIRQState *porgates;
 
     for (i = 0; i < ARRAY_SIZE(ast2700_gic_intcmap); i++) {
         if (sc->irqmap[dev] == ast2700_gic_intcmap[i].irq) {
             assert(ast2700_gic_intcmap[i].ptr);
             or_idx = ast2700_gic_intcmap[i].orgate_idx;
             idx = ast2700_gic_intcmap[i].intc_idx;
-            return qdev_get_gpio_in(DEVICE(&a->intc[idx].orgates[or_idx]),
+            if (idx < ASPEED_INTC_NUM) {
+                porgates = &a->intc[idx].orgates[or_idx];
+                return qdev_get_gpio_in(DEVICE(porgates),
                                     ast2700_gic_intcmap[i].ptr[dev] + index);
+            } else {
+                idx -= ASPEED_INTC_NUM;
+                porgates = &a->intcioexp[idx].orgates[or_idx];
+                return qdev_get_gpio_in(DEVICE(porgates),
+                                    ast2700_gic_intcmap[i].ptr[dev] + index);
+            }
         }
     }
 
@@ -442,6 +485,10 @@
     object_initialize_child(obj, "intc", &a->intc[0], TYPE_ASPEED_2700_INTC);
     object_initialize_child(obj, "intcio", &a->intc[1],
                             TYPE_ASPEED_2700_INTCIO);
+    object_initialize_child(obj, "intc-ioexp0", &a->intcioexp[0],
+                            TYPE_ASPEED_2700_INTCIOEXP1);
+    object_initialize_child(obj, "intc-ioexp1", &a->intcioexp[1],
+                            TYPE_ASPEED_2700_INTCIOEXP2);
 
     snprintf(typename, sizeof(typename), "aspeed.adc-%s", socname);
     object_initialize_child(obj, "adc", &s->adc, typename);
@@ -489,10 +536,21 @@
         object_property_set_int(OBJECT(&s->pcie[i]), "id", i, &error_abort);
     }
 
+    for (i = 0; i < ASPEED_IOEXP_NUM; i++) {
+        object_initialize_child(obj, "ltpi-ctrl[*]",
+                                &s->ltpi_ctrl[i], TYPE_ASPEED_LTPI);
+    }
+
+    for (i = 0; i < sc->ioexp_num; i++) {
+        /* AST1700 IOEXP */
+        object_initialize_child(obj, "ioexp[*]", &s->ioexp[i],
+                                TYPE_ASPEED_AST1700);
+        qdev_prop_set_uint32(DEVICE(&s->ioexp[i]), "silicon-rev",
+                             sc->silicon_rev);
+    }
+
     object_initialize_child(obj, "dpmcu", &s->dpmcu,
                             TYPE_UNIMPLEMENTED_DEVICE);
-    object_initialize_child(obj, "ltpi", &s->ltpi,
-                            TYPE_UNIMPLEMENTED_DEVICE);
     object_initialize_child(obj, "iomem", &s->iomem,
                             TYPE_UNIMPLEMENTED_DEVICE);
     object_initialize_child(obj, "iomem0", &s->iomem0,
@@ -677,6 +735,22 @@
     aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intc[1]), 0,
                     sc->memmap[ASPEED_DEV_INTCIO]);
 
+    /* INTCIOEXP0 */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&a->intcioexp[0]), errp)) {
+        return;
+    }
+
+    aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intcioexp[0]), 0,
+                    sc->memmap[ASPEED_DEV_IOEXP0_INTCIO]);
+
+    /* INTCIOEXP1 */
+    if (!sysbus_realize(SYS_BUS_DEVICE(&a->intcioexp[1]), errp)) {
+        return;
+    }
+
+    aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(&a->intcioexp[1]), 0,
+                    sc->memmap[ASPEED_DEV_IOEXP1_INTCIO]);
+
     /* irq sources -> orgates -> INTC */
     for (i = 0; i < ic->num_inpins; i++) {
         qdev_connect_gpio_out(DEVICE(&a->intc[0].orgates[i]), 0,
@@ -972,14 +1046,82 @@
         return;
     }
 
+    /* LTPI controller */
+    for (i = 0; i < ASPEED_IOEXP_NUM; i++) {
+        AspeedLTPIState *ltpi_ctrl;
+        hwaddr ltpi_base;
+
+        ltpi_ctrl = ASPEED_LTPI(&s->ltpi_ctrl[i]);
+        ltpi_base = sc->memmap[ASPEED_DEV_LTPI_CTRL1 + i];
+
+        if (!sysbus_realize(SYS_BUS_DEVICE(ltpi_ctrl), errp)) {
+            return;
+        }
+        aspeed_mmio_map(s->memory, SYS_BUS_DEVICE(ltpi_ctrl), 0, ltpi_base);
+    }
+
+    /* IO Expander */
+    for (i = 0; i < sc->ioexp_num; i++) {
+        AspeedI2CClass *i2c_ctl;
+
+        qdev_prop_set_uint8(DEVICE(&s->ioexp[i]), "board-idx", i);
+        object_property_set_link(OBJECT(&s->ioexp[i]), "dram",
+                                 OBJECT(s->dram_mr), &error_abort);
+        if (!sysbus_realize(SYS_BUS_DEVICE(&s->ioexp[i]), errp)) {
+            return;
+        }
+        sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioexp[i]), 0,
+                        sc->memmap[ASPEED_DEV_LTPI_IO0 + i]);
+
+        icio = ASPEED_INTC_GET_CLASS(&a->intcioexp[i]);
+        /* INTC_IOEXP internal: orgate[i] -> input[i] */
+        for (int j = 0; j < icio->num_inpins; j++) {
+            irq = qdev_get_gpio_in(DEVICE(&a->intcioexp[i]), j);
+            qdev_connect_gpio_out(DEVICE(&a->intcioexp[i].orgates[j]), 0,
+                                  irq);
+        }
+
+        /* INTC_IOEXP output[i] -> INTC0.orgate[0].input[i] */
+        for (int j = 0; j < icio->num_outpins; j++) {
+            irq = qdev_get_gpio_in(DEVICE(&a->intc[0].orgates[0]), j);
+            sysbus_connect_irq(SYS_BUS_DEVICE(&a->intcioexp[i]), j,
+                               irq);
+        }
+
+        /* ADC */
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->ioexp[i].adc), 0,
+                           aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_ADC));
+
+        /* GPIO */
+        sysbus_connect_irq(SYS_BUS_DEVICE(&s->ioexp[i].gpio), 0,
+                           aspeed_soc_ast2700_get_irq(s, ASPEED_DEV_GPIO));
+
+        /* I2C */
+        i2c_ctl = ASPEED_I2C_GET_CLASS(&s->ioexp[i].i2c);
+        for (int j = 0; j < i2c_ctl->num_busses; j++) {
+            /*
+             * For I2C on AST1700:
+             * I2C bus interrupts are connected to the OR gate from bit 0 to bit
+             * 15, and the OR gate output pin is connected to the input pin of
+             * GICINT192 of IO expander Interrupt controller (INTC2/3). Then,
+             * the output pin is connected to the INTC (CPU Die) input pin, and
+             * its output pin is connected to the GIC.
+             *
+             * I2C bus 0 is connected to the OR gate at bit 0.
+             * I2C bus 15 is connected to the OR gate at bit 15.
+             */
+            irq = aspeed_soc_ast2700_get_irq_index(s,
+                                                   ASPEED_DEV_IOEXP0_I2C + i,
+                                                   j);
+            sysbus_connect_irq(SYS_BUS_DEVICE(&s->ioexp[i].i2c.busses[j]),
+                               0, irq);
+        }
+    }
+
     aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->dpmcu),
                                   "aspeed.dpmcu",
                                   sc->memmap[ASPEED_DEV_DPMCU],
                                   AST2700_SOC_DPMCU_SIZE);
-    aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->ltpi),
-                                  "aspeed.ltpi",
-                                  sc->memmap[ASPEED_DEV_LTPI],
-                                  AST2700_SOC_LTPI_SIZE);
     aspeed_mmio_map_unimplemented(s->memory, SYS_BUS_DEVICE(&s->iomem),
                                   "aspeed.io",
                                   sc->memmap[ASPEED_DEV_IOMEM],
@@ -1018,6 +1160,7 @@
     sc->macs_num     = 3;
     sc->uarts_num    = 13;
     sc->num_cpus     = 4;
+    sc->ioexp_num    = 2;
     sc->uarts_base   = ASPEED_DEV_UART0;
     sc->irqmap       = aspeed_soc_ast2700a1_irqmap;
     sc->memmap       = aspeed_soc_ast2700_memmap;
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
index c250487..47cdc51 100644
--- a/hw/arm/meson.build
+++ b/hw/arm/meson.build
@@ -70,6 +70,7 @@
   'aspeed_ast10x0_evb.c',
   'fby35.c'))
 arm_common_ss.add(when: ['CONFIG_ASPEED_SOC', 'TARGET_AARCH64'], if_true: files(
+  'aspeed_ast1700.c',
   'aspeed_ast27x0.c',
   'aspeed_ast27x0_evb.c',
   'aspeed_ast27x0-fc.c',
diff --git a/hw/gpio/pca9552.c b/hw/gpio/pca9552.c
index dd3c795..dd3f153 100644
--- a/hw/gpio/pca9552.c
+++ b/hw/gpio/pca9552.c
@@ -31,6 +31,7 @@
 
     uint8_t pin_count;
     uint8_t max_reg;
+    bool has_led_support;
 };
 typedef struct PCA955xClass PCA955xClass;
 
@@ -113,32 +114,59 @@
     for (i = 0; i < k->pin_count; i++) {
         uint8_t input_reg = PCA9552_INPUT0 + (i / 8);
         uint8_t bit_mask = 1 << (i % 8);
-        uint8_t config = pca955x_pin_get_config(s, i);
         uint8_t old_value = s->regs[input_reg] & bit_mask;
         uint8_t new_value;
 
-        switch (config) {
-        case PCA9552_LED_ON:
-            /* Pin is set to 0V to turn on LED */
-            s->regs[input_reg] &= ~bit_mask;
-            break;
-        case PCA9552_LED_OFF:
-            /*
-             * Pin is set to Hi-Z to turn off LED and
-             * pullup sets it to a logical 1 unless
-             * external device drives it low.
-             */
-            if (s->ext_state[i] == PCA9552_PIN_LOW) {
+        if (k->has_led_support) {
+            /* PCA9552: LED control behavior */
+            uint8_t config = pca955x_pin_get_config(s, i);
+
+            switch (config) {
+            case PCA9552_LED_ON:
+                /* Pin is set to 0V to turn on LED */
                 s->regs[input_reg] &= ~bit_mask;
-            } else {
-                s->regs[input_reg] |=  bit_mask;
+                break;
+            case PCA9552_LED_OFF:
+                /*
+                 * Pin is set to Hi-Z to turn off LED and
+                 * pullup sets it to a logical 1 unless
+                 * external device drives it low.
+                 */
+                if (s->ext_state[i] == PCA9552_PIN_LOW) {
+                    s->regs[input_reg] &= ~bit_mask;
+                } else {
+                    s->regs[input_reg] |=  bit_mask;
+                }
+                break;
+            case PCA9552_LED_PWM0:
+            case PCA9552_LED_PWM1:
+                /* TODO */
+            default:
+                break;
             }
-            break;
-        case PCA9552_LED_PWM0:
-        case PCA9552_LED_PWM1:
-            /* TODO */
-        default:
-            break;
+        } else {
+            /* PCA9535: Simple GPIO behavior */
+            uint8_t config_reg = PCA9535_CONFIG0 + (i / 8);
+            uint8_t output_reg = PCA9535_OUTPUT0 + (i / 8);
+            uint8_t polarity_reg = PCA9535_POLARITY0 + (i / 8);
+
+            /* Check if pin is configured as input */
+            if (s->regs[config_reg] & bit_mask) {
+                /* Input mode - reflect external state */
+                if (s->ext_state[i] == PCA9552_PIN_LOW) {
+                    s->regs[input_reg] &= ~bit_mask;
+                } else {
+                    s->regs[input_reg] |= bit_mask;
+                }
+            } else {
+                /* Output mode - reflect output register value */
+                uint8_t output_bit = s->regs[output_reg] & bit_mask;
+                uint8_t polarity_bit = s->regs[polarity_reg] & bit_mask;
+
+                /* Apply polarity inversion if set */
+                s->regs[input_reg] = (s->regs[input_reg] & ~bit_mask) |
+                                    ((output_bit ^ polarity_bit) & bit_mask);
+            }
         }
 
         /* update irq state only if pin state changed */
@@ -151,52 +179,52 @@
 
 static uint8_t pca955x_read(PCA955xState *s, uint8_t reg)
 {
-    switch (reg) {
-    case PCA9552_INPUT0:
-    case PCA9552_INPUT1:
-    case PCA9552_PSC0:
-    case PCA9552_PWM0:
-    case PCA9552_PSC1:
-    case PCA9552_PWM1:
-    case PCA9552_LS0:
-    case PCA9552_LS1:
-    case PCA9552_LS2:
-    case PCA9552_LS3:
-        return s->regs[reg];
-    default:
+    PCA955xClass *k = PCA955X_GET_CLASS(s);
+
+    if (reg > k->max_reg) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: unexpected read to register %d\n",
                       __func__, reg);
         return 0xFF;
     }
+
+    return s->regs[reg];
 }
 
 static void pca955x_write(PCA955xState *s, uint8_t reg, uint8_t data)
 {
+    PCA955xClass *k = PCA955X_GET_CLASS(s);
     uint16_t pins_status;
 
-    switch (reg) {
-    case PCA9552_PSC0:
-    case PCA9552_PWM0:
-    case PCA9552_PSC1:
-    case PCA9552_PWM1:
-        s->regs[reg] = data;
-        break;
-
-    case PCA9552_LS0:
-    case PCA9552_LS1:
-    case PCA9552_LS2:
-    case PCA9552_LS3:
-        pins_status = pca955x_pins_get_status(s);
-        s->regs[reg] = data;
-        pca955x_update_pin_input(s);
-        pca955x_display_pins_status(s, pins_status);
-        break;
-
-    case PCA9552_INPUT0:
-    case PCA9552_INPUT1:
-    default:
+    if (reg > k->max_reg) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: unexpected write to register %d\n",
                       __func__, reg);
+        return;
+    }
+
+    /* Handle read-only registers */
+    if (reg == PCA9552_INPUT0 || reg == PCA9552_INPUT1) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: unexpected write to read-only register %d\n",
+                      __func__, reg);
+        return;
+    }
+
+    pins_status = pca955x_pins_get_status(s);
+    s->regs[reg] = data;
+
+    /* Update GPIO state if this register affects outputs */
+    if (k->has_led_support) {
+        /* PCA9552: Update on LED selector register writes */
+        if (reg >= PCA9552_LS0 && reg <= PCA9552_LS3) {
+            pca955x_update_pin_input(s);
+            pca955x_display_pins_status(s, pins_status);
+        }
+    } else {
+        /* PCA9535: Update on OUTPUT, POLARITY, or CONFIG register writes */
+        if (reg >= PCA9535_OUTPUT0 && reg <= PCA9535_CONFIG1) {
+            pca955x_update_pin_input(s);
+            pca955x_display_pins_status(s, pins_status);
+        }
     }
 }
 
@@ -379,6 +407,26 @@
     s->len = 0;
 }
 
+static void pca9535_reset(DeviceState *dev)
+{
+    PCA955xState *s = PCA955X(dev);
+
+    s->regs[PCA9535_INPUT0] = 0xFF;   /* All inputs high (pull-ups) */
+    s->regs[PCA9535_INPUT1] = 0xFF;   /* All inputs high (pull-ups) */
+    s->regs[PCA9535_OUTPUT0] = 0xFF;  /* All outputs high */
+    s->regs[PCA9535_OUTPUT1] = 0xFF;  /* All outputs high */
+    s->regs[PCA9535_POLARITY0] = 0x00; /* No polarity inversion */
+    s->regs[PCA9535_POLARITY1] = 0x00; /* No polarity inversion */
+    s->regs[PCA9535_CONFIG0] = 0xFF;  /* All pins as inputs */
+    s->regs[PCA9535_CONFIG1] = 0xFF;  /* All pins as inputs */
+
+    memset(s->ext_state, PCA9552_PIN_HIZ, PCA955X_PIN_COUNT_MAX);
+    pca955x_update_pin_input(s);
+
+    s->pointer = 0xFF;
+    s->len = 0;
+}
+
 static void pca955x_initfn(Object *obj)
 {
     PCA955xClass *k = PCA955X_GET_CLASS(obj);
@@ -463,6 +511,19 @@
     dc->vmsd = &pca9552_vmstate;
     pc->max_reg = PCA9552_LS3;
     pc->pin_count = 16;
+    pc->has_led_support = true;
+}
+
+static void pca9535_class_init(ObjectClass *oc, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+    PCA955xClass *pc = PCA955X_CLASS(oc);
+
+    device_class_set_legacy_reset(dc, pca9535_reset);
+    dc->vmsd = &pca9552_vmstate;
+    pc->max_reg = PCA9535_CONFIG1;
+    pc->pin_count = 16;
+    pc->has_led_support = false;
 }
 
 static const TypeInfo pca9552_info = {
@@ -471,10 +532,17 @@
     .class_init    = pca9552_class_init,
 };
 
+static const TypeInfo pca9535_info = {
+    .name          = TYPE_PCA9535,
+    .parent        = TYPE_PCA955X,
+    .class_init    = pca9535_class_init,
+};
+
 static void pca955x_register_types(void)
 {
     type_register_static(&pca955x_info);
     type_register_static(&pca9552_info);
+    type_register_static(&pca9535_info);
 }
 
 type_init(pca955x_register_types)
diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c
index 1b8ac56..fb3d6a5 100644
--- a/hw/i2c/aspeed_i2c.c
+++ b/hw/i2c/aspeed_i2c.c
@@ -116,8 +116,6 @@
             value = -1;
             break;
         }
-
-        value = extract64(bus->dma_dram_offset, 0, 32);
         break;
     case A_I2CD_DMA_LEN:
         if (!aic->has_dma) {
@@ -221,6 +219,64 @@
     return SHARED_ARRAY_FIELD_EX32(bus->regs, R_I2CD_CMD, TX_STATE);
 }
 
+/*
+ * The AST2700 support the maximum DRAM size is 8 GB.
+ * The DRAM offset range is from 0x0_0000_0000 to
+ * 0x1_FFFF_FFFF and it is enough to use bits [33:0]
+ * saving the dram offset.
+ * Therefore, save the high part physical address bit[1:0]
+ * of Tx/Rx buffer address as dma_dram_offset bit[33:32].
+ */
+static void aspeed_i2c_set_tx_dma_dram_offset(AspeedI2CBus *bus)
+{
+    AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
+    uint32_t value;
+
+    assert(aic->has_dma);
+
+    if (aspeed_i2c_is_new_mode(bus->controller)) {
+        value = bus->regs[R_I2CM_DMA_TX_ADDR];
+        bus->dma_dram_offset =
+            deposit64(bus->dma_dram_offset, 0, 32,
+                      FIELD_EX32(value, I2CM_DMA_TX_ADDR, ADDR));
+        if (!aic->has_dma64) {
+            value = bus->regs[R_I2CM_DMA_TX_ADDR_HI];
+            bus->dma_dram_offset =
+                deposit64(bus->dma_dram_offset, 32, 32,
+                          extract32(value, 0, 2));
+        }
+    } else {
+        value = bus->regs[R_I2CD_DMA_ADDR];
+        bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32,
+                                         value & 0x3ffffffc);
+    }
+}
+
+static void aspeed_i2c_set_rx_dma_dram_offset(AspeedI2CBus *bus)
+{
+    AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
+    uint32_t value;
+
+    assert(aic->has_dma);
+
+    if (aspeed_i2c_is_new_mode(bus->controller)) {
+        value = bus->regs[R_I2CM_DMA_RX_ADDR];
+        bus->dma_dram_offset =
+            deposit64(bus->dma_dram_offset, 0, 32,
+                      FIELD_EX32(value, I2CM_DMA_RX_ADDR, ADDR));
+        if (!aic->has_dma64) {
+            value = bus->regs[R_I2CM_DMA_RX_ADDR_HI];
+            bus->dma_dram_offset =
+                deposit64(bus->dma_dram_offset, 32, 32,
+                          extract32(value, 0, 2));
+        }
+    } else {
+        value = bus->regs[R_I2CD_DMA_ADDR];
+        bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32,
+                                         value & 0x3ffffffc);
+    }
+}
+
 static int aspeed_i2c_dma_read(AspeedI2CBus *bus, uint8_t *data)
 {
     MemTxResult result;
@@ -270,9 +326,14 @@
         if (aspeed_i2c_is_new_mode(bus->controller)) {
             ARRAY_FIELD_DP32(bus->regs, I2CM_DMA_LEN_STS, TX_LEN, 0);
         }
+        aspeed_i2c_set_tx_dma_dram_offset(bus);
         while (bus->regs[reg_dma_len]) {
             uint8_t data;
-            aspeed_i2c_dma_read(bus, &data);
+            ret = aspeed_i2c_dma_read(bus, &data);
+            /* Check that we were able to read the DMA */
+            if (ret) {
+                break;
+            }
             trace_aspeed_i2c_bus_send("DMA", bus->regs[reg_dma_len],
                                       bus->regs[reg_dma_len], data);
             ret = i2c_send(bus->bus, data);
@@ -331,6 +392,7 @@
             ARRAY_FIELD_DP32(bus->regs, I2CM_DMA_LEN_STS, RX_LEN, 0);
         }
 
+        aspeed_i2c_set_rx_dma_dram_offset(bus);
         while (bus->regs[reg_dma_len]) {
             MemTxResult result;
 
@@ -397,6 +459,7 @@
     } else if (SHARED_ARRAY_FIELD_EX32(bus->regs, reg_cmd, TX_DMA_EN)) {
         uint8_t data;
 
+        aspeed_i2c_set_tx_dma_dram_offset(bus);
         aspeed_i2c_dma_read(bus, &data);
         return data;
     } else {
@@ -653,16 +716,10 @@
     case A_I2CM_DMA_TX_ADDR:
         bus->regs[R_I2CM_DMA_TX_ADDR] = FIELD_EX32(value, I2CM_DMA_TX_ADDR,
                                                    ADDR);
-        bus->dma_dram_offset =
-            deposit64(bus->dma_dram_offset, 0, 32,
-                      FIELD_EX32(value, I2CM_DMA_TX_ADDR, ADDR));
         break;
     case A_I2CM_DMA_RX_ADDR:
         bus->regs[R_I2CM_DMA_RX_ADDR] = FIELD_EX32(value, I2CM_DMA_RX_ADDR,
                                                    ADDR);
-        bus->dma_dram_offset =
-            deposit64(bus->dma_dram_offset, 0, 32,
-                      FIELD_EX32(value, I2CM_DMA_RX_ADDR, ADDR));
         break;
     case A_I2CM_DMA_LEN:
         w1t = FIELD_EX32(value, I2CM_DMA_LEN, RX_BUF_LEN_W1T) ||
@@ -744,15 +801,6 @@
         qemu_log_mask(LOG_UNIMP, "%s: Slave mode DMA TX is not implemented\n",
                       __func__);
         break;
-
-    /*
-     * The AST2700 support the maximum DRAM size is 8 GB.
-     * The DRAM offset range is from 0x0_0000_0000 to
-     * 0x1_FFFF_FFFF and it is enough to use bits [33:0]
-     * saving the dram offset.
-     * Therefore, save the high part physical address bit[1:0]
-     * of Tx/Rx buffer address as dma_dram_offset bit[33:32].
-     */
     case A_I2CM_DMA_TX_ADDR_HI:
         if (!aic->has_dma64) {
             qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA 64 bits support\n",
@@ -762,8 +810,6 @@
         bus->regs[R_I2CM_DMA_TX_ADDR_HI] = FIELD_EX32(value,
                                                       I2CM_DMA_TX_ADDR_HI,
                                                       ADDR_HI);
-        bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 32, 32,
-                                         extract32(value, 0, 2));
         break;
     case A_I2CM_DMA_RX_ADDR_HI:
         if (!aic->has_dma64) {
@@ -774,8 +820,6 @@
         bus->regs[R_I2CM_DMA_RX_ADDR_HI] = FIELD_EX32(value,
                                                       I2CM_DMA_RX_ADDR_HI,
                                                       ADDR_HI);
-        bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 32, 32,
-                                         extract32(value, 0, 2));
         break;
     case A_I2CS_DMA_TX_ADDR_HI:
         qemu_log_mask(LOG_UNIMP,
@@ -791,8 +835,6 @@
         bus->regs[R_I2CS_DMA_RX_ADDR_HI] = FIELD_EX32(value,
                                                       I2CS_DMA_RX_ADDR_HI,
                                                       ADDR_HI);
-        bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 32, 32,
-                                         extract32(value, 0, 2));
         break;
     default:
         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
@@ -883,9 +925,6 @@
             qemu_log_mask(LOG_GUEST_ERROR, "%s: No DMA support\n",  __func__);
             break;
         }
-
-        bus->dma_dram_offset = deposit64(bus->dma_dram_offset, 0, 32,
-                                         value & 0x3ffffffc);
         break;
 
     case A_I2CD_DMA_LEN:
@@ -1215,9 +1254,16 @@
                           "aspeed.i2c", aic->mem_size);
     sysbus_init_mmio(sbd, &s->iomem);
 
+    /* default value */
+    if (!s->bus_label) {
+        s->bus_label = g_strdup(TYPE_ASPEED_I2C_BUS);
+    }
+
     for (i = 0; i < aic->num_busses; i++) {
         Object *bus = OBJECT(&s->busses[i]);
         int offset = i < aic->gap ? 1 : 5;
+        g_autofree char *name = g_strdup_printf("%s.%d",
+                                                s->bus_label, i);
 
         if (!object_property_set_link(bus, "controller", OBJECT(s), errp)) {
             return;
@@ -1227,6 +1273,10 @@
             return;
         }
 
+        if (!object_property_set_str(bus, "bus-name", name, errp)) {
+            return;
+        }
+
         if (!sysbus_realize(SYS_BUS_DEVICE(bus), errp)) {
             return;
         }
@@ -1263,6 +1313,7 @@
 static const Property aspeed_i2c_properties[] = {
     DEFINE_PROP_LINK("dram", AspeedI2CState, dram_mr,
                      TYPE_MEMORY_REGION, MemoryRegion *),
+    DEFINE_PROP_STRING("bus-label", AspeedI2CState, bus_label),
 };
 
 static void aspeed_i2c_class_init(ObjectClass *klass, const void *data)
@@ -1423,24 +1474,26 @@
 {
     AspeedI2CBus *s = ASPEED_I2C_BUS(dev);
     AspeedI2CClass *aic;
-    g_autofree char *name = g_strdup_printf(TYPE_ASPEED_I2C_BUS ".%d", s->id);
-    g_autofree char *pool_name = g_strdup_printf("%s.pool", name);
+    g_autofree char *pool_name = NULL;
 
-    if (!s->controller) {
-        error_setg(errp, TYPE_ASPEED_I2C_BUS ": 'controller' link not set");
+    if (!s->controller || !s->name) {
+        error_setg(errp, TYPE_ASPEED_I2C_BUS
+                   ": 'controller' or 'bus-name' not set");
         return;
     }
 
+    pool_name = g_strdup_printf("%s.pool", s->name);
+
     aic = ASPEED_I2C_GET_CLASS(s->controller);
 
     sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
 
-    s->bus = i2c_init_bus(dev, name);
+    s->bus = i2c_init_bus(dev, s->name);
     s->slave = i2c_slave_create_simple(s->bus, TYPE_ASPEED_I2C_BUS_SLAVE,
                                        0xff);
 
     memory_region_init_io(&s->mr, OBJECT(s), &aspeed_i2c_bus_ops,
-                          s, name, aic->reg_size);
+                          s, s->name, aic->reg_size);
     sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr);
 
     memory_region_init_io(&s->mr_pool, OBJECT(s), &aspeed_i2c_bus_pool_ops,
@@ -1452,6 +1505,7 @@
     DEFINE_PROP_UINT8("bus-id", AspeedI2CBus, id, 0),
     DEFINE_PROP_LINK("controller", AspeedI2CBus, controller, TYPE_ASPEED_I2C,
                      AspeedI2CState *),
+    DEFINE_PROP_STRING("bus-name", AspeedI2CBus, name),
 };
 
 static void aspeed_i2c_bus_class_init(ObjectClass *klass, const void *data)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9446a9f..19c6236 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2249,3 +2249,12 @@
      */
     acpi_build_tables_cleanup(&tables, false);
 }
+
+GArray *acpi_build_madt_standalone(MachineState *machine)
+{
+  X86MachineState *x86ms = X86_MACHINE(machine);
+  GArray *table = g_array_new(false, true, 1);
+  acpi_build_madt(table, NULL, x86ms, x86ms->oem_id,
+                  x86ms->oem_table_id);
+  return table;
+}
diff --git a/hw/i386/acpi-build.h b/hw/i386/acpi-build.h
index 8ba3c33..00e19bb 100644
--- a/hw/i386/acpi-build.h
+++ b/hw/i386/acpi-build.h
@@ -8,4 +8,6 @@
 void acpi_setup(void);
 Object *acpi_get_i386_pci_host(void);
 
+GArray *acpi_build_madt_standalone(MachineState *machine);
+
 #endif
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index fea158f..878db572 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -320,16 +320,6 @@
                                x86_nvdimm_acpi_dsmio,
                                x86ms->fw_cfg, OBJECT(pcms));
     }
-
-#if defined(CONFIG_IGVM)
-    /* Apply guest state from IGVM if supplied */
-    if (x86ms->igvm) {
-        if (IGVM_CFG_GET_CLASS(x86ms->igvm)
-                ->process(x86ms->igvm, machine->cgs, false, &error_fatal) < 0) {
-            g_assert_not_reached();
-        }
-    }
-#endif
 }
 
 typedef enum PCSouthBridgeOption {
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 4d6046e..6e5a23d 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -328,16 +328,6 @@
                                x86_nvdimm_acpi_dsmio,
                                x86ms->fw_cfg, OBJECT(pcms));
     }
-
-#if defined(CONFIG_IGVM)
-    /* Apply guest state from IGVM if supplied */
-    if (x86ms->igvm) {
-        if (IGVM_CFG_GET_CLASS(x86ms->igvm)
-                ->process(x86ms->igvm, machine->cgs, false, &error_fatal) < 0) {
-            g_assert_not_reached();
-        }
-    }
-#endif
 }
 
 #define DEFINE_Q35_MACHINE(major, minor) \
diff --git a/hw/intc/aspeed_intc.c b/hw/intc/aspeed_intc.c
index 77fae39..52f2f94 100644
--- a/hw/intc/aspeed_intc.c
+++ b/hw/intc/aspeed_intc.c
@@ -793,6 +793,64 @@
     .class_init = aspeed_2700_intc_class_init,
 };
 
+static AspeedINTCIRQ aspeed_2700_intcioexp2_irqs[ASPEED_INTC_MAX_INPINS] = {
+    {0, 8, 1, R_GICINT192_EN, R_GICINT192_STATUS},
+    {1, 9, 1, R_GICINT193_EN, R_GICINT193_STATUS},
+};
+
+static void aspeed_2700_intcioexp2_class_init(ObjectClass *klass,
+                                              const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
+
+    dc->desc = "ASPEED 2700 IOEXP2 INTC Controller";
+    aic->num_lines = 32;
+    aic->num_inpins = 2;
+    aic->num_outpins = 10;
+    aic->mem_size = 0x400;
+    aic->nr_regs = 0x58 >> 2;
+    aic->reg_offset = 0x100;
+    aic->reg_ops = &aspeed_intcio_ops;
+    aic->irq_table = aspeed_2700_intcioexp2_irqs;
+    aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcioexp2_irqs);
+}
+
+static const TypeInfo aspeed_2700_intcioexp2_info = {
+    .name = TYPE_ASPEED_2700_INTCIOEXP2,
+    .parent = TYPE_ASPEED_INTC,
+    .class_init = aspeed_2700_intcioexp2_class_init,
+};
+
+static AspeedINTCIRQ aspeed_2700_intcioexp1_irqs[ASPEED_INTC_MAX_INPINS] = {
+    {0, 6, 1, R_GICINT192_EN, R_GICINT192_STATUS},
+    {1, 7, 1, R_GICINT193_EN, R_GICINT193_STATUS},
+};
+
+static void aspeed_2700_intcioexp1_class_init(ObjectClass *klass,
+                                              const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    AspeedINTCClass *aic = ASPEED_INTC_CLASS(klass);
+
+    dc->desc = "ASPEED 2700 IOEXP1 INTC Controller";
+    aic->num_lines = 32;
+    aic->num_inpins = 2;
+    aic->num_outpins = 10;
+    aic->mem_size = 0x400;
+    aic->nr_regs = 0x58 >> 2;
+    aic->reg_offset = 0x100;
+    aic->reg_ops = &aspeed_intcio_ops;
+    aic->irq_table = aspeed_2700_intcioexp1_irqs;
+    aic->irq_table_count = ARRAY_SIZE(aspeed_2700_intcioexp1_irqs);
+}
+
+static const TypeInfo aspeed_2700_intcioexp1_info = {
+    .name = TYPE_ASPEED_2700_INTCIOEXP1,
+    .parent = TYPE_ASPEED_INTC,
+    .class_init = aspeed_2700_intcioexp1_class_init,
+};
+
 static AspeedINTCIRQ aspeed_2700_intcio_irqs[ASPEED_INTC_MAX_INPINS] = {
     {0, 0, 1, R_GICINT192_EN, R_GICINT192_STATUS},
     {1, 1, 1, R_GICINT193_EN, R_GICINT193_STATUS},
@@ -950,6 +1008,8 @@
     type_register_static(&aspeed_intc_info);
     type_register_static(&aspeed_2700_intc_info);
     type_register_static(&aspeed_2700_intcio_info);
+    type_register_static(&aspeed_2700_intcioexp1_info);
+    type_register_static(&aspeed_2700_intcioexp2_info);
     type_register_static(&aspeed_2700ssp_intc_info);
     type_register_static(&aspeed_2700ssp_intcio_info);
     type_register_static(&aspeed_2700tsp_intc_info);
diff --git a/hw/misc/aspeed_ltpi.c b/hw/misc/aspeed_ltpi.c
new file mode 100644
index 0000000..131cea9
--- /dev/null
+++ b/hw/misc/aspeed_ltpi.c
@@ -0,0 +1,193 @@
+/*
+ * ASPEED LTPI Controller
+ *
+ * Copyright (C) 2025 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "hw/misc/aspeed_ltpi.h"
+
+#define ASPEED_LTPI_CTRL_BASE   0x000
+#define ASPEED_LTPI_PHY_BASE    0x200
+#define ASPEED_LTPI_TOP_BASE    0x800
+
+#define LTPI_CTRL_LINK_MNG 0x42
+#define LTPI_PHY_MODE 0x0
+
+static uint64_t aspeed_ltpi_top_read(void *opaque, hwaddr offset, unsigned size)
+{
+    AspeedLTPIState *s = opaque;
+    uint32_t idx = offset >> 2;
+
+    return s->top_regs[idx];
+}
+
+static void aspeed_ltpi_top_write(void *opaque, hwaddr offset,
+                              uint64_t val, unsigned size)
+{
+    AspeedLTPIState *s = opaque;
+    uint32_t idx = offset >> 2;
+
+    switch (offset) {
+    default:
+        s->top_regs[idx] = (uint32_t)val;
+        break;
+    }
+}
+
+static const MemoryRegionOps aspeed_ltpi_top_ops = {
+    .read = aspeed_ltpi_top_read,
+    .write = aspeed_ltpi_top_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static uint64_t aspeed_ltpi_phy_read(void *opaque, hwaddr offset, unsigned size)
+{
+    AspeedLTPIState *s = opaque;
+    uint32_t idx = offset >> 2;
+
+    return s->phy_regs[idx];
+}
+
+static void aspeed_ltpi_phy_write(void *opaque, hwaddr offset,
+                              uint64_t val, unsigned size)
+{
+    AspeedLTPIState *s = opaque;
+    uint32_t idx = offset >> 2;
+
+    switch (offset) {
+    default:
+        s->phy_regs[idx] = (uint32_t)val;
+        break;
+    }
+}
+
+static const MemoryRegionOps aspeed_ltpi_phy_ops = {
+    .read = aspeed_ltpi_phy_read,
+    .write = aspeed_ltpi_phy_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static uint64_t aspeed_ltpi_ctrl_read(void *opaque,
+                                      hwaddr offset, unsigned size)
+{
+    AspeedLTPIState *s = opaque;
+    uint32_t idx = offset >> 2;
+
+    return s->ctrl_regs[idx];
+}
+
+static void aspeed_ltpi_ctrl_write(void *opaque, hwaddr offset,
+                              uint64_t val, unsigned size)
+{
+    AspeedLTPIState *s = opaque;
+    uint32_t idx = offset >> 2;
+
+    switch (offset) {
+    default:
+        s->ctrl_regs[idx] = (uint32_t)val;
+        break;
+    }
+}
+
+static const MemoryRegionOps aspeed_ltpi_ctrl_ops = {
+    .read = aspeed_ltpi_ctrl_read,
+    .write = aspeed_ltpi_ctrl_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static void aspeed_ltpi_reset(DeviceState *dev)
+{
+    AspeedLTPIState *s = ASPEED_LTPI(dev);
+
+    memset(s->ctrl_regs, 0, sizeof(s->ctrl_regs));
+    memset(s->phy_regs, 0, sizeof(s->phy_regs));
+    memset(s->top_regs, 0, sizeof(s->top_regs));
+    /* set default values */
+    s->ctrl_regs[LTPI_CTRL_LINK_MNG] = 0x11900007;
+    s->phy_regs[LTPI_PHY_MODE] = 0x2;
+}
+
+
+static const VMStateDescription vmstate_aspeed_ltpi = {
+    .name = TYPE_ASPEED_LTPI,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(ctrl_regs, AspeedLTPIState,
+                             ASPEED_LTPI_CTRL_SIZE >> 2),
+        VMSTATE_UINT32_ARRAY(phy_regs, AspeedLTPIState,
+                             ASPEED_LTPI_PHY_SIZE >> 2),
+        VMSTATE_UINT32_ARRAY(top_regs, AspeedLTPIState,
+                             ASPEED_LTPI_TOP_SIZE >> 2),
+
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void aspeed_ltpi_realize(DeviceState *dev, Error **errp)
+{
+    AspeedLTPIState *s = ASPEED_LTPI(dev);
+
+    memory_region_init(&s->mmio, OBJECT(s), TYPE_ASPEED_LTPI,
+                       ASPEED_LTPI_TOTAL_SIZE);
+
+    memory_region_init_io(&s->mmio_ctrl, OBJECT(s),
+                          &aspeed_ltpi_ctrl_ops, s,
+                          "aspeed-ltpi-ctrl", ASPEED_LTPI_CTRL_SIZE);
+
+    memory_region_init_io(&s->mmio_phy, OBJECT(s),
+                          &aspeed_ltpi_phy_ops, s,
+                          "aspeed-ltpi-phy", ASPEED_LTPI_PHY_SIZE);
+
+    memory_region_init_io(&s->mmio_top, OBJECT(s),
+                          &aspeed_ltpi_top_ops, s,
+                          "aspeed-ltpi-top", ASPEED_LTPI_TOP_SIZE);
+
+    memory_region_add_subregion(&s->mmio,
+                                ASPEED_LTPI_CTRL_BASE, &s->mmio_ctrl);
+    memory_region_add_subregion(&s->mmio,
+                                ASPEED_LTPI_PHY_BASE, &s->mmio_phy);
+    memory_region_add_subregion(&s->mmio,
+                                ASPEED_LTPI_TOP_BASE, &s->mmio_top);
+
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio);
+}
+
+static void aspeed_ltpi_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    dc->realize = aspeed_ltpi_realize;
+    dc->vmsd = &vmstate_aspeed_ltpi;
+    device_class_set_legacy_reset(dc, aspeed_ltpi_reset);
+}
+
+static const TypeInfo aspeed_ltpi_info = {
+    .name          = TYPE_ASPEED_LTPI,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AspeedLTPIState),
+    .class_init    = aspeed_ltpi_class_init,
+};
+
+static void aspeed_ltpi_register_types(void)
+{
+    type_register_static(&aspeed_ltpi_info);
+}
+
+type_init(aspeed_ltpi_register_types);
diff --git a/hw/misc/aspeed_pwm.c b/hw/misc/aspeed_pwm.c
new file mode 100644
index 0000000..ee3d588
--- /dev/null
+++ b/hw/misc/aspeed_pwm.c
@@ -0,0 +1,120 @@
+/*
+ * ASPEED PWM Controller
+ *
+ * Copyright (C) 2017-2021 IBM Corp.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "hw/misc/aspeed_pwm.h"
+#include "qapi/error.h"
+#include "migration/vmstate.h"
+
+#include "trace.h"
+
+static uint64_t aspeed_pwm_read(void *opaque, hwaddr addr,
+                                     unsigned int size)
+{
+    AspeedPWMState *s = ASPEED_PWM(opaque);
+    uint64_t val = 0;
+
+    addr >>= 2;
+
+    if (addr >= ASPEED_PWM_NR_REGS) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
+                      __func__, addr << 2);
+    } else {
+        val = s->regs[addr];
+    }
+
+    trace_aspeed_pwm_read(addr << 2, val);
+
+    return val;
+}
+
+static void aspeed_pwm_write(void *opaque, hwaddr addr, uint64_t data,
+                              unsigned int size)
+{
+    AspeedPWMState *s = ASPEED_PWM(opaque);
+
+    trace_aspeed_pwm_write(addr, data);
+
+    addr >>= 2;
+
+    if (addr >= ASPEED_PWM_NR_REGS) {
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
+                      __func__, addr << 2);
+        return;
+    }
+
+    s->regs[addr] = data;
+}
+
+static const MemoryRegionOps aspeed_pwm_ops = {
+    .read = aspeed_pwm_read,
+    .write = aspeed_pwm_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static void aspeed_pwm_reset(DeviceState *dev)
+{
+    struct AspeedPWMState *s = ASPEED_PWM(dev);
+
+    memset(s->regs, 0, sizeof(s->regs));
+}
+
+static void aspeed_pwm_realize(DeviceState *dev, Error **errp)
+{
+    AspeedPWMState *s = ASPEED_PWM(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    sysbus_init_irq(sbd, &s->irq);
+
+    memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_pwm_ops, s,
+            TYPE_ASPEED_PWM, 0x1000);
+
+    sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_aspeed_pwm = {
+    .name = TYPE_ASPEED_PWM,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, AspeedPWMState, ASPEED_PWM_NR_REGS),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static void aspeed_pwm_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = aspeed_pwm_realize;
+    device_class_set_legacy_reset(dc, aspeed_pwm_reset);
+    dc->desc = "Aspeed PWM Controller";
+    dc->vmsd = &vmstate_aspeed_pwm;
+}
+
+static const TypeInfo aspeed_pwm_info = {
+    .name = TYPE_ASPEED_PWM,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AspeedPWMState),
+    .class_init = aspeed_pwm_class_init,
+};
+
+static void aspeed_pwm_register_types(void)
+{
+    type_register_static(&aspeed_pwm_info);
+}
+
+type_init(aspeed_pwm_register_types);
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index c444e03..d304a98 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -137,6 +137,8 @@
   'aspeed_hace.c',
   'aspeed_i3c.c',
   'aspeed_lpc.c',
+  'aspeed_ltpi.c',
+  'aspeed_pwm.c',
   'aspeed_scu.c',
   'aspeed_sbc.c',
   'aspeed_sdmc.c',
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 4cee8a2..d6af2fc 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -299,6 +299,10 @@
 aspeed_i3c_device_read(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] read: offset 0x%" PRIx64 " data 0x%" PRIx64
 aspeed_i3c_device_write(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] write: offset 0x%" PRIx64 " data 0x%" PRIx64
 
+# aspeed_pwm.c
+aspeed_pwm_read(uint64_t offset, uint64_t data) "read: offset 0x%" PRIx64 " data 0x%" PRIx64
+aspeed_pwm_write(uint64_t offset, uint64_t data) "write: offset 0x%" PRIx64 " data 0x%" PRIx64
+
 # aspeed_sdmc.c
 aspeed_sdmc_write(uint64_t reg, uint64_t data) "reg @0x%" PRIx64 " data: 0x%" PRIx64
 aspeed_sdmc_read(uint64_t reg, uint64_t data) "reg @0x%" PRIx64 " data: 0x%" PRIx64
diff --git a/hw/pci-host/aspeed_pcie.c b/hw/pci-host/aspeed_pcie.c
index 8eeba1f..c150496 100644
--- a/hw/pci-host/aspeed_pcie.c
+++ b/hw/pci-host/aspeed_pcie.c
@@ -27,44 +27,6 @@
 #include "trace.h"
 
 /*
- * PCIe Root Device
- * This device exists only on AST2600.
- */
-
-static void aspeed_pcie_root_device_class_init(ObjectClass *klass,
-                                               const void *data)
-{
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-    DeviceClass *dc = DEVICE_CLASS(klass);
-
-    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
-    dc->desc = "ASPEED PCIe Root Device";
-    k->vendor_id = PCI_VENDOR_ID_ASPEED;
-    k->device_id = 0x2600;
-    k->class_id = PCI_CLASS_BRIDGE_HOST;
-    k->subsystem_vendor_id = k->vendor_id;
-    k->subsystem_id = k->device_id;
-    k->revision = 0;
-
-    /*
-     * PCI-facing part of the host bridge,
-     * not usable without the host-facing part
-     */
-    dc->user_creatable = false;
-}
-
-static const TypeInfo aspeed_pcie_root_device_info = {
-    .name = TYPE_ASPEED_PCIE_ROOT_DEVICE,
-    .parent = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(AspeedPCIERootDeviceState),
-    .class_init = aspeed_pcie_root_device_class_init,
-    .interfaces = (const InterfaceInfo[]) {
-        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
-        { },
-    },
-};
-
-/*
  * PCIe Root Port
  */
 
@@ -291,18 +253,6 @@
                                 &rc->dram_alias);
     pci_setup_iommu(pci->bus, &aspeed_pcie_rc_iommu_ops, rc);
 
-    /* setup root device */
-    if (rc->has_rd) {
-        object_initialize_child(OBJECT(rc), "root_device", &rc->root_device,
-                                TYPE_ASPEED_PCIE_ROOT_DEVICE);
-        qdev_prop_set_int32(DEVICE(&rc->root_device), "addr",
-                            PCI_DEVFN(0, 0));
-        qdev_prop_set_bit(DEVICE(&rc->root_device), "multifunction", false);
-        if (!qdev_realize(DEVICE(&rc->root_device), BUS(pci->bus), errp)) {
-            return;
-        }
-    }
-
     /* setup root port */
     qdev_prop_set_int32(DEVICE(&rc->root_port), "addr", rc->rp_addr);
     qdev_prop_set_uint16(DEVICE(&rc->root_port), "chassis", cfg->id);
@@ -318,7 +268,7 @@
     AspeedPCIECfgState *cfg =
            container_of(rc, AspeedPCIECfgState, rc);
 
-    snprintf(rc->name, sizeof(rc->name), "%04x:%02x", cfg->id, rc->bus_nr);
+    snprintf(rc->name, sizeof(rc->name), "%04x:00", cfg->id);
 
     return rc->name;
 }
@@ -333,8 +283,6 @@
 }
 
 static const Property aspeed_pcie_rc_props[] = {
-    DEFINE_PROP_UINT32("bus-nr", AspeedPCIERcState, bus_nr, 0),
-    DEFINE_PROP_BOOL("has-rd", AspeedPCIERcState, has_rd, 0),
     DEFINE_PROP_UINT32("rp-addr", AspeedPCIERcState, rp_addr, 0),
     DEFINE_PROP_UINT32("msi-addr", AspeedPCIERcState, msi_addr, 0),
     DEFINE_PROP_UINT64("dram-base", AspeedPCIERcState, dram_base, 0),
@@ -540,17 +488,6 @@
     offset = cfg_addr & 0xffc;
 
     pci = PCI_HOST_BRIDGE(rc);
-
-    /*
-     * On the AST2600, the RC_H bus number range from 0x80 to 0xFF, with the
-     * root device and root port assigned to bus 0x80 instead of the standard
-     * 0x00. To allow the PCI subsystem to correctly discover devices on the
-     * root bus, bus 0x80 is remapped to 0x00.
-     */
-    if (bus == rc->bus_nr) {
-        bus = 0;
-    }
-
     pdev = pci_find_device(pci->bus, bus, devfn);
     if (!pdev) {
         s->regs[desc->rdata_reg] = ~0;
@@ -700,12 +637,6 @@
                           apc->nr_regs << 2);
     sysbus_init_mmio(sbd, &s->mmio);
 
-    object_property_set_int(OBJECT(&s->rc), "bus-nr",
-                            apc->rc_bus_nr,
-                            &error_abort);
-    object_property_set_bool(OBJECT(&s->rc), "has-rd",
-                            apc->rc_has_rd,
-                            &error_abort);
     object_property_set_int(OBJECT(&s->rc), "rp-addr",
                             apc->rc_rp_addr,
                             &error_abort);
@@ -744,8 +675,6 @@
     apc->reg_map = &aspeed_regmap;
     apc->nr_regs = 0x100 >> 2;
     apc->rc_msi_addr = 0x1e77005C;
-    apc->rc_bus_nr = 0x80;
-    apc->rc_has_rd = true;
     apc->rc_rp_addr = PCI_DEVFN(8, 0);
 }
 
@@ -865,8 +794,6 @@
     apc->reg_map = &aspeed_2700_regmap;
     apc->nr_regs = 0x100 >> 2;
     apc->rc_msi_addr = 0x000000F0;
-    apc->rc_bus_nr = 0;
-    apc->rc_has_rd = false;
     apc->rc_rp_addr = PCI_DEVFN(0, 0);
 }
 
@@ -1040,7 +967,6 @@
 static void aspeed_pcie_register_types(void)
 {
     type_register_static(&aspeed_pcie_rc_info);
-    type_register_static(&aspeed_pcie_root_device_info);
     type_register_static(&aspeed_pcie_root_port_info);
     type_register_static(&aspeed_pcie_cfg_info);
     type_register_static(&aspeed_2700_pcie_cfg_info);
diff --git a/hw/uefi/var-service-vars.c b/hw/uefi/var-service-vars.c
index 8533533..94f40ef 100644
--- a/hw/uefi/var-service-vars.c
+++ b/hw/uefi/var-service-vars.c
@@ -475,7 +475,8 @@
                 goto rollback;
             }
             if (old_var && new_var) {
-                if (uefi_time_compare(&old_var->time, &new_var->time) > 0) {
+                if ((va->attributes & EFI_VARIABLE_APPEND_WRITE) == 0 &&
+                    uefi_time_compare(&old_var->time, &new_var->time) > 0) {
                     trace_uefi_vars_security_violation("time check failed");
                     mvar->status = EFI_SECURITY_VIOLATION;
                     goto rollback;
@@ -592,7 +593,7 @@
         return uefi_vars_mm_error(mhdr, mvar, EFI_BAD_BUFFER_SIZE);
     }
 
-    ps->payload_size = uv->buf_size;
+    ps->payload_size = uv->buf_size - sizeof(*mhdr) - sizeof(*mvar);
     mvar->status = EFI_SUCCESS;
     return length;
 }
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index 3b50ecf..9113527 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -397,7 +397,7 @@
   bool show_opcodes;
 
   /* Field intended to be used by targets in any way they deem suitable.  */
-  void *target_info;
+  const void *target_info;
 
   /* Options for Capstone disassembly.  */
   int cap_arch;
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index 4b8ee09..b036116 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -203,4 +203,7 @@
 };
 int acpi_get_slic_oem(AcpiSlicOem *oem);
 
+/* core.c */
+int acpi_checksum(const uint8_t *data, int len);
+
 #endif /* QEMU_HW_ACPI_H */
diff --git a/include/hw/arm/aspeed_ast1700.h b/include/hw/arm/aspeed_ast1700.h
new file mode 100644
index 0000000..f7bd4e8
--- /dev/null
+++ b/include/hw/arm/aspeed_ast1700.h
@@ -0,0 +1,54 @@
+/*
+ * ASPEED AST1700 IO Expander
+ *
+ * Copyright (C) 2025 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef ASPEED_AST1700_H
+#define ASPEED_AST1700_H
+
+#include "hw/core/sysbus.h"
+#include "hw/misc/aspeed_scu.h"
+#include "hw/adc/aspeed_adc.h"
+#include "hw/gpio/aspeed_gpio.h"
+#include "hw/gpio/aspeed_sgpio.h"
+#include "hw/i2c/aspeed_i2c.h"
+#include "hw/misc/aspeed_ltpi.h"
+#include "hw/misc/aspeed_pwm.h"
+#include "hw/ssi/aspeed_smc.h"
+#include "hw/watchdog/wdt_aspeed.h"
+#include "hw/char/serial-mm.h"
+#include "hw/misc/unimp.h"
+
+#define AST1700_SGPIO_NUM            2
+#define AST1700_WDT_NUM              9
+
+#define TYPE_ASPEED_AST1700 "aspeed.ast1700"
+
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedAST1700SoCState, ASPEED_AST1700)
+
+struct AspeedAST1700SoCState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+    MemoryRegion *dram_mr;
+    uint8_t board_idx;
+    uint32_t silicon_rev;
+
+    AspeedLTPIState ltpi;
+    SerialMM uart;
+    MemoryRegion sram;
+    AspeedSMCState spi;
+    AspeedADCState adc;
+    AspeedSCUState scu;
+    AspeedGPIOState gpio;
+    AspeedSGPIOState sgpiom[AST1700_SGPIO_NUM];
+    AspeedI2CState i2c;
+    AspeedPWMState pwm;
+    AspeedWDTState wdt[AST1700_WDT_NUM];
+
+    UnimplementedDeviceState i3c;
+};
+
+#endif /* ASPEED_AST1700_H */
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
index 18ff961..b185b04 100644
--- a/include/hw/arm/aspeed_soc.h
+++ b/include/hw/arm/aspeed_soc.h
@@ -28,6 +28,7 @@
 #include "hw/misc/aspeed_hace.h"
 #include "hw/misc/aspeed_sbc.h"
 #include "hw/misc/aspeed_sli.h"
+#include "hw/misc/aspeed_pwm.h"
 #include "hw/watchdog/wdt_aspeed.h"
 #include "hw/net/ftgmac100.h"
 #include "target/arm/cpu.h"
@@ -43,6 +44,8 @@
 #include "hw/fsi/aspeed_apb2opb.h"
 #include "hw/char/serial-mm.h"
 #include "hw/intc/arm_gicv3.h"
+#include "hw/misc/aspeed_ltpi.h"
+#include "hw/arm/aspeed_ast1700.h"
 
 #define VBOOTROM_FILE_NAME  "ast27x0_bootrom.bin"
 
@@ -55,6 +58,8 @@
 #define ASPEED_UARTS_NUM 13
 #define ASPEED_JTAG_NUM  2
 #define ASPEED_PCIE_NUM  3
+#define ASPEED_INTC_NUM  2
+#define ASPEED_IOEXP_NUM 2
 
 struct AspeedSoCState {
     DeviceState parent;
@@ -86,6 +91,7 @@
     MemoryRegion secsram;
     UnimplementedDeviceState sbc_unimplemented;
     AspeedSDMCState sdmc;
+    AspeedPWMState pwm;
     AspeedWDTState wdt[ASPEED_WDTS_NUM];
     FTGMAC100State ftgmac100[ASPEED_MACS_NUM];
     AspeedMiiState mii[ASPEED_MACS_NUM];
@@ -106,12 +112,12 @@
     UnimplementedDeviceState video;
     UnimplementedDeviceState emmc_boot_controller;
     UnimplementedDeviceState dpmcu;
-    UnimplementedDeviceState pwm;
     UnimplementedDeviceState espi;
     UnimplementedDeviceState udc;
-    UnimplementedDeviceState ltpi;
     UnimplementedDeviceState jtag[ASPEED_JTAG_NUM];
     AspeedAPB2OPBState fsi[2];
+    AspeedLTPIState ltpi_ctrl[ASPEED_IOEXP_NUM];
+    AspeedAST1700SoCState ioexp[ASPEED_IOEXP_NUM];
 };
 
 #define TYPE_ASPEED_SOC "aspeed-soc"
@@ -141,7 +147,8 @@
     AspeedSoCState parent;
 
     ARMCPU cpu[ASPEED_CPUS_NUM];
-    AspeedINTCState intc[2];
+    AspeedINTCState intc[ASPEED_INTC_NUM];
+    AspeedINTCState intcioexp[ASPEED_IOEXP_NUM];
     GICv3State gic;
     MemoryRegion dram_empty;
 };
@@ -174,6 +181,7 @@
     int macs_num;
     int uarts_num;
     int uarts_base;
+    int ioexp_num;
     const int *irqmap;
     const hwaddr *memmap;
     uint32_t num_cpus;
@@ -186,7 +194,6 @@
     ASPEED_DEV_IOMEM,
     ASPEED_DEV_IOMEM0,
     ASPEED_DEV_IOMEM1,
-    ASPEED_DEV_LTPI,
     ASPEED_DEV_UART0,
     ASPEED_DEV_UART1,
     ASPEED_DEV_UART2,
@@ -279,6 +286,16 @@
     ASPEED_GIC_REDIST,
     ASPEED_DEV_IPC0,
     ASPEED_DEV_IPC1,
+    ASPEED_DEV_LTPI_CTRL1,
+    ASPEED_DEV_LTPI_CTRL2,
+    ASPEED_DEV_LTPI_IO0,
+    ASPEED_DEV_LTPI_IO1,
+    ASPEED_DEV_IOEXP0_I2C,
+    ASPEED_DEV_IOEXP1_I2C,
+    ASPEED_DEV_IOEXP0_INTCIO,
+    ASPEED_DEV_IOEXP1_INTCIO,
+    ASPEED_DEV_IOEXP0_I3C,
+    ASPEED_DEV_IOEXP1_I3C,
 };
 
 const char *aspeed_soc_cpu_type(const char * const *valid_cpu_types);
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 9867870..ef20cb3 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -175,7 +175,7 @@
     const char * (*gdb_arch_name)(CPUState *cpu);
     const char * (*gdb_get_core_xml_file)(CPUState *cpu);
 
-    void (*disas_set_info)(CPUState *cpu, disassemble_info *info);
+    void (*disas_set_info)(const CPUState *cpu, disassemble_info *info);
 
     const char *deprecation_note;
     struct AccelCPUClass *accel_cpu;
diff --git a/include/hw/gpio/pca9552.h b/include/hw/gpio/pca9552.h
index c36525f..43b1752 100644
--- a/include/hw/gpio/pca9552.h
+++ b/include/hw/gpio/pca9552.h
@@ -14,6 +14,7 @@
 
 #define TYPE_PCA9552 "pca9552"
 #define TYPE_PCA955X "pca955x"
+#define TYPE_PCA9535 "pca9535"
 typedef struct PCA955xState PCA955xState;
 DECLARE_INSTANCE_CHECKER(PCA955xState, PCA955X,
                          TYPE_PCA955X)
diff --git a/include/hw/gpio/pca9552_regs.h b/include/hw/gpio/pca9552_regs.h
index d8051cf..5a6bb03 100644
--- a/include/hw/gpio/pca9552_regs.h
+++ b/include/hw/gpio/pca9552_regs.h
@@ -29,4 +29,14 @@
  */
 #define PCA9552_AUTOINC  (1 << 4)
 
+/* PCA9535 Registers (same addresses, different semantics) */
+#define PCA9535_INPUT0      0 /* read only input register 0 */
+#define PCA9535_INPUT1      1 /* read only input register 1  */
+#define PCA9535_OUTPUT0     2 /* read/write output register 0 */
+#define PCA9535_OUTPUT1     3 /* read/write output register 1 */
+#define PCA9535_POLARITY0   4 /* read/write polarity inversion register 0 */
+#define PCA9535_POLARITY1   5 /* read/write polarity inversion register 1 */
+#define PCA9535_CONFIG0     6 /* read/write configuration register 0 */
+#define PCA9535_CONFIG1     7 /* read/write configuration register 1 */
+
 #endif
diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index ffcff25..68bd138 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -252,6 +252,7 @@
     MemoryRegion mr_pool;
 
     I2CBus *bus;
+    char *name;
     uint8_t id;
     qemu_irq irq;
 
@@ -269,6 +270,7 @@
     uint32_t intr_status;
     uint32_t ctrl_global;
     uint32_t new_clk_divider;
+    char *bus_label;
     MemoryRegion pool_iomem;
     uint8_t share_pool[ASPEED_I2C_SHARE_POOL_SIZE];
 
diff --git a/include/hw/intc/aspeed_intc.h b/include/hw/intc/aspeed_intc.h
index 5d10268..b25ef4a 100644
--- a/include/hw/intc/aspeed_intc.h
+++ b/include/hw/intc/aspeed_intc.h
@@ -15,6 +15,8 @@
 #define TYPE_ASPEED_INTC "aspeed.intc"
 #define TYPE_ASPEED_2700_INTC TYPE_ASPEED_INTC "-ast2700"
 #define TYPE_ASPEED_2700_INTCIO TYPE_ASPEED_INTC "io-ast2700"
+#define TYPE_ASPEED_2700_INTCIOEXP1 TYPE_ASPEED_INTC "-ast2700-ioexp1"
+#define TYPE_ASPEED_2700_INTCIOEXP2 TYPE_ASPEED_INTC "-ast2700-ioexp2"
 #define TYPE_ASPEED_2700SSP_INTC TYPE_ASPEED_INTC "-ast2700ssp"
 #define TYPE_ASPEED_2700SSP_INTCIO TYPE_ASPEED_INTC "io-ast2700ssp"
 #define TYPE_ASPEED_2700TSP_INTC TYPE_ASPEED_INTC "-ast2700tsp"
diff --git a/include/hw/misc/aspeed_ltpi.h b/include/hw/misc/aspeed_ltpi.h
new file mode 100644
index 0000000..3330a49
--- /dev/null
+++ b/include/hw/misc/aspeed_ltpi.h
@@ -0,0 +1,33 @@
+/*
+ * ASPEED LTPI Controller
+ *
+ * Copyright (C) 2025 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef ASPEED_LTPI_H
+#define ASPEED_LTPI_H
+
+#include "hw/core/sysbus.h"
+
+#define TYPE_ASPEED_LTPI "aspeed.ltpi-ctrl"
+OBJECT_DECLARE_SIMPLE_TYPE(AspeedLTPIState, ASPEED_LTPI)
+
+#define ASPEED_LTPI_TOTAL_SIZE  0x900
+#define ASPEED_LTPI_CTRL_SIZE   0x200
+#define ASPEED_LTPI_PHY_SIZE    0x100
+#define ASPEED_LTPI_TOP_SIZE    0x100
+
+struct AspeedLTPIState {
+    SysBusDevice parent;
+    MemoryRegion mmio;
+    MemoryRegion mmio_ctrl;
+    MemoryRegion mmio_phy;
+    MemoryRegion mmio_top;
+
+    uint32_t ctrl_regs[ASPEED_LTPI_CTRL_SIZE >> 2];
+    uint32_t phy_regs[ASPEED_LTPI_PHY_SIZE >> 2];
+    uint32_t top_regs[ASPEED_LTPI_TOP_SIZE >> 2];
+};
+
+#endif /* ASPEED_LTPI_H */
diff --git a/include/hw/misc/aspeed_pwm.h b/include/hw/misc/aspeed_pwm.h
new file mode 100644
index 0000000..f4104ad
--- /dev/null
+++ b/include/hw/misc/aspeed_pwm.h
@@ -0,0 +1,30 @@
+/*
+ * ASPEED PWM Controller
+ *
+ * Copyright (C) 2017-2021 IBM Corp.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef ASPEED_PWM_H
+#define ASPEED_PWM_H
+
+#include "hw/core/sysbus.h"
+
+#define TYPE_ASPEED_PWM "aspeed.pwm"
+#define ASPEED_PWM(obj) OBJECT_CHECK(AspeedPWMState, (obj), TYPE_ASPEED_PWM)
+
+#define ASPEED_PWM_NR_REGS (0x10C >> 2)
+
+typedef struct AspeedPWMState {
+    /* <private> */
+    SysBusDevice parent;
+
+    /*< public >*/
+    MemoryRegion iomem;
+    qemu_irq irq;
+
+    uint32_t regs[ASPEED_PWM_NR_REGS];
+} AspeedPWMState;
+
+#endif /* _ASPEED_PWM_H_ */
diff --git a/include/hw/pci-host/aspeed_pcie.h b/include/hw/pci-host/aspeed_pcie.h
index e660119..143b356 100644
--- a/include/hw/pci-host/aspeed_pcie.h
+++ b/include/hw/pci-host/aspeed_pcie.h
@@ -50,13 +50,6 @@
     PCIESlot parent_obj;
 } AspeedPCIERootPortState;
 
-#define TYPE_ASPEED_PCIE_ROOT_DEVICE "aspeed.pcie-root-device"
-OBJECT_DECLARE_SIMPLE_TYPE(AspeedPCIERootDeviceState, ASPEED_PCIE_ROOT_DEVICE);
-
-struct AspeedPCIERootDeviceState {
-    PCIBridge parent_obj;
-};
-
 #define TYPE_ASPEED_PCIE_RC "aspeed.pcie-rc"
 OBJECT_DECLARE_SIMPLE_TYPE(AspeedPCIERcState, ASPEED_PCIE_RC);
 
@@ -76,12 +69,9 @@
     uint64_t dram_base;
     uint32_t msi_addr;
     uint32_t rp_addr;
-    uint32_t bus_nr;
     char name[16];
-    bool has_rd;
     qemu_irq irq;
 
-    AspeedPCIERootDeviceState root_device;
     AspeedPCIERootPortState root_port;
 };
 
@@ -111,7 +101,6 @@
 
     uint32_t rc_msi_addr;
     uint32_t rc_rp_addr;
-    uint64_t rc_bus_nr;
     uint64_t nr_regs;
     bool rc_has_rd;
 };
diff --git a/include/qemu/target-info.h b/include/qemu/target-info.h
index 6235962..e328733 100644
--- a/include/qemu/target-info.h
+++ b/include/qemu/target-info.h
@@ -71,4 +71,25 @@
  */
 bool target_aarch64(void);
 
+/**
+ * target_base_ppc:
+ *
+ * Returns whether the target architecture is PowerPC 32-bit or 64-bit.
+ */
+bool target_base_ppc(void);
+
+/**
+ * target_ppc:
+ *
+ * Returns whether the target architecture is PowerPC 32-bit.
+ */
+bool target_ppc(void);
+
+/**
+ * target_ppc64:
+ *
+ * Returns whether the target architecture is PowerPC 64-bit.
+ */
+bool target_ppc64(void);
+
 #endif
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 4a94af9..416a8c9 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -55,6 +55,7 @@
 typedef struct HostMemoryBackend HostMemoryBackend;
 typedef struct I2CBus I2CBus;
 typedef struct I2SCodec I2SCodec;
+typedef struct IgvmCfg IgvmCfg;
 typedef struct IOMMUMemoryRegion IOMMUMemoryRegion;
 typedef struct ISABus ISABus;
 typedef struct ISADevice ISADevice;
diff --git a/include/system/igvm-cfg.h b/include/system/igvm-cfg.h
index 944f23a..e06d611 100644
--- a/include/system/igvm-cfg.h
+++ b/include/system/igvm-cfg.h
@@ -12,19 +12,10 @@
 #ifndef QEMU_IGVM_CFG_H
 #define QEMU_IGVM_CFG_H
 
+#include "hw/core/boards.h"
+#include "qemu/typedefs.h"
 #include "qom/object.h"
 
-typedef struct IgvmCfg {
-    ObjectClass parent_class;
-
-    /*
-     * filename: Filename that specifies a file that contains the configuration
-     *           of the guest in Independent Guest Virtual Machine (IGVM)
-     *           format.
-     */
-    char *filename;
-} IgvmCfg;
-
 typedef struct IgvmCfgClass {
     ObjectClass parent_class;
 
@@ -37,7 +28,7 @@
      *
      * Returns 0 for ok and -1 on error.
      */
-    int (*process)(IgvmCfg *cfg, ConfidentialGuestSupport *cgs,
+    int (*process)(IgvmCfg *cfg, MachineState *machine_state,
                    bool onlyVpContext, Error **errp);
 
 } IgvmCfgClass;
diff --git a/include/system/igvm-internal.h b/include/system/igvm-internal.h
new file mode 100644
index 0000000..38004bd
--- /dev/null
+++ b/include/system/igvm-internal.h
@@ -0,0 +1,82 @@
+/*
+ * QEMU IGVM private data structures
+ *
+ * Everything which depends on igvm library headers goes here.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef QEMU_IGVM_INTERNAL_H
+#define QEMU_IGVM_INTERNAL_H
+
+#include "qemu/queue.h"
+#include "qemu/typedefs.h"
+#include "qom/object.h"
+#include "hw/core/boards.h"
+#include "hw/core/resettable.h"
+
+#include "system/confidential-guest-support.h"
+#include <igvm/igvm.h>
+
+struct IgvmCfg {
+    ObjectClass parent_class;
+
+    /*
+     * filename: Filename that specifies a file that contains the configuration
+     *           of the guest in Independent Guest Virtual Machine (IGVM)
+     *           format.
+     */
+    char *filename;
+    IgvmHandle file;
+    ResettableState reset_state;
+};
+
+typedef struct QIgvmParameterData {
+    QTAILQ_ENTRY(QIgvmParameterData) next;
+    uint8_t *data;
+    uint32_t size;
+    uint32_t index;
+} QIgvmParameterData;
+
+/*
+ * QIgvm contains the information required during processing of a single IGVM
+ * file.
+ */
+typedef struct QIgvm {
+    IgvmHandle file;
+    MachineState *machine_state;
+    ConfidentialGuestSupportClass *cgsc;
+    uint32_t compatibility_mask;
+    unsigned current_header_index;
+    QTAILQ_HEAD(, QIgvmParameterData) parameter_data;
+    IgvmPlatformType platform_type;
+
+    /*
+     * SEV-SNP platforms can contain an ID block and authentication
+     * that should be verified by the guest.
+     */
+    struct sev_id_block *id_block;
+    struct sev_id_authentication *id_auth;
+
+    /* Define the guest policy for SEV guests */
+    uint64_t sev_policy;
+
+    /* These variables keep track of contiguous page regions */
+    IGVM_VHS_PAGE_DATA region_prev_page_data;
+    uint64_t region_start;
+    unsigned region_start_index;
+    unsigned region_last_index;
+    unsigned region_page_count;
+} QIgvm;
+
+IgvmHandle qigvm_file_init(char *filename, Error **errp);
+
+QIgvmParameterData*
+qigvm_find_param_entry(QIgvm *igvm, uint32_t parameter_area_index);
+
+/*
+ *  IGVM parameter handlers
+ */
+int qigvm_directive_madt(QIgvm *ctx, const uint8_t *header_data, Error **errp);
+
+#endif
diff --git a/include/system/igvm.h b/include/system/igvm.h
index 48ce206..5573a61 100644
--- a/include/system/igvm.h
+++ b/include/system/igvm.h
@@ -12,12 +12,13 @@
 #ifndef BACKENDS_IGVM_H
 #define BACKENDS_IGVM_H
 
+#include "hw/core/boards.h"
+#include "qemu/typedefs.h"
 #include "system/confidential-guest-support.h"
-#include "system/igvm-cfg.h"
 #include "qapi/error.h"
 
-int qigvm_process_file(IgvmCfg *igvm, ConfidentialGuestSupport *cgs,
-                      bool onlyVpContext, Error **errp);
+int qigvm_process_file(IgvmCfg *igvm, MachineState *machine_state,
+                       bool onlyVpContext, Error **errp);
 
 /* x86 native */
 int qigvm_x86_get_mem_map_entry(int index,
diff --git a/pc-bios/ast27x0_bootrom.bin b/pc-bios/ast27x0_bootrom.bin
index a4c94d6..626499b 100644
--- a/pc-bios/ast27x0_bootrom.bin
+++ b/pc-bios/ast27x0_bootrom.bin
Binary files differ
diff --git a/pc-bios/npcm7xx_bootrom.bin b/pc-bios/npcm7xx_bootrom.bin
index 9228289..60e5517 100644
--- a/pc-bios/npcm7xx_bootrom.bin
+++ b/pc-bios/npcm7xx_bootrom.bin
Binary files differ
diff --git a/pc-bios/npcm8xx_bootrom.bin b/pc-bios/npcm8xx_bootrom.bin
index 45fb40f..4b6f82f 100644
--- a/pc-bios/npcm8xx_bootrom.bin
+++ b/pc-bios/npcm8xx_bootrom.bin
Binary files differ
diff --git a/roms/vbootrom b/roms/vbootrom
index 183c9ff..1c8e951 160000
--- a/roms/vbootrom
+++ b/roms/vbootrom
@@ -1 +1 @@
-Subproject commit 183c9ff8056b7946db1ae49cc23e8980ac413174
+Subproject commit 1c8e9510b22c5b0fd7d7753f08042a4bcbd2939d
diff --git a/stubs/igvm.c b/stubs/igvm.c
index 17cd1e9..47d5130 100644
--- a/stubs/igvm.c
+++ b/stubs/igvm.c
@@ -12,6 +12,7 @@
 #include "qemu/osdep.h"
 
 #include "system/igvm.h"
+#include "system/igvm-internal.h"
 
 int qigvm_x86_get_mem_map_entry(int index,
                                 ConfidentialGuestMemoryMapEntry *entry,
@@ -24,3 +25,8 @@
 {
     return -1;
 }
+
+int qigvm_directive_madt(QIgvm *ctx, const uint8_t *header_data, Error **errp)
+{
+    return -1;
+}
diff --git a/stubs/meson.build b/stubs/meson.build
index 2b5fd8a..8a07059 100644
--- a/stubs/meson.build
+++ b/stubs/meson.build
@@ -71,7 +71,9 @@
   stub_ss.add(files('dump.c'))
   stub_ss.add(files('cmos.c'))
   stub_ss.add(files('fw_cfg.c'))
-  stub_ss.add(files('igvm.c'))
+  if igvm.found()
+    stub_ss.add(files('igvm.c'))
+  endif
   stub_ss.add(files('target-get-monitor-def.c'))
   stub_ss.add(files('target-monitor-defs.c'))
   stub_ss.add(files('win32-kbd-hook.c'))
diff --git a/target-info.c b/target-info.c
index 24696ff..5a6d728 100644
--- a/target-info.c
+++ b/target-info.c
@@ -73,3 +73,24 @@
 {
     return target_arch() == SYS_EMU_TARGET_AARCH64;
 }
+
+bool target_base_ppc(void)
+{
+    switch (target_arch()) {
+    case SYS_EMU_TARGET_PPC:
+    case SYS_EMU_TARGET_PPC64:
+        return true;
+    default:
+        return false;
+    }
+}
+
+bool target_ppc(void)
+{
+    return target_arch() == SYS_EMU_TARGET_PPC;
+}
+
+bool target_ppc64(void)
+{
+    return target_arch() == SYS_EMU_TARGET_PPC64;
+}
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index 932cdda..1780db7 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -98,7 +98,8 @@
     return alpha_env_mmu_index(cpu_env(cs));
 }
 
-static void alpha_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void alpha_cpu_disas_set_info(const CPUState *cpu,
+                                     disassemble_info *info)
 {
     info->endian = BFD_ENDIAN_LITTLE;
     info->mach = bfd_mach_alpha_ev6;
diff --git a/target/alpha/gdbstub.c b/target/alpha/gdbstub.c
index 1a7e2dd..a7110e8 100644
--- a/target/alpha/gdbstub.c
+++ b/target/alpha/gdbstub.c
@@ -59,7 +59,7 @@
 int alpha_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
     CPUAlphaState *env = cpu_env(cs);
-    target_ulong tmp = ldq_le_p(mem_buf);
+    uint64_t tmp = ldq_le_p(mem_buf);
     CPU_DoubleU d;
 
     switch (n) {
diff --git a/target/alpha/helper.c b/target/alpha/helper.c
index 126a53c..179dc2d 100644
--- a/target/alpha/helper.c
+++ b/target/alpha/helper.c
@@ -129,7 +129,7 @@
                               bool maperr, uintptr_t retaddr)
 {
     CPUAlphaState *env = cpu_env(cs);
-    target_ulong mmcsr, cause;
+    uint64_t mmcsr, cause;
 
     /* Assuming !maperr, infer the missing protection. */
     switch (access_type) {
@@ -165,16 +165,17 @@
 }
 #else
 /* Returns the OSF/1 entMM failure indication, or -1 on success.  */
-static int get_physical_address(CPUAlphaState *env, target_ulong addr,
+static int get_physical_address(CPUAlphaState *env, vaddr addr,
                                 int prot_need, int mmu_idx,
-                                target_ulong *pphys, int *pprot)
+                                hwaddr *pphys, int *pprot)
 {
     const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
     CPUState *cs = env_cpu(env);
     target_long saddr = addr;
-    target_ulong phys = 0;
-    target_ulong L1pte, L2pte, L3pte;
-    target_ulong pt, index;
+    hwaddr phys = 0;
+    uint64_t L1pte, L2pte, L3pte;
+    uint64_t pt;
+    uint16_t index;
     int prot = 0;
     int ret = MM_K_ACV;
     MemTxResult txres;
@@ -296,7 +297,7 @@
 
 hwaddr alpha_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
-    target_ulong phys;
+    hwaddr phys;
     int prot, fail;
 
     fail = get_physical_address(cpu_env(cs), addr, 0, 0, &phys, &prot);
@@ -308,7 +309,7 @@
                         bool probe, uintptr_t retaddr)
 {
     CPUAlphaState *env = cpu_env(cs);
-    target_ulong phys;
+    hwaddr phys;
     int prot, fail;
 
     fail = get_physical_address(env, addr, 1 << access_type,
diff --git a/target/alpha/machine.c b/target/alpha/machine.c
index 6828b12..dcba5d4 100644
--- a/target/alpha/machine.c
+++ b/target/alpha/machine.c
@@ -1,6 +1,7 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
-#include "migration/cpu.h"
+#include "migration/qemu-file-types.h"
+#include "migration/vmstate.h"
 
 static int get_fpcr(QEMUFile *f, void *opaque, size_t size,
                     const VMStateField *field)
diff --git a/target/alpha/meson.build b/target/alpha/meson.build
index 7dbbd55..9447f80 100644
--- a/target/alpha/meson.build
+++ b/target/alpha/meson.build
@@ -18,4 +18,4 @@
 ))
 
 target_arch += {'alpha': alpha_ss}
-target_system_arch += {'alpha': alpha_system_ss}
+target_common_system_arch += {'alpha': alpha_system_ss}
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index 48ac50a..4442462 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -65,11 +65,11 @@
     int tb_ftz;
 
     /* The set of registers active in the current context.  */
-    TCGv *ir;
+    TCGv_i64 *ir;
 
     /* Temporaries for $31 and $f31 as source and destination.  */
-    TCGv zero;
-    TCGv sink;
+    TCGv_i64 zero;
+    TCGv_i64 sink;
 };
 
 #ifdef CONFIG_USER_ONLY
@@ -86,21 +86,21 @@
 #define DISAS_PC_STALE            DISAS_TARGET_2
 
 /* global register indexes */
-static TCGv cpu_std_ir[31];
-static TCGv cpu_fir[31];
-static TCGv cpu_pc;
-static TCGv cpu_lock_addr;
-static TCGv cpu_lock_value;
+static TCGv_i64 cpu_std_ir[31];
+static TCGv_i64 cpu_fir[31];
+static TCGv_i64 cpu_pc;
+static TCGv_i64 cpu_lock_addr;
+static TCGv_i64 cpu_lock_value;
 
 #ifndef CONFIG_USER_ONLY
-static TCGv cpu_pal_ir[31];
+static TCGv_i64 cpu_pal_ir[31];
 #endif
 
 void alpha_translate_init(void)
 {
 #define DEF_VAR(V)  { &cpu_##V, #V, offsetof(CPUAlphaState, V) }
 
-    typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar;
+    typedef struct { TCGv_i64 *var; const char *name; int ofs; } GlobalVar;
     static const GlobalVar vars[] = {
         DEF_VAR(pc),
         DEF_VAR(lock_addr),
@@ -160,7 +160,7 @@
     }
 }
 
-static TCGv load_zero(DisasContext *ctx)
+static TCGv_i64 load_zero(DisasContext *ctx)
 {
     if (!ctx->zero) {
         ctx->zero = tcg_constant_i64(0);
@@ -168,10 +168,10 @@
     return ctx->zero;
 }
 
-static TCGv dest_sink(DisasContext *ctx)
+static TCGv_i64 dest_sink(DisasContext *ctx)
 {
     if (!ctx->sink) {
-        ctx->sink = tcg_temp_new();
+        ctx->sink = tcg_temp_new_i64();
     }
     return ctx->sink;
 }
@@ -184,7 +184,7 @@
     }
 }
 
-static TCGv load_gpr(DisasContext *ctx, unsigned reg)
+static TCGv_i64 load_gpr(DisasContext *ctx, unsigned reg)
 {
     if (likely(reg < 31)) {
         return ctx->ir[reg];
@@ -193,7 +193,7 @@
     }
 }
 
-static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
+static TCGv_i64 load_gpr_lit(DisasContext *ctx, unsigned reg,
                          uint8_t lit, bool islit)
 {
     if (islit) {
@@ -205,7 +205,7 @@
     }
 }
 
-static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
+static TCGv_i64 dest_gpr(DisasContext *ctx, unsigned reg)
 {
     if (likely(reg < 31)) {
         return ctx->ir[reg];
@@ -214,7 +214,7 @@
     }
 }
 
-static TCGv load_fpr(DisasContext *ctx, unsigned reg)
+static TCGv_i64 load_fpr(DisasContext *ctx, unsigned reg)
 {
     if (likely(reg < 31)) {
         return cpu_fir[reg];
@@ -223,7 +223,7 @@
     }
 }
 
-static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
+static TCGv_i64 dest_fpr(DisasContext *ctx, unsigned reg)
 {
     if (likely(reg < 31)) {
         return cpu_fir[reg];
@@ -243,17 +243,17 @@
     return ofs;
 }
 
-static void ld_flag_byte(TCGv val, unsigned shift)
+static void ld_flag_byte(TCGv_i64 val, unsigned shift)
 {
     tcg_gen_ld8u_i64(val, tcg_env, get_flag_ofs(shift));
 }
 
-static void st_flag_byte(TCGv val, unsigned shift)
+static void st_flag_byte(TCGv_i64 val, unsigned shift)
 {
     tcg_gen_st8_i64(val, tcg_env, get_flag_ofs(shift));
 }
 
-static void gen_pc_disp(DisasContext *ctx, TCGv dest, int32_t disp)
+static void gen_pc_disp(DisasContext *ctx, TCGv_i64 dest, int32_t disp)
 {
     uint64_t addr = ctx->base.pc_next + disp;
     if (ctx->pcrel) {
@@ -284,38 +284,38 @@
     return gen_excp(ctx, EXCP_OPCDEC, 0);
 }
 
-static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
+static void gen_ldf(DisasContext *ctx, TCGv_i64 dest, TCGv_i64 addr)
 {
     TCGv_i32 tmp32 = tcg_temp_new_i32();
     tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
     gen_helper_memory_to_f(dest, tmp32);
 }
 
-static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
+static void gen_ldg(DisasContext *ctx, TCGv_i64 dest, TCGv_i64 addr)
 {
-    TCGv tmp = tcg_temp_new();
+    TCGv_i64 tmp = tcg_temp_new_i64();
     tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
     gen_helper_memory_to_g(dest, tmp);
 }
 
-static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
+static void gen_lds(DisasContext *ctx, TCGv_i64 dest, TCGv_i64 addr)
 {
     TCGv_i32 tmp32 = tcg_temp_new_i32();
     tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
     gen_helper_memory_to_s(dest, tmp32);
 }
 
-static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
+static void gen_ldt(DisasContext *ctx, TCGv_i64 dest, TCGv_i64 addr)
 {
     tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
 }
 
 static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
-                        void (*func)(DisasContext *, TCGv, TCGv))
+                        void (*func)(DisasContext *, TCGv_i64, TCGv_i64))
 {
     /* Loads to $f31 are prefetches, which we can treat as nops. */
     if (likely(ra != 31)) {
-        TCGv addr = tcg_temp_new();
+        TCGv_i64 addr = tcg_temp_new_i64();
         tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
         func(ctx, cpu_fir[ra], addr);
     }
@@ -324,7 +324,7 @@
 static void gen_load_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
                          MemOp op, bool clear, bool locked)
 {
-    TCGv addr, dest;
+    TCGv_i64 addr, dest;
 
     /* LDQ_U with ra $31 is UNOP.  Other various loads are forms of
        prefetches, which we can treat as nops.  No worries about
@@ -333,7 +333,7 @@
         return;
     }
 
-    addr = tcg_temp_new();
+    addr = tcg_temp_new_i64();
     tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
     if (clear) {
         tcg_gen_andi_i64(addr, addr, ~0x7);
@@ -350,36 +350,36 @@
     }
 }
 
-static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr)
+static void gen_stf(DisasContext *ctx, TCGv_i64 src, TCGv_i64 addr)
 {
     TCGv_i32 tmp32 = tcg_temp_new_i32();
     gen_helper_f_to_memory(tmp32, addr);
     tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
 }
 
-static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr)
+static void gen_stg(DisasContext *ctx, TCGv_i64 src, TCGv_i64 addr)
 {
-    TCGv tmp = tcg_temp_new();
+    TCGv_i64 tmp = tcg_temp_new_i64();
     gen_helper_g_to_memory(tmp, src);
     tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
 }
 
-static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr)
+static void gen_sts(DisasContext *ctx, TCGv_i64 src, TCGv_i64 addr)
 {
     TCGv_i32 tmp32 = tcg_temp_new_i32();
     gen_helper_s_to_memory(tmp32, src);
     tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
 }
 
-static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr)
+static void gen_stt(DisasContext *ctx, TCGv_i64 src, TCGv_i64 addr)
 {
     tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
 }
 
 static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
-                         void (*func)(DisasContext *, TCGv, TCGv))
+                         void (*func)(DisasContext *, TCGv_i64, TCGv_i64))
 {
-    TCGv addr = tcg_temp_new();
+    TCGv_i64 addr = tcg_temp_new_i64();
     tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
     func(ctx, load_fpr(ctx, ra), addr);
 }
@@ -387,9 +387,9 @@
 static void gen_store_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
                           MemOp op, bool clear)
 {
-    TCGv addr, src;
+    TCGv_i64 addr, src;
 
-    addr = tcg_temp_new();
+    addr = tcg_temp_new_i64();
     tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
     if (clear) {
         tcg_gen_andi_i64(addr, addr, ~0x7);
@@ -406,7 +406,7 @@
                                            MemOp op)
 {
     TCGLabel *lab_fail, *lab_done;
-    TCGv addr, val;
+    TCGv_i64 addr, val;
 
     addr = tcg_temp_new_i64();
     tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
@@ -469,7 +469,8 @@
 }
 
 static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond,
-                                        TCGv cmp, uint64_t imm, int32_t disp)
+                                        TCGv_i64 cmp,
+                                        uint64_t imm, int32_t disp)
 {
     TCGLabel *lab_true = gen_new_label();
 
@@ -616,9 +617,9 @@
 #endif
 }
 
-static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
+static TCGv_i64 gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
 {
-    TCGv val;
+    TCGv_i64 val;
 
     if (unlikely(reg == 31)) {
         val = load_zero(ctx);
@@ -674,9 +675,9 @@
     }
 }
 
-static void gen_cvtlq(TCGv vc, TCGv vb)
+static void gen_cvtlq(TCGv_i64 vc, TCGv_i64 vb)
 {
-    TCGv tmp = tcg_temp_new();
+    TCGv_i64 tmp = tcg_temp_new_i64();
 
     /* The arithmetic right shift here, plus the sign-extended mask below
        yields a sign-extended result without an explicit ext32s_i64.  */
@@ -686,10 +687,10 @@
 }
 
 static void gen_ieee_arith2(DisasContext *ctx,
-                            void (*helper)(TCGv, TCGv_ptr, TCGv),
+                            void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64),
                             int rb, int rc, int fn11)
 {
-    TCGv vb;
+    TCGv_i64 vb;
 
     gen_qual_roundmode(ctx, fn11);
     gen_qual_flushzero(ctx, fn11);
@@ -713,7 +714,7 @@
 
 static void gen_cvttq(DisasContext *ctx, int rb, int rc, int fn11)
 {
-    TCGv vb, vc;
+    TCGv_i64 vb, vc;
 
     /* No need to set flushzero, since we have an integer output.  */
     vb = gen_ieee_input(ctx, rb, fn11, 0);
@@ -731,10 +732,10 @@
 }
 
 static void gen_ieee_intcvt(DisasContext *ctx,
-                            void (*helper)(TCGv, TCGv_ptr, TCGv),
+                            void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64),
                             int rb, int rc, int fn11)
 {
-    TCGv vb, vc;
+    TCGv_i64 vb, vc;
 
     gen_qual_roundmode(ctx, fn11);
     vb = load_fpr(ctx, rb);
@@ -760,10 +761,11 @@
 IEEE_INTCVT(cvtqs)
 IEEE_INTCVT(cvtqt)
 
-static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
+static void gen_cpy_mask(TCGv_i64 vc, TCGv_i64 va, TCGv_i64 vb,
+                         bool inv_a, uint64_t mask)
 {
-    TCGv vmask = tcg_constant_i64(mask);
-    TCGv tmp = tcg_temp_new_i64();
+    TCGv_i64 vmask = tcg_constant_i64(mask);
+    TCGv_i64 tmp = tcg_temp_new_i64();
 
     if (inv_a) {
         tcg_gen_andc_i64(tmp, vmask, va);
@@ -776,10 +778,11 @@
 }
 
 static void gen_ieee_arith3(DisasContext *ctx,
-                            void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
+                            void (*helper)(TCGv_i64, TCGv_ptr,
+                                           TCGv_i64, TCGv_i64),
                             int ra, int rb, int rc, int fn11)
 {
-    TCGv va, vb, vc;
+    TCGv_i64 va, vb, vc;
 
     gen_qual_roundmode(ctx, fn11);
     gen_qual_flushzero(ctx, fn11);
@@ -808,10 +811,11 @@
 IEEE_ARITH3(divt)
 
 static void gen_ieee_compare(DisasContext *ctx,
-                             void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
+                             void (*helper)(TCGv_i64, TCGv_ptr,
+                                            TCGv_i64, TCGv_i64),
                              int ra, int rb, int rc, int fn11)
 {
-    TCGv va, vb, vc;
+    TCGv_i64 va, vb, vc;
 
     va = gen_ieee_input(ctx, ra, fn11, 1);
     vb = gen_ieee_input(ctx, rb, fn11, 1);
@@ -848,7 +852,7 @@
 /* Implement zapnot with an immediate operand, which expands to some
    form of immediate AND.  This is a basic building block in the
    definition of many of the other byte manipulation instructions.  */
-static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
+static void gen_zapnoti(TCGv_i64 dest, TCGv_i64 src, uint8_t lit)
 {
     switch (lit) {
     case 0x00:
@@ -873,8 +877,8 @@
 }
 
 /* EXTWH, EXTLH, EXTQH */
-static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
-                      uint8_t lit, uint8_t byte_mask)
+static void gen_ext_h(DisasContext *ctx, TCGv_i64 vc, TCGv_i64 va,
+                      int rb, bool islit, uint8_t lit, uint8_t byte_mask)
 {
     if (islit) {
         int pos = (64 - lit * 8) & 0x3f;
@@ -885,7 +889,7 @@
             tcg_gen_movi_i64(vc, 0);
         }
     } else {
-        TCGv tmp = tcg_temp_new();
+        TCGv_i64 tmp = tcg_temp_new_i64();
         tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
         tcg_gen_neg_i64(tmp, tmp);
         tcg_gen_andi_i64(tmp, tmp, 0x3f);
@@ -895,8 +899,8 @@
 }
 
 /* EXTBL, EXTWL, EXTLL, EXTQL */
-static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
-                      uint8_t lit, uint8_t byte_mask)
+static void gen_ext_l(DisasContext *ctx, TCGv_i64 vc, TCGv_i64 va,
+                      int rb, bool islit, uint8_t lit, uint8_t byte_mask)
 {
     if (islit) {
         int pos = (lit & 7) * 8;
@@ -906,7 +910,7 @@
         }
         tcg_gen_extract_i64(vc, va, pos, len);
     } else {
-        TCGv tmp = tcg_temp_new();
+        TCGv_i64 tmp = tcg_temp_new_i64();
         tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
         tcg_gen_shli_i64(tmp, tmp, 3);
         tcg_gen_shr_i64(vc, va, tmp);
@@ -915,8 +919,8 @@
 }
 
 /* INSWH, INSLH, INSQH */
-static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
-                      uint8_t lit, uint8_t byte_mask)
+static void gen_ins_h(DisasContext *ctx, TCGv_i64 vc, TCGv_i64 va,
+                      int rb, bool islit, uint8_t lit, uint8_t byte_mask)
 {
     if (islit) {
         int pos = 64 - (lit & 7) * 8;
@@ -927,8 +931,8 @@
             tcg_gen_movi_i64(vc, 0);
         }
     } else {
-        TCGv tmp = tcg_temp_new();
-        TCGv shift = tcg_temp_new();
+        TCGv_i64 tmp = tcg_temp_new_i64();
+        TCGv_i64 shift = tcg_temp_new_i64();
 
         /* The instruction description has us left-shift the byte mask
            and extract bits <15:8> and apply that zap at the end.  This
@@ -951,8 +955,8 @@
 }
 
 /* INSBL, INSWL, INSLL, INSQL */
-static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
-                      uint8_t lit, uint8_t byte_mask)
+static void gen_ins_l(DisasContext *ctx, TCGv_i64 vc, TCGv_i64 va,
+                      int rb, bool islit, uint8_t lit, uint8_t byte_mask)
 {
     if (islit) {
         int pos = (lit & 7) * 8;
@@ -962,8 +966,8 @@
         }
         tcg_gen_deposit_z_i64(vc, va, pos, len);
     } else {
-        TCGv tmp = tcg_temp_new();
-        TCGv shift = tcg_temp_new();
+        TCGv_i64 tmp = tcg_temp_new_i64();
+        TCGv_i64 shift = tcg_temp_new_i64();
 
         /* The instruction description has us left-shift the byte mask
            and extract bits <15:8> and apply that zap at the end.  This
@@ -978,14 +982,14 @@
 }
 
 /* MSKWH, MSKLH, MSKQH */
-static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
-                      uint8_t lit, uint8_t byte_mask)
+static void gen_msk_h(DisasContext *ctx, TCGv_i64 vc, TCGv_i64 va,
+                      int rb, bool islit, uint8_t lit, uint8_t byte_mask)
 {
     if (islit) {
         gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8));
     } else {
-        TCGv shift = tcg_temp_new();
-        TCGv mask = tcg_temp_new();
+        TCGv_i64 shift = tcg_temp_new_i64();
+        TCGv_i64 mask = tcg_temp_new_i64();
 
         /* The instruction description is as above, where the byte_mask
            is shifted left, and then we extract bits <15:8>.  This can be
@@ -1008,14 +1012,14 @@
 }
 
 /* MSKBL, MSKWL, MSKLL, MSKQL */
-static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
-                      uint8_t lit, uint8_t byte_mask)
+static void gen_msk_l(DisasContext *ctx, TCGv_i64 vc, TCGv_i64 va,
+                      int rb, bool islit, uint8_t lit, uint8_t byte_mask)
 {
     if (islit) {
         gen_zapnoti(vc, va, ~(byte_mask << (lit & 7)));
     } else {
-        TCGv shift = tcg_temp_new();
-        TCGv mask = tcg_temp_new();
+        TCGv_i64 shift = tcg_temp_new_i64();
+        TCGv_i64 mask = tcg_temp_new_i64();
 
         tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
         tcg_gen_shli_i64(shift, shift, 3);
@@ -1100,7 +1104,7 @@
 
             /* But make sure and store only the 3 IPL bits from the user.  */
             {
-                TCGv tmp = tcg_temp_new();
+                TCGv_i64 tmp = tcg_temp_new_i64();
                 tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
                 st_flag_byte(tmp, ENV_FLAG_PS_SHIFT);
             }
@@ -1151,7 +1155,7 @@
     return gen_excp(ctx, EXCP_CALL_PAL, palcode);
 #else
     {
-        TCGv tmp = tcg_temp_new();
+        TCGv_i64 tmp = tcg_temp_new_i64();
 
         gen_pc_disp(ctx, tmp, 0);
         if (ctx->tbflags & ENV_FLAG_PAL_MODE) {
@@ -1199,9 +1203,9 @@
     return 0;
 }
 
-static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv va, int regno)
+static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv_i64 va, int regno)
 {
-    void (*helper)(TCGv);
+    void (*helper)(TCGv_i64);
     int data;
 
     switch (regno) {
@@ -1249,7 +1253,7 @@
     return DISAS_NEXT;
 }
 
-static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
+static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv_i64 vb, int regno)
 {
     int data;
     DisasJumpType ret = DISAS_NEXT;
@@ -1361,7 +1365,7 @@
     uint16_t fn11;
     uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
     bool islit, real_islit;
-    TCGv va, vb, vc, tmp, tmp2;
+    TCGv_i64 va, vb, vc, tmp, tmp2;
     TCGv_i32 t32;
     DisasJumpType ret;
 
@@ -1484,7 +1488,7 @@
             break;
         case 0x02:
             /* S4ADDL */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_shli_i64(tmp, va, 2);
             tcg_gen_add_i64(tmp, tmp, vb);
             tcg_gen_ext32s_i64(vc, tmp);
@@ -1496,7 +1500,7 @@
             break;
         case 0x0B:
             /* S4SUBL */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_shli_i64(tmp, va, 2);
             tcg_gen_sub_i64(tmp, tmp, vb);
             tcg_gen_ext32s_i64(vc, tmp);
@@ -1512,14 +1516,14 @@
             break;
         case 0x12:
             /* S8ADDL */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_shli_i64(tmp, va, 3);
             tcg_gen_add_i64(tmp, tmp, vb);
             tcg_gen_ext32s_i64(vc, tmp);
             break;
         case 0x1B:
             /* S8SUBL */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_shli_i64(tmp, va, 3);
             tcg_gen_sub_i64(tmp, tmp, vb);
             tcg_gen_ext32s_i64(vc, tmp);
@@ -1534,7 +1538,7 @@
             break;
         case 0x22:
             /* S4ADDQ */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_shli_i64(tmp, va, 2);
             tcg_gen_add_i64(vc, tmp, vb);
             break;
@@ -1544,7 +1548,7 @@
             break;
         case 0x2B:
             /* S4SUBQ */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_shli_i64(tmp, va, 2);
             tcg_gen_sub_i64(vc, tmp, vb);
             break;
@@ -1554,13 +1558,13 @@
             break;
         case 0x32:
             /* S8ADDQ */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_shli_i64(tmp, va, 3);
             tcg_gen_add_i64(vc, tmp, vb);
             break;
         case 0x3B:
             /* S8SUBQ */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_shli_i64(tmp, va, 3);
             tcg_gen_sub_i64(vc, tmp, vb);
             break;
@@ -1570,7 +1574,7 @@
             break;
         case 0x40:
             /* ADDL/V */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_ext32s_i64(tmp, va);
             tcg_gen_ext32s_i64(vc, vb);
             tcg_gen_add_i64(tmp, tmp, vc);
@@ -1579,7 +1583,7 @@
             break;
         case 0x49:
             /* SUBL/V */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_ext32s_i64(tmp, va);
             tcg_gen_ext32s_i64(vc, vb);
             tcg_gen_sub_i64(tmp, tmp, vc);
@@ -1592,8 +1596,8 @@
             break;
         case 0x60:
             /* ADDQ/V */
-            tmp = tcg_temp_new();
-            tmp2 = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
+            tmp2 = tcg_temp_new_i64();
             tcg_gen_eqv_i64(tmp, va, vb);
             tcg_gen_mov_i64(tmp2, va);
             tcg_gen_add_i64(vc, va, vb);
@@ -1605,8 +1609,8 @@
             break;
         case 0x69:
             /* SUBQ/V */
-            tmp = tcg_temp_new();
-            tmp2 = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
+            tmp2 = tcg_temp_new_i64();
             tcg_gen_xor_i64(tmp, va, vb);
             tcg_gen_mov_i64(tmp2, va);
             tcg_gen_sub_i64(vc, va, vb);
@@ -1798,7 +1802,7 @@
             if (islit) {
                 tcg_gen_shri_i64(vc, va, lit & 0x3f);
             } else {
-                tmp = tcg_temp_new();
+                tmp = tcg_temp_new_i64();
                 vb = load_gpr(ctx, rb);
                 tcg_gen_andi_i64(tmp, vb, 0x3f);
                 tcg_gen_shr_i64(vc, va, tmp);
@@ -1813,7 +1817,7 @@
             if (islit) {
                 tcg_gen_shli_i64(vc, va, lit & 0x3f);
             } else {
-                tmp = tcg_temp_new();
+                tmp = tcg_temp_new_i64();
                 vb = load_gpr(ctx, rb);
                 tcg_gen_andi_i64(tmp, vb, 0x3f);
                 tcg_gen_shl_i64(vc, va, tmp);
@@ -1828,7 +1832,7 @@
             if (islit) {
                 tcg_gen_sari_i64(vc, va, lit & 0x3f);
             } else {
-                tmp = tcg_temp_new();
+                tmp = tcg_temp_new_i64();
                 vb = load_gpr(ctx, rb);
                 tcg_gen_andi_i64(tmp, vb, 0x3f);
                 tcg_gen_sar_i64(vc, va, tmp);
@@ -1891,12 +1895,12 @@
             break;
         case 0x30:
             /* UMULH */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_mulu2_i64(tmp, vc, va, vb);
             break;
         case 0x40:
             /* MULL/V */
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_ext32s_i64(tmp, va);
             tcg_gen_ext32s_i64(vc, vb);
             tcg_gen_mul_i64(tmp, tmp, vc);
@@ -1905,8 +1909,8 @@
             break;
         case 0x60:
             /* MULQ/V */
-            tmp = tcg_temp_new();
-            tmp2 = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
+            tmp2 = tcg_temp_new_i64();
             tcg_gen_muls2_i64(vc, tmp, va, vb);
             tcg_gen_sari_i64(tmp2, vc, 63);
             gen_helper_check_overflow(tcg_env, tmp, tmp2);
@@ -2351,7 +2355,7 @@
            prediction stack action, which of course we don't implement.  */
         vb = load_gpr(ctx, rb);
         if (ra != 31) {
-            tmp = tcg_temp_new();
+            tmp = tcg_temp_new_i64();
             tcg_gen_andi_i64(tmp, vb, ~3);
             gen_pc_disp(ctx, ctx->ir[ra], 0);
             tcg_gen_mov_i64(cpu_pc, tmp);
@@ -2366,7 +2370,7 @@
 #ifndef CONFIG_USER_ONLY
         REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
         {
-            TCGv addr = tcg_temp_new();
+            TCGv_i64 addr = tcg_temp_new_i64();
             vb = load_gpr(ctx, rb);
             va = dest_gpr(ctx, ra);
 
@@ -2615,7 +2619,7 @@
         }
         tcg_gen_movi_i64(cpu_lock_addr, -1);
         st_flag_byte(load_zero(ctx), ENV_FLAG_RX_SHIFT);
-        tmp = tcg_temp_new();
+        tmp = tcg_temp_new_i64();
         tcg_gen_andi_i64(tmp, vb, 1);
         st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
         tcg_gen_andi_i64(cpu_pc, vb, ~3);
@@ -2636,7 +2640,7 @@
                 /* Longword physical access */
                 va = load_gpr(ctx, ra);
                 vb = load_gpr(ctx, rb);
-                tmp = tcg_temp_new();
+                tmp = tcg_temp_new_i64();
                 tcg_gen_addi_i64(tmp, vb, disp12);
                 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
                 break;
@@ -2644,7 +2648,7 @@
                 /* Quadword physical access */
                 va = load_gpr(ctx, ra);
                 vb = load_gpr(ctx, rb);
-                tmp = tcg_temp_new();
+                tmp = tcg_temp_new_i64();
                 tcg_gen_addi_i64(tmp, vb, disp12);
                 tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
                 break;
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index a7ca410..f7b1437 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -1643,6 +1643,6 @@
  * Forward to the above feature tests given an ARMCPU pointer.
  */
 #define cpu_isar_feature(name, cpu) \
-    ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); })
+    ({ const ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); })
 
 #endif
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 5862020..c535b29 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -789,10 +789,10 @@
 }
 #endif
 
-static void arm_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void arm_disas_set_info(const CPUState *cpu, disassemble_info *info)
 {
-    ARMCPU *ac = ARM_CPU(cpu);
-    CPUARMState *env = &ac->env;
+    const ARMCPU *ac = ARM_CPU(cpu);
+    const CPUARMState *env = &ac->env;
     bool sctlr_b = arm_sctlr_b(env);
 
     if (is_a64(env)) {
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 21fee5e..e146f7e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1345,7 +1345,7 @@
 /* Likewise, but using @sm = PSTATE.SM. */
 uint32_t sve_vqm1_for_el(CPUARMState *env, int el);
 
-static inline bool is_a64(CPUARMState *env)
+static inline bool is_a64(const CPUARMState *env)
 {
     return env->aarch64;
 }
@@ -2140,7 +2140,7 @@
     ARM_FEATURE_BACKCOMPAT_CNTFRQ, /* 62.5MHz timer default */
 };
 
-static inline int arm_feature(CPUARMState *env, int feature)
+static inline int arm_feature(const CPUARMState *env, int feature)
 {
     return (env->features & (1ULL << feature)) != 0;
 }
@@ -2385,7 +2385,7 @@
     return (GET_IDREG(&cpu->isar, CLIDR) & R_V7M_CLIDR_CTYPE_ALL_MASK) != 0;
 }
 
-static inline bool arm_sctlr_b(CPUARMState *env)
+static inline bool arm_sctlr_b(const CPUARMState *env)
 {
     return
         /* We need not implement SCTLR.ITD in user-mode emulation, so
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index 52237da..8579a72 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -116,7 +116,7 @@
     memset(env->r, 0, sizeof(env->r));
 }
 
-static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void avr_cpu_disas_set_info(const CPUState *cpu, disassemble_info *info)
 {
     info->endian = BFD_ENDIAN_LITTLE;
     info->mach = bfd_arch_avr;
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 8ac4f49..58a22ee 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -301,7 +301,8 @@
     set_float_default_nan_pattern(0b11111111, &env->fp_status);
 }
 
-static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
+static void hexagon_cpu_disas_set_info(const CPUState *cs,
+                                       disassemble_info *info)
 {
     info->print_insn = print_insn_hexagon;
     info->endian = BFD_ENDIAN_LITTLE;
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 0ca79ee..714f3bb 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -150,7 +150,7 @@
     return env->psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX;
 }
 
-static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
+static void hppa_cpu_disas_set_info(const CPUState *cs, disassemble_info *info)
 {
     info->mach = bfd_mach_hppa20;
     info->endian = BFD_ENDIAN_BIG;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 45f0b80..0a7b884 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -10359,10 +10359,10 @@
 }
 #endif /* !CONFIG_USER_ONLY */
 
-static void x86_disas_set_info(CPUState *cs, disassemble_info *info)
+static void x86_disas_set_info(const CPUState *cs, disassemble_info *info)
 {
-    X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
+    const X86CPU *cpu = X86_CPU(cs);
+    const CPUX86State *env = &cpu->env;
 
     info->endian = BFD_ENDIAN_LITTLE;
     info->mach = (env->hflags & HF_CS64_MASK ? bfd_mach_x86_64
diff --git a/target/i386/igvm.c b/target/i386/igvm.c
index 457c253..f41b498 100644
--- a/target/i386/igvm.c
+++ b/target/i386/igvm.c
@@ -13,7 +13,9 @@
 
 #include "cpu.h"
 #include "hw/i386/e820_memory_layout.h"
+#include "hw/i386/acpi-build.h"
 #include "system/igvm.h"
+#include "system/igvm-internal.h"
 
 struct IgvmNativeVpContextX64 {
     uint64_t rax;
@@ -178,3 +180,33 @@
 
     qigvm_x86_load_context(bsp_context, env);
 }
+
+/*
+ * Process MADT IGVM parameter
+ */
+int qigvm_directive_madt(QIgvm *ctx, const uint8_t *header_data, Error **errp)
+{
+    const IGVM_VHS_PARAMETER *param = (const IGVM_VHS_PARAMETER *)header_data;
+    QIgvmParameterData *param_entry;
+    int result = 0;
+
+    /* Find the parameter area that should hold the MADT data */
+    param_entry = qigvm_find_param_entry(ctx, param->parameter_area_index);
+    if (param_entry == NULL) {
+        return 0;
+    }
+
+    GArray *madt = acpi_build_madt_standalone(ctx->machine_state);
+
+    if (madt->len <= param_entry->size) {
+        memcpy(param_entry->data, madt->data, madt->len);
+    } else {
+        error_setg(
+            errp,
+            "IGVM: MADT size exceeds parameter area defined in IGVM file");
+        result = -1;
+    }
+
+    g_array_free(madt, true);
+    return result;
+}
diff --git a/target/i386/sev.c b/target/i386/sev.c
index fef9f44..acdcb9c 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -1892,8 +1892,7 @@
          */
         if (x86machine->igvm) {
             if (IGVM_CFG_GET_CLASS(x86machine->igvm)
-                    ->process(x86machine->igvm, machine->cgs, true, errp) ==
-                -1) {
+                    ->process(x86machine->igvm, machine, true, errp) == -1) {
                 return -1;
             }
             /*
diff --git a/target/i386/tcg/decode-new.c.inc b/target/i386/tcg/decode-new.c.inc
index 086a3bc..bc105aa 100644
--- a/target/i386/tcg/decode-new.c.inc
+++ b/target/i386/tcg/decode-new.c.inc
@@ -315,18 +315,18 @@
 
 static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
 {
-    return translator_lduw(env, &s->base, advance_pc(env, s, 2));
+    return translator_lduw_end(env, &s->base, advance_pc(env, s, 2), MO_LE);
 }
 
 static inline uint32_t x86_ldl_code(CPUX86State *env, DisasContext *s)
 {
-    return translator_ldl(env, &s->base, advance_pc(env, s, 4));
+    return translator_ldl_end(env, &s->base, advance_pc(env, s, 4), MO_LE);
 }
 
 #ifdef TARGET_X86_64
 static inline uint64_t x86_ldq_code(CPUX86State *env, DisasContext *s)
 {
-    return translator_ldq(env, &s->base, advance_pc(env, s, 8));
+    return translator_ldq_end(env, &s->base, advance_pc(env, s, 8), MO_LE);
 }
 #endif
 
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index b653948..4fa629c 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -506,7 +506,8 @@
     cs->exception_index = -1;
 }
 
-static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info)
+static void loongarch_cpu_disas_set_info(const CPUState *cs,
+                                         disassemble_info *info)
 {
     info->endian = BFD_ENDIAN_LITTLE;
     info->print_insn = print_insn_loongarch;
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index b55e604..c721a23 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -176,7 +176,7 @@
     env->pc = 0;
 }
 
-static void m68k_cpu_disas_set_info(CPUState *s, disassemble_info *info)
+static void m68k_cpu_disas_set_info(const CPUState *cs, disassemble_info *info)
 {
     info->print_insn = print_insn_m68k;
     info->endian = BFD_ENDIAN_BIG;
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 7216686..a030993 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -347,7 +347,7 @@
 static inline uint16_t read_im16(CPUM68KState *env, DisasContext *s)
 {
     uint16_t im;
-    im = translator_lduw(env, &s->base, s->pc);
+    im = translator_lduw_end(env, &s->base, s->pc, MO_BE);
     s->pc += 2;
     return im;
 }
@@ -1412,12 +1412,12 @@
     if (s->pc % 4 != 0) {
         return false;
     }
-    test = translator_lduw(s->env, &s->base, s->pc - 4);
+    test = translator_lduw_end(s->env, &s->base, s->pc - 4, MO_BE);
     if (test != 0x4e71) {
         return false;
     }
     /* "... and followed by an invalid sentinel instruction movec %sp,0." */
-    test = translator_ldl(s->env, &s->base, s->pc);
+    test = translator_ldl_end(s->env, &s->base, s->pc, MO_BE);
     if (test != 0x4e7bf000) {
         return false;
     }
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index 53649ec..ae41a1a 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -233,7 +233,7 @@
 #endif
 }
 
-static void mb_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void mb_disas_set_info(const CPUState *cpu, disassemble_info *info)
 {
     info->mach = bfd_arch_microblaze;
     info->print_insn = print_insn_microblaze;
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index f74a9d5..e424d11 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -422,9 +422,12 @@
 #endif
 }
 
-static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info)
+static void mips_cpu_disas_set_info(const CPUState *cs, disassemble_info *info)
 {
-    if (!(cpu_env(s)->insn_flags & ISA_NANOMIPS32)) {
+    const MIPSCPU *cpu = MIPS_CPU(cs);
+    const CPUMIPSState *env = &cpu->env;
+
+    if (!(env->insn_flags & ISA_NANOMIPS32)) {
         info->endian = TARGET_BIG_ENDIAN ? BFD_ENDIAN_BIG
                                          : BFD_ENDIAN_LITTLE;
         info->print_insn = TARGET_BIG_ENDIAN ? print_insn_big_mips
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 9bbfe22..c64542a 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -94,7 +94,7 @@
     return MMU_NOMMU_IDX;  /* mmu is disabled */
 }
 
-static void openrisc_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void openrisc_disas_set_info(const CPUState *cpu, disassemble_info *info)
 {
     info->endian = BFD_ENDIAN_BIG;
     info->print_insn = print_insn_or1k;
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 58816c5..c36fd11 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7364,7 +7364,7 @@
 {
     cpu_synchronize_state(cs);
 
-    return !FIELD_EX64(cpu_env(cs)->msr, MSR, LE);
+    return !ppc_env_is_little_endian(cpu_env(cs));
 }
 
 static bool ppc_get_irq_stats(InterruptStatsProvider *obj,
@@ -7452,15 +7452,13 @@
     return pcc->pvr == pvr;
 }
 
-static void ppc_disas_set_info(CPUState *cs, disassemble_info *info)
+static void ppc_disas_set_info(const CPUState *cs, disassemble_info *info)
 {
-    CPUPPCState *env = cpu_env(cs);
+    const PowerPCCPU *cpu = POWERPC_CPU(cs);
+    const CPUPPCState *env = &cpu->env;
 
-    if ((env->hflags >> MSR_LE) & 1) {
-        info->endian = BFD_ENDIAN_LITTLE;
-    } else {
-        info->endian = BFD_ENDIAN_BIG;
-    }
+    info->endian = ppc_env_is_little_endian(env) ? BFD_ENDIAN_LITTLE
+                                                 : BFD_ENDIAN_BIG;
     info->mach = env->bfd_mach;
     if (!env->bfd_mach) {
 #ifdef TARGET_PPC64
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 3b28d4e..b19c0f1 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -84,7 +84,7 @@
 void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
 {
 #ifndef CONFIG_USER_ONLY
-    if (!FIELD_EX64(env->msr, MSR, LE)) {
+    if (!ppc_env_is_little_endian(env)) {
         /* do nothing */
     } else if (len == 4) {
         bswap32s((uint32_t *)mem_buf);
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index 58f315f..dda23b6 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -19,10 +19,27 @@
 #define PPC_INTERNAL_H
 
 #include "exec/breakpoint.h"
+#include "exec/memop.h"
 #include "hw/core/registerfields.h"
 #include "exec/page-protection.h"
 #include "accel/tcg/tb-cpu-state.h"
 
+static inline bool ppc_env_is_little_endian(const CPUPPCState *env)
+{
+    return FIELD_EX64(env->msr, MSR, LE);
+}
+
+/**
+ * ppc_data_endian_env:
+ * @env: the cpu context
+ *
+ * Return the MemOp endianness of the DATA path.
+ */
+static inline MemOp ppc_data_endian_env(const CPUPPCState *env)
+{
+    return ppc_env_is_little_endian(env) ? MO_LE : MO_BE;
+}
+
 /* PM instructions */
 typedef enum {
     PPC_PM_DOZE,
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
index 7318b02..119dc1d 100644
--- a/target/ppc/mem_helper.c
+++ b/target/ppc/mem_helper.c
@@ -88,8 +88,11 @@
         }
     } else {
         /* Slow path -- at least some of the operation requires i/o.  */
+        MemOp op = ppc_data_endian_env(env) | MO_UL | MO_UNALN;
+        MemOpIdx oi = make_memop_idx(op, mmu_idx);
+
         for (; reg < 32; reg++) {
-            env->gpr[reg] = cpu_ldl_mmuidx_ra(env, addr, mmu_idx, raddr);
+            env->gpr[reg] = cpu_ldl_mmu(env, addr, oi, raddr);
             addr = addr_add(env, addr, 4);
         }
     }
@@ -111,7 +114,10 @@
     } else {
         /* Slow path -- at least some of the operation requires i/o.  */
         for (; reg < 32; reg++) {
-            cpu_stl_mmuidx_ra(env, addr, env->gpr[reg], mmu_idx, raddr);
+            MemOp op = ppc_data_endian_env(env) | MO_UL | MO_UNALN;
+            MemOpIdx oi = make_memop_idx(op, mmu_idx);
+
+            cpu_stl_mmu(env, addr, env->gpr[reg], oi, raddr);
             addr = addr_add(env, addr, 4);
         }
     }
@@ -152,9 +158,12 @@
             break;
         }
     } else {
+        MemOp op = ppc_data_endian_env(env) | MO_UL | MO_UNALN;
+        MemOpIdx oi = make_memop_idx(op, mmu_idx);
+
         /* Slow path -- at least some of the operation requires i/o.  */
         for (; nb > 3; nb -= 4) {
-            env->gpr[reg] = cpu_ldl_mmuidx_ra(env, addr, mmu_idx, raddr);
+            env->gpr[reg] = cpu_ldl_mmu(env, addr, oi, raddr);
             reg = (reg + 1) % 32;
             addr = addr_add(env, addr, 4);
         }
@@ -165,10 +174,14 @@
             val = cpu_ldub_mmuidx_ra(env, addr, mmu_idx, raddr) << 24;
             break;
         case 2:
-            val = cpu_lduw_mmuidx_ra(env, addr, mmu_idx, raddr) << 16;
+            op = ppc_data_endian_env(env) | MO_UW | MO_UNALN;
+            oi = make_memop_idx(op, mmu_idx);
+            val = cpu_ldw_mmu(env, addr, oi, raddr) << 16;
             break;
         case 3:
-            val = cpu_lduw_mmuidx_ra(env, addr, mmu_idx, raddr) << 16;
+            op = ppc_data_endian_env(env) | MO_UW | MO_UNALN;
+            oi = make_memop_idx(op, mmu_idx);
+            val = cpu_ldw_mmu(env, addr, oi, raddr) << 16;
             addr = addr_add(env, addr, 2);
             val |= cpu_ldub_mmuidx_ra(env, addr, mmu_idx, raddr) << 8;
             break;
@@ -241,8 +254,11 @@
             break;
         }
     } else {
+        MemOp op = ppc_data_endian_env(env) | MO_UL | MO_UNALN;
+        MemOpIdx oi = make_memop_idx(op, mmu_idx);
+
         for (; nb > 3; nb -= 4) {
-            cpu_stl_mmuidx_ra(env, addr, env->gpr[reg], mmu_idx, raddr);
+            cpu_stl_mmu(env, addr, env->gpr[reg], oi, raddr);
             reg = (reg + 1) % 32;
             addr = addr_add(env, addr, 4);
         }
@@ -252,10 +268,14 @@
             cpu_stb_mmuidx_ra(env, addr, val >> 24, mmu_idx, raddr);
             break;
         case 2:
-            cpu_stw_mmuidx_ra(env, addr, val >> 16, mmu_idx, raddr);
+            op = ppc_data_endian_env(env) | MO_UW | MO_UNALN;
+            oi = make_memop_idx(op, mmu_idx);
+            cpu_stw_mmu(env, addr, val >> 16, oi, raddr);
             break;
         case 3:
-            cpu_stw_mmuidx_ra(env, addr, val >> 16, mmu_idx, raddr);
+            op = ppc_data_endian_env(env) | MO_UW | MO_UNALN;
+            oi = make_memop_idx(op, mmu_idx);
+            cpu_stw_mmu(env, addr, val >> 16, oi, raddr);
             addr = addr_add(env, addr, 2);
             cpu_stb_mmuidx_ra(env, addr, val >> 8, mmu_idx, raddr);
             break;
@@ -284,8 +304,11 @@
     haddr = probe_write(env, addr, dcbz_size, mmu_idx, retaddr);
     if (unlikely(!haddr)) {
         /* Slow path */
+        MemOp op = ppc_data_endian_env(env) | MO_UQ | MO_UNALN;
+        MemOpIdx oi = make_memop_idx(op, mmu_idx);
+
         for (int i = 0; i < dcbz_size; i += 8) {
-            cpu_stq_mmuidx_ra(env, addr + i, 0, mmu_idx, retaddr);
+            cpu_stq_mmu(env, addr + i, 0, oi, retaddr);
         }
         return;
     }
@@ -320,22 +343,27 @@
 
 void helper_icbi(CPUPPCState *env, target_ulong addr)
 {
+    unsigned mmu_idx = cpu_mmu_index(env_cpu(env), false);
+    MemOpIdx oi = make_memop_idx(MO_UL | MO_UNALN, mmu_idx);
+
     addr &= ~(env->dcache_line_size - 1);
     /*
      * Invalidate one cache line :
      * PowerPC specification says this is to be treated like a load
      * (not a fetch) by the MMU. To be sure it will be so,
-     * do the load "by hand".
+     * do the load "by hand". As the returned data is not consumed,
+     * endianness is irrelevant.
      */
-    cpu_ldl_data_ra(env, addr, GETPC());
+    cpu_ldl_mmu(env, addr, oi, GETPC());
 }
 
 void helper_icbiep(CPUPPCState *env, target_ulong addr)
 {
 #if !defined(CONFIG_USER_ONLY)
+    MemOpIdx oi = make_memop_idx(MO_UL | MO_UNALN, PPC_TLB_EPID_LOAD);
     /* See comments above */
     addr &= ~(env->dcache_line_size - 1);
-    cpu_ldl_mmuidx_ra(env, addr, PPC_TLB_EPID_LOAD, GETPC());
+    cpu_ldl_mmu(env, addr, oi, GETPC());
 #endif
 }
 
@@ -392,7 +420,7 @@
         int adjust = HI_IDX * (n_elems - 1);                    \
         int sh = sizeof(r->element[0]) >> 1;                    \
         int index = (addr & 0xf) >> sh;                         \
-        bool byteswap = FIELD_EX64(env->msr, MSR, LE);          \
+        bool byteswap = ppc_env_is_little_endian(env);          \
                                                                 \
         if (byteswap) {                                         \
             index = n_elems - index - 1;                        \
@@ -418,7 +446,7 @@
         int adjust = HI_IDX * (n_elems - 1);                            \
         int sh = sizeof(r->element[0]) >> 1;                            \
         int index = (addr & 0xf) >> sh;                                 \
-        bool byteswap = FIELD_EX64(env->msr, MSR, LE);                  \
+        bool byteswap = ppc_env_is_little_endian(env);                  \
                                                                         \
         if (byteswap) {                                                 \
             index = n_elems - index - 1;                                \
@@ -451,7 +479,7 @@
     t.s128 = int128_zero();                                             \
     if (nb) {                                                           \
         nb = (nb >= 16) ? 16 : nb;                                      \
-        if (FIELD_EX64(env->msr, MSR, LE) && !lj) {                     \
+        if (ppc_env_is_little_endian(env) && !lj) {                     \
             for (i = 16; i > 16 - nb; i--) {                            \
                 t.VsrB(i - 1) = cpu_ldub_data_ra(env, addr, GETPC());   \
                 addr = addr_add(env, addr, 1);                          \
@@ -482,7 +510,7 @@
     }                                                             \
                                                                   \
     nb = (nb >= 16) ? 16 : nb;                                    \
-    if (FIELD_EX64(env->msr, MSR, LE) && !lj) {                   \
+    if (ppc_env_is_little_endian(env) && !lj) {                   \
         for (i = 16; i > 16 - nb; i--) {                          \
             cpu_stb_data_ra(env, addr, xt->VsrB(i - 1), GETPC()); \
             addr = addr_add(env, addr, 1);                        \
diff --git a/target/ppc/tcg-excp_helper.c b/target/ppc/tcg-excp_helper.c
index edecfb8..5e6c1e3 100644
--- a/target/ppc/tcg-excp_helper.c
+++ b/target/ppc/tcg-excp_helper.c
@@ -160,14 +160,18 @@
                     target_ulong rb, uint64_t key, bool store)
 {
     uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash;
+    unsigned mmu_idx = cpu_mmu_index(env_cpu(env), false);
+    MemOp op = ppc_data_endian_env(env) | MO_UQ;
+    MemOpIdx oi = make_memop_idx(op, mmu_idx);
+    uintptr_t retaddr = GETPC();
 
     if (store) {
-        cpu_stq_data_ra(env, ea, calculated_hash, GETPC());
+        cpu_stq_mmu(env, ea, calculated_hash, oi, retaddr);
     } else {
-        loaded_hash = cpu_ldq_data_ra(env, ea, GETPC());
+        loaded_hash = cpu_ldq_mmu(env, ea, oi, retaddr);
         if (loaded_hash != calculated_hash) {
             raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
-                POWERPC_EXCP_TRAP, GETPC());
+                                   POWERPC_EXCP_TRAP, retaddr);
         }
     }
 }
@@ -424,22 +428,13 @@
     cpu_loop_exit_noexc(cs);
 }
 
-/* Return true iff byteswap is needed to load instruction */
-static inline bool insn_need_byteswap(CPUArchState *env)
-{
-    /* SYSTEM builds TARGET_BIG_ENDIAN. Need to swap when MSR[LE] is set */
-    return !!(env->msr & ((target_ulong)1 << MSR_LE));
-}
-
 uint32_t ppc_ldl_code(CPUArchState *env, target_ulong addr)
 {
-    uint32_t insn = cpu_ldl_code(env, addr);
+    CPUState *cs = env_cpu(env);
+    MemOp op_end = ppc_data_endian_env(env);
+    MemOpIdx oi = make_memop_idx(MO_UL | op_end, cpu_mmu_index(cs, true));
 
-    if (insn_need_byteswap(env)) {
-        insn = bswap32(insn);
-    }
-
-    return insn;
+    return cpu_ldl_code_mmu(env, addr, oi, 0);
 }
 
 #if defined(TARGET_PPC64)
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 17e6d07..e9acfa2 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -214,14 +214,15 @@
     return !!(ctx->flags & POWERPC_FLAG_PPE42);
 }
 
-/* Return true iff byteswap is needed in a scalar memop */
-static inline bool need_byteswap(const DisasContext *ctx)
+/**
+ * ppc_code_endian_dc:
+ * @dc: the disassembly context
+ *
+ * Return the MemOp endianness of the CODE path.
+ */
+static inline MemOp ppc_code_endian_dc(const DisasContext *ctx)
 {
-#if TARGET_BIG_ENDIAN
-     return ctx->le_mode;
-#else
-     return !ctx->le_mode;
-#endif
+    return MO_BE ^ (ctx->le_mode * MO_BSWAP);
 }
 
 /* True when active word size < size of target_long.  */
@@ -6588,6 +6589,7 @@
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
     PowerPCCPU *cpu = POWERPC_CPU(cs);
     CPUPPCState *env = cpu_env(cs);
+    MemOp mo_endian = ppc_code_endian_dc(ctx);
     target_ulong pc;
     uint32_t insn;
     bool ok;
@@ -6597,7 +6599,7 @@
               ctx->base.pc_next, ctx->mem_idx, (int)msr_ir);
 
     ctx->cia = pc = ctx->base.pc_next;
-    insn = translator_ldl_swap(env, dcbase, pc, need_byteswap(ctx));
+    insn = translator_ldl_end(env, dcbase, pc, mo_endian);
     ctx->base.pc_next = pc += 4;
 
     if (!is_prefix_insn(ctx, insn)) {
@@ -6613,8 +6615,7 @@
         gen_exception_err(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_INSN);
         ok = true;
     } else {
-        uint32_t insn2 = translator_ldl_swap(env, dcbase, pc,
-                                             need_byteswap(ctx));
+        uint32_t insn2 = translator_ldl_end(env, dcbase, pc, mo_endian);
         ctx->base.pc_next = pc += 4;
         ok = decode_insn64(ctx, deposit64(insn2, 32, 32, insn));
     }
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index e95eea0..e56470a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -795,10 +795,11 @@
 #endif
 }
 
-static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
+static void riscv_cpu_disas_set_info(const CPUState *s, disassemble_info *info)
 {
-    RISCVCPU *cpu = RISCV_CPU(s);
-    CPURISCVState *env = &cpu->env;
+    const RISCVCPU *cpu = RISCV_CPU(s);
+    const CPURISCVState *env = &cpu->env;
+
     info->target_info = &cpu->cfg;
 
     /*
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index f687c75..cb4f443 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1181,8 +1181,9 @@
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
     CPUState *cpu = ctx->cs;
     CPURISCVState *env = cpu_env(cpu);
+    MemOpIdx oi = make_memop_idx(MO_LEUL, cpu_mmu_index(cpu, true));
 
-    return cpu_ldl_code(env, pc);
+    return cpu_ldl_code_mmu(env, pc, oi, 0);
 }
 
 #define SS_MMU_INDEX(ctx) (ctx->mem_idx | MMU_IDX_SS_WRITE)
@@ -1253,13 +1254,16 @@
          * real one is 2 or 4 bytes. Instruction preload wouldn't trigger
          * additional page fault.
          */
-        opcode = translator_ldl(env, &ctx->base, ctx->base.pc_next);
+        opcode = translator_ldl_end(env, &ctx->base, ctx->base.pc_next,
+                                    mo_endian(ctx));
     } else {
         /*
          * For unaligned pc, instruction preload may trigger additional
          * page fault so we only load 2 bytes here.
          */
-        opcode = (uint32_t) translator_lduw(env, &ctx->base, ctx->base.pc_next);
+        opcode = (uint32_t) translator_lduw_end(env, &ctx->base,
+                                                ctx->base.pc_next,
+                                                mo_endian(ctx));
     }
     ctx->ol = ctx->xl;
 
@@ -1279,8 +1283,9 @@
         if (!pc_is_4byte_align) {
             /* Load last 2 bytes of instruction here */
             opcode = deposit32(opcode, 16, 16,
-                               translator_lduw(env, &ctx->base,
-                                               ctx->base.pc_next + 2));
+                               translator_lduw_end(env, &ctx->base,
+                                                   ctx->base.pc_next + 2,
+                                                   mo_endian(ctx)));
         }
         ctx->opcode = opcode;
 
@@ -1395,7 +1400,8 @@
 
             if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
                 uint16_t next_insn =
-                    translator_lduw(env, &ctx->base, ctx->base.pc_next);
+                    translator_lduw_end(env, &ctx->base, ctx->base.pc_next,
+                                        mo_endian(ctx));
                 int len = insn_len(next_insn);
 
                 if (!translator_is_same_page(&ctx->base, ctx->base.pc_next + len - 1)) {
diff --git a/target/riscv/zce_helper.c b/target/riscv/zce_helper.c
index 55221f5..15bf0a9 100644
--- a/target/riscv/zce_helper.c
+++ b/target/riscv/zce_helper.c
@@ -23,6 +23,8 @@
 
 target_ulong HELPER(cm_jalt)(CPURISCVState *env, uint32_t index)
 {
+    unsigned mmu_index = cpu_mmu_index(env_cpu(env), true);
+    MemOpIdx oi;
 
 #if !defined(CONFIG_USER_ONLY)
     RISCVException ret = smstateen_acc_ok(env, 0, SMSTATEEN0_JVT);
@@ -43,11 +45,13 @@
     }
 
     if (xlen == 32) {
+        oi = make_memop_idx(MO_LEUL, mmu_index);
         t0 = base + (index << 2);
-        target = cpu_ldl_code(env, t0);
+        target = cpu_ldl_code_mmu(env, t0, oi, 0);
     } else {
+        oi = make_memop_idx(MO_LEUQ, mmu_index);
         t0 = base + (index << 3);
-        target = cpu_ldq_code(env, t0);
+        target = cpu_ldq_code_mmu(env, t0, oi, 0);
     }
 
     return target & ~0x1;
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
index 0437edc..b528419 100644
--- a/target/rx/cpu.c
+++ b/target/rx/cpu.c
@@ -178,7 +178,7 @@
     }
 }
 
-static void rx_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void rx_cpu_disas_set_info(const CPUState *cpu, disassemble_info *info)
 {
     info->endian = BFD_ENDIAN_LITTLE;
     info->mach = bfd_mach_rx;
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index cd472d3..c074e12 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -222,7 +222,7 @@
     }
 }
 
-static void s390_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void s390_cpu_disas_set_info(const CPUState *cpu, disassemble_info *info)
 {
     info->mach = bfd_mach_s390_64;
     info->cap_arch = CS_ARCH_SYSZ;
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index 1dd21ad..e2bde45 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -164,7 +164,8 @@
     set_float_ftz_detection(float_ftz_before_rounding, &env->fp_status);
 }
 
-static void superh_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void superh_cpu_disas_set_info(const CPUState *cpu,
+                                      disassemble_info *info)
 {
     info->endian = TARGET_BIG_ENDIAN ? BFD_ENDIAN_BIG
                                      : BFD_ENDIAN_LITTLE;
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index bfc6fb9..3991681 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -103,7 +103,8 @@
 }
 #endif /* !CONFIG_USER_ONLY */
 
-static void cpu_sparc_disas_set_info(CPUState *cpu, disassemble_info *info)
+static void cpu_sparc_disas_set_info(const CPUState *cpu,
+                                     disassemble_info *info)
 {
     info->print_insn = print_insn_sparc;
     info->endian = BFD_ENDIAN_BIG;
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index ecc5e09..86ec899 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -226,7 +226,8 @@
     return oc;
 }
 
-static void xtensa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
+static void xtensa_cpu_disas_set_info(const CPUState *cs,
+                                      disassemble_info *info)
 {
     XtensaCPU *cpu = XTENSA_CPU(cs);
 
diff --git a/tests/functional/aarch64/test_aspeed_ast2700.py b/tests/functional/aarch64/test_aspeed_ast2700.py
index 0ced1a2..61373ff 100755
--- a/tests/functional/aarch64/test_aspeed_ast2700.py
+++ b/tests/functional/aarch64/test_aspeed_ast2700.py
@@ -9,60 +9,94 @@
 import os
 
 from qemu_test import QemuSystemTest, Asset
-from qemu_test import wait_for_console_pattern
+from qemu_test import wait_for_console_pattern, exec_command
 from qemu_test import exec_command_and_wait_for_pattern
 
 
 class AST2x00MachineSDK(QemuSystemTest):
 
-    def do_test_aarch64_aspeed_sdk_start(self, image):
+    def do_test_aarch64_aspeed_sdk_start(self, image, bus_id):
+        bus_str = str(bus_id)
         self.require_netdev('user')
         self.vm.set_console()
-        self.vm.add_args('-device',
-                         'tmp105,bus=aspeed.i2c.bus.1,address=0x4d,id=tmp-test')
+        self.vm.add_args(
+            '-device',
+            f'tmp105,'
+            f'bus=aspeed.i2c.bus.{bus_str},'
+            f'address=0x4d,'
+            f'id=tmp-test-{bus_str}'
+        )
         self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw',
                          '-net', 'nic', '-net', 'user', '-snapshot')
 
         self.vm.launch()
 
     def verify_vbootrom_firmware_flow(self):
-        wait_for_console_pattern(self, 'Found valid FIT image')
-        wait_for_console_pattern(self, '[uboot] loading')
-        wait_for_console_pattern(self, 'done')
-        wait_for_console_pattern(self, '[fdt] loading')
-        wait_for_console_pattern(self, 'done')
-        wait_for_console_pattern(self, '[tee] loading')
-        wait_for_console_pattern(self, 'done')
-        wait_for_console_pattern(self, '[atf] loading')
-        wait_for_console_pattern(self, 'done')
+        wait_for_console_pattern(self, 'Found valid caliptra flash image')
+        wait_for_console_pattern(self, 'Check flash image checksum')
+        wait_for_console_pattern(self, 'pass')
+        wait_for_console_pattern(self, 'Read abb header')
+        wait_for_console_pattern(self, 'pass')
+        wait_for_console_pattern(self, 'Read soc manifest')
+        wait_for_console_pattern(self, 'pass')
+        wait_for_console_pattern(self, 'Load atf image')
+        wait_for_console_pattern(self, 'pass')
+        wait_for_console_pattern(self, 'Load optee image')
+        wait_for_console_pattern(self, 'pass')
+        wait_for_console_pattern(self, 'Load uboot image')
+        wait_for_console_pattern(self, 'pass')
+        wait_for_console_pattern(self, 'Load ssp image')
+        wait_for_console_pattern(self, 'pass')
+        wait_for_console_pattern(self, 'Load tsp image')
+        wait_for_console_pattern(self, 'pass')
         wait_for_console_pattern(self, 'Jumping to BL31 (Trusted Firmware-A)')
 
-    def verify_openbmc_boot_start(self):
+    def enable_ast2700_pcie2(self):
+        wait_for_console_pattern(self, 'Hit any key to stop autoboot')
+        exec_command_and_wait_for_pattern(self, '\012', '=>')
+        exec_command_and_wait_for_pattern(self,
+            'cp 100420000 403000000 900000', '=>')
+        exec_command_and_wait_for_pattern(self,
+            'bootm start 403000000', '=>')
+        exec_command_and_wait_for_pattern(self, 'bootm loados', '=>')
+        exec_command_and_wait_for_pattern(self, 'bootm ramdisk', '=>')
+        exec_command_and_wait_for_pattern(self, 'bootm prep', '=>')
+        exec_command_and_wait_for_pattern(self,
+            'fdt set /soc@14000000/pcie@140d0000 status "okay"', '=>')
+        exec_command(self, 'bootm go')
+
+    def verify_openbmc_boot_start(self, enable_pcie=True):
         wait_for_console_pattern(self, 'U-Boot 2023.10')
-        wait_for_console_pattern(self, '## Loading kernel from FIT Image')
+        if enable_pcie:
+            self.enable_ast2700_pcie2()
         wait_for_console_pattern(self, 'Linux version ')
 
-    def verify_openbmc_boot_and_login(self, name):
-        self.verify_openbmc_boot_start()
+    def verify_openbmc_boot_and_login(self, name, enable_pcie=True):
+        self.verify_openbmc_boot_start(enable_pcie)
 
         wait_for_console_pattern(self, f'{name} login:')
         exec_command_and_wait_for_pattern(self, 'root', 'Password:')
         exec_command_and_wait_for_pattern(self, '0penBmc', f'root@{name}:~#')
 
-    ASSET_SDK_V908_AST2700A1 = Asset(
-            'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2700-default-obmc.tar.gz',
-            'eac3dc409b7ea3cd4b03d4792d3cebd469792ad893cb51e1d15f0fc20bd1e2cd')
+    ASSET_SDK_V1100_AST2700A1 = Asset(
+            'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2700-a1-obmc.tar.gz',
+            'd5ceed511cd0dfefbb102fff2d731159e0472948a28066dc0d90bcd54be76525')
 
-    def do_ast2700_i2c_test(self):
+    ASSET_SDK_V1100_AST2700A1_DCSCM = Asset(
+            'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2700-a1-dcscm-obmc.tar.gz',
+            '4f8778be176ece1b57d33c4aee13bb989be114c3e4703150eaeb6f996bd5587f')
+
+    def do_ast2700_i2c_test(self, bus_id):
+        bus_str = str(bus_id)
         exec_command_and_wait_for_pattern(self,
-            'echo lm75 0x4d > /sys/class/i2c-dev/i2c-1/device/new_device ',
-            'i2c i2c-1: new_device: Instantiated device lm75 at 0x4d')
+            f'echo lm75 0x4d > /sys/class/i2c-dev/i2c-{bus_str}/device/new_device ',
+            f'i2c i2c-{bus_str}: new_device: Instantiated device lm75 at 0x4d')
         exec_command_and_wait_for_pattern(self,
-            'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '0')
-        self.vm.cmd('qom-set', path='/machine/peripheral/tmp-test',
+            f'cat /sys/bus/i2c/devices/{bus_str}-004d/hwmon/hwmon*/temp1_input', '0')
+        self.vm.cmd('qom-set', path=f'/machine/peripheral/tmp-test-{bus_str}',
                     property='temperature', value=18000)
         exec_command_and_wait_for_pattern(self,
-            'cat /sys/bus/i2c/devices/1-004d/hwmon/hwmon*/temp1_input', '18000')
+            f'cat /sys/bus/i2c/devices/{bus_str}-004d/hwmon/hwmon*/temp1_input', '18000')
 
     def do_ast2700_pcie_test(self):
         exec_command_and_wait_for_pattern(self,
@@ -77,21 +111,12 @@ def do_ast2700_pcie_test(self):
             'ip addr show dev eth2',
             'inet 10.0.2.15/24')
 
-    def start_ast2700_test(self, name):
+    def start_ast2700_test(self, name, bus_id):
         num_cpu = 4
-        uboot_size = os.path.getsize(self.scratch_file(name,
-                                                       'u-boot-nodtb.bin'))
-        uboot_dtb_load_addr = hex(0x400000000 + uboot_size)
-
         load_images_list = [
             {
                 'addr': '0x400000000',
-                'file': self.scratch_file(name,
-                                          'u-boot-nodtb.bin')
-            },
-            {
-                'addr': str(uboot_dtb_load_addr),
-                'file': self.scratch_file(name, 'u-boot.dtb')
+                'file': self.scratch_file(name, 'u-boot.bin')
             },
             {
                 'addr': '0x430000000',
@@ -99,8 +124,7 @@ def start_ast2700_test(self, name):
             },
             {
                 'addr': '0x430080000',
-                'file': self.scratch_file(name, 'optee',
-                                          'tee-raw.bin')
+                'file': self.scratch_file(name, 'optee', 'tee-raw.bin')
             }
         ]
 
@@ -116,35 +140,48 @@ def start_ast2700_test(self, name):
 
         self.vm.add_args('-smp', str(num_cpu))
         self.do_test_aarch64_aspeed_sdk_start(
-            self.scratch_file(name, 'image-bmc'))
+            self.scratch_file(name, 'image-bmc'), bus_id)
 
-    def start_ast2700_test_vbootrom(self, name):
+    def start_ast2700_test_vbootrom(self, name, bus_id):
         self.vm.add_args('-bios', 'ast27x0_bootrom.bin')
         self.do_test_aarch64_aspeed_sdk_start(
-                self.scratch_file(name, 'image-bmc'))
+                self.scratch_file(name, 'image-bmc'), bus_id)
 
-    def test_aarch64_ast2700a1_evb_sdk_v09_08(self):
+    def test_aarch64_ast2700a1_evb_sdk_v11_00(self):
         self.set_machine('ast2700a1-evb')
         self.require_netdev('user')
 
-        self.archive_extract(self.ASSET_SDK_V908_AST2700A1)
+        self.archive_extract(self.ASSET_SDK_V1100_AST2700A1)
         self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2')
         self.vm.add_args('-netdev', 'user,id=net1')
-        self.start_ast2700_test('ast2700-default')
-        self.verify_openbmc_boot_and_login('ast2700-default')
-        self.do_ast2700_i2c_test()
+        self.start_ast2700_test('ast2700-a1', 1)
+        self.verify_openbmc_boot_and_login('ast2700-a1')
+        self.do_ast2700_i2c_test(1)
         self.do_ast2700_pcie_test()
 
-    def test_aarch64_ast2700a1_evb_sdk_vbootrom_v09_08(self):
+    def test_aarch64_ast2700a1_evb_sdk_vbootrom_v11_00(self):
         self.set_machine('ast2700a1-evb')
         self.require_netdev('user')
 
-        self.archive_extract(self.ASSET_SDK_V908_AST2700A1)
+        self.archive_extract(self.ASSET_SDK_V1100_AST2700A1)
         self.vm.add_args('-device', 'e1000e,netdev=net1,bus=pcie.2')
         self.vm.add_args('-netdev', 'user,id=net1')
-        self.start_ast2700_test_vbootrom('ast2700-default')
+        self.start_ast2700_test_vbootrom('ast2700-a1', 1)
         self.verify_vbootrom_firmware_flow()
         self.verify_openbmc_boot_start()
 
+    def test_aarch64_ast2700a1_evb_ioexp_v11_00(self):
+        self.set_machine('ast2700a1-evb')
+        self.require_netdev('user')
+
+        self.archive_extract(self.ASSET_SDK_V1100_AST2700A1_DCSCM)
+        self.vm.set_machine('ast2700a1-evb,fmc-model=w25q512jv')
+        self.vm.add_args('-device',
+                         'tmp105,bus=ioexp0.0,address=0x4d,id=tmp-test-16')
+        self.start_ast2700_test('ast2700-a1-dcscm', 8)
+        self.verify_openbmc_boot_and_login('ast2700-a1-dcscm', False)
+        self.do_ast2700_i2c_test(8)
+        self.do_ast2700_i2c_test(16)
+
 if __name__ == '__main__':
     QemuSystemTest.main()
diff --git a/tests/functional/aarch64/test_aspeed_ast2700fc.py b/tests/functional/aarch64/test_aspeed_ast2700fc.py
index 8dbc8f2..47e56dc 100755
--- a/tests/functional/aarch64/test_aspeed_ast2700fc.py
+++ b/tests/functional/aarch64/test_aspeed_ast2700fc.py
@@ -9,7 +9,7 @@
 import os
 
 from qemu_test import QemuSystemTest, Asset
-from qemu_test import wait_for_console_pattern
+from qemu_test import wait_for_console_pattern, exec_command
 from qemu_test import exec_command_and_wait_for_pattern
 
 
@@ -27,9 +27,23 @@ def do_test_aarch64_aspeed_sdk_start(self, image):
 
         self.vm.launch()
 
+    def enable_ast2700_pcie2(self):
+        wait_for_console_pattern(self, 'Hit any key to stop autoboot')
+        exec_command_and_wait_for_pattern(self, '\012', '=>')
+        exec_command_and_wait_for_pattern(self,
+            'cp 100420000 403000000 900000', '=>')
+        exec_command_and_wait_for_pattern(self,
+            'bootm start 403000000', '=>')
+        exec_command_and_wait_for_pattern(self, 'bootm loados', '=>')
+        exec_command_and_wait_for_pattern(self, 'bootm ramdisk', '=>')
+        exec_command_and_wait_for_pattern(self, 'bootm prep', '=>')
+        exec_command_and_wait_for_pattern(self,
+            'fdt set /soc@14000000/pcie@140d0000 status "okay"', '=>')
+        exec_command(self, 'bootm go')
+
     def verify_openbmc_boot_and_login(self, name):
         wait_for_console_pattern(self, 'U-Boot 2023.10')
-        wait_for_console_pattern(self, '## Loading kernel from FIT Image')
+        self.enable_ast2700_pcie2()
         wait_for_console_pattern(self, 'Starting kernel ...')
 
         wait_for_console_pattern(self, f'{name} login:')
@@ -47,9 +61,9 @@ def load_ast2700fc_coprocessor(self, name):
             self.vm.add_args('-device',
                              f'loader,file={file},cpu-num={cpu_num}')
 
-    ASSET_SDK_V908_AST2700 = Asset(
-            'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2700-default-obmc.tar.gz',
-            'eac3dc409b7ea3cd4b03d4792d3cebd469792ad893cb51e1d15f0fc20bd1e2cd')
+    ASSET_SDK_V1100_AST2700 = Asset(
+            'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2700-a1-obmc.tar.gz',
+            'd5ceed511cd0dfefbb102fff2d731159e0472948a28066dc0d90bcd54be76525')
 
     def do_ast2700_i2c_test(self):
         exec_command_and_wait_for_pattern(self,
@@ -99,19 +113,10 @@ def do_ast2700fc_tsp_test(self):
 
     def start_ast2700fc_test(self, name):
         ca35_core = 4
-        uboot_size = os.path.getsize(self.scratch_file(name,
-                                                       'u-boot-nodtb.bin'))
-        uboot_dtb_load_addr = hex(0x400000000 + uboot_size)
-
         load_images_list = [
             {
                 'addr': '0x400000000',
-                'file': self.scratch_file(name,
-                                          'u-boot-nodtb.bin')
-            },
-            {
-                'addr': str(uboot_dtb_load_addr),
-                'file': self.scratch_file(name, 'u-boot.dtb')
+                'file': self.scratch_file(name, 'u-boot.bin')
             },
             {
                 'addr': '0x430000000',
@@ -119,8 +124,7 @@ def start_ast2700fc_test(self, name):
             },
             {
                 'addr': '0x430080000',
-                'file': self.scratch_file(name, 'optee',
-                                          'tee-raw.bin')
+                'file': self.scratch_file(name, 'optee', 'tee-raw.bin')
             }
         ]
 
@@ -144,24 +148,24 @@ def start_ast2700fc_test_vbootrom(self, name):
         self.do_test_aarch64_aspeed_sdk_start(
                 self.scratch_file(name, 'image-bmc'))
 
-    def test_aarch64_ast2700fc_sdk_v09_08(self):
+    def test_aarch64_ast2700fc_sdk_v11_00(self):
         self.set_machine('ast2700fc')
         self.require_netdev('user')
 
-        self.archive_extract(self.ASSET_SDK_V908_AST2700)
-        self.start_ast2700fc_test('ast2700-default')
-        self.verify_openbmc_boot_and_login('ast2700-default')
+        self.archive_extract(self.ASSET_SDK_V1100_AST2700)
+        self.start_ast2700fc_test('ast2700-a1')
+        self.verify_openbmc_boot_and_login('ast2700-a1')
         self.do_ast2700_i2c_test()
         self.do_ast2700_pcie_test()
         self.do_ast2700fc_ssp_test()
         self.do_ast2700fc_tsp_test()
 
-    def test_aarch64_ast2700fc_sdk_vbootrom_v09_08(self):
+    def test_aarch64_ast2700fc_sdk_vbootrom_v11_00(self):
         self.set_machine('ast2700fc')
 
-        self.archive_extract(self.ASSET_SDK_V908_AST2700)
-        self.start_ast2700fc_test_vbootrom('ast2700-default')
-        self.verify_openbmc_boot_and_login('ast2700-default')
+        self.archive_extract(self.ASSET_SDK_V1100_AST2700)
+        self.start_ast2700fc_test_vbootrom('ast2700-a1')
+        self.verify_openbmc_boot_and_login('ast2700-a1')
         self.do_ast2700fc_ssp_test()
         self.do_ast2700fc_tsp_test()
 
diff --git a/tests/functional/arm/test_aspeed_ast1030.py b/tests/functional/arm/test_aspeed_ast1030.py
index d1822ed..0defa7c 100755
--- a/tests/functional/arm/test_aspeed_ast1030.py
+++ b/tests/functional/arm/test_aspeed_ast1030.py
@@ -12,17 +12,17 @@
 
 class AST1030Machine(AspeedTest):
 
-    ASSET_ZEPHYR_3_03 = Asset(
+    ASSET_ZEPHYR_3_05 = Asset(
         ('https://github.com/AspeedTech-BMC'
-         '/zephyr/releases/download/v00.03.03/ast1030-evb-demo.zip'),
-         '27cd73cdee6374bceb4ee58b3ace87989fa3f0684f4e612510804b588b24d4e0')
+         '/zephyr/releases/download/v00.03.05/ast1030-evb-demo.zip'),
+         '057528d343490b1fbb5a721e91084b4f04fec60dc114bd65e724554f9c217f4b')
 
-    def test_arm_ast1030_zephyros_3_03(self):
+    def test_arm_ast1030_zephyros_3_05(self):
         self.set_machine('ast1030-evb')
 
         kernel_name = "ast1030-evb-demo/zephyr.elf"
         kernel_file = self.archive_extract(
-            self.ASSET_ZEPHYR_3_03, member=kernel_name)
+            self.ASSET_ZEPHYR_3_05, member=kernel_name)
 
         self.vm.set_console()
         self.vm.add_args('-kernel', kernel_file, '-nographic')
@@ -72,7 +72,7 @@ def test_arm_ast1030_otp_blockdev_device(self):
         self.vm.set_machine("ast1030-evb")
 
         kernel_name = "ast1030-evb-demo/zephyr.elf"
-        kernel_file = self.archive_extract(self.ASSET_ZEPHYR_3_03,
+        kernel_file = self.archive_extract(self.ASSET_ZEPHYR_3_05,
                                            member=kernel_name)
         otp_img = self.generate_otpmem_image()
 
diff --git a/tests/functional/arm/test_aspeed_ast1060.py b/tests/functional/arm/test_aspeed_ast1060.py
index 034efa5..eccb425 100644
--- a/tests/functional/arm/test_aspeed_ast1060.py
+++ b/tests/functional/arm/test_aspeed_ast1060.py
@@ -11,18 +11,18 @@
 
 
 class AST1060Machine(AspeedTest):
-    ASSET_ASPEED_AST1060_PROT_3_02 = Asset(
+    ASSET_ASPEED_AST1060_PROT_3_04 = Asset(
         ('https://github.com/AspeedTech-BMC'
-         '/aspeed-zephyr-project/releases/download/v03.02'
-         '/ast1060_prot_v03.02.tgz'),
-         'dd5f1adc935316ddd1906506a02e15567bd7290657b52320f1a225564cc175bd')
+         '/aspeed-zephyr-project/releases/download/v03.04'
+         '/ast1060_prot_v03.04.tgz'),
+         'c0319df55f5b7a547efefc5a6ba374b881223d5fe1a776bfdd36f97fd1f31d50')
 
-    def test_arm_ast1060_prot_3_02(self):
+    def test_arm_ast1060_prot_3_04(self):
         self.set_machine('ast1060-evb')
 
         kernel_name = "ast1060_prot/zephyr.bin"
         kernel_file = self.archive_extract(
-            self.ASSET_ASPEED_AST1060_PROT_3_02, member=kernel_name)
+            self.ASSET_ASPEED_AST1060_PROT_3_04, member=kernel_name)
 
         self.vm.set_console()
         self.vm.add_args('-kernel', kernel_file, '-nographic')
@@ -35,7 +35,7 @@ def test_arm_ast1060_otp_blockdev_device(self):
         self.vm.set_machine("ast1060-evb")
 
         kernel_name = "ast1060_prot/zephyr.bin"
-        kernel_file = self.archive_extract(self.ASSET_ASPEED_AST1060_PROT_3_02,
+        kernel_file = self.archive_extract(self.ASSET_ASPEED_AST1060_PROT_3_04,
                                            member=kernel_name)
         otp_img = self.generate_otpmem_image()
 
diff --git a/tests/functional/arm/test_aspeed_ast2500.py b/tests/functional/arm/test_aspeed_ast2500.py
index 5efd104..5d75e20 100755
--- a/tests/functional/arm/test_aspeed_ast2500.py
+++ b/tests/functional/arm/test_aspeed_ast2500.py
@@ -10,15 +10,15 @@
 
 class AST2500Machine(AspeedTest):
 
-    ASSET_BR2_202411_AST2500_FLASH = Asset(
+    ASSET_BR2_202511_AST2500_FLASH = Asset(
         ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
-         'images/ast2500-evb/buildroot-2024.11/flash.img'),
-        '641e6906c18c0f19a2aeb48099d66d4771929c361001d554d0d45c667413e13a')
+         'images/ast2500-evb/buildroot-2025.11/flash.img'),
+        '31e5a8e280b982fb0e7c07eb71c94851002f99ac604dfe620e71a5d47cc87e78')
 
     def test_arm_ast2500_evb_buildroot(self):
         self.set_machine('ast2500-evb')
 
-        image_path = self.ASSET_BR2_202411_AST2500_FLASH.fetch()
+        image_path = self.ASSET_BR2_202511_AST2500_FLASH.fetch()
 
         self.vm.add_args('-device',
                          'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test')
@@ -37,14 +37,14 @@ def test_arm_ast2500_evb_buildroot(self):
 
         self.do_test_arm_aspeed_buildroot_poweroff()
 
-    ASSET_SDK_V908_AST2500 = Asset(
-        'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2500-default-obmc.tar.gz',
-        'c0a2ba169efd19be5eb77c50ec2a6afd9d826e196a0be3432f969fc72d4b7c0e')
+    ASSET_SDK_V1000_AST2500 = Asset(
+        'https://github.com/AspeedTech-BMC/openbmc/releases/download/v10.00/ast2500-default-obmc.tar.gz',
+        '7d71a3f71d5f4d9f3451f59a73bf9baf8fd9f6a24107eb504a3216151a8b2b5b')
 
     def test_arm_ast2500_evb_sdk(self):
         self.set_machine('ast2500-evb')
 
-        self.archive_extract(self.ASSET_SDK_V908_AST2500)
+        self.archive_extract(self.ASSET_SDK_V1000_AST2500)
 
         self.do_test_arm_aspeed_sdk_start(
             self.scratch_file("ast2500-default", "image-bmc"))
diff --git a/tests/functional/arm/test_aspeed_ast2600_buildroot.py b/tests/functional/arm/test_aspeed_ast2600_buildroot.py
index 575a5f6..3d130b9 100755
--- a/tests/functional/arm/test_aspeed_ast2600_buildroot.py
+++ b/tests/functional/arm/test_aspeed_ast2600_buildroot.py
@@ -16,15 +16,15 @@
 
 class AST2600Machine(AspeedTest):
 
-    ASSET_BR2_202411_AST2600_FLASH = Asset(
+    ASSET_BR2_202511_AST2600_FLASH = Asset(
         ('https://github.com/legoater/qemu-aspeed-boot/raw/master/'
-         'images/ast2600-evb/buildroot-2024.11/flash.img'),
-        '4bb2f3dfdea31199b51d66b42f686dc5374c144a7346fdc650194a5578b73609')
+         'images/ast2600-evb/buildroot-2025.11/flash.img'),
+        'c64a0755501393d570ca318e326e1e9f8372edc5a6452cdccc3649bc9fd2c138')
 
     def test_arm_ast2600_evb_buildroot(self):
         self.set_machine('ast2600-evb')
 
-        image_path = self.ASSET_BR2_202411_AST2600_FLASH.fetch()
+        image_path = self.ASSET_BR2_202511_AST2600_FLASH.fetch()
 
         self.vm.add_args('-device',
                          'tmp105,bus=aspeed.i2c.bus.3,address=0x4d,id=tmp-test')
diff --git a/tests/functional/arm/test_aspeed_ast2600_sdk.py b/tests/functional/arm/test_aspeed_ast2600_sdk.py
index e3d4ed0..6236aeb 100755
--- a/tests/functional/arm/test_aspeed_ast2600_sdk.py
+++ b/tests/functional/arm/test_aspeed_ast2600_sdk.py
@@ -14,22 +14,18 @@
 
 class AST2600Machine(AspeedTest):
 
-    ASSET_SDK_V908_AST2600 = Asset(
-        'https://github.com/AspeedTech-BMC/openbmc/releases/download/v09.08/ast2600-default-obmc.tar.gz',
-        'a0414f14ad696550efe083c2156dbeda855c08cc9ae7f40fe1b41bf292295f82')
+    ASSET_SDK_V1100_AST2600 = Asset(
+        'https://github.com/AspeedTech-BMC/openbmc/releases/download/v11.00/ast2600-default-obmc.tar.gz',
+        '64d8926a7d01b649168be96c986603b5690f06391286c438a3a772c8c7039e93')
 
     def do_ast2600_pcie_test(self):
         exec_command_and_wait_for_pattern(self,
-            'lspci -s 80:00.0',
-            '80:00.0 Host bridge: '
-            'ASPEED Technology, Inc. Device 2600')
-        exec_command_and_wait_for_pattern(self,
-            'lspci -s 80:08.0',
-            '80:08.0 PCI bridge: '
+            'lspci -s 00:08.0',
+            '00:08.0 PCI bridge: '
             'ASPEED Technology, Inc. AST1150 PCI-to-PCI Bridge')
         exec_command_and_wait_for_pattern(self,
-            'lspci -s 81:00.0',
-            '81:00.0 Ethernet controller: '
+            'lspci -s 01:00.0',
+            '01:00.0 Ethernet controller: '
             'Intel Corporation 82574L Gigabit Network Connection')
         exec_command_and_wait_for_pattern(self,
             'ip addr show dev eth4',
@@ -39,7 +35,7 @@ def test_arm_ast2600_evb_sdk(self):
         self.set_machine('ast2600-evb')
         self.require_netdev('user')
 
-        self.archive_extract(self.ASSET_SDK_V908_AST2600)
+        self.archive_extract(self.ASSET_SDK_V1100_AST2600)
 
         self.vm.add_args('-device',
             'tmp105,bus=aspeed.i2c.bus.5,address=0x4d,id=tmp-test')
@@ -77,7 +73,7 @@ def test_arm_ast2600_evb_sdk(self):
     def test_arm_ast2600_otp_blockdev_device(self):
         self.vm.set_machine("ast2600-evb")
 
-        image_path = self.archive_extract(self.ASSET_SDK_V908_AST2600)
+        image_path = self.archive_extract(self.ASSET_SDK_V1100_AST2600)
         otp_img = self.generate_otpmem_image()
 
         self.vm.set_console()