diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2021-02-17 11:04:00 +0000 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2021-02-17 11:04:01 +0000 |
| commit | 65d6ae4927d2974bcfe9326c3fdfa0fac5c6295b (patch) | |
| tree | 776b9e34b1d6916a9672b8af112c1c03dc65acad /linux-user/uaccess.c | |
| parent | 18543229fd7a2c79dcd6818c7b1f0f62512b5220 (diff) | |
| parent | 59c7a187dd8bd8ef675768dd8af9de11528ea7e2 (diff) | |
| download | focaccia-qemu-65d6ae4927d2974bcfe9326c3fdfa0fac5c6295b.tar.gz focaccia-qemu-65d6ae4927d2974bcfe9326c3fdfa0fac5c6295b.zip | |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210217' into staging
target-arm queue: * Support ARMv8.5-MemTag for linux-user * ncpm7xx: Support SMBus * MAINTAINERS: add section for Clock framework # gpg: Signature made Wed 17 Feb 2021 11:01:45 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20210217: (37 commits) MAINTAINERS: add myself maintainer for the clock framework hw/i2c: Implement NPCM7XX SMBus Module FIFO Mode hw/i2c: Add a QTest for NPCM7XX SMBus Device hw/arm: Add I2C sensors and EEPROM for GSJ machine hw/arm: Add I2C sensors for NPCM750 eval board hw/i2c: Implement NPCM7XX SMBus Module Single Mode tests/tcg/aarch64: Add mte smoke tests target/arm: Enable MTE for user-only target/arm: Add allocation tag storage for user mode linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault linux-user/aarch64: Pass syndrome to EXC_*_ABORT target/arm: Split out syndrome.h from internals.h linux-user/aarch64: Implement PROT_MTE linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG target/arm: Use the proper TBI settings for linux-user target/arm: Improve gen_top_byte_ignore linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE linux-user: Handle tags in lock_user/unlock_user linux-user: Fix types in uaccess.c ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/uaccess.c')
| -rw-r--r-- | linux-user/uaccess.c | 82 |
1 files changed, 65 insertions, 17 deletions
diff --git a/linux-user/uaccess.c b/linux-user/uaccess.c index e215ecc2a6..c696913016 100644 --- a/linux-user/uaccess.c +++ b/linux-user/uaccess.c @@ -4,46 +4,93 @@ #include "qemu.h" +void *lock_user(int type, abi_ulong guest_addr, size_t len, bool copy) +{ + void *host_addr; + + guest_addr = cpu_untagged_addr(thread_cpu, guest_addr); + if (!access_ok_untagged(type, guest_addr, len)) { + return NULL; + } + host_addr = g2h_untagged(guest_addr); +#ifdef DEBUG_REMAP + if (copy) { + host_addr = g_memdup(host_addr, len); + } else { + host_addr = g_malloc0(len); + } +#endif + return host_addr; +} + +#ifdef DEBUG_REMAP +void unlock_user(void *host_ptr, abi_ulong guest_addr, size_t len); +{ + void *host_ptr_conv; + + if (!host_ptr) { + return; + } + host_ptr_conv = g2h(thread_cpu, guest_addr); + if (host_ptr == host_ptr_conv) { + return; + } + if (len != 0) { + memcpy(host_ptr_conv, host_ptr, len); + } + g_free(host_ptr); +} +#endif + +void *lock_user_string(abi_ulong guest_addr) +{ + ssize_t len = target_strlen(guest_addr); + if (len < 0) { + return NULL; + } + return lock_user(VERIFY_READ, guest_addr, (size_t)len + 1, 1); +} + /* copy_from_user() and copy_to_user() are usually used to copy data * buffers between the target and host. These internally perform * locking/unlocking of the memory. */ -abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len) +int copy_from_user(void *hptr, abi_ulong gaddr, size_t len) { - abi_long ret = 0; - void *ghptr; + int ret = 0; + void *ghptr = lock_user(VERIFY_READ, gaddr, len, 1); - if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) { + if (ghptr) { memcpy(hptr, ghptr, len); unlock_user(ghptr, gaddr, 0); - } else + } else { ret = -TARGET_EFAULT; - + } return ret; } - -abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len) +int copy_to_user(abi_ulong gaddr, void *hptr, size_t len) { - abi_long ret = 0; - void *ghptr; + int ret = 0; + void *ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0); - if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) { + if (ghptr) { memcpy(ghptr, hptr, len); unlock_user(ghptr, gaddr, len); - } else + } else { ret = -TARGET_EFAULT; + } return ret; } /* Return the length of a string in target memory or -TARGET_EFAULT if access error */ -abi_long target_strlen(abi_ulong guest_addr1) +ssize_t target_strlen(abi_ulong guest_addr1) { uint8_t *ptr; abi_ulong guest_addr; - int max_len, len; + size_t max_len, len; guest_addr = guest_addr1; for(;;) { @@ -55,11 +102,12 @@ abi_long target_strlen(abi_ulong guest_addr1) unlock_user(ptr, guest_addr, 0); guest_addr += len; /* we don't allow wrapping or integer overflow */ - if (guest_addr == 0 || - (guest_addr - guest_addr1) > 0x7fffffff) + if (guest_addr == 0 || (guest_addr - guest_addr1) > 0x7fffffff) { return -TARGET_EFAULT; - if (len != max_len) + } + if (len != max_len) { break; + } } return guest_addr - guest_addr1; } |