diff mbox

[Bug,1625216,NEW] memory writes via gdb don't work for memory mapped hardware

Message ID 20160919143701.1959.82839.malonedeb@soybean.canonical.com
State New
Headers show

Commit Message

Thomas Huth Sept. 19, 2016, 2:37 p.m. UTC
Public bug reported:

When I remote-debug a qemu-guest and attempt to write to a memory mapped location, the
write-handler for the concerned device will not be called. All write-requiests from
gdb are delegated to cpu_physical_memory_write_rom(...). a function that writes to the 
underlying ram-block.

I believe requests to memory mapped hardware should be delegated to 
address_space_rw(). 

example:
;; a memory mapped device. No effect, the write-handler is not called
(gdb) set *0xfff3c000 = 48

;; a ram or rom-block. Thos works. The value is changed.
(gdb) set *0x100000 = 48


----------------------------------------

Here's my suggested patch. As noted in the comment, it could perhaps be
improved for the (rare) case when the write-request from gdb spans multiple 
memory regions.

$ git diff   85bc2a15121e8bcd9f15eb75794a1eacca9d84bd HEAD ../exec.c

** Affects: qemu
     Importance: Undecided
         Status: New


** Tags: gdb mmio write

Comments

no-reply@patchew.org Sept. 19, 2016, 4:13 p.m. UTC | #1
Hi,

Your series seems to have some coding style problems. See output below for
more information:

Type: series
Subject: [Qemu-devel] [Bug 1625216] [NEW] memory writes via gdb don't work for memory mapped hardware
Message-id: 20160919143701.1959.82839.malonedeb@soybean.canonical.com

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git show --no-patch --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
f1cd6ef memory writes via gdb don't work for memory mapped hardware

=== OUTPUT BEGIN ===
Checking PATCH 1/1: memory writes via gdb don't work for memory mapped hardware...
ERROR: trailing whitespace
#50: FILE: exec.c:3622:
+            /* if ram/rom region we access the memory $

ERROR: line over 90 characters
#54: FILE: exec.c:3626:
+            MemoryRegion *mr = address_space_translate(as, phys_addr, &addr1, &mr_len, is_write);

WARNING: line over 80 characters
#55: FILE: exec.c:3627:
+            is_memcpy_access  = memory_region_is_ram(mr) || memory_region_is_romd(mr);

ERROR: space required before the open parenthesis '('
#56: FILE: exec.c:3628:
+            if(mr_len < len) {

ERROR: trailing whitespace
#57: FILE: exec.c:3629:
+                /* TODO, mimic more of the loop over mr chunks as $

ERROR: trailing whitespace
#58: FILE: exec.c:3630:
+                   done in cpu_physical_memory_write_internal */ $

ERROR: else should follow close brace '}'
#63: FILE: exec.c:3635:
+        }
+        else {

ERROR: trailing whitespace
#66: FILE: exec.c:3638:
+        $

ERROR: Missing Signed-off-by: line(s)

total: 8 errors, 1 warnings, 40 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org
Thomas Huth Nov. 18, 2020, 4:08 p.m. UTC | #2
The code has moved around somewhat, but it's still true that writes by
gdb don't go to devices -- cpu_memory_rw_debug() calls
address_space_write_rom() which calls address_space_write_rom_internal()
which simply skips writing for non-ram/rom regions.

I'm not sure if the gdb accesses should be special cased or if we should
just make address_space_write_rom() write to devices (which would also
affect eg ELF file loading, which is useful in some odd corner cases).


** Changed in: qemu
       Status: New => Confirmed
Thomas Huth Feb. 9, 2021, 8:52 p.m. UTC | #3
** Tags added: gdbstub
Thomas Huth May 8, 2021, 5:37 a.m. UTC | #4
This is an automated cleanup. This bug report has been moved to QEMU's
new bug tracker on gitlab.com and thus gets marked as 'expired' now.
Please continue with the discussion here:

 https://gitlab.com/qemu-project/qemu/-/issues/213


** Changed in: qemu
       Status: Confirmed => Expired

** Bug watch added: gitlab.com/qemu-project/qemu/-/issues #213
   https://gitlab.com/qemu-project/qemu/-/issues/213
diff mbox

Patch

diff --git a/exec.c b/exec.c
index c4f9036..45ef896 100644
--- a/exec.c
+++ b/exec.c
@@ -3676,6 +3676,7 @@  int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
     int l;
     hwaddr phys_addr;
     target_ulong page;
+    bool is_memcpy_access;
 
     while (len > 0) {
         int asidx;
@@ -3691,13 +3692,32 @@  int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
         if (l > len)
             l = len;
         phys_addr += (addr & ~TARGET_PAGE_MASK);
+
         if (is_write) {
+            /* if ram/rom region we access the memory 
+               via memcpy instead of via the cpu */
+            hwaddr mr_len, addr1;
+            AddressSpace *as = cpu->cpu_ases[asidx].as;
+            MemoryRegion *mr = address_space_translate(as, phys_addr, &addr1, &mr_len, is_write);
+            is_memcpy_access  = memory_region_is_ram(mr) || memory_region_is_romd(mr);
+            if(mr_len < len) {
+                /* TODO, mimic more of the loop over mr chunks as 
+                   done in cpu_physical_memory_write_internal */ 
+                printf("warning: we dont know whether all bytes "
+                       "to be written are ram/rom or io\n");
+            }
+        }
+        else {
+            is_memcpy_access = false;
+        }
+        
+        if (is_write && is_memcpy_access) {
             cpu_physical_memory_write_rom(cpu->cpu_ases[asidx].as,
                                           phys_addr, buf, l);
         } else {
             address_space_rw(cpu->cpu_ases[asidx].as, phys_addr,
                              MEMTXATTRS_UNSPECIFIED,
-                             buf, l, 0);
+                             buf, l, is_write);
         }
         len -= l;
         buf += l;