[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 17/60] tcg: Avoid double lock if page tables happen to be in mmio
From: |
Richard Henderson |
Subject: |
[PATCH 17/60] tcg: Avoid double lock if page tables happen to be in mmio memory. |
Date: |
Fri, 1 Mar 2024 13:05:36 -1000 |
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
On i386, after fixing the page walking code to work with pages in
MMIO memory (specifically CXL emulated interleaved memory),
a crash was seen in an interrupt handling path.
Useful part of backtrace
7 0x0000555555ab1929 in bql_lock_impl (file=0x555556049122
"../../accel/tcg/cputlb.c", line=2033) at ../../system/cpus.c:524
8 bql_lock_impl (file=file@entry=0x555556049122 "../../accel/tcg/cputlb.c",
line=line@entry=2033) at ../../system/cpus.c:520
9 0x0000555555c9f7d6 in do_ld_mmio_beN (cpu=0x5555578e0cb0,
full=0x7ffe88012950, ret_be=ret_be@entry=0, addr=19595792376,
size=size@entry=8, mmu_idx=4, type=MMU_DATA_LOAD, ra=0) at
../../accel/tcg/cputlb.c:2033
10 0x0000555555ca0fbd in do_ld_8 (cpu=cpu@entry=0x5555578e0cb0,
p=p@entry=0x7ffff4efd1d0, mmu_idx=<optimized out>,
type=type@entry=MMU_DATA_LOAD, memop=<optimized out>, ra=ra@entry=0) at
../../accel/tcg/cputlb.c:2356
11 0x0000555555ca341f in do_ld8_mmu (cpu=cpu@entry=0x5555578e0cb0,
addr=addr@entry=19595792376, oi=oi@entry=52, ra=0, ra@entry=52,
access_type=access_type@entry=MMU_DATA_LOAD) at ../../accel/tcg/cputlb.c:2439
12 0x0000555555ca5f59 in cpu_ldq_mmu (ra=52, oi=52, addr=19595792376,
env=0x5555578e3470) at ../../accel/tcg/ldst_common.c.inc:169
13 cpu_ldq_le_mmuidx_ra (env=0x5555578e3470, addr=19595792376,
mmu_idx=<optimized out>, ra=ra@entry=0) at ../../accel/tcg/ldst_common.c.inc:301
14 0x0000555555b4b5fc in ptw_ldq (ra=0, in=0x7ffff4efd320) at
../../target/i386/tcg/sysemu/excp_helper.c:98
15 ptw_ldq (ra=0, in=0x7ffff4efd320) at
../../target/i386/tcg/sysemu/excp_helper.c:93
16 mmu_translate (env=env@entry=0x5555578e3470, in=0x7ffff4efd3e0,
out=0x7ffff4efd3b0, err=err@entry=0x7ffff4efd3c0, ra=ra@entry=0) at
../../target/i386/tcg/sysemu/excp_helper.c:174
17 0x0000555555b4c4b3 in get_physical_address (ra=0, err=0x7ffff4efd3c0,
out=0x7ffff4efd3b0, mmu_idx=0, access_type=MMU_DATA_LOAD,
addr=18446741874686299840, env=0x5555578e3470) at
../../target/i386/tcg/sysemu/excp_helper.c:580
18 x86_cpu_tlb_fill (cs=0x5555578e0cb0, addr=18446741874686299840,
size=<optimized out>, access_type=MMU_DATA_LOAD, mmu_idx=0, probe=<optimized
out>, retaddr=0) at ../../target/i386/tcg/sysemu/excp_helper.c:606
19 0x0000555555ca0ee9 in tlb_fill (retaddr=0, mmu_idx=0,
access_type=MMU_DATA_LOAD, size=<optimized out>, addr=18446741874686299840,
cpu=0x7ffff4efd540) at ../../accel/tcg/cputlb.c:1315
20 mmu_lookup1 (cpu=cpu@entry=0x5555578e0cb0, data=data@entry=0x7ffff4efd540,
mmu_idx=0, access_type=access_type@entry=MMU_DATA_LOAD, ra=ra@entry=0) at
../../accel/tcg/cputlb.c:1713
21 0x0000555555ca2c61 in mmu_lookup (cpu=cpu@entry=0x5555578e0cb0,
addr=addr@entry=18446741874686299840, oi=oi@entry=32, ra=ra@entry=0,
type=type@entry=MMU_DATA_LOAD, l=l@entry=0x7ffff4efd540) at
../../accel/tcg/cputlb.c:1803
22 0x0000555555ca3165 in do_ld4_mmu (cpu=cpu@entry=0x5555578e0cb0,
addr=addr@entry=18446741874686299840, oi=oi@entry=32, ra=ra@entry=0,
access_type=access_type@entry=MMU_DATA_LOAD) at ../../accel/tcg/cputlb.c:2416
23 0x0000555555ca5ef9 in cpu_ldl_mmu (ra=0, oi=32, addr=18446741874686299840,
env=0x5555578e3470) at ../../accel/tcg/ldst_common.c.inc:158
24 cpu_ldl_le_mmuidx_ra (env=env@entry=0x5555578e3470,
addr=addr@entry=18446741874686299840, mmu_idx=<optimized out>, ra=ra@entry=0)
at ../../accel/tcg/ldst_common.c.inc:294
25 0x0000555555bb6cdd in do_interrupt64 (is_hw=1,
next_eip=18446744072399775809, error_code=0, is_int=0, intno=236,
env=0x5555578e3470) at ../../target/i386/tcg/seg_helper.c:889
26 do_interrupt_all (cpu=cpu@entry=0x5555578e0cb0, intno=236,
is_int=is_int@entry=0, error_code=error_code@entry=0,
next_eip=next_eip@entry=0, is_hw=is_hw@entry=1) at
../../target/i386/tcg/seg_helper.c:1130
27 0x0000555555bb87da in do_interrupt_x86_hardirq
(env=env@entry=0x5555578e3470, intno=<optimized out>, is_hw=is_hw@entry=1) at
../../target/i386/tcg/seg_helper.c:1162
28 0x0000555555b5039c in x86_cpu_exec_interrupt (cs=0x5555578e0cb0,
interrupt_request=<optimized out>) at
../../target/i386/tcg/sysemu/seg_helper.c:197
29 0x0000555555c94480 in cpu_handle_interrupt (last_tb=<synthetic pointer>,
cpu=0x5555578e0cb0) at ../../accel/tcg/cpu-exec.c:844
Peter identified this as being due to the BQL already being
held when the page table walker encounters MMIO memory and attempts
to take the lock again. There are other examples of similar paths
TCG, so this follows the approach taken in those of simply checking
if the lock is already held and if it is, don't take it again.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20240219173153.12114-4-Jonathan.Cameron@huawei.com>
[rth: Use BQL_LOCK_GUARD]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
accel/tcg/cputlb.c | 34 ++++++++++------------------------
1 file changed, 10 insertions(+), 24 deletions(-)
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 047cd2cc0a..6243bcb179 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -2022,7 +2022,6 @@ static uint64_t do_ld_mmio_beN(CPUState *cpu,
CPUTLBEntryFull *full,
MemoryRegion *mr;
hwaddr mr_offset;
MemTxAttrs attrs;
- uint64_t ret;
tcg_debug_assert(size > 0 && size <= 8);
@@ -2030,12 +2029,9 @@ static uint64_t do_ld_mmio_beN(CPUState *cpu,
CPUTLBEntryFull *full,
section = io_prepare(&mr_offset, cpu, full->xlat_section, attrs, addr, ra);
mr = section->mr;
- bql_lock();
- ret = int_ld_mmio_beN(cpu, full, ret_be, addr, size, mmu_idx,
- type, ra, mr, mr_offset);
- bql_unlock();
-
- return ret;
+ BQL_LOCK_GUARD();
+ return int_ld_mmio_beN(cpu, full, ret_be, addr, size, mmu_idx,
+ type, ra, mr, mr_offset);
}
static Int128 do_ld16_mmio_beN(CPUState *cpu, CPUTLBEntryFull *full,
@@ -2054,13 +2050,11 @@ static Int128 do_ld16_mmio_beN(CPUState *cpu,
CPUTLBEntryFull *full,
section = io_prepare(&mr_offset, cpu, full->xlat_section, attrs, addr, ra);
mr = section->mr;
- bql_lock();
+ BQL_LOCK_GUARD();
a = int_ld_mmio_beN(cpu, full, ret_be, addr, size - 8, mmu_idx,
MMU_DATA_LOAD, ra, mr, mr_offset);
b = int_ld_mmio_beN(cpu, full, ret_be, addr + size - 8, 8, mmu_idx,
MMU_DATA_LOAD, ra, mr, mr_offset + size - 8);
- bql_unlock();
-
return int128_make128(b, a);
}
@@ -2569,7 +2563,6 @@ static uint64_t do_st_mmio_leN(CPUState *cpu,
CPUTLBEntryFull *full,
hwaddr mr_offset;
MemoryRegion *mr;
MemTxAttrs attrs;
- uint64_t ret;
tcg_debug_assert(size > 0 && size <= 8);
@@ -2577,12 +2570,9 @@ static uint64_t do_st_mmio_leN(CPUState *cpu,
CPUTLBEntryFull *full,
section = io_prepare(&mr_offset, cpu, full->xlat_section, attrs, addr, ra);
mr = section->mr;
- bql_lock();
- ret = int_st_mmio_leN(cpu, full, val_le, addr, size, mmu_idx,
- ra, mr, mr_offset);
- bql_unlock();
-
- return ret;
+ BQL_LOCK_GUARD();
+ return int_st_mmio_leN(cpu, full, val_le, addr, size, mmu_idx,
+ ra, mr, mr_offset);
}
static uint64_t do_st16_mmio_leN(CPUState *cpu, CPUTLBEntryFull *full,
@@ -2593,7 +2583,6 @@ static uint64_t do_st16_mmio_leN(CPUState *cpu,
CPUTLBEntryFull *full,
MemoryRegion *mr;
hwaddr mr_offset;
MemTxAttrs attrs;
- uint64_t ret;
tcg_debug_assert(size > 8 && size <= 16);
@@ -2601,14 +2590,11 @@ static uint64_t do_st16_mmio_leN(CPUState *cpu,
CPUTLBEntryFull *full,
section = io_prepare(&mr_offset, cpu, full->xlat_section, attrs, addr, ra);
mr = section->mr;
- bql_lock();
+ BQL_LOCK_GUARD();
int_st_mmio_leN(cpu, full, int128_getlo(val_le), addr, 8,
mmu_idx, ra, mr, mr_offset);
- ret = int_st_mmio_leN(cpu, full, int128_gethi(val_le), addr + 8,
- size - 8, mmu_idx, ra, mr, mr_offset + 8);
- bql_unlock();
-
- return ret;
+ return int_st_mmio_leN(cpu, full, int128_gethi(val_le), addr + 8,
+ size - 8, mmu_idx, ra, mr, mr_offset + 8);
}
/*
--
2.34.1
- [PATCH 35/60] linux-user: Move some mmap checks outside the lock, (continued)
- [PATCH 35/60] linux-user: Move some mmap checks outside the lock, Richard Henderson, 2024/03/01
- [PATCH 37/60] linux-user: Split out mmap_end, Richard Henderson, 2024/03/01
- [PATCH 33/60] linux-user: Remove qemu_host_page_size from main, Richard Henderson, 2024/03/01
- [PATCH 34/60] linux-user: Split out target_mmap__locked, Richard Henderson, 2024/03/01
- [PATCH 21/60] linux-user: Remove qemu_host_page_size from create_elf_tables, Richard Henderson, 2024/03/01
- [PATCH 22/60] linux-user/hppa: Simplify init_guest_commpage, Richard Henderson, 2024/03/01
- [PATCH 24/60] linux-user/arm: Remove qemu_host_page_size from init_guest_commpage, Richard Henderson, 2024/03/01
- [PATCH 30/60] hw/tpm: Remove HOST_PAGE_ALIGN from tpm_ppi_init, Richard Henderson, 2024/03/01
- [PATCH 32/60] softmmu/physmem: Remove HOST_PAGE_ALIGN, Richard Henderson, 2024/03/01
- [PATCH 10/60] linux-user/elfload: Write corefile elf header in one block, Richard Henderson, 2024/03/01
- [PATCH 17/60] tcg: Avoid double lock if page tables happen to be in mmio memory.,
Richard Henderson <=
- [PATCH 29/60] migration: Remove qemu_host_page_size, Richard Henderson, 2024/03/01
- [PATCH 31/60] softmmu/physmem: Remove qemu_host_page_size, Richard Henderson, 2024/03/01
- [PATCH 36/60] linux-user: Fix sub-host-page mmap, Richard Henderson, 2024/03/01
- [PATCH 38/60] linux-user: Do early mmap placement only for reserved_va, Richard Henderson, 2024/03/01
- [PATCH 39/60] linux-user: Split out do_munmap, Richard Henderson, 2024/03/01
- [PATCH 41/60] linux-user: Split out mmap_h_eq_g, Richard Henderson, 2024/03/01
- [PATCH 45/60] tests/tcg: Extend file in linux-madvise.c, Richard Henderson, 2024/03/01
- [PATCH 42/60] linux-user: Split out mmap_h_lt_g, Richard Henderson, 2024/03/01
- [PATCH 50/60] target/arm: Enable TARGET_PAGE_BITS_VARY for AArch64 user-only, Richard Henderson, 2024/03/01
- [PATCH 47/60] cpu: Remove page_size_init, Richard Henderson, 2024/03/01