* [PATCH 0/4] linux-user: shmat/shmdt improvements
@ 2023-08-20 20:44 Richard Henderson
2023-08-20 20:44 ` [PATCH 1/4] linux-user: Move shmat and shmdt implementations to mmap.c Richard Henderson
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Richard Henderson @ 2023-08-20 20:44 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent, imp, kariem.taha2.7
A couple of points I noticed with bsd-user copying linux-user:
(1) Make sure to remap memory for reserved_va
(2) Use something better than an array for tracking shmat.
r~
Richard Henderson (4):
linux-user: Move shmat and shmdt implementations to mmap.c
linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat,shmdt}
linux-user: Fix shmdt
linux-user: Track shm regions with an interval tree
linux-user/user-mmap.h | 4 +
linux-user/mmap.c | 168 +++++++++++++++++++++++++++++++++++++++++
linux-user/syscall.c | 143 +----------------------------------
3 files changed, 176 insertions(+), 139 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/4] linux-user: Move shmat and shmdt implementations to mmap.c
2023-08-20 20:44 [PATCH 0/4] linux-user: shmat/shmdt improvements Richard Henderson
@ 2023-08-20 20:44 ` Richard Henderson
2023-08-21 6:25 ` Philippe Mathieu-Daudé
2023-08-22 16:55 ` Warner Losh
2023-08-20 20:44 ` [PATCH 2/4] linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat, shmdt} Richard Henderson
` (2 subsequent siblings)
3 siblings, 2 replies; 7+ messages in thread
From: Richard Henderson @ 2023-08-20 20:44 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent, imp, kariem.taha2.7
Rename from do_* to target_*. Fix some minor checkpatch errors.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/user-mmap.h | 4 ++
linux-user/mmap.c | 138 +++++++++++++++++++++++++++++++++++++++
linux-user/syscall.c | 143 ++---------------------------------------
3 files changed, 146 insertions(+), 139 deletions(-)
diff --git a/linux-user/user-mmap.h b/linux-user/user-mmap.h
index 0f4883eb57..b94bcdcf83 100644
--- a/linux-user/user-mmap.h
+++ b/linux-user/user-mmap.h
@@ -58,4 +58,8 @@ abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong);
void mmap_fork_start(void);
void mmap_fork_end(int child);
+abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
+ abi_ulong shmaddr, int shmflg);
+abi_long target_shmdt(abi_ulong shmaddr);
+
#endif /* LINUX_USER_USER_MMAP_H */
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 9aab48d4a3..3aeacd1ecd 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -17,6 +17,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
+#include <sys/shm.h>
#include "trace.h"
#include "exec/log.h"
#include "qemu.h"
@@ -27,6 +28,14 @@
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
static __thread int mmap_lock_count;
+#define N_SHM_REGIONS 32
+
+static struct shm_region {
+ abi_ulong start;
+ abi_ulong size;
+ bool in_use;
+} shm_regions[N_SHM_REGIONS];
+
void mmap_lock(void)
{
if (mmap_lock_count++ == 0) {
@@ -981,3 +990,132 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice)
return ret;
}
+
+#ifndef TARGET_FORCE_SHMLBA
+/*
+ * For most architectures, SHMLBA is the same as the page size;
+ * some architectures have larger values, in which case they should
+ * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
+ * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
+ * and defining its own value for SHMLBA.
+ *
+ * The kernel also permits SHMLBA to be set by the architecture to a
+ * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
+ * this means that addresses are rounded to the large size if
+ * SHM_RND is set but addresses not aligned to that size are not rejected
+ * as long as they are at least page-aligned. Since the only architecture
+ * which uses this is ia64 this code doesn't provide for that oddity.
+ */
+static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
+{
+ return TARGET_PAGE_SIZE;
+}
+#endif
+
+abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
+ abi_ulong shmaddr, int shmflg)
+{
+ CPUState *cpu = env_cpu(cpu_env);
+ abi_ulong raddr;
+ void *host_raddr;
+ struct shmid_ds shm_info;
+ int i, ret;
+ abi_ulong shmlba;
+
+ /* shmat pointers are always untagged */
+
+ /* find out the length of the shared memory segment */
+ ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
+ if (is_error(ret)) {
+ /* can't get length, bail out */
+ return ret;
+ }
+
+ shmlba = target_shmlba(cpu_env);
+
+ if (shmaddr & (shmlba - 1)) {
+ if (shmflg & SHM_RND) {
+ shmaddr &= ~(shmlba - 1);
+ } else {
+ return -TARGET_EINVAL;
+ }
+ }
+ if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
+ return -TARGET_EINVAL;
+ }
+
+ mmap_lock();
+
+ /*
+ * We're mapping shared memory, so ensure we generate code for parallel
+ * execution and flush old translations. This will work up to the level
+ * supported by the host -- anything that requires EXCP_ATOMIC will not
+ * be atomic with respect to an external process.
+ */
+ if (!(cpu->tcg_cflags & CF_PARALLEL)) {
+ cpu->tcg_cflags |= CF_PARALLEL;
+ tb_flush(cpu);
+ }
+
+ if (shmaddr) {
+ host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
+ } else {
+ abi_ulong mmap_start;
+
+ /* In order to use the host shmat, we need to honor host SHMLBA. */
+ mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
+
+ if (mmap_start == -1) {
+ errno = ENOMEM;
+ host_raddr = (void *)-1;
+ } else {
+ host_raddr = shmat(shmid, g2h_untagged(mmap_start),
+ shmflg | SHM_REMAP);
+ }
+ }
+
+ if (host_raddr == (void *)-1) {
+ mmap_unlock();
+ return get_errno((intptr_t)host_raddr);
+ }
+ raddr = h2g((uintptr_t)host_raddr);
+
+ page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
+ PAGE_VALID | PAGE_RESET | PAGE_READ |
+ (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
+
+ for (i = 0; i < N_SHM_REGIONS; i++) {
+ if (!shm_regions[i].in_use) {
+ shm_regions[i].in_use = true;
+ shm_regions[i].start = raddr;
+ shm_regions[i].size = shm_info.shm_segsz;
+ break;
+ }
+ }
+
+ mmap_unlock();
+ return raddr;
+}
+
+abi_long target_shmdt(abi_ulong shmaddr)
+{
+ int i;
+ abi_long rv;
+
+ /* shmdt pointers are always untagged */
+
+ mmap_lock();
+
+ for (i = 0; i < N_SHM_REGIONS; ++i) {
+ if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
+ shm_regions[i].in_use = false;
+ page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
+ break;
+ }
+ }
+ rv = get_errno(shmdt(g2h_untagged(shmaddr)));
+
+ mmap_unlock();
+
+ return rv;
+}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9353268cc1..df001469eb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -3725,14 +3725,6 @@ static abi_long do_socketcall(int num, abi_ulong vptr)
}
#endif
-#define N_SHM_REGIONS 32
-
-static struct shm_region {
- abi_ulong start;
- abi_ulong size;
- bool in_use;
-} shm_regions[N_SHM_REGIONS];
-
#ifndef TARGET_SEMID64_DS
/* asm-generic version of this struct */
struct target_semid64_ds
@@ -4482,133 +4474,6 @@ static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
return ret;
}
-#ifndef TARGET_FORCE_SHMLBA
-/* For most architectures, SHMLBA is the same as the page size;
- * some architectures have larger values, in which case they should
- * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
- * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
- * and defining its own value for SHMLBA.
- *
- * The kernel also permits SHMLBA to be set by the architecture to a
- * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
- * this means that addresses are rounded to the large size if
- * SHM_RND is set but addresses not aligned to that size are not rejected
- * as long as they are at least page-aligned. Since the only architecture
- * which uses this is ia64 this code doesn't provide for that oddity.
- */
-static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
-{
- return TARGET_PAGE_SIZE;
-}
-#endif
-
-static abi_ulong do_shmat(CPUArchState *cpu_env, int shmid,
- abi_ulong shmaddr, int shmflg)
-{
- CPUState *cpu = env_cpu(cpu_env);
- abi_ulong raddr;
- void *host_raddr;
- struct shmid_ds shm_info;
- int i, ret;
- abi_ulong shmlba;
-
- /* shmat pointers are always untagged */
-
- /* find out the length of the shared memory segment */
- ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
- if (is_error(ret)) {
- /* can't get length, bail out */
- return ret;
- }
-
- shmlba = target_shmlba(cpu_env);
-
- if (shmaddr & (shmlba - 1)) {
- if (shmflg & SHM_RND) {
- shmaddr &= ~(shmlba - 1);
- } else {
- return -TARGET_EINVAL;
- }
- }
- if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
- return -TARGET_EINVAL;
- }
-
- mmap_lock();
-
- /*
- * We're mapping shared memory, so ensure we generate code for parallel
- * execution and flush old translations. This will work up to the level
- * supported by the host -- anything that requires EXCP_ATOMIC will not
- * be atomic with respect to an external process.
- */
- if (!(cpu->tcg_cflags & CF_PARALLEL)) {
- cpu->tcg_cflags |= CF_PARALLEL;
- tb_flush(cpu);
- }
-
- if (shmaddr)
- host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
- else {
- abi_ulong mmap_start;
-
- /* In order to use the host shmat, we need to honor host SHMLBA. */
- mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
-
- if (mmap_start == -1) {
- errno = ENOMEM;
- host_raddr = (void *)-1;
- } else
- host_raddr = shmat(shmid, g2h_untagged(mmap_start),
- shmflg | SHM_REMAP);
- }
-
- if (host_raddr == (void *)-1) {
- mmap_unlock();
- return get_errno((intptr_t)host_raddr);
- }
- raddr = h2g((uintptr_t)host_raddr);
-
- page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
- PAGE_VALID | PAGE_RESET | PAGE_READ |
- (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
-
- for (i = 0; i < N_SHM_REGIONS; i++) {
- if (!shm_regions[i].in_use) {
- shm_regions[i].in_use = true;
- shm_regions[i].start = raddr;
- shm_regions[i].size = shm_info.shm_segsz;
- break;
- }
- }
-
- mmap_unlock();
- return raddr;
-}
-
-static inline abi_long do_shmdt(abi_ulong shmaddr)
-{
- int i;
- abi_long rv;
-
- /* shmdt pointers are always untagged */
-
- mmap_lock();
-
- for (i = 0; i < N_SHM_REGIONS; ++i) {
- if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
- shm_regions[i].in_use = false;
- page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
- break;
- }
- }
- rv = get_errno(shmdt(g2h_untagged(shmaddr)));
-
- mmap_unlock();
-
- return rv;
-}
-
#ifdef TARGET_NR_ipc
/* ??? This only works with linear mappings. */
/* do_ipc() must return target values and target errnos. */
@@ -4695,7 +4560,7 @@ static abi_long do_ipc(CPUArchState *cpu_env,
default:
{
abi_ulong raddr;
- raddr = do_shmat(cpu_env, first, ptr, second);
+ raddr = target_shmat(cpu_env, first, ptr, second);
if (is_error(raddr))
return get_errno(raddr);
if (put_user_ual(raddr, third))
@@ -4708,7 +4573,7 @@ static abi_long do_ipc(CPUArchState *cpu_env,
}
break;
case IPCOP_shmdt:
- ret = do_shmdt(ptr);
+ ret = target_shmdt(ptr);
break;
case IPCOP_shmget:
@@ -11129,11 +10994,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_shmat
case TARGET_NR_shmat:
- return do_shmat(cpu_env, arg1, arg2, arg3);
+ return target_shmat(cpu_env, arg1, arg2, arg3);
#endif
#ifdef TARGET_NR_shmdt
case TARGET_NR_shmdt:
- return do_shmdt(arg1);
+ return target_shmdt(arg1);
#endif
case TARGET_NR_fsync:
return get_errno(fsync(arg1));
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/4] linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat, shmdt}
2023-08-20 20:44 [PATCH 0/4] linux-user: shmat/shmdt improvements Richard Henderson
2023-08-20 20:44 ` [PATCH 1/4] linux-user: Move shmat and shmdt implementations to mmap.c Richard Henderson
@ 2023-08-20 20:44 ` Richard Henderson
2023-08-20 20:44 ` [PATCH 3/4] linux-user: Fix shmdt Richard Henderson
2023-08-20 20:44 ` [PATCH 4/4] linux-user: Track shm regions with an interval tree Richard Henderson
3 siblings, 0 replies; 7+ messages in thread
From: Richard Henderson @ 2023-08-20 20:44 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent, imp, kariem.taha2.7
Move the CF_PARALLEL setting outside of the mmap lock.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/mmap.c | 98 ++++++++++++++++++++++-------------------------
1 file changed, 46 insertions(+), 52 deletions(-)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 3aeacd1ecd..f45b2d307c 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1017,9 +1017,8 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
{
CPUState *cpu = env_cpu(cpu_env);
abi_ulong raddr;
- void *host_raddr;
struct shmid_ds shm_info;
- int i, ret;
+ int ret;
abi_ulong shmlba;
/* shmat pointers are always untagged */
@@ -1044,7 +1043,43 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
return -TARGET_EINVAL;
}
- mmap_lock();
+ WITH_MMAP_LOCK_GUARD() {
+ void *host_raddr;
+
+ if (shmaddr) {
+ host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
+ } else {
+ abi_ulong mmap_start;
+
+ /* In order to use the host shmat, we need to honor host SHMLBA. */
+ mmap_start = mmap_find_vma(0, shm_info.shm_segsz,
+ MAX(SHMLBA, shmlba));
+
+ if (mmap_start == -1) {
+ return -TARGET_ENOMEM;
+ }
+ host_raddr = shmat(shmid, g2h_untagged(mmap_start),
+ shmflg | SHM_REMAP);
+ }
+
+ if (host_raddr == (void *)-1) {
+ return get_errno(-1);
+ }
+ raddr = h2g(host_raddr);
+
+ page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
+ PAGE_VALID | PAGE_RESET | PAGE_READ |
+ (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
+
+ for (int i = 0; i < N_SHM_REGIONS; i++) {
+ if (!shm_regions[i].in_use) {
+ shm_regions[i].in_use = true;
+ shm_regions[i].start = raddr;
+ shm_regions[i].size = shm_info.shm_segsz;
+ break;
+ }
+ }
+ }
/*
* We're mapping shared memory, so ensure we generate code for parallel
@@ -1057,65 +1092,24 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
tb_flush(cpu);
}
- if (shmaddr) {
- host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
- } else {
- abi_ulong mmap_start;
-
- /* In order to use the host shmat, we need to honor host SHMLBA. */
- mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
-
- if (mmap_start == -1) {
- errno = ENOMEM;
- host_raddr = (void *)-1;
- } else {
- host_raddr = shmat(shmid, g2h_untagged(mmap_start),
- shmflg | SHM_REMAP);
- }
- }
-
- if (host_raddr == (void *)-1) {
- mmap_unlock();
- return get_errno((intptr_t)host_raddr);
- }
- raddr = h2g((uintptr_t)host_raddr);
-
- page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
- PAGE_VALID | PAGE_RESET | PAGE_READ |
- (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
-
- for (i = 0; i < N_SHM_REGIONS; i++) {
- if (!shm_regions[i].in_use) {
- shm_regions[i].in_use = true;
- shm_regions[i].start = raddr;
- shm_regions[i].size = shm_info.shm_segsz;
- break;
- }
- }
-
- mmap_unlock();
return raddr;
}
abi_long target_shmdt(abi_ulong shmaddr)
{
- int i;
abi_long rv;
/* shmdt pointers are always untagged */
- mmap_lock();
-
- for (i = 0; i < N_SHM_REGIONS; ++i) {
- if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
- shm_regions[i].in_use = false;
- page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
- break;
+ WITH_MMAP_LOCK_GUARD() {
+ for (int i = 0; i < N_SHM_REGIONS; ++i) {
+ if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
+ shm_regions[i].in_use = false;
+ page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
+ break;
+ }
}
+ rv = get_errno(shmdt(g2h_untagged(shmaddr)));
}
- rv = get_errno(shmdt(g2h_untagged(shmaddr)));
-
- mmap_unlock();
-
return rv;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/4] linux-user: Fix shmdt
2023-08-20 20:44 [PATCH 0/4] linux-user: shmat/shmdt improvements Richard Henderson
2023-08-20 20:44 ` [PATCH 1/4] linux-user: Move shmat and shmdt implementations to mmap.c Richard Henderson
2023-08-20 20:44 ` [PATCH 2/4] linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat, shmdt} Richard Henderson
@ 2023-08-20 20:44 ` Richard Henderson
2023-08-20 20:44 ` [PATCH 4/4] linux-user: Track shm regions with an interval tree Richard Henderson
3 siblings, 0 replies; 7+ messages in thread
From: Richard Henderson @ 2023-08-20 20:44 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent, imp, kariem.taha2.7
If the shm region is not mapped at shmaddr, EINVAL.
Do not unmap the region until the syscall succeeds.
Use mmap_reserve_or_unmap to preserve reserved_va semantics.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/mmap.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index f45b2d307c..44116c014b 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -1102,14 +1102,25 @@ abi_long target_shmdt(abi_ulong shmaddr)
/* shmdt pointers are always untagged */
WITH_MMAP_LOCK_GUARD() {
- for (int i = 0; i < N_SHM_REGIONS; ++i) {
+ int i;
+
+ for (i = 0; i < N_SHM_REGIONS; ++i) {
if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
- shm_regions[i].in_use = false;
- page_set_flags(shmaddr, shmaddr + shm_regions[i].size - 1, 0);
break;
}
}
+ if (i == N_SHM_REGIONS) {
+ return -TARGET_EINVAL;
+ }
+
rv = get_errno(shmdt(g2h_untagged(shmaddr)));
+ if (rv == 0) {
+ abi_ulong size = shm_regions[i].size;
+
+ shm_regions[i].in_use = false;
+ page_set_flags(shmaddr, shmaddr + size - 1, 0);
+ mmap_reserve_or_unmap(shmaddr, size);
+ }
}
return rv;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/4] linux-user: Track shm regions with an interval tree
2023-08-20 20:44 [PATCH 0/4] linux-user: shmat/shmdt improvements Richard Henderson
` (2 preceding siblings ...)
2023-08-20 20:44 ` [PATCH 3/4] linux-user: Fix shmdt Richard Henderson
@ 2023-08-20 20:44 ` Richard Henderson
3 siblings, 0 replies; 7+ messages in thread
From: Richard Henderson @ 2023-08-20 20:44 UTC (permalink / raw)
To: qemu-devel; +Cc: laurent, imp, kariem.taha2.7
Remove the fixed size shm_regions[] array.
Remove references when other mappings completely remove
or replace a region.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
linux-user/mmap.c | 81 +++++++++++++++++++++++++++++++----------------
1 file changed, 53 insertions(+), 28 deletions(-)
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 44116c014b..8eaf57b208 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -24,18 +24,11 @@
#include "user-internals.h"
#include "user-mmap.h"
#include "target_mman.h"
+#include "qemu/interval-tree.h"
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
static __thread int mmap_lock_count;
-#define N_SHM_REGIONS 32
-
-static struct shm_region {
- abi_ulong start;
- abi_ulong size;
- bool in_use;
-} shm_regions[N_SHM_REGIONS];
-
void mmap_lock(void)
{
if (mmap_lock_count++ == 0) {
@@ -73,6 +66,44 @@ void mmap_fork_end(int child)
}
}
+/* Protected by mmap_lock. */
+static IntervalTreeRoot shm_regions;
+
+static void shm_region_add(abi_ptr start, abi_ptr last)
+{
+ IntervalTreeNode *i = g_new0(IntervalTreeNode, 1);
+
+ i->start = start;
+ i->last = last;
+ interval_tree_insert(i, &shm_regions);
+}
+
+static abi_ptr shm_region_find(abi_ptr start)
+{
+ IntervalTreeNode *i;
+
+ for (i = interval_tree_iter_first(&shm_regions, start, start); i;
+ i = interval_tree_iter_next(i, start, start)) {
+ if (i->start == start) {
+ return i->last;
+ }
+ }
+ return 0;
+}
+
+static void shm_region_rm_complete(abi_ptr start, abi_ptr last)
+{
+ IntervalTreeNode *i, *n;
+
+ for (i = interval_tree_iter_first(&shm_regions, start, last); i; i = n) {
+ n = interval_tree_iter_next(i, start, last);
+ if (i->start >= start && i->last <= last) {
+ interval_tree_remove(i, &shm_regions);
+ g_free(i);
+ }
+ }
+}
+
/*
* Validate target prot bitmask.
* Return the prot bitmask for the host in *HOST_PROT.
@@ -729,6 +760,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
page_set_flags(passthrough_last + 1, last, page_flags);
}
}
+ shm_region_rm_complete(start, last);
the_end:
trace_target_mmap_complete(start);
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
@@ -826,6 +858,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
mmap_lock();
mmap_reserve_or_unmap(start, len);
page_set_flags(start, start + len - 1, 0);
+ shm_region_rm_complete(start, start + len - 1);
mmap_unlock();
return 0;
@@ -915,8 +948,10 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
new_addr = h2g(host_addr);
prot = page_get_flags(old_addr);
page_set_flags(old_addr, old_addr + old_size - 1, 0);
+ shm_region_rm_complete(old_addr, old_addr + old_size - 1);
page_set_flags(new_addr, new_addr + new_size - 1,
prot | PAGE_VALID | PAGE_RESET);
+ shm_region_rm_complete(new_addr, new_addr + new_size - 1);
}
mmap_unlock();
return new_addr;
@@ -1045,6 +1080,7 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
WITH_MMAP_LOCK_GUARD() {
void *host_raddr;
+ abi_ulong last;
if (shmaddr) {
host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
@@ -1066,19 +1102,14 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid,
return get_errno(-1);
}
raddr = h2g(host_raddr);
+ last = raddr + shm_info.shm_segsz - 1;
- page_set_flags(raddr, raddr + shm_info.shm_segsz - 1,
+ page_set_flags(raddr, last,
PAGE_VALID | PAGE_RESET | PAGE_READ |
(shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
- for (int i = 0; i < N_SHM_REGIONS; i++) {
- if (!shm_regions[i].in_use) {
- shm_regions[i].in_use = true;
- shm_regions[i].start = raddr;
- shm_regions[i].size = shm_info.shm_segsz;
- break;
- }
- }
+ shm_region_rm_complete(raddr, last);
+ shm_region_add(raddr, last);
}
/*
@@ -1102,23 +1133,17 @@ abi_long target_shmdt(abi_ulong shmaddr)
/* shmdt pointers are always untagged */
WITH_MMAP_LOCK_GUARD() {
- int i;
-
- for (i = 0; i < N_SHM_REGIONS; ++i) {
- if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
- break;
- }
- }
- if (i == N_SHM_REGIONS) {
+ abi_ulong last = shm_region_find(shmaddr);
+ if (last == 0) {
return -TARGET_EINVAL;
}
rv = get_errno(shmdt(g2h_untagged(shmaddr)));
if (rv == 0) {
- abi_ulong size = shm_regions[i].size;
+ abi_ulong size = last - shmaddr + 1;
- shm_regions[i].in_use = false;
- page_set_flags(shmaddr, shmaddr + size - 1, 0);
+ page_set_flags(shmaddr, last, 0);
+ shm_region_rm_complete(shmaddr, last);
mmap_reserve_or_unmap(shmaddr, size);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/4] linux-user: Move shmat and shmdt implementations to mmap.c
2023-08-20 20:44 ` [PATCH 1/4] linux-user: Move shmat and shmdt implementations to mmap.c Richard Henderson
@ 2023-08-21 6:25 ` Philippe Mathieu-Daudé
2023-08-22 16:55 ` Warner Losh
1 sibling, 0 replies; 7+ messages in thread
From: Philippe Mathieu-Daudé @ 2023-08-21 6:25 UTC (permalink / raw)
To: Richard Henderson, qemu-devel; +Cc: laurent, imp, kariem.taha2.7
On 20/8/23 22:44, Richard Henderson wrote:
> Rename from do_* to target_*. Fix some minor checkpatch errors.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/user-mmap.h | 4 ++
> linux-user/mmap.c | 138 +++++++++++++++++++++++++++++++++++++++
> linux-user/syscall.c | 143 ++---------------------------------------
> 3 files changed, 146 insertions(+), 139 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/4] linux-user: Move shmat and shmdt implementations to mmap.c
2023-08-20 20:44 ` [PATCH 1/4] linux-user: Move shmat and shmdt implementations to mmap.c Richard Henderson
2023-08-21 6:25 ` Philippe Mathieu-Daudé
@ 2023-08-22 16:55 ` Warner Losh
1 sibling, 0 replies; 7+ messages in thread
From: Warner Losh @ 2023-08-22 16:55 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, laurent, kariem.taha2.7
[-- Attachment #1: Type: text/plain, Size: 529 bytes --]
On Sun, Aug 20, 2023 at 2:44 PM Richard Henderson <
richard.henderson@linaro.org> wrote:
> Rename from do_* to target_*. Fix some minor checkpatch errors.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> linux-user/user-mmap.h | 4 ++
> linux-user/mmap.c | 138 +++++++++++++++++++++++++++++++++++++++
> linux-user/syscall.c | 143 ++---------------------------------------
> 3 files changed, 146 insertions(+), 139 deletions(-)
>
Reviewed-by: Warner Losh <imp@bsdimp.com>
[-- Attachment #2: Type: text/html, Size: 1004 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-08-22 16:56 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-20 20:44 [PATCH 0/4] linux-user: shmat/shmdt improvements Richard Henderson
2023-08-20 20:44 ` [PATCH 1/4] linux-user: Move shmat and shmdt implementations to mmap.c Richard Henderson
2023-08-21 6:25 ` Philippe Mathieu-Daudé
2023-08-22 16:55 ` Warner Losh
2023-08-20 20:44 ` [PATCH 2/4] linux-user: Use WITH_MMAP_LOCK_GUARD in target_{shmat, shmdt} Richard Henderson
2023-08-20 20:44 ` [PATCH 3/4] linux-user: Fix shmdt Richard Henderson
2023-08-20 20:44 ` [PATCH 4/4] linux-user: Track shm regions with an interval tree Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).