accel/tcg: Rename CPUIOTLBEntry to CPUTLBEntryFull
This structure will shortly contain more than just data for accessing MMIO. Rename the 'addr' member to 'xlat_section' to more clearly indicate its purpose. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
8810ee2ac0
commit
25d3ec5831
|
@ -200,13 +200,13 @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(fast->table);
|
g_free(fast->table);
|
||||||
g_free(desc->iotlb);
|
g_free(desc->fulltlb);
|
||||||
|
|
||||||
tlb_window_reset(desc, now, 0);
|
tlb_window_reset(desc, now, 0);
|
||||||
/* desc->n_used_entries is cleared by the caller */
|
/* desc->n_used_entries is cleared by the caller */
|
||||||
fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
|
fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
|
||||||
fast->table = g_try_new(CPUTLBEntry, new_size);
|
fast->table = g_try_new(CPUTLBEntry, new_size);
|
||||||
desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
|
desc->fulltlb = g_try_new(CPUTLBEntryFull, new_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the allocations fail, try smaller sizes. We just freed some
|
* If the allocations fail, try smaller sizes. We just freed some
|
||||||
|
@ -215,7 +215,7 @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
|
||||||
* allocations to fail though, so we progressively reduce the allocation
|
* allocations to fail though, so we progressively reduce the allocation
|
||||||
* size, aborting if we cannot even allocate the smallest TLB we support.
|
* size, aborting if we cannot even allocate the smallest TLB we support.
|
||||||
*/
|
*/
|
||||||
while (fast->table == NULL || desc->iotlb == NULL) {
|
while (fast->table == NULL || desc->fulltlb == NULL) {
|
||||||
if (new_size == (1 << CPU_TLB_DYN_MIN_BITS)) {
|
if (new_size == (1 << CPU_TLB_DYN_MIN_BITS)) {
|
||||||
error_report("%s: %s", __func__, strerror(errno));
|
error_report("%s: %s", __func__, strerror(errno));
|
||||||
abort();
|
abort();
|
||||||
|
@ -224,9 +224,9 @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast,
|
||||||
fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
|
fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS;
|
||||||
|
|
||||||
g_free(fast->table);
|
g_free(fast->table);
|
||||||
g_free(desc->iotlb);
|
g_free(desc->fulltlb);
|
||||||
fast->table = g_try_new(CPUTLBEntry, new_size);
|
fast->table = g_try_new(CPUTLBEntry, new_size);
|
||||||
desc->iotlb = g_try_new(CPUIOTLBEntry, new_size);
|
desc->fulltlb = g_try_new(CPUTLBEntryFull, new_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +258,7 @@ static void tlb_mmu_init(CPUTLBDesc *desc, CPUTLBDescFast *fast, int64_t now)
|
||||||
desc->n_used_entries = 0;
|
desc->n_used_entries = 0;
|
||||||
fast->mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
|
fast->mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS;
|
||||||
fast->table = g_new(CPUTLBEntry, n_entries);
|
fast->table = g_new(CPUTLBEntry, n_entries);
|
||||||
desc->iotlb = g_new(CPUIOTLBEntry, n_entries);
|
desc->fulltlb = g_new(CPUTLBEntryFull, n_entries);
|
||||||
tlb_mmu_flush_locked(desc, fast);
|
tlb_mmu_flush_locked(desc, fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ void tlb_destroy(CPUState *cpu)
|
||||||
CPUTLBDescFast *fast = &env_tlb(env)->f[i];
|
CPUTLBDescFast *fast = &env_tlb(env)->f[i];
|
||||||
|
|
||||||
g_free(fast->table);
|
g_free(fast->table);
|
||||||
g_free(desc->iotlb);
|
g_free(desc->fulltlb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,7 +1219,7 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
|
||||||
|
|
||||||
/* Evict the old entry into the victim tlb. */
|
/* Evict the old entry into the victim tlb. */
|
||||||
copy_tlb_helper_locked(tv, te);
|
copy_tlb_helper_locked(tv, te);
|
||||||
desc->viotlb[vidx] = desc->iotlb[index];
|
desc->vfulltlb[vidx] = desc->fulltlb[index];
|
||||||
tlb_n_used_entries_dec(env, mmu_idx);
|
tlb_n_used_entries_dec(env, mmu_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1236,8 +1236,8 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
|
||||||
* subtract here is that of the page base, and not the same as the
|
* subtract here is that of the page base, and not the same as the
|
||||||
* vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
|
* vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
|
||||||
*/
|
*/
|
||||||
desc->iotlb[index].addr = iotlb - vaddr_page;
|
desc->fulltlb[index].xlat_section = iotlb - vaddr_page;
|
||||||
desc->iotlb[index].attrs = attrs;
|
desc->fulltlb[index].attrs = attrs;
|
||||||
|
|
||||||
/* Now calculate the new entry */
|
/* Now calculate the new entry */
|
||||||
tn.addend = addend - vaddr_page;
|
tn.addend = addend - vaddr_page;
|
||||||
|
@ -1327,7 +1327,7 @@ static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
static uint64_t io_readx(CPUArchState *env, CPUTLBEntryFull *full,
|
||||||
int mmu_idx, target_ulong addr, uintptr_t retaddr,
|
int mmu_idx, target_ulong addr, uintptr_t retaddr,
|
||||||
MMUAccessType access_type, MemOp op)
|
MMUAccessType access_type, MemOp op)
|
||||||
{
|
{
|
||||||
|
@ -1339,9 +1339,9 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
||||||
bool locked = false;
|
bool locked = false;
|
||||||
MemTxResult r;
|
MemTxResult r;
|
||||||
|
|
||||||
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
|
section = iotlb_to_section(cpu, full->xlat_section, full->attrs);
|
||||||
mr = section->mr;
|
mr = section->mr;
|
||||||
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
|
mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
|
||||||
cpu->mem_io_pc = retaddr;
|
cpu->mem_io_pc = retaddr;
|
||||||
if (!cpu->can_do_io) {
|
if (!cpu->can_do_io) {
|
||||||
cpu_io_recompile(cpu, retaddr);
|
cpu_io_recompile(cpu, retaddr);
|
||||||
|
@ -1351,14 +1351,14 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
locked = true;
|
locked = true;
|
||||||
}
|
}
|
||||||
r = memory_region_dispatch_read(mr, mr_offset, &val, op, iotlbentry->attrs);
|
r = memory_region_dispatch_read(mr, mr_offset, &val, op, full->attrs);
|
||||||
if (r != MEMTX_OK) {
|
if (r != MEMTX_OK) {
|
||||||
hwaddr physaddr = mr_offset +
|
hwaddr physaddr = mr_offset +
|
||||||
section->offset_within_address_space -
|
section->offset_within_address_space -
|
||||||
section->offset_within_region;
|
section->offset_within_region;
|
||||||
|
|
||||||
cpu_transaction_failed(cpu, physaddr, addr, memop_size(op), access_type,
|
cpu_transaction_failed(cpu, physaddr, addr, memop_size(op), access_type,
|
||||||
mmu_idx, iotlbentry->attrs, r, retaddr);
|
mmu_idx, full->attrs, r, retaddr);
|
||||||
}
|
}
|
||||||
if (locked) {
|
if (locked) {
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
|
@ -1368,8 +1368,8 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save a potentially trashed IOTLB entry for later lookup by plugin.
|
* Save a potentially trashed CPUTLBEntryFull for later lookup by plugin.
|
||||||
* This is read by tlb_plugin_lookup if the iotlb entry doesn't match
|
* This is read by tlb_plugin_lookup if the fulltlb entry doesn't match
|
||||||
* because of the side effect of io_writex changing memory layout.
|
* because of the side effect of io_writex changing memory layout.
|
||||||
*/
|
*/
|
||||||
static void save_iotlb_data(CPUState *cs, hwaddr addr,
|
static void save_iotlb_data(CPUState *cs, hwaddr addr,
|
||||||
|
@ -1383,7 +1383,7 @@ static void save_iotlb_data(CPUState *cs, hwaddr addr,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
static void io_writex(CPUArchState *env, CPUTLBEntryFull *full,
|
||||||
int mmu_idx, uint64_t val, target_ulong addr,
|
int mmu_idx, uint64_t val, target_ulong addr,
|
||||||
uintptr_t retaddr, MemOp op)
|
uintptr_t retaddr, MemOp op)
|
||||||
{
|
{
|
||||||
|
@ -1394,9 +1394,9 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
||||||
bool locked = false;
|
bool locked = false;
|
||||||
MemTxResult r;
|
MemTxResult r;
|
||||||
|
|
||||||
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
|
section = iotlb_to_section(cpu, full->xlat_section, full->attrs);
|
||||||
mr = section->mr;
|
mr = section->mr;
|
||||||
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
|
mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
|
||||||
if (!cpu->can_do_io) {
|
if (!cpu->can_do_io) {
|
||||||
cpu_io_recompile(cpu, retaddr);
|
cpu_io_recompile(cpu, retaddr);
|
||||||
}
|
}
|
||||||
|
@ -1406,20 +1406,20 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
||||||
* The memory_region_dispatch may trigger a flush/resize
|
* The memory_region_dispatch may trigger a flush/resize
|
||||||
* so for plugins we save the iotlb_data just in case.
|
* so for plugins we save the iotlb_data just in case.
|
||||||
*/
|
*/
|
||||||
save_iotlb_data(cpu, iotlbentry->addr, section, mr_offset);
|
save_iotlb_data(cpu, full->xlat_section, section, mr_offset);
|
||||||
|
|
||||||
if (!qemu_mutex_iothread_locked()) {
|
if (!qemu_mutex_iothread_locked()) {
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
locked = true;
|
locked = true;
|
||||||
}
|
}
|
||||||
r = memory_region_dispatch_write(mr, mr_offset, val, op, iotlbentry->attrs);
|
r = memory_region_dispatch_write(mr, mr_offset, val, op, full->attrs);
|
||||||
if (r != MEMTX_OK) {
|
if (r != MEMTX_OK) {
|
||||||
hwaddr physaddr = mr_offset +
|
hwaddr physaddr = mr_offset +
|
||||||
section->offset_within_address_space -
|
section->offset_within_address_space -
|
||||||
section->offset_within_region;
|
section->offset_within_region;
|
||||||
|
|
||||||
cpu_transaction_failed(cpu, physaddr, addr, memop_size(op),
|
cpu_transaction_failed(cpu, physaddr, addr, memop_size(op),
|
||||||
MMU_DATA_STORE, mmu_idx, iotlbentry->attrs, r,
|
MMU_DATA_STORE, mmu_idx, full->attrs, r,
|
||||||
retaddr);
|
retaddr);
|
||||||
}
|
}
|
||||||
if (locked) {
|
if (locked) {
|
||||||
|
@ -1466,9 +1466,10 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
|
||||||
copy_tlb_helper_locked(vtlb, &tmptlb);
|
copy_tlb_helper_locked(vtlb, &tmptlb);
|
||||||
qemu_spin_unlock(&env_tlb(env)->c.lock);
|
qemu_spin_unlock(&env_tlb(env)->c.lock);
|
||||||
|
|
||||||
CPUIOTLBEntry tmpio, *io = &env_tlb(env)->d[mmu_idx].iotlb[index];
|
CPUTLBEntryFull *f1 = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
||||||
CPUIOTLBEntry *vio = &env_tlb(env)->d[mmu_idx].viotlb[vidx];
|
CPUTLBEntryFull *f2 = &env_tlb(env)->d[mmu_idx].vfulltlb[vidx];
|
||||||
tmpio = *io; *io = *vio; *vio = tmpio;
|
CPUTLBEntryFull tmpf;
|
||||||
|
tmpf = *f1; *f1 = *f2; *f2 = tmpf;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1481,9 +1482,9 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
|
||||||
(ADDR) & TARGET_PAGE_MASK)
|
(ADDR) & TARGET_PAGE_MASK)
|
||||||
|
|
||||||
static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
|
static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
|
||||||
CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
|
CPUTLBEntryFull *full, uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
ram_addr_t ram_addr = mem_vaddr + iotlbentry->addr;
|
ram_addr_t ram_addr = mem_vaddr + full->xlat_section;
|
||||||
|
|
||||||
trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
|
trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size);
|
||||||
|
|
||||||
|
@ -1575,9 +1576,9 @@ int probe_access_flags(CPUArchState *env, target_ulong addr,
|
||||||
/* Handle clean RAM pages. */
|
/* Handle clean RAM pages. */
|
||||||
if (unlikely(flags & TLB_NOTDIRTY)) {
|
if (unlikely(flags & TLB_NOTDIRTY)) {
|
||||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
||||||
CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
|
CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
||||||
|
|
||||||
notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr);
|
notdirty_write(env_cpu(env), addr, 1, full, retaddr);
|
||||||
flags &= ~TLB_NOTDIRTY;
|
flags &= ~TLB_NOTDIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1602,19 +1603,19 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
||||||
|
|
||||||
if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) {
|
if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) {
|
||||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
||||||
CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
|
CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
||||||
|
|
||||||
/* Handle watchpoints. */
|
/* Handle watchpoints. */
|
||||||
if (flags & TLB_WATCHPOINT) {
|
if (flags & TLB_WATCHPOINT) {
|
||||||
int wp_access = (access_type == MMU_DATA_STORE
|
int wp_access = (access_type == MMU_DATA_STORE
|
||||||
? BP_MEM_WRITE : BP_MEM_READ);
|
? BP_MEM_WRITE : BP_MEM_READ);
|
||||||
cpu_check_watchpoint(env_cpu(env), addr, size,
|
cpu_check_watchpoint(env_cpu(env), addr, size,
|
||||||
iotlbentry->attrs, wp_access, retaddr);
|
full->attrs, wp_access, retaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle clean RAM pages. */
|
/* Handle clean RAM pages. */
|
||||||
if (flags & TLB_NOTDIRTY) {
|
if (flags & TLB_NOTDIRTY) {
|
||||||
notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr);
|
notdirty_write(env_cpu(env), addr, 1, full, retaddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1671,7 +1672,7 @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
|
||||||
* should have just filled the TLB. The one corner case is io_writex
|
* should have just filled the TLB. The one corner case is io_writex
|
||||||
* which can cause TLB flushes and potential resizing of the TLBs
|
* which can cause TLB flushes and potential resizing of the TLBs
|
||||||
* losing the information we need. In those cases we need to recover
|
* losing the information we need. In those cases we need to recover
|
||||||
* data from a copy of the iotlbentry. As long as this always occurs
|
* data from a copy of the CPUTLBEntryFull. As long as this always occurs
|
||||||
* from the same thread (which a mem callback will be) this is safe.
|
* from the same thread (which a mem callback will be) this is safe.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1686,11 +1687,12 @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx,
|
||||||
if (likely(tlb_hit(tlb_addr, addr))) {
|
if (likely(tlb_hit(tlb_addr, addr))) {
|
||||||
/* We must have an iotlb entry for MMIO */
|
/* We must have an iotlb entry for MMIO */
|
||||||
if (tlb_addr & TLB_MMIO) {
|
if (tlb_addr & TLB_MMIO) {
|
||||||
CPUIOTLBEntry *iotlbentry;
|
CPUTLBEntryFull *full;
|
||||||
iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
|
full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
||||||
data->is_io = true;
|
data->is_io = true;
|
||||||
data->v.io.section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
|
data->v.io.section =
|
||||||
data->v.io.offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
|
iotlb_to_section(cpu, full->xlat_section, full->attrs);
|
||||||
|
data->v.io.offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
|
||||||
} else {
|
} else {
|
||||||
data->is_io = false;
|
data->is_io = false;
|
||||||
data->v.ram.hostaddr = (void *)((uintptr_t)addr + tlbe->addend);
|
data->v.ram.hostaddr = (void *)((uintptr_t)addr + tlbe->addend);
|
||||||
|
@ -1798,7 +1800,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||||
|
|
||||||
if (unlikely(tlb_addr & TLB_NOTDIRTY)) {
|
if (unlikely(tlb_addr & TLB_NOTDIRTY)) {
|
||||||
notdirty_write(env_cpu(env), addr, size,
|
notdirty_write(env_cpu(env), addr, size,
|
||||||
&env_tlb(env)->d[mmu_idx].iotlb[index], retaddr);
|
&env_tlb(env)->d[mmu_idx].fulltlb[index], retaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hostaddr;
|
return hostaddr;
|
||||||
|
@ -1906,7 +1908,7 @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
|
||||||
|
|
||||||
/* Handle anything that isn't just a straight memory access. */
|
/* Handle anything that isn't just a straight memory access. */
|
||||||
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
||||||
CPUIOTLBEntry *iotlbentry;
|
CPUTLBEntryFull *full;
|
||||||
bool need_swap;
|
bool need_swap;
|
||||||
|
|
||||||
/* For anything that is unaligned, recurse through full_load. */
|
/* For anything that is unaligned, recurse through full_load. */
|
||||||
|
@ -1914,20 +1916,20 @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi,
|
||||||
goto do_unaligned_access;
|
goto do_unaligned_access;
|
||||||
}
|
}
|
||||||
|
|
||||||
iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
|
full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
||||||
|
|
||||||
/* Handle watchpoints. */
|
/* Handle watchpoints. */
|
||||||
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
|
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
|
||||||
/* On watchpoint hit, this will longjmp out. */
|
/* On watchpoint hit, this will longjmp out. */
|
||||||
cpu_check_watchpoint(env_cpu(env), addr, size,
|
cpu_check_watchpoint(env_cpu(env), addr, size,
|
||||||
iotlbentry->attrs, BP_MEM_READ, retaddr);
|
full->attrs, BP_MEM_READ, retaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
|
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
|
||||||
|
|
||||||
/* Handle I/O access. */
|
/* Handle I/O access. */
|
||||||
if (likely(tlb_addr & TLB_MMIO)) {
|
if (likely(tlb_addr & TLB_MMIO)) {
|
||||||
return io_readx(env, iotlbentry, mmu_idx, addr, retaddr,
|
return io_readx(env, full, mmu_idx, addr, retaddr,
|
||||||
access_type, op ^ (need_swap * MO_BSWAP));
|
access_type, op ^ (need_swap * MO_BSWAP));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2242,12 +2244,12 @@ store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||||
*/
|
*/
|
||||||
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
|
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
|
||||||
cpu_check_watchpoint(env_cpu(env), addr, size - size2,
|
cpu_check_watchpoint(env_cpu(env), addr, size - size2,
|
||||||
env_tlb(env)->d[mmu_idx].iotlb[index].attrs,
|
env_tlb(env)->d[mmu_idx].fulltlb[index].attrs,
|
||||||
BP_MEM_WRITE, retaddr);
|
BP_MEM_WRITE, retaddr);
|
||||||
}
|
}
|
||||||
if (unlikely(tlb_addr2 & TLB_WATCHPOINT)) {
|
if (unlikely(tlb_addr2 & TLB_WATCHPOINT)) {
|
||||||
cpu_check_watchpoint(env_cpu(env), page2, size2,
|
cpu_check_watchpoint(env_cpu(env), page2, size2,
|
||||||
env_tlb(env)->d[mmu_idx].iotlb[index2].attrs,
|
env_tlb(env)->d[mmu_idx].fulltlb[index2].attrs,
|
||||||
BP_MEM_WRITE, retaddr);
|
BP_MEM_WRITE, retaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2311,7 +2313,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||||
|
|
||||||
/* Handle anything that isn't just a straight memory access. */
|
/* Handle anything that isn't just a straight memory access. */
|
||||||
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
|
||||||
CPUIOTLBEntry *iotlbentry;
|
CPUTLBEntryFull *full;
|
||||||
bool need_swap;
|
bool need_swap;
|
||||||
|
|
||||||
/* For anything that is unaligned, recurse through byte stores. */
|
/* For anything that is unaligned, recurse through byte stores. */
|
||||||
|
@ -2319,20 +2321,20 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||||
goto do_unaligned_access;
|
goto do_unaligned_access;
|
||||||
}
|
}
|
||||||
|
|
||||||
iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
|
full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
||||||
|
|
||||||
/* Handle watchpoints. */
|
/* Handle watchpoints. */
|
||||||
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
|
if (unlikely(tlb_addr & TLB_WATCHPOINT)) {
|
||||||
/* On watchpoint hit, this will longjmp out. */
|
/* On watchpoint hit, this will longjmp out. */
|
||||||
cpu_check_watchpoint(env_cpu(env), addr, size,
|
cpu_check_watchpoint(env_cpu(env), addr, size,
|
||||||
iotlbentry->attrs, BP_MEM_WRITE, retaddr);
|
full->attrs, BP_MEM_WRITE, retaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
|
need_swap = size > 1 && (tlb_addr & TLB_BSWAP);
|
||||||
|
|
||||||
/* Handle I/O access. */
|
/* Handle I/O access. */
|
||||||
if (tlb_addr & TLB_MMIO) {
|
if (tlb_addr & TLB_MMIO) {
|
||||||
io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr,
|
io_writex(env, full, mmu_idx, val, addr, retaddr,
|
||||||
op ^ (need_swap * MO_BSWAP));
|
op ^ (need_swap * MO_BSWAP));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2344,7 +2346,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
|
||||||
|
|
||||||
/* Handle clean RAM pages. */
|
/* Handle clean RAM pages. */
|
||||||
if (tlb_addr & TLB_NOTDIRTY) {
|
if (tlb_addr & TLB_NOTDIRTY) {
|
||||||
notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr);
|
notdirty_write(env_cpu(env), addr, size, full, retaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
haddr = (void *)((uintptr_t)addr + entry->addend);
|
haddr = (void *)((uintptr_t)addr + entry->addend);
|
||||||
|
|
|
@ -108,6 +108,7 @@ typedef uint64_t target_ulong;
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
/* Minimalized TLB entry for use by TCG fast path. */
|
||||||
typedef struct CPUTLBEntry {
|
typedef struct CPUTLBEntry {
|
||||||
/* bit TARGET_LONG_BITS to TARGET_PAGE_BITS : virtual address
|
/* bit TARGET_LONG_BITS to TARGET_PAGE_BITS : virtual address
|
||||||
bit TARGET_PAGE_BITS-1..4 : Nonzero for accesses that should not
|
bit TARGET_PAGE_BITS-1..4 : Nonzero for accesses that should not
|
||||||
|
@ -131,14 +132,14 @@ typedef struct CPUTLBEntry {
|
||||||
|
|
||||||
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
|
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
|
||||||
|
|
||||||
/* The IOTLB is not accessed directly inline by generated TCG code,
|
/*
|
||||||
* so the CPUIOTLBEntry layout is not as critical as that of the
|
* The full TLB entry, which is not accessed by generated TCG code,
|
||||||
* CPUTLBEntry. (This is also why we don't want to combine the two
|
* so the layout is not as critical as that of CPUTLBEntry. This is
|
||||||
* structs into one.)
|
* also why we don't want to combine the two structs.
|
||||||
*/
|
*/
|
||||||
typedef struct CPUIOTLBEntry {
|
typedef struct CPUTLBEntryFull {
|
||||||
/*
|
/*
|
||||||
* @addr contains:
|
* @xlat_section contains:
|
||||||
* - in the lower TARGET_PAGE_BITS, a physical section number
|
* - in the lower TARGET_PAGE_BITS, a physical section number
|
||||||
* - with the lower TARGET_PAGE_BITS masked off, an offset which
|
* - with the lower TARGET_PAGE_BITS masked off, an offset which
|
||||||
* must be added to the virtual address to obtain:
|
* must be added to the virtual address to obtain:
|
||||||
|
@ -146,9 +147,9 @@ typedef struct CPUIOTLBEntry {
|
||||||
* number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM)
|
* number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM)
|
||||||
* + the offset within the target MemoryRegion (otherwise)
|
* + the offset within the target MemoryRegion (otherwise)
|
||||||
*/
|
*/
|
||||||
hwaddr addr;
|
hwaddr xlat_section;
|
||||||
MemTxAttrs attrs;
|
MemTxAttrs attrs;
|
||||||
} CPUIOTLBEntry;
|
} CPUTLBEntryFull;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data elements that are per MMU mode, minus the bits accessed by
|
* Data elements that are per MMU mode, minus the bits accessed by
|
||||||
|
@ -172,9 +173,8 @@ typedef struct CPUTLBDesc {
|
||||||
size_t vindex;
|
size_t vindex;
|
||||||
/* The tlb victim table, in two parts. */
|
/* The tlb victim table, in two parts. */
|
||||||
CPUTLBEntry vtable[CPU_VTLB_SIZE];
|
CPUTLBEntry vtable[CPU_VTLB_SIZE];
|
||||||
CPUIOTLBEntry viotlb[CPU_VTLB_SIZE];
|
CPUTLBEntryFull vfulltlb[CPU_VTLB_SIZE];
|
||||||
/* The iotlb. */
|
CPUTLBEntryFull *fulltlb;
|
||||||
CPUIOTLBEntry *iotlb;
|
|
||||||
} CPUTLBDesc;
|
} CPUTLBDesc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -106,7 +106,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
|
||||||
return tags + index;
|
return tags + index;
|
||||||
#else
|
#else
|
||||||
uintptr_t index;
|
uintptr_t index;
|
||||||
CPUIOTLBEntry *iotlbentry;
|
CPUTLBEntryFull *full;
|
||||||
int in_page, flags;
|
int in_page, flags;
|
||||||
ram_addr_t ptr_ra;
|
ram_addr_t ptr_ra;
|
||||||
hwaddr ptr_paddr, tag_paddr, xlat;
|
hwaddr ptr_paddr, tag_paddr, xlat;
|
||||||
|
@ -129,7 +129,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
|
||||||
assert(!(flags & TLB_INVALID_MASK));
|
assert(!(flags & TLB_INVALID_MASK));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the iotlbentry for ptr. This *must* be present in the TLB
|
* Find the CPUTLBEntryFull for ptr. This *must* be present in the TLB
|
||||||
* because we just found the mapping.
|
* because we just found the mapping.
|
||||||
* TODO: Perhaps there should be a cputlb helper that returns a
|
* TODO: Perhaps there should be a cputlb helper that returns a
|
||||||
* matching tlb entry + iotlb entry.
|
* matching tlb entry + iotlb entry.
|
||||||
|
@ -144,10 +144,10 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
|
||||||
g_assert(tlb_hit(comparator, ptr));
|
g_assert(tlb_hit(comparator, ptr));
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
iotlbentry = &env_tlb(env)->d[ptr_mmu_idx].iotlb[index];
|
full = &env_tlb(env)->d[ptr_mmu_idx].fulltlb[index];
|
||||||
|
|
||||||
/* If the virtual page MemAttr != Tagged, access unchecked. */
|
/* If the virtual page MemAttr != Tagged, access unchecked. */
|
||||||
if (!arm_tlb_mte_tagged(&iotlbentry->attrs)) {
|
if (!arm_tlb_mte_tagged(&full->attrs)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
|
||||||
int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE;
|
int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE;
|
||||||
assert(ra != 0);
|
assert(ra != 0);
|
||||||
cpu_check_watchpoint(env_cpu(env), ptr, ptr_size,
|
cpu_check_watchpoint(env_cpu(env), ptr, ptr_size,
|
||||||
iotlbentry->attrs, wp, ra);
|
full->attrs, wp, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -202,11 +202,11 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx,
|
||||||
tag_paddr = ptr_paddr >> (LOG2_TAG_GRANULE + 1);
|
tag_paddr = ptr_paddr >> (LOG2_TAG_GRANULE + 1);
|
||||||
|
|
||||||
/* Look up the address in tag space. */
|
/* Look up the address in tag space. */
|
||||||
tag_asi = iotlbentry->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
|
tag_asi = full->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS;
|
||||||
tag_as = cpu_get_address_space(env_cpu(env), tag_asi);
|
tag_as = cpu_get_address_space(env_cpu(env), tag_asi);
|
||||||
mr = address_space_translate(tag_as, tag_paddr, &xlat, NULL,
|
mr = address_space_translate(tag_as, tag_paddr, &xlat, NULL,
|
||||||
tag_access == MMU_DATA_STORE,
|
tag_access == MMU_DATA_STORE,
|
||||||
iotlbentry->attrs);
|
full->attrs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that @mr will never be NULL. If there is nothing in the address
|
* Note that @mr will never be NULL. If there is nothing in the address
|
||||||
|
|
|
@ -5384,8 +5384,8 @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
|
||||||
g_assert(tlb_hit(comparator, addr));
|
g_assert(tlb_hit(comparator, addr));
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index];
|
CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
||||||
info->attrs = iotlbentry->attrs;
|
info->attrs = full->attrs;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -14624,7 +14624,7 @@ static bool is_guarded_page(CPUARMState *env, DisasContext *s)
|
||||||
* table entry even for that case.
|
* table entry even for that case.
|
||||||
*/
|
*/
|
||||||
return (tlb_hit(entry->addr_code, addr) &&
|
return (tlb_hit(entry->addr_code, addr) &&
|
||||||
arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].iotlb[index].attrs));
|
arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].fulltlb[index].attrs));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue