Commit b0f9690e authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/vivier/tags/m68k-staging-pull-request' into staging



code cleanup, switch to transaction_failed hook

# gpg: Signature made Thu 16 May 2019 23:33:00 BST
# gpg:                using RSA key F30C38BD3F2FBE3C
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* remotes/vivier/tags/m68k-staging-pull-request:
  target/m68k: Optimize rotate_x() using extract_i32()
  target/m68k: Fix a tcg_temp leak
  target/m68k: Reduce the l1 TCGLabel scope
  target/m68k: Switch to transaction_failed hook
  target/m68k: In get_physical_address() check for memory access failures
  target/m68k: In dump_address_map() check for memory access failures

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>

# Conflicts:
#	target/m68k/cpu.h
parents d8276573 60d3d0cf
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -271,7 +271,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
    cc->gdb_write_register = m68k_cpu_gdb_write_register;
    cc->tlb_fill = m68k_cpu_tlb_fill;
#if defined(CONFIG_SOFTMMU)
    cc->do_unassigned_access = m68k_cpu_unassigned_access;
    cc->do_transaction_failed = m68k_cpu_transaction_failed;
    cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug;
#endif
    cc->disas_set_info = m68k_cpu_disas_set_info;
+4 −3
Original line number Diff line number Diff line
@@ -545,9 +545,10 @@ static inline int cpu_mmu_index (CPUM68KState *env, bool ifetch)
bool m68k_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
                       MMUAccessType access_type, int mmu_idx,
                       bool probe, uintptr_t retaddr);
void m68k_cpu_unassigned_access(CPUState *cs, hwaddr addr,
                                bool is_write, bool is_exec, int is_asi,
                                unsigned size);
void m68k_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
                                 unsigned size, MMUAccessType access_type,
                                 int mmu_idx, MemTxAttrs attrs,
                                 MemTxResult response, uintptr_t retaddr);

#include "exec/cpu-all.h"

+67 −17
Original line number Diff line number Diff line
@@ -390,6 +390,7 @@ static void dump_address_map(CPUM68KState *env, uint32_t root_pointer)
    int last_attr = -1, attr = -1;
    M68kCPU *cpu = m68k_env_get_cpu(env);
    CPUState *cs = CPU(cpu);
    MemTxResult txres;

    if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
        /* 8k page */
