diff mbox series

[v3,11/12] accel/tcg: Replace target_ulong with vaddr in page_*()

Message ID 20230621135633.1649-12-anjo@rev.ng (mailing list archive)
State New, archived
Headers show
Series Start replacing target_ulong with vaddr | expand

Commit Message

Anton Johansson June 21, 2023, 1:56 p.m. UTC
Use vaddr for guest virtual addresses for functions dealing with page
flags.

Signed-off-by: Anton Johansson <anjo@rev.ng>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
 accel/tcg/user-exec.c        | 44 +++++++++++++++++-------------------
 include/exec/cpu-all.h       | 10 ++++----
 include/exec/translate-all.h |  2 +-
 3 files changed, 27 insertions(+), 29 deletions(-)

Comments

Richard Henderson June 26, 2023, 1:59 p.m. UTC | #1
On 6/21/23 15:56, Anton Johansson via wrote:
> Use vaddr for guest virtual addresses for functions dealing with page
> flags.
> 
> Signed-off-by: Anton Johansson <anjo@rev.ng>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   accel/tcg/user-exec.c        | 44 +++++++++++++++++-------------------
>   include/exec/cpu-all.h       | 10 ++++----
>   include/exec/translate-all.h |  2 +-
>   3 files changed, 27 insertions(+), 29 deletions(-)

This causes other failures, such as

https://gitlab.com/rth7680/qemu/-/jobs/4540151776#L4468

qemu-hppa: ../accel/tcg/user-exec.c:490: page_set_flags: Assertion `last <= 
GUEST_ADDR_MAX' failed.

which is caused by

#8  0x00005555556e5b77 in do_shmat (cpu_env=cpu_env@entry=0x555556274378,
     shmid=54, shmaddr=<optimized out>, shmflg=0)
     at ../src/linux-user/syscall.c:4598

4598	    page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
4599	                   PAGE_VALID | PAGE_RESET | PAGE_READ |
4600	                   (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));

The host shm_info.shm_segsz is uint64_t, which means that the whole expression gets 
converted to uint64_t.  With this patch, it is not properly truncated to a guest address.

In this particular case, raddr is signed (abi_long), which is a mistake.  Fixing that 
avoids this particular error.

But since user-only is outside of the scope of this work, I'm going to drop this patch for 
now.


r~
Zhijian Li (Fujitsu)" via June 26, 2023, 3:04 p.m. UTC | #2
On 6/26/23 15:59, Richard Henderson wrote:
> On 6/21/23 15:56, Anton Johansson via wrote:
>> Use vaddr for guest virtual addresses for functions dealing with page
>> flags.
>>
>> Signed-off-by: Anton Johansson <anjo@rev.ng>
>> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   accel/tcg/user-exec.c        | 44 +++++++++++++++++-------------------
>>   include/exec/cpu-all.h       | 10 ++++----
>>   include/exec/translate-all.h |  2 +-
>>   3 files changed, 27 insertions(+), 29 deletions(-)
>
> This causes other failures, such as
>
> https://gitlab.com/rth7680/qemu/-/jobs/4540151776#L4468
>
> qemu-hppa: ../accel/tcg/user-exec.c:490: page_set_flags: Assertion 
> `last <= GUEST_ADDR_MAX' failed.
>
> which is caused by
>
> #8  0x00005555556e5b77 in do_shmat (cpu_env=cpu_env@entry=0x555556274378,
>     shmid=54, shmaddr=<optimized out>, shmflg=0)
>     at ../src/linux-user/syscall.c:4598
>
> 4598        page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
> 4599                       PAGE_VALID | PAGE_RESET | PAGE_READ |
> 4600                       (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
>
> The host shm_info.shm_segsz is uint64_t, which means that the whole 
> expression gets converted to uint64_t.  With this patch, it is not 
> properly truncated to a guest address.
>
> In this particular case, raddr is signed (abi_long), which is a 
> mistake.  Fixing that avoids this particular error.
>
> But since user-only is outside of the scope of this work, I'm going to 
> drop this patch for now.
>
>
> r~
My bad! I saw the CI failure post-rebase but didn't look closely enough, 
I saw a build-user failure in the branch I was based on
and assumed they were related.

Thanks for the explanation, makes sense!:)
diff mbox series

Patch

diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index f8b16d6ab8..6b0cbcf2e5 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -144,7 +144,7 @@  typedef struct PageFlagsNode {
 
 static IntervalTreeRoot pageflags_root;
 
-static PageFlagsNode *pageflags_find(target_ulong start, target_long last)
+static PageFlagsNode *pageflags_find(vaddr start, vaddr last)
 {
     IntervalTreeNode *n;
 
@@ -152,8 +152,7 @@  static PageFlagsNode *pageflags_find(target_ulong start, target_long last)
     return n ? container_of(n, PageFlagsNode, itree) : NULL;
 }
 
-static PageFlagsNode *pageflags_next(PageFlagsNode *p, target_ulong start,
-                                     target_long last)
+static PageFlagsNode *pageflags_next(PageFlagsNode *p, vaddr start, vaddr last)
 {
     IntervalTreeNode *n;
 
@@ -205,7 +204,7 @@  void page_dump(FILE *f)
     walk_memory_regions(f, dump_region);
 }
 
-int page_get_flags(target_ulong address)
+int page_get_flags(vaddr address)
 {
     PageFlagsNode *p = pageflags_find(address, address);
 
@@ -228,7 +227,7 @@  int page_get_flags(target_ulong address)
 }
 
 /* A subroutine of page_set_flags: insert a new node for [start,last]. */
-static void pageflags_create(target_ulong start, target_ulong last, int flags)
+static void pageflags_create(vaddr start, vaddr last, int flags)
 {
     PageFlagsNode *p = g_new(PageFlagsNode, 1);
 
@@ -239,13 +238,13 @@  static void pageflags_create(target_ulong start, target_ulong last, int flags)
 }
 
 /* A subroutine of page_set_flags: remove everything in [start,last]. */
-static bool pageflags_unset(target_ulong start, target_ulong last)
+static bool pageflags_unset(vaddr start, vaddr last)
 {
     bool inval_tb = false;
 
     while (true) {
         PageFlagsNode *p = pageflags_find(start, last);
-        target_ulong p_last;
+        vaddr p_last;
 
         if (!p) {
             break;
@@ -284,8 +283,7 @@  static bool pageflags_unset(target_ulong start, target_ulong last)
  * A subroutine of page_set_flags: nothing overlaps [start,last],
  * but check adjacent mappings and maybe merge into a single range.
  */
-static void pageflags_create_merge(target_ulong start, target_ulong last,
-                                   int flags)
+static void pageflags_create_merge(vaddr start, vaddr last, int flags)
 {
     PageFlagsNode *next = NULL, *prev = NULL;
 
@@ -336,11 +334,11 @@  static void pageflags_create_merge(target_ulong start, target_ulong last,
 #define PAGE_STICKY  (PAGE_ANON | PAGE_PASSTHROUGH | PAGE_TARGET_STICKY)
 
 /* A subroutine of page_set_flags: add flags to [start,last]. */
-static bool pageflags_set_clear(target_ulong start, target_ulong last,
+static bool pageflags_set_clear(vaddr start, vaddr last,
                                 int set_flags, int clear_flags)
 {
     PageFlagsNode *p;
-    target_ulong p_start, p_last;
+    vaddr p_start, p_last;
     int p_flags, merge_flags;
     bool inval_tb = false;
 
@@ -480,7 +478,7 @@  static bool pageflags_set_clear(target_ulong start, target_ulong last,
  * The flag PAGE_WRITE_ORG is positioned automatically depending
  * on PAGE_WRITE.  The mmap_lock should already be held.
  */
-void page_set_flags(target_ulong start, target_ulong last, int flags)
+void page_set_flags(vaddr start, vaddr last, int flags)
 {
     bool reset = false;
     bool inval_tb = false;
@@ -520,9 +518,9 @@  void page_set_flags(target_ulong start, target_ulong last, int flags)
     }
 }
 
-int page_check_range(target_ulong start, target_ulong len, int flags)
+int page_check_range(vaddr start, vaddr len, int flags)
 {
-    target_ulong last;
+    vaddr last;
     int locked;  /* tri-state: =0: unlocked, +1: global, -1: local */
     int ret;
 
@@ -601,7 +599,7 @@  int page_check_range(target_ulong start, target_ulong len, int flags)
 void page_protect(tb_page_addr_t address)
 {
     PageFlagsNode *p;
-    target_ulong start, last;
+    vaddr start, last;
     int prot;
 
     assert_memory_lock();
@@ -642,7 +640,7 @@  void page_protect(tb_page_addr_t address)
  * immediately exited. (We can only return 2 if the 'pc' argument is
  * non-zero.)
  */
-int page_unprotect(target_ulong address, uintptr_t pc)
+int page_unprotect(vaddr address, uintptr_t pc)
 {
     PageFlagsNode *p;
     bool current_tb_invalidated;
@@ -676,7 +674,7 @@  int page_unprotect(target_ulong address, uintptr_t pc)
         }
 #endif
     } else {
-        target_ulong start, len, i;
+        vaddr start, len, i;
         int prot;
 
         if (qemu_host_page_size <= TARGET_PAGE_SIZE) {
@@ -691,7 +689,7 @@  int page_unprotect(target_ulong address, uintptr_t pc)
             prot = 0;
 
             for (i = 0; i < len; i += TARGET_PAGE_SIZE) {
-                target_ulong addr = start + i;
+                vaddr addr = start + i;
 
                 p = pageflags_find(addr, addr);
                 if (p) {
@@ -814,7 +812,7 @@  typedef struct TargetPageDataNode {
 
 static IntervalTreeRoot targetdata_root;
 
-void page_reset_target_data(target_ulong start, target_ulong last)
+void page_reset_target_data(vaddr start, vaddr last)
 {
     IntervalTreeNode *n, *next;
 
@@ -828,7 +826,7 @@  void page_reset_target_data(target_ulong start, target_ulong last)
          n != NULL;
          n = next,
          next = next ? interval_tree_iter_next(n, start, last) : NULL) {
-        target_ulong n_start, n_last, p_ofs, p_len;
+        vaddr n_start, n_last, p_ofs, p_len;
         TargetPageDataNode *t = container_of(n, TargetPageDataNode, itree);
 
         if (n->start >= start && n->last <= last) {
@@ -851,11 +849,11 @@  void page_reset_target_data(target_ulong start, target_ulong last)
     }
 }
 
-void *page_get_target_data(target_ulong address)
+void *page_get_target_data(vaddr address)
 {
     IntervalTreeNode *n;
     TargetPageDataNode *t;
-    target_ulong page, region;
+    vaddr page, region;
 
     page = address & TARGET_PAGE_MASK;
     region = address & TBD_MASK;
@@ -884,7 +882,7 @@  void *page_get_target_data(target_ulong address)
     return t->data[(page - region) >> TARGET_PAGE_BITS];
 }
 #else
-void page_reset_target_data(target_ulong start, target_ulong last) { }
+void page_reset_target_data(vaddr start, vaddr last) { }
 #endif /* TARGET_PAGE_DATA_SIZE */
 
 /* The softmmu versions of these helpers are in cputlb.c.  */
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 09bf4c0cc6..97be7c2c3c 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -219,10 +219,10 @@  typedef int (*walk_memory_regions_fn)(void *, target_ulong,
                                       target_ulong, unsigned long);
 int walk_memory_regions(void *, walk_memory_regions_fn);
 
-int page_get_flags(target_ulong address);
-void page_set_flags(target_ulong start, target_ulong last, int flags);
-void page_reset_target_data(target_ulong start, target_ulong last);
-int page_check_range(target_ulong start, target_ulong len, int flags);
+int page_get_flags(vaddr address);
+void page_set_flags(vaddr start, vaddr last, int flags);
+void page_reset_target_data(vaddr start, vaddr last);
+int page_check_range(vaddr start, vaddr len, int flags);
 
 /**
  * page_get_target_data(address)
@@ -235,7 +235,7 @@  int page_check_range(target_ulong start, target_ulong len, int flags);
  * The memory will be freed when the guest page is deallocated,
  * e.g. with the munmap system call.
  */
-void *page_get_target_data(target_ulong address)
+void *page_get_target_data(vaddr address)
     __attribute__((returns_nonnull));
 #endif
 
diff --git a/include/exec/translate-all.h b/include/exec/translate-all.h
index 88602ae8d8..0b9d2e3b32 100644
--- a/include/exec/translate-all.h
+++ b/include/exec/translate-all.h
@@ -28,7 +28,7 @@  void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr);
 
 #ifdef CONFIG_USER_ONLY
 void page_protect(tb_page_addr_t page_addr);
-int page_unprotect(target_ulong address, uintptr_t pc);
+int page_unprotect(vaddr address, uintptr_t pc);
 #endif
 
 #endif /* TRANSLATE_ALL_H */