2
0

uaccess.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * Helper routines to provide target memory access for semihosting
  3. * syscalls in system emulation mode.
  4. *
  5. * Copyright (c) 2007 CodeSourcery.
  6. *
  7. * This code is licensed under the GPL
  8. */
  9. #include "qemu/osdep.h"
  10. #include "exec/exec-all.h"
  11. #include "semihosting/softmmu-uaccess.h"
  12. void *softmmu_lock_user(CPUArchState *env, target_ulong addr,
  13. target_ulong len, bool copy)
  14. {
  15. void *p = malloc(len);
  16. if (p && copy) {
  17. if (cpu_memory_rw_debug(env_cpu(env), addr, p, len, 0)) {
  18. free(p);
  19. p = NULL;
  20. }
  21. }
  22. return p;
  23. }
  24. ssize_t softmmu_strlen_user(CPUArchState *env, target_ulong addr)
  25. {
  26. int mmu_idx = cpu_mmu_index(env, false);
  27. size_t len = 0;
  28. while (1) {
  29. size_t left_in_page;
  30. int flags;
  31. void *h;
  32. /* Find the number of bytes remaining in the page. */
  33. left_in_page = TARGET_PAGE_SIZE - (addr & ~TARGET_PAGE_MASK);
  34. flags = probe_access_flags(env, addr, 0, MMU_DATA_LOAD,
  35. mmu_idx, true, &h, 0);
  36. if (flags & TLB_INVALID_MASK) {
  37. return -1;
  38. }
  39. if (flags & TLB_MMIO) {
  40. do {
  41. uint8_t c;
  42. if (cpu_memory_rw_debug(env_cpu(env), addr, &c, 1, 0)) {
  43. return -1;
  44. }
  45. if (c == 0) {
  46. return len;
  47. }
  48. addr++;
  49. len++;
  50. if (len > INT32_MAX) {
  51. return -1;
  52. }
  53. } while (--left_in_page != 0);
  54. } else {
  55. char *p = memchr(h, 0, left_in_page);
  56. if (p) {
  57. len += p - (char *)h;
  58. return len <= INT32_MAX ? (ssize_t)len : -1;
  59. }
  60. addr += left_in_page;
  61. len += left_in_page;
  62. if (len > INT32_MAX) {
  63. return -1;
  64. }
  65. }
  66. }
  67. }
  68. char *softmmu_lock_user_string(CPUArchState *env, target_ulong addr)
  69. {
  70. ssize_t len = softmmu_strlen_user(env, addr);
  71. if (len < 0) {
  72. return NULL;
  73. }
  74. return softmmu_lock_user(env, addr, len + 1, true);
  75. }
  76. void softmmu_unlock_user(CPUArchState *env, void *p,
  77. target_ulong addr, target_ulong len)
  78. {
  79. if (len) {
  80. cpu_memory_rw_debug(env_cpu(env), addr, p, len, 1);
  81. }
  82. free(p);
  83. }