@@ -403,22 +404,29 @@ static void dump_address_map(CPUM68KState *env, uint32_t root_pointer)
        tib_mask = M68K_4K_PAGE_MASK;
    }
    for (i = 0; i < M68K_ROOT_POINTER_ENTRIES; i++) {
        tia = ldl_phys(cs->as, M68K_POINTER_BASE(root_pointer) + i * 4);
        if (!M68K_UDT_VALID(tia)) {
        tia = address_space_ldl(cs->as, M68K_POINTER_BASE(root_pointer) + i * 4,
                                MEMTXATTRS_UNSPECIFIED, &txres);
        if (txres != MEMTX_OK || !M68K_UDT_VALID(tia)) {
            continue;
        }
        for (j = 0; j < M68K_ROOT_POINTER_ENTRIES; j++) {
            tib = ldl_phys(cs->as, M68K_POINTER_BASE(tia) + j * 4);
            if (!M68K_UDT_VALID(tib)) {
            tib = address_space_ldl(cs->as, M68K_POINTER_BASE(tia) + j * 4,
                                    MEMTXATTRS_UNSPECIFIED, &txres);
            if (txres != MEMTX_OK || !M68K_UDT_VALID(tib)) {
                continue;
            }
            for (k = 0; k < tic_size; k++) {
                tic = ldl_phys(cs->as, (tib & tib_mask) + k * 4);
                if (!M68K_PDT_VALID(tic)) {
                tic = address_space_ldl(cs->as, (tib & tib_mask) + k * 4,
                                        MEMTXATTRS_UNSPECIFIED, &txres);
                if (txres != MEMTX_OK || !M68K_PDT_VALID(tic)) {
                    continue;
                }
                if (M68K_PDT_INDIRECT(tic)) {
                    tic = ldl_phys(cs->as, M68K_INDIRECT_POINTER(tic));
                    tic = address_space_ldl(cs->as, M68K_INDIRECT_POINTER(tic),
                                            MEMTXATTRS_UNSPECIFIED, &txres);
                    if (txres != MEMTX_OK) {
                        continue;
                    }
                }

                last_logical = logical;
@@ -630,6 +638,7 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
    bool debug = access_type & ACCESS_DEBUG;
    int page_bits;
    int i;
    MemTxResult txres;

    /* Transparent Translation (physical = logical) */
    for (i = 0; i < M68K_MAX_TTR; i++) {
@@ -659,12 +668,19 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
    /* Root Index */
    entry = M68K_POINTER_BASE(next) | M68K_ROOT_INDEX(address);

    next = ldl_phys(cs->as, entry);
    next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres);
    if (txres != MEMTX_OK) {
        goto txfail;
    }
    if (!M68K_UDT_VALID(next)) {
        return -1;
    }
    if (!(next & M68K_DESC_USED) && !debug) {
        stl_phys(cs->as, entry, next | M68K_DESC_USED);
        address_space_stl(cs->as, entry, next | M68K_DESC_USED,
                          MEMTXATTRS_UNSPECIFIED, &txres);
        if (txres != MEMTX_OK) {
            goto txfail;
        }
    }
    if (next & M68K_DESC_WRITEPROT) {
        if (access_type & ACCESS_PTEST) {
@@ -679,12 +695,19 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
    /* Pointer Index */
    entry = M68K_POINTER_BASE(next) | M68K_POINTER_INDEX(address);

    next = ldl_phys(cs->as, entry);
    next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres);
    if (txres != MEMTX_OK) {
        goto txfail;
    }
    if (!M68K_UDT_VALID(next)) {
        return -1;
    }
    if (!(next & M68K_DESC_USED) && !debug) {
        stl_phys(cs->as, entry, next | M68K_DESC_USED);
        address_space_stl(cs->as, entry, next | M68K_DESC_USED,
                          MEMTXATTRS_UNSPECIFIED, &txres);
        if (txres != MEMTX_OK) {
            goto txfail;
        }
    }
    if (next & M68K_DESC_WRITEPROT) {
        if (access_type & ACCESS_PTEST) {
@@ -703,27 +726,46 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
        entry = M68K_4K_PAGE_BASE(next) | M68K_4K_PAGE_INDEX(address);
    }

    next = ldl_phys(cs->as, entry);
    next = address_space_ldl(cs->as, entry, MEMTXATTRS_UNSPECIFIED, &txres);
    if (txres != MEMTX_OK) {
        goto txfail;
    }

    if (!M68K_PDT_VALID(next)) {
        return -1;
    }
    if (M68K_PDT_INDIRECT(next)) {
        next = ldl_phys(cs->as, M68K_INDIRECT_POINTER(next));
        next = address_space_ldl(cs->as, M68K_INDIRECT_POINTER(next),
                                 MEMTXATTRS_UNSPECIFIED, &txres);
        if (txres != MEMTX_OK) {
            goto txfail;
        }
    }
    if (access_type & ACCESS_STORE) {
        if (next & M68K_DESC_WRITEPROT) {
            if (!(next & M68K_DESC_USED) && !debug) {
                stl_phys(cs->as, entry, next | M68K_DESC_USED);
                address_space_stl(cs->as, entry, next | M68K_DESC_USED,
                                  MEMTXATTRS_UNSPECIFIED, &txres);
                if (txres != MEMTX_OK) {
                    goto txfail;
                }
            }
        } else if ((next & (M68K_DESC_MODIFIED | M68K_DESC_USED)) !=
                           (M68K_DESC_MODIFIED | M68K_DESC_USED) && !debug) {
                stl_phys(cs->as, entry,
                         next | (M68K_DESC_MODIFIED | M68K_DESC_USED));
            address_space_stl(cs->as, entry,
                              next | (M68K_DESC_MODIFIED | M68K_DESC_USED),
                              MEMTXATTRS_UNSPECIFIED, &txres);
            if (txres != MEMTX_OK) {
                goto txfail;
            }
        }
    } else {
        if (!(next & M68K_DESC_USED) && !debug) {
            stl_phys(cs->as, entry, next | M68K_DESC_USED);
            address_space_stl(cs->as, entry, next | M68K_DESC_USED,
                              MEMTXATTRS_UNSPECIFIED, &txres);
            if (txres != MEMTX_OK) {
                goto txfail;
            }
        }
    }

@@ -755,6 +797,14 @@ static int get_physical_address(CPUM68KState *env, hwaddr *physical,
    }

    return 0;

txfail:
    /*
     * A page table load/store failed. TODO: we should really raise a
     * suitable guest fault here if this is not a debug access.
     * For now just return that the translation failed.
     */
    return -1;
}

hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+8 −12
Original line number Diff line number Diff line
@@ -439,19 +439,15 @@ static inline void do_interrupt_m68k_hardirq(CPUM68KState *env)
    do_interrupt_all(env, 1);
}

void m68k_cpu_unassigned_access(CPUState *cs, hwaddr addr, bool is_write,
                                bool is_exec, int is_asi, unsigned size)
void m68k_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
                                 unsigned size, MMUAccessType access_type,
                                 int mmu_idx, MemTxAttrs attrs,
                                 MemTxResult response, uintptr_t retaddr)
{
    M68kCPU *cpu = M68K_CPU(cs);
    CPUM68KState *env = &cpu->env;
#ifdef DEBUG_UNASSIGNED
    qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
             addr, is_write, is_exec);
#endif
    if (env == NULL) {
        /* when called from gdb, env is NULL */
        return;
    }

    cpu_restore_state(cs, retaddr, true);

    if (m68k_feature(env, M68K_FEATURE_M68040)) {
        env->mmu.mmusr = 0;
@@ -461,7 +457,7 @@ void m68k_cpu_unassigned_access(CPUState *cs, hwaddr addr, bool is_write,
        if (env->sr & SR_S) { /* SUPERVISOR */
            env->mmu.ssw |= M68K_TM_040_SUPER;
        }
        if (is_exec) { /* instruction or data */
        if (access_type == MMU_INST_FETCH) { /* instruction or data */
            env->mmu.ssw |= M68K_TM_040_CODE;
        } else {
            env->mmu.ssw |= M68K_TM_040_DATA;
@@ -479,7 +475,7 @@ void m68k_cpu_unassigned_access(CPUState *cs, hwaddr addr, bool is_write,
            break;
        }

        if (!is_write) {
        if (access_type != MMU_DATA_STORE) {
            env->mmu.ssw |= M68K_RW_040;
        }

+4 −5
Original line number Diff line number Diff line
@@ -2227,6 +2227,7 @@ static TCGv gen_get_sr(DisasContext *s)
    sr = tcg_temp_new();
    tcg_gen_andi_i32(sr, QREG_SR, 0xffe0);
    tcg_gen_or_i32(sr, sr, ccr);
    tcg_temp_free(ccr);
    return sr;
}

@@ -3020,7 +3021,6 @@ DISAS_INSN(branch)
    int32_t offset;
    uint32_t base;
    int op;
    TCGLabel *l1;

    base = s->pc;
    op = (insn >> 8) & 0xf;
@@ -3036,7 +3036,7 @@ DISAS_INSN(branch)
    }
    if (op > 1) {
        /* Bcc */
        l1 = gen_new_label();
        TCGLabel *l1 = gen_new_label();
        gen_jmpcc(s, ((insn >> 8) & 0xf) ^ 1, l1);
        gen_jmp_tb(s, 1, base + offset);
        gen_set_label(l1);
@@ -3693,6 +3693,7 @@ static TCGv rotate_x(TCGv reg, TCGv shift, int left, int size)
        tcg_gen_sub_i32(shl, shl, shift); /* shl = size + 1 - shift */
        tcg_gen_sub_i32(shx, sz, shift); /* shx = size - shift */
    }
    tcg_temp_free_i32(sz);

    /* reg = (reg << shl) | (reg >> shr) | (x << shx); */

@@ -3708,9 +3709,7 @@ static TCGv rotate_x(TCGv reg, TCGv shift, int left, int size)
    /* X = (reg >> size) & 1 */

    X = tcg_temp_new();
    tcg_gen_shr_i32(X, reg, sz);
    tcg_gen_andi_i32(X, X, 1);
    tcg_temp_free(sz);
    tcg_gen_extract_i32(X, reg, size, 1);

    return X;
}