gaccess.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * access guest memory
  3. *
  4. * Copyright IBM Corp. 2008, 2009
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License (version 2 only)
  8. * as published by the Free Software Foundation.
  9. *
  10. * Author(s): Carsten Otte <cotte@de.ibm.com>
  11. */
  12. #ifndef __KVM_S390_GACCESS_H
  13. #define __KVM_S390_GACCESS_H
  14. #include <linux/compiler.h>
  15. #include <linux/kvm_host.h>
  16. #include <asm/uaccess.h>
  17. #include "kvm-s390.h"
  18. static inline void __user *__gptr_to_uptr(struct kvm_vcpu *vcpu,
  19. void __user *gptr,
  20. int prefixing)
  21. {
  22. unsigned long prefix = vcpu->arch.sie_block->prefix;
  23. unsigned long gaddr = (unsigned long) gptr;
  24. unsigned long uaddr;
  25. if (prefixing) {
  26. if (gaddr < 2 * PAGE_SIZE)
  27. gaddr += prefix;
  28. else if ((gaddr >= prefix) && (gaddr < prefix + 2 * PAGE_SIZE))
  29. gaddr -= prefix;
  30. }
  31. uaddr = gmap_fault(gaddr, vcpu->arch.gmap);
  32. if (IS_ERR_VALUE(uaddr))
  33. uaddr = -EFAULT;
  34. return (void __user *)uaddr;
  35. }
  36. #define get_guest(vcpu, x, gptr) \
  37. ({ \
  38. __typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\
  39. int __mask = sizeof(__typeof__(*(gptr))) - 1; \
  40. int __ret = PTR_RET((void __force *)__uptr); \
  41. \
  42. if (!__ret) { \
  43. BUG_ON((unsigned long)__uptr & __mask); \
  44. __ret = get_user(x, __uptr); \
  45. } \
  46. __ret; \
  47. })
  48. #define put_guest(vcpu, x, gptr) \
  49. ({ \
  50. __typeof__(gptr) __uptr = __gptr_to_uptr(vcpu, gptr, 1);\
  51. int __mask = sizeof(__typeof__(*(gptr))) - 1; \
  52. int __ret = PTR_RET((void __force *)__uptr); \
  53. \
  54. if (!__ret) { \
  55. BUG_ON((unsigned long)__uptr & __mask); \
  56. __ret = put_user(x, __uptr); \
  57. } \
  58. __ret; \
  59. })
  60. static inline int __copy_guest(struct kvm_vcpu *vcpu, unsigned long to,
  61. unsigned long from, unsigned long len,
  62. int to_guest, int prefixing)
  63. {
  64. unsigned long _len, rc;
  65. void __user *uptr;
  66. while (len) {
  67. uptr = to_guest ? (void __user *)to : (void __user *)from;
  68. uptr = __gptr_to_uptr(vcpu, uptr, prefixing);
  69. if (IS_ERR((void __force *)uptr))
  70. return -EFAULT;
  71. _len = PAGE_SIZE - ((unsigned long)uptr & (PAGE_SIZE - 1));
  72. _len = min(_len, len);
  73. if (to_guest)
  74. rc = copy_to_user((void __user *) uptr, (void *)from, _len);
  75. else
  76. rc = copy_from_user((void *)to, (void __user *)uptr, _len);
  77. if (rc)
  78. return -EFAULT;
  79. len -= _len;
  80. from += _len;
  81. to += _len;
  82. }
  83. return 0;
  84. }
  85. #define copy_to_guest(vcpu, to, from, size) \
  86. __copy_guest(vcpu, to, (unsigned long)from, size, 1, 1)
  87. #define copy_from_guest(vcpu, to, from, size) \
  88. __copy_guest(vcpu, (unsigned long)to, from, size, 0, 1)
  89. #define copy_to_guest_absolute(vcpu, to, from, size) \
  90. __copy_guest(vcpu, to, (unsigned long)from, size, 1, 0)
  91. #define copy_from_guest_absolute(vcpu, to, from, size) \
  92. __copy_guest(vcpu, (unsigned long)to, from, size, 0, 0)
  93. #endif /* __KVM_S390_GACCESS_H */