mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-tcg-20250528' of https://gitlab.com/rth7680/qemu into staging
accel/tcg: Fix atomic_mmu_lookup vs TLB_FORCE_SLOW linux-user: implement pgid field of /proc/self/stat target/sh4: Use MO_ALIGN for system UNALIGN() target/microblaze: Use TARGET_LONG_BITS == 32 for system mode accel/tcg: Add TCGCPUOps.pointer_wrap target/*: Populate TCGCPUOps.pointer_wrap # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmg2xZAdHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/VmAgAu5PHIARUuNqneUPQ # 2JxqpZHGVbaXE0ACi9cslpfThFM/I4OXmK21ZWb1dHB3qasNiKU8cdImXSUVH3dj # DLsr/tliReerZGUoHEtFsYd+VOtqb3wcrvXxnzG/xB761uZjFCnqwy4MrXMfSXVh # 6w+eysWOblYHQb9rAZho4nyw6BgjYAX2vfMFxLJBcDP/fjILFB7xoXHEyqKWMmE1 # 0enA0KUotyLOCRXVEXSsfPDYD8szXfMkII3YcGnscthm5j58oc3skVdKFGVjNkNb # /aFpyvoU7Vp3JpxkYEIWLQrRM75VSb1KzJwMipHgYy3GoV++BrY10T0jyEPrx0iq # RFzK4A== # =XQzq # -----END PGP SIGNATURE----- # gpg: Signature made Wed 28 May 2025 04:13:04 EDT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * tag 'pull-tcg-20250528' of https://gitlab.com/rth7680/qemu: (28 commits) accel/tcg: Assert TCGCPUOps.pointer_wrap is set target/sparc: Fill in TCGCPUOps.pointer_wrap target/s390x: Fill in TCGCPUOps.pointer_wrap target/riscv: Fill in TCGCPUOps.pointer_wrap target/ppc: Fill in TCGCPUOps.pointer_wrap target/mips: Fill in TCGCPUOps.pointer_wrap target/loongarch: Fill in TCGCPUOps.pointer_wrap target/i386: Fill in TCGCPUOps.pointer_wrap target/arm: Fill in TCGCPUOps.pointer_wrap target: Use cpu_pointer_wrap_uint32 for 32-bit targets target: Use cpu_pointer_wrap_notreached for strict align targets accel/tcg: Add TCGCPUOps.pointer_wrap target/sh4: Use MO_ALIGN for system UNALIGN() tcg: Drop TCGContext.page_{mask,bits} tcg: Drop TCGContext.tlb_dyn_max_bits target/microblaze: Simplify compute_ldst_addr_type{a,b} target/microblaze: Drop DisasContext.r0 target/microblaze: Use TARGET_LONG_BITS == 32 for system mode target/microblaze: Fix printf format in mmu_translate target/microblaze: Use TCGv_i64 for compute_ldst_addr_ea ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -1039,6 +1039,7 @@ bool tcg_exec_realizefn(CPUState *cpu, Error **errp)
|
||||
assert(tcg_ops->cpu_exec_halt);
|
||||
assert(tcg_ops->cpu_exec_interrupt);
|
||||
assert(tcg_ops->cpu_exec_reset);
|
||||
assert(tcg_ops->pointer_wrap);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
assert(tcg_ops->translate_code);
|
||||
assert(tcg_ops->get_tb_cpu_state);
|
||||
|
||||
+30
-7
@@ -1773,6 +1773,9 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
l->page[1].size = l->page[0].size - size0;
|
||||
l->page[0].size = size0;
|
||||
|
||||
l->page[1].addr = cpu->cc->tcg_ops->pointer_wrap(cpu, l->mmu_idx,
|
||||
l->page[1].addr, addr);
|
||||
|
||||
/*
|
||||
* Lookup both pages, recognizing exceptions from either. If the
|
||||
* second lookup potentially resized, refresh first CPUTLBEntryFull.
|
||||
@@ -1871,8 +1874,12 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
goto stop_the_world;
|
||||
}
|
||||
|
||||
/* Collect tlb flags for read. */
|
||||
/* Finish collecting tlb flags for both read and write. */
|
||||
full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index];
|
||||
tlb_addr |= tlbe->addr_read;
|
||||
tlb_addr &= TLB_FLAGS_MASK & ~TLB_FORCE_SLOW;
|
||||
tlb_addr |= full->slow_flags[MMU_DATA_STORE];
|
||||
tlb_addr |= full->slow_flags[MMU_DATA_LOAD];
|
||||
|
||||
/* Notice an IO access or a needs-MMU-lookup access */
|
||||
if (unlikely(tlb_addr & (TLB_MMIO | TLB_DISCARD_WRITE))) {
|
||||
@@ -1882,13 +1889,12 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
}
|
||||
|
||||
hostaddr = (void *)((uintptr_t)addr + tlbe->addend);
|
||||
full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index];
|
||||
|
||||
if (unlikely(tlb_addr & TLB_NOTDIRTY)) {
|
||||
notdirty_write(cpu, addr, size, full, retaddr);
|
||||
}
|
||||
|
||||
if (unlikely(tlb_addr & TLB_FORCE_SLOW)) {
|
||||
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
|
||||
int wp_flags = 0;
|
||||
|
||||
if (full->slow_flags[MMU_DATA_STORE] & TLB_WATCHPOINT) {
|
||||
@@ -1897,10 +1903,8 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,
|
||||
if (full->slow_flags[MMU_DATA_LOAD] & TLB_WATCHPOINT) {
|
||||
wp_flags |= BP_MEM_READ;
|
||||
}
|
||||
if (wp_flags) {
|
||||
cpu_check_watchpoint(cpu, addr, size,
|
||||
full->attrs, wp_flags, retaddr);
|
||||
}
|
||||
cpu_check_watchpoint(cpu, addr, size,
|
||||
full->attrs, wp_flags, retaddr);
|
||||
}
|
||||
|
||||
return hostaddr;
|
||||
@@ -2926,3 +2930,22 @@ uint64_t cpu_ldq_code_mmu(CPUArchState *env, vaddr addr,
|
||||
{
|
||||
return do_ld8_mmu(env_cpu(env), addr, oi, retaddr, MMU_INST_FETCH);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common pointer_wrap implementations.
|
||||
*/
|
||||
|
||||
/*
|
||||
* To be used for strict alignment targets.
|
||||
* Because no accesses are unaligned, no accesses wrap either.
|
||||
*/
|
||||
vaddr cpu_pointer_wrap_notreached(CPUState *cs, int idx, vaddr res, vaddr base)
|
||||
{
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
/* To be used for strict 32-bit targets. */
|
||||
vaddr cpu_pointer_wrap_uint32(CPUState *cs, int idx, vaddr res, vaddr base)
|
||||
{
|
||||
return (uint32_t)res;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "tcg/tcg.h"
|
||||
#include "exec/mmap-lock.h"
|
||||
#include "tb-internal.h"
|
||||
#include "tlb-bounds.h"
|
||||
#include "exec/tb-flush.h"
|
||||
#include "qemu/cacheinfo.h"
|
||||
#include "qemu/target-info.h"
|
||||
@@ -313,11 +312,6 @@ TranslationBlock *tb_gen_code(CPUState *cpu, TCGTBCPUState s)
|
||||
|
||||
tcg_ctx->gen_tb = tb;
|
||||
tcg_ctx->addr_type = target_long_bits() == 32 ? TCG_TYPE_I32 : TCG_TYPE_I64;
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
tcg_ctx->page_bits = TARGET_PAGE_BITS;
|
||||
tcg_ctx->page_mask = TARGET_PAGE_MASK;
|
||||
tcg_ctx->tlb_dyn_max_bits = CPU_TLB_DYN_MAX_BITS;
|
||||
#endif
|
||||
tcg_ctx->guest_mo = cpu->cc->tcg_ops->guest_default_memory_order;
|
||||
|
||||
restart_translate:
|
||||
|
||||
@@ -3,6 +3,4 @@ TARGET_BIG_ENDIAN=y
|
||||
# needed by boot.c
|
||||
TARGET_NEED_FDT=y
|
||||
TARGET_XML_FILES=gdb-xml/microblaze-core.xml gdb-xml/microblaze-stack-protect.xml
|
||||
# System mode can address up to 64 bits via lea/sea instructions.
|
||||
# TODO: These bypass the mmu, so we could emulate these differently.
|
||||
TARGET_LONG_BITS=64
|
||||
TARGET_LONG_BITS=32
|
||||
|
||||
@@ -2,6 +2,4 @@ TARGET_ARCH=microblaze
|
||||
# needed by boot.c
|
||||
TARGET_NEED_FDT=y
|
||||
TARGET_XML_FILES=gdb-xml/microblaze-core.xml gdb-xml/microblaze-stack-protect.xml
|
||||
# System mode can address up to 64 bits via lea/sea instructions.
|
||||
# TODO: These bypass the mmu, so we could emulate these differently.
|
||||
TARGET_LONG_BITS=64
|
||||
TARGET_LONG_BITS=32
|
||||
|
||||
@@ -222,6 +222,13 @@ struct TCGCPUOps {
|
||||
bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr);
|
||||
/**
|
||||
* @pointer_wrap:
|
||||
*
|
||||
* We have incremented @base to @result, resulting in a page change.
|
||||
* For the current cpu state, adjust @result for possible overflow.
|
||||
*/
|
||||
vaddr (*pointer_wrap)(CPUState *cpu, int mmu_idx, vaddr result, vaddr base);
|
||||
/**
|
||||
* @do_transaction_failed: Callback for handling failed memory transactions
|
||||
* (ie bus faults or external aborts; not MMU faults)
|
||||
@@ -315,6 +322,12 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
|
||||
*/
|
||||
int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len);
|
||||
|
||||
/*
|
||||
* Common pointer_wrap implementations.
|
||||
*/
|
||||
vaddr cpu_pointer_wrap_notreached(CPUState *, int, vaddr, vaddr);
|
||||
vaddr cpu_pointer_wrap_uint32(CPUState *, int, vaddr, vaddr);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* TCG_CPU_OPS_H */
|
||||
|
||||
@@ -365,10 +365,6 @@ struct TCGContext {
|
||||
int nb_indirects;
|
||||
int nb_ops;
|
||||
TCGType addr_type; /* TCG_TYPE_I32 or TCG_TYPE_I64 */
|
||||
|
||||
int page_mask;
|
||||
uint8_t page_bits;
|
||||
uint8_t tlb_dyn_max_bits;
|
||||
TCGBar guest_mo;
|
||||
|
||||
TCGRegSet reserved_regs;
|
||||
|
||||
@@ -8235,6 +8235,9 @@ static int open_self_stat(CPUArchState *cpu_env, int fd)
|
||||
} else if (i == 3) {
|
||||
/* ppid */
|
||||
g_string_printf(buf, FMT_pid " ", getppid());
|
||||
} else if (i == 4) {
|
||||
/* pgid */
|
||||
g_string_printf(buf, FMT_pid " ", getpgrp());
|
||||
} else if (i == 19) {
|
||||
/* num_threads */
|
||||
int cpus = 0;
|
||||
|
||||
@@ -69,8 +69,21 @@ int (*qemu_main)(void) = os_darwin_cfrunloop_main;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
qemu_init(argc, argv);
|
||||
|
||||
/*
|
||||
* qemu_init acquires the BQL and replay mutex lock. BQL is acquired when
|
||||
* initializing cpus, to block associated threads until initialization is
|
||||
* complete. Replay_mutex lock is acquired on initialization, because it
|
||||
* must be held when configuring icount_mode.
|
||||
*
|
||||
* On MacOS, qemu main event loop runs in a background thread, as main
|
||||
* thread must be reserved for UI. Thus, we need to transfer lock ownership,
|
||||
* and the simplest way to do that is to release them, and reacquire them
|
||||
* from qemu_default_main.
|
||||
*/
|
||||
bql_unlock();
|
||||
replay_mutex_unlock();
|
||||
|
||||
if (qemu_main) {
|
||||
QemuThread main_loop_thread;
|
||||
qemu_thread_create(&main_loop_thread, "qemu_main",
|
||||
|
||||
@@ -261,6 +261,7 @@ static const TCGCPUOps alpha_tcg_ops = {
|
||||
.record_sigbus = alpha_cpu_record_sigbus,
|
||||
#else
|
||||
.tlb_fill = alpha_cpu_tlb_fill,
|
||||
.pointer_wrap = cpu_pointer_wrap_notreached,
|
||||
.cpu_exec_interrupt = alpha_cpu_exec_interrupt,
|
||||
.cpu_exec_halt = alpha_cpu_has_work,
|
||||
.cpu_exec_reset = cpu_reset,
|
||||
|
||||
@@ -2703,6 +2703,29 @@ static const struct SysemuCPUOps arm_sysemu_ops = {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static vaddr aprofile_pointer_wrap(CPUState *cs, int mmu_idx,
|
||||
vaddr result, vaddr base)
|
||||
{
|
||||
/*
|
||||
* The Stage2 and Phys indexes are only used for ptw on arm32,
|
||||
* and all pte's are aligned, so we never produce a wrap for these.
|
||||
* Double check that we're not truncating a 40-bit physical address.
|
||||
*/
|
||||
assert((unsigned)mmu_idx < (ARMMMUIdx_Stage2_S & ARM_MMU_IDX_COREIDX_MASK));
|
||||
|
||||
if (!is_a64(cpu_env(cs))) {
|
||||
return (uint32_t)result;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: For FEAT_CPA2, decide how to we want to resolve
|
||||
* Unpredictable_CPACHECK in AddressIncrement.
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
static const TCGCPUOps arm_tcg_ops = {
|
||||
.mttcg_supported = true,
|
||||
/* ARM processors have a weak memory model */
|
||||
@@ -2722,6 +2745,7 @@ static const TCGCPUOps arm_tcg_ops = {
|
||||
.untagged_addr = aarch64_untagged_addr,
|
||||
#else
|
||||
.tlb_fill_align = arm_cpu_tlb_fill_align,
|
||||
.pointer_wrap = aprofile_pointer_wrap,
|
||||
.cpu_exec_interrupt = arm_cpu_exec_interrupt,
|
||||
.cpu_exec_halt = arm_cpu_exec_halt,
|
||||
.cpu_exec_reset = cpu_reset,
|
||||
|
||||
@@ -249,6 +249,7 @@ static const TCGCPUOps arm_v7m_tcg_ops = {
|
||||
.record_sigbus = arm_cpu_record_sigbus,
|
||||
#else
|
||||
.tlb_fill_align = arm_cpu_tlb_fill_align,
|
||||
.pointer_wrap = cpu_pointer_wrap_uint32,
|
||||
.cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
|
||||
.cpu_exec_halt = arm_cpu_exec_halt,
|
||||
.cpu_exec_reset = cpu_reset,
|
||||
|
||||
@@ -250,6 +250,12 @@ static const TCGCPUOps avr_tcg_ops = {
|
||||
.cpu_exec_reset = cpu_reset,
|
||||
.tlb_fill = avr_cpu_tlb_fill,
|
||||
.do_interrupt = avr_cpu_do_interrupt,
|
||||
/*
|
||||
* TODO: code and data wrapping are different, but for the most part
|
||||
* AVR only references bytes or aligned code fetches. But we use
|
||||
* non-aligned MO_16 accesses for stack push/pop.
|
||||
*/
|
||||
.pointer_wrap = cpu_pointer_wrap_uint32,
|
||||
};
|
||||
|
||||
static void avr_cpu_class_init(ObjectClass *oc, const void *data)
|
||||
|
||||
@@ -269,6 +269,7 @@ static const TCGCPUOps hppa_tcg_ops = {
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.tlb_fill_align = hppa_cpu_tlb_fill_align,
|
||||
.pointer_wrap = cpu_pointer_wrap_notreached,
|
||||
.cpu_exec_interrupt = hppa_cpu_exec_interrupt,
|
||||
.cpu_exec_halt = hppa_cpu_has_work,
|
||||
.cpu_exec_reset = cpu_reset,
|
||||
|
||||
@@ -149,6 +149,12 @@ static void x86_cpu_exec_reset(CPUState *cs)
|
||||
do_cpu_init(env_archcpu(env));
|
||||
cs->exception_index = EXCP_HALTED;
|
||||
}
|
||||
|
||||
static vaddr x86_pointer_wrap(CPUState *cs, int mmu_idx,
|
||||
vaddr result, vaddr base)
|
||||
{
|
||||
return cpu_env(cs)->hflags & HF_CS64_MASK ? result : (uint32_t)result;
|
||||
}
|
||||
#endif
|
||||
|
||||
const TCGCPUOps x86_tcg_ops = {
|
||||
@@ -172,6 +178,7 @@ const TCGCPUOps x86_tcg_ops = {
|
||||
.record_sigbus = x86_cpu_record_sigbus,
|
||||
#else
|
||||
.tlb_fill = x86_cpu_tlb_fill,
|
||||
.pointer_wrap = x86_pointer_wrap,
|
||||
.do_interrupt = x86_cpu_do_interrupt,
|
||||
.cpu_exec_halt = x86_cpu_exec_halt,
|
||||
.cpu_exec_interrupt = x86_cpu_exec_interrupt,
|
||||
|
||||
@@ -334,6 +334,12 @@ static bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static vaddr loongarch_pointer_wrap(CPUState *cs, int mmu_idx,
|
||||
vaddr result, vaddr base)
|
||||
{
|
||||
return is_va32(cpu_env(cs)) ? (uint32_t)result : result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static TCGTBCPUState loongarch_get_tb_cpu_state(CPUState *cs)
|
||||
@@ -889,6 +895,7 @@ static const TCGCPUOps loongarch_tcg_ops = {
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.tlb_fill = loongarch_cpu_tlb_fill,
|
||||
.pointer_wrap = loongarch_pointer_wrap,
|
||||
.cpu_exec_interrupt = loongarch_cpu_exec_interrupt,
|
||||
.cpu_exec_halt = loongarch_cpu_has_work,
|
||||
.cpu_exec_reset = cpu_reset,
|
||||
|
||||
@@ -619,6 +619,7 @@ static const TCGCPUOps m68k_tcg_ops = {
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.tlb_fill = m68k_cpu_tlb_fill,
|
||||
.pointer_wrap = cpu_pointer_wrap_uint32,
|
||||
.cpu_exec_interrupt = m68k_cpu_exec_interrupt,
|
||||
.cpu_exec_halt = m68k_cpu_has_work,
|
||||
.cpu_exec_reset = cpu_reset,
|
||||
|
||||
@@ -447,6 +447,7 @@ static const TCGCPUOps mb_tcg_ops = {
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.tlb_fill = mb_cpu_tlb_fill,
|
||||
.pointer_wrap = cpu_pointer_wrap_uint32,
|
||||
.cpu_exec_interrupt = mb_cpu_exec_interrupt,
|
||||
.cpu_exec_halt = mb_cpu_has_work,
|
||||
.cpu_exec_reset = cpu_reset,
|
||||
|
||||
@@ -248,7 +248,7 @@ struct CPUArchState {
|
||||
uint32_t pc;
|
||||
uint32_t msr; /* All bits of MSR except MSR[C] and MSR[CC] */
|
||||
uint32_t msr_c; /* MSR[C], in low bit; other bits must be 0 */
|
||||
target_ulong ear;
|
||||
uint64_t ear;
|
||||
uint32_t esr;
|
||||
uint32_t fsr;
|
||||
uint32_t btr;
|
||||
|
||||
+43
-28
@@ -26,8 +26,51 @@
|
||||
#include "exec/target_page.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
|
||||
G_NORETURN
|
||||
static void mb_unaligned_access_internal(CPUState *cs, uint64_t addr,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
CPUMBState *env = cpu_env(cs);
|
||||
uint32_t esr, iflags;
|
||||
|
||||
/* Recover the pc and iflags from the corresponding insn_start. */
|
||||
cpu_restore_state(cs, retaddr);
|
||||
iflags = env->iflags;
|
||||
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"Unaligned access addr=0x%" PRIx64 " pc=%x iflags=%x\n",
|
||||
addr, env->pc, iflags);
|
||||
|
||||
esr = ESR_EC_UNALIGNED_DATA;
|
||||
if (likely(iflags & ESR_ESS_FLAG)) {
|
||||
esr |= iflags & ESR_ESS_MASK;
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP, "Unaligned access without ESR_ESS_FLAG\n");
|
||||
}
|
||||
|
||||
env->ear = addr;
|
||||
env->esr = esr;
|
||||
cs->exception_index = EXCP_HW_EXCP;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
void mb_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
|
||||
MMUAccessType access_type,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
mb_unaligned_access_internal(cs, addr, retaddr);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
void HELPER(unaligned_access)(CPUMBState *env, uint64_t addr)
|
||||
{
|
||||
mb_unaligned_access_internal(env_cpu(env), addr, GETPC());
|
||||
}
|
||||
|
||||
static bool mb_cpu_access_is_secure(MicroBlazeCPU *cpu,
|
||||
MMUAccessType access_type)
|
||||
{
|
||||
@@ -269,31 +312,3 @@ bool mb_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
void mb_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
|
||||
MMUAccessType access_type,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
|
||||
uint32_t esr, iflags;
|
||||
|
||||
/* Recover the pc and iflags from the corresponding insn_start. */
|
||||
cpu_restore_state(cs, retaddr);
|
||||
iflags = cpu->env.iflags;
|
||||
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"Unaligned access addr=" TARGET_FMT_lx " pc=%x iflags=%x\n",
|
||||
(target_ulong)addr, cpu->env.pc, iflags);
|
||||
|
||||
esr = ESR_EC_UNALIGNED_DATA;
|
||||
if (likely(iflags & ESR_ESS_FLAG)) {
|
||||
esr |= iflags & ESR_ESS_MASK;
|
||||
} else {
|
||||
qemu_log_mask(LOG_UNIMP, "Unaligned access without ESR_ESS_FLAG\n");
|
||||
}
|
||||
|
||||
cpu->env.ear = addr;
|
||||
cpu->env.esr = esr;
|
||||
cs->exception_index = EXCP_HW_EXCP;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user