qemu/accel/tcg/cputlb.c
/* Probe for a read-modify-write atomic operation.  Do not allow unaligned
 * operations, or io operations to proceed.  Return the host address.  */
Probe for a read-modify-write atomic operation.  Do not allow unaligned
operations, or io operations to proceed.  Return the host address.
Probe for a read - modify - write atomic operation . Do not allow unaligned operations or io operations to proceed . Return the host address .
static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
                               TCGMemOpIdx oi, uintptr_t retaddr,
                               NotDirtyInfo *ndi)
{
    size_t mmu_idx = get_mmuidx(oi);
    uintptr_t index = tlb_index(env, mmu_idx, addr);
    CPUTLBEntry *tlbe = tlb_entry(env, mmu_idx, addr);
    target_ulong tlb_addr = tlb_addr_write(tlbe);
    TCGMemOp mop = get_memop(oi);
    int a_bits = get_alignment_bits(mop);
    int s_bits = mop & MO_SIZE;
    void *hostaddr;
    retaddr -= GETPC_ADJ;
    if (unlikely(a_bits > 0 && (addr & ((1 << a_bits) - 1)))) {
        cpu_unaligned_access(ENV_GET_CPU(env), addr, MMU_DATA_STORE,
                             mmu_idx, retaddr);
    }
    if (unlikely(addr & ((1 << s_bits) - 1))) {
        goto stop_the_world;
    }
    if (!tlb_hit(tlb_addr, addr)) {
        if (!VICTIM_TLB_HIT(addr_write, addr)) {
            tlb_fill(ENV_GET_CPU(env), addr, 1 << s_bits, MMU_DATA_STORE,
                     mmu_idx, retaddr);
        }
        tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK;
    }
    if (unlikely(tlb_addr & (TLB_MMIO | TLB_RECHECK))) {
        goto stop_the_world;
    }
    if (unlikely(tlbe->addr_read != (tlb_addr & ~TLB_NOTDIRTY))) {
        tlb_fill(ENV_GET_CPU(env), addr, 1 << s_bits, MMU_DATA_LOAD,
                 mmu_idx, retaddr);
        goto stop_the_world;
    }
    hostaddr = (void *)((uintptr_t)addr + tlbe->addend);
    ndi->active = false;
    if (unlikely(tlb_addr & TLB_NOTDIRTY)) {
        ndi->active = true;
        memory_notdirty_write_prepare(ndi, ENV_GET_CPU(env), addr,
                                      qemu_ram_addr_from_host_nofail(hostaddr),
                                      1 << s_bits);
    }
    return hostaddr;
 stop_the_world:
    cpu_loop_exit_atomic(ENV_GET_CPU(env), retaddr);
}
static void * atomic_mmu_lookup ( CPUArchState * env , target_ulong addr , TCGMemOpIdx oi , uintptr_t retaddr , NotDirtyInfo * ndi ) { size_t mmu_idx = get_mmuidx ( oi ) ; uintptr_t index = tlb_index ( env , mmu_idx , addr ) ; CPUTLBEntry * tlbe = tlb_entry ( env , mmu_idx , addr ) ; target_ulong tlb_addr = tlb_addr_write ( tlbe ) ; TCGMemOp mop = get_memop ( oi ) ; int a_bits = get_alignment_bits ( mop ) ; int s_bits = mop & MO_SIZE ; void * hostaddr ; retaddr -= GETPC_ADJ ; if ( unlikely ( a_bits > 0 && ( addr & ( ( 1 << a_bits ) - 1 ) ) ) ) { cpu_unaligned_access ( ENV_GET_CPU ( env ) , addr , MMU_DATA_STORE , mmu_idx , retaddr ) ; } if ( unlikely ( addr & ( ( 1 << s_bits ) - 1 ) ) ) { goto stop_the_world ; } if ( ! tlb_hit ( tlb_addr , addr ) ) { if ( ! VICTIM_TLB_HIT ( addr_write , addr ) ) { tlb_fill ( ENV_GET_CPU ( env ) , addr , 1 << s_bits , MMU_DATA_STORE , mmu_idx , retaddr ) ; } tlb_addr = tlb_addr_write ( tlbe ) & ~ TLB_INVALID_MASK ; } if ( unlikely ( tlb_addr & ( TLB_MMIO | TLB_RECHECK ) ) ) { goto stop_the_world ; } if ( unlikely ( tlbe -> addr_read != ( tlb_addr & ~ TLB_NOTDIRTY ) ) ) { tlb_fill ( ENV_GET_CPU ( env ) , addr , 1 << s_bits , MMU_DATA_LOAD , mmu_idx , retaddr ) ; goto stop_the_world ; } hostaddr = ( void * ) ( ( uintptr_t ) addr + tlbe -> addend ) ; ndi -> active = false ; if ( unlikely ( tlb_addr & TLB_NOTDIRTY ) ) { ndi -> active = true ; memory_notdirty_write_prepare ( ndi , ENV_GET_CPU ( env ) , addr , qemu_ram_addr_from_host_nofail ( hostaddr ) , 1 << s_bits ) ; } return hostaddr ; stop_the_world : cpu_loop_exit_atomic ( ENV_GET_CPU ( env ) , retaddr ) ; }
Probe for a read-modify-write atomic operation.
Probe for a read - modify - write atomic operation .
/* Adjust the given return address.  */ /* Enforce guest required alignment.  */ /* ??? Maybe indicate atomic op to cpu_unaligned_access */ /* Enforce qemu required alignment.  */ /* We get here if guest alignment was not requested,
           or was not enforced by cpu_unaligned_access above.
           We might widen the access and emulate, but for now
           mark an exception and exit the cpu loop.  */ /* Check TLB entry and enforce page permissions.  */ /* Notice an IO access or a needs-MMU-lookup access */ /* There's really nothing that can be done to
           support this apart from stop-the-world.  */ /* Let the guest notice RMW on a write-only page.  */ /* Since we don't support reads and writes to different addresses,
           and we do have the proper page loaded for write, this shouldn't
           ever return.  But just in case, handle via stop-the-world.  */