Patchwork [3/5] exec: fix code tlb entry misused as iotlb in get_page_addr_code()

login
register
mail settings
Submitter Avi Kivity
Date March 8, 2012, 5:20 p.m.
Message ID <1331227233-18601-4-git-send-email-avi@redhat.com>
Download mbox | patch
Permalink /patch/145584/
State New
Headers show

Comments

Avi Kivity - March 8, 2012, 5:20 p.m.
get_page_addr_code() reads a code tlb entry, but interprets it as an
iotlb entry.  This works by accident since the low bits of a RAM code
tlb entry are clear, and match a RAM iotlb entry.  This accident is
about to unhappen, so fix the code to use an iotlb entry (using the
code entry with TLB_MMIO may fail if the page is a watchpoint).

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 exec.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Max Filippov - March 15, 2012, 7:23 p.m.
Hi.

> get_page_addr_code() reads a code tlb entry, but interprets it as an
> iotlb entry.  This works by accident since the low bits of a RAM code
> tlb entry are clear, and match a RAM iotlb entry.  This accident is
> about to unhappen, so fix the code to use an iotlb entry (using the
> code entry with TLB_MMIO may fail if the page is a watchpoint).
>
> Signed-off-by: Avi Kivity<avi@redhat.com>
> ---
>   exec.c |    2 +-
>   1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/exec.c b/exec.c
> index a35eb4f..f26d1b0 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -4685,7 +4685,7 @@ tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
>                    (addr&  TARGET_PAGE_MASK))) {
>           ldub_code(addr);
>       }
> -    pd = env1->tlb_table[mmu_idx][page_index].addr_code&  ~TARGET_PAGE_MASK;
> +    pd = env1->iotlb[mmu_idx][page_index]&  ~TARGET_PAGE_MASK;
>       if (pd != io_mem_ram.ram_addr&&  pd != io_mem_rom.ram_addr
>           &&  !io_mem_region[pd]->rom_device) {
>   #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)

With this patch xtensa debug option unit test causes qemu abort with the message

  qemu: fatal: Trying to execute code outside RAM or ROM at 0xd000088c

This happens immediately after a watchpoint setup for a data breakpoint at the same memory page where the currently
executed code is located. Any idea on how to fix it?

(gdb) bt
#0  cpu_abort (env=0x55555626a310, fmt=0x55555573f540 "Trying to execute code outside RAM or ROM at 0x%08x\n") at 
/home/dumb/ws/m/awt/emu/xtensa/qemu/exec.c:1848
#1  0x00005555556c1657 in get_page_addr_code (env1=0x55555626a310, addr=0xd000088c) at 
/home/dumb/ws/m/awt/emu/xtensa/qemu/exec.c:4694
#2  0x00005555556b3441 in tb_find_slow (env=0x55555626a310, pc=0xd000088c, cs_base=0x0, flags=0x0) at 
/home/dumb/ws/m/awt/emu/xtensa/qemu/cpu-exec.c:95
#3  0x00005555556b36ac in tb_find_fast (env=0x55555626a310) at /home/dumb/ws/m/awt/emu/xtensa/qemu/cpu-exec.c:151
#4  0x00005555556b3a2d in cpu_xtensa_exec (env=0x55555626a310) at /home/dumb/ws/m/awt/emu/xtensa/qemu/cpu-exec.c:534
#5  0x00005555556b6380 in tcg_cpu_exec (env=0x55555626a310) at /home/dumb/ws/m/awt/emu/xtensa/qemu/cpus.c:1022
#6  0x00005555556b6498 in tcg_exec_all () at /home/dumb/ws/m/awt/emu/xtensa/qemu/cpus.c:1054
#7  0x00005555556b5a30 in qemu_tcg_cpu_thread_fn (arg=0x55555626a310) at /home/dumb/ws/m/awt/emu/xtensa/qemu/cpus.c:772
#8  0x00007ffff62e0d90 in start_thread () from /lib64/libpthread.so.0
#9  0x00007ffff6011f5d in clone () from /lib64/libc.so.6

Memory maps are the following:

(qemu) info mtree
memory
00000000-fffffffe (prio 0, RW): system
   00000000-07ffffff (prio 0, RW): xtensa.sram
   fe000000-fe000fff (prio 0, RW): xtensa.rom
(qemu) info tlb
ITLB:
Way 5 (128 MB)
         Vaddr       Paddr       ASID  Attr RWX
         ----------  ----------  ----  ---- ---
         0xd0000000  0x00000000  0x01  0x07 RWX
         0xd8000000  0x00000000  0x01  0x03 RWX
Way 6 (256 MB)
         Vaddr       Paddr       ASID  Attr RWX
         ----------  ----------  ----  ---- ---
         0xe0000000  0xf0000000  0x01  0x07 RWX
         0xf0000000  0xf0000000  0x01  0x03 RWX

DTLB:
Way 5 (128 MB)
         Vaddr       Paddr       ASID  Attr RWX
         ----------  ----------  ----  ---- ---
         0xd0000000  0x00000000  0x01  0x07 RWX
         0xd8000000  0x00000000  0x01  0x03 RWX
Way 6 (256 MB)
         Vaddr       Paddr       ASID  Attr RWX
         ----------  ----------  ----  ---- ---
         0xe0000000  0xf0000000  0x01  0x07 RWX
         0xf0000000  0xf0000000  0x01  0x03 RWX

--
Thanks.
-- Max
Avi Kivity - March 18, 2012, 10:26 a.m.
On 03/15/2012 09:23 PM, jcmvbkbc wrote:
> Hi.
>
>> get_page_addr_code() reads a code tlb entry, but interprets it as an
>> iotlb entry.  This works by accident since the low bits of a RAM code
>> tlb entry are clear, and match a RAM iotlb entry.  This accident is
>> about to unhappen, so fix the code to use an iotlb entry (using the
>> code entry with TLB_MMIO may fail if the page is a watchpoint).
>>
>> Signed-off-by: Avi Kivity<avi@redhat.com>
>> ---
>>   exec.c |    2 +-
>>   1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/exec.c b/exec.c
>> index a35eb4f..f26d1b0 100644
>> --- a/exec.c
>> +++ b/exec.c
>> @@ -4685,7 +4685,7 @@ tb_page_addr_t get_page_addr_code(CPUState
>> *env1, target_ulong addr)
>>                    (addr&  TARGET_PAGE_MASK))) {
>>           ldub_code(addr);
>>       }
>> -    pd = env1->tlb_table[mmu_idx][page_index].addr_code& 
>> ~TARGET_PAGE_MASK;
>> +    pd = env1->iotlb[mmu_idx][page_index]&  ~TARGET_PAGE_MASK;
>>       if (pd != io_mem_ram.ram_addr&&  pd != io_mem_rom.ram_addr
>>           &&  !io_mem_region[pd]->rom_device) {
>>   #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) ||
>> defined(TARGET_SPARC)
>
> With this patch xtensa debug option unit test causes qemu abort with
> the message
>
>  qemu: fatal: Trying to execute code outside RAM or ROM at 0xd000088c
>
> This happens immediately after a watchpoint setup for a data
> breakpoint at the same memory page where the currently
> executed code is located. Any idea on how to fix it?

Can you provide details on how to reproduce this?
Max Filippov - March 18, 2012, 11:07 a.m.
>>> get_page_addr_code() reads a code tlb entry, but interprets it as an
>>> iotlb entry.  This works by accident since the low bits of a RAM code
>>> tlb entry are clear, and match a RAM iotlb entry.  This accident is
>>> about to unhappen, so fix the code to use an iotlb entry (using the
>>> code entry with TLB_MMIO may fail if the page is a watchpoint).
>>>
>>> Signed-off-by: Avi Kivity<avi@redhat.com>
>>> ---
>>>   exec.c |    2 +-
>>>   1 files changed, 1 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/exec.c b/exec.c
>>> index a35eb4f..f26d1b0 100644
>>> --- a/exec.c
>>> +++ b/exec.c
>>> @@ -4685,7 +4685,7 @@ tb_page_addr_t get_page_addr_code(CPUState
>>> *env1, target_ulong addr)
>>>                    (addr&  TARGET_PAGE_MASK))) {
>>>           ldub_code(addr);
>>>       }
>>> -    pd = env1->tlb_table[mmu_idx][page_index].addr_code&
>>> ~TARGET_PAGE_MASK;
>>> +    pd = env1->iotlb[mmu_idx][page_index]&  ~TARGET_PAGE_MASK;
>>>       if (pd != io_mem_ram.ram_addr&&  pd != io_mem_rom.ram_addr
>>>           &&  !io_mem_region[pd]->rom_device) {
>>>   #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) ||
>>> defined(TARGET_SPARC)
>>
>> With this patch xtensa debug option unit test causes qemu abort with
>> the message
>>
>>  qemu: fatal: Trying to execute code outside RAM or ROM at 0xd000088c
>>
>> This happens immediately after a watchpoint setup for a data
>> breakpoint at the same memory page where the currently
>> executed code is located. Any idea on how to fix it?
>
> Can you provide details on how to reproduce this?

It may be reproduced by running test_break.tst unit test:

qemu-system-xtensa -M sim -cpu dc232b -nographic -semihosting  -kernel
./test_break.tst

Compiled test binary is here:
http://jcmvbkbc.spb.ru/~dumb/ws/osll/qemu-xtensa/20120318/test_break.tst

Patch

diff --git a/exec.c b/exec.c
index a35eb4f..f26d1b0 100644
--- a/exec.c
+++ b/exec.c
@@ -4685,7 +4685,7 @@  tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong addr)
                  (addr & TARGET_PAGE_MASK))) {
         ldub_code(addr);
     }
-    pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
+    pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK;
     if (pd != io_mem_ram.ram_addr && pd != io_mem_rom.ram_addr
         && !io_mem_region[pd]->rom_device) {
 #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)