1 /****************************************************************************** 2 * guest_access.h 3 * 4 * Copyright (c) 2006, K A Fraser 5 */ 6 7 #ifndef __ASM_X86_GUEST_ACCESS_H__ 8 #define __ASM_X86_GUEST_ACCESS_H__ 9 10 #include <asm/uaccess.h> 11 #include <asm/paging.h> 12 #include <asm/hvm/support.h> 13 #include <asm/hvm/guest_access.h> 14 15 /* Raw access functions: no type checking. */ 16 #define raw_copy_to_guest(dst, src, len) \ 17 (is_hvm_vcpu(current) ? \ 18 copy_to_user_hvm((dst), (src), (len)) : \ 19 copy_to_user((dst), (src), (len))) 20 #define raw_copy_from_guest(dst, src, len) \ 21 (is_hvm_vcpu(current) ? \ 22 copy_from_user_hvm((dst), (src), (len)) : \ 23 copy_from_user((dst), (src), (len))) 24 #define raw_clear_guest(dst, len) \ 25 (is_hvm_vcpu(current) ? \ 26 clear_user_hvm((dst), (len)) : \ 27 clear_user((dst), (len))) 28 #define __raw_copy_to_guest(dst, src, len) \ 29 (is_hvm_vcpu(current) ? \ 30 copy_to_user_hvm((dst), (src), (len)) : \ 31 __copy_to_user((dst), (src), (len))) 32 #define __raw_copy_from_guest(dst, src, len) \ 33 (is_hvm_vcpu(current) ? \ 34 copy_from_user_hvm((dst), (src), (len)) : \ 35 __copy_from_user((dst), (src), (len))) 36 #define __raw_clear_guest(dst, len) \ 37 (is_hvm_vcpu(current) ? \ 38 clear_user_hvm((dst), (len)) : \ 39 clear_user((dst), (len))) 40 41 /* Is the guest handle a NULL reference? */ 42 #define guest_handle_is_null(hnd) ((hnd).p == NULL) 43 44 /* Offset the given guest handle into the array it refers to. */ 45 #define guest_handle_add_offset(hnd, nr) ((hnd).p += (nr)) 46 #define guest_handle_subtract_offset(hnd, nr) ((hnd).p -= (nr)) 47 48 /* Cast a guest handle (either XEN_GUEST_HANDLE or XEN_GUEST_HANDLE_PARAM) 49 * to the specified type of XEN_GUEST_HANDLE_PARAM. */ 50 #define guest_handle_cast(hnd, type) ({ \ 51 type *_x = (hnd).p; \ 52 (XEN_GUEST_HANDLE_PARAM(type)) { _x }; \ 53 }) 54 55 /* Convert a XEN_GUEST_HANDLE to XEN_GUEST_HANDLE_PARAM */ 56 #define guest_handle_to_param(hnd, type) ({ \ 57 /* type checking: make sure that the pointers inside \ 58 * XEN_GUEST_HANDLE and XEN_GUEST_HANDLE_PARAM are of \ 59 * the same type, then return hnd */ \ 60 (void)((typeof(&(hnd).p)) 0 == \ 61 (typeof(&((XEN_GUEST_HANDLE_PARAM(type)) {}).p)) 0); \ 62 (hnd); \ 63 }) 64 65 #define guest_handle_for_field(hnd, type, fld) \ 66 ((XEN_GUEST_HANDLE(type)) { &(hnd).p->fld }) 67 68 #define guest_handle_from_ptr(ptr, type) \ 69 ((XEN_GUEST_HANDLE_PARAM(type)) { (type *)ptr }) 70 #define const_guest_handle_from_ptr(ptr, type) \ 71 ((XEN_GUEST_HANDLE_PARAM(const_##type)) { (const type *)ptr }) 72 73 /* 74 * Copy an array of objects to guest context via a guest handle, 75 * specifying an offset into the guest array. 76 */ 77 #define copy_to_guest_offset(hnd, off, ptr, nr) ({ \ 78 const typeof(*(ptr)) *_s = (ptr); \ 79 char (*_d)[sizeof(*_s)] = (void *)(hnd).p; \ 80 /* Check that the handle is not for a const type */ \ 81 void *__maybe_unused _t = (hnd).p; \ 82 (void)((hnd).p == _s); \ 83 raw_copy_to_guest(_d+(off), _s, sizeof(*_s)*(nr)); \ 84 }) 85 86 /* 87 * Copy an array of objects from guest context via a guest handle, 88 * specifying an offset into the guest array. 89 */ 90 #define copy_from_guest_offset(ptr, hnd, off, nr) ({ \ 91 const typeof(*(ptr)) *_s = (hnd).p; \ 92 typeof(*(ptr)) *_d = (ptr); \ 93 raw_copy_from_guest(_d, _s+(off), sizeof(*_d)*(nr));\ 94 }) 95 96 #define clear_guest_offset(hnd, off, nr) ({ \ 97 void *_d = (hnd).p; \ 98 raw_clear_guest(_d+(off), nr); \ 99 }) 100 101 /* Copy sub-field of a structure to guest context via a guest handle. */ 102 #define copy_field_to_guest(hnd, ptr, field) ({ \ 103 const typeof(&(ptr)->field) _s = &(ptr)->field; \ 104 void *_d = &(hnd).p->field; \ 105 (void)(&(hnd).p->field == _s); \ 106 raw_copy_to_guest(_d, _s, sizeof(*_s)); \ 107 }) 108 109 /* Copy sub-field of a structure from guest context via a guest handle. */ 110 #define copy_field_from_guest(ptr, hnd, field) ({ \ 111 const typeof(&(ptr)->field) _s = &(hnd).p->field; \ 112 typeof(&(ptr)->field) _d = &(ptr)->field; \ 113 raw_copy_from_guest(_d, _s, sizeof(*_d)); \ 114 }) 115 116 /* 117 * Pre-validate a guest handle. 118 * Allows use of faster __copy_* functions. 119 */ 120 #define guest_handle_okay(hnd, nr) \ 121 (paging_mode_external(current->domain) || \ 122 array_access_ok((hnd).p, (nr), sizeof(*(hnd).p))) 123 #define guest_handle_subrange_okay(hnd, first, last) \ 124 (paging_mode_external(current->domain) || \ 125 array_access_ok((hnd).p + (first), \ 126 (last)-(first)+1, \ 127 sizeof(*(hnd).p))) 128 129 #define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \ 130 const typeof(*(ptr)) *_s = (ptr); \ 131 char (*_d)[sizeof(*_s)] = (void *)(hnd).p; \ 132 /* Check that the handle is not for a const type */ \ 133 void *__maybe_unused _t = (hnd).p; \ 134 (void)((hnd).p == _s); \ 135 __raw_copy_to_guest(_d+(off), _s, sizeof(*_s)*(nr));\ 136 }) 137 138 #define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \ 139 const typeof(*(ptr)) *_s = (hnd).p; \ 140 typeof(*(ptr)) *_d = (ptr); \ 141 __raw_copy_from_guest(_d, _s+(off), sizeof(*_d)*(nr));\ 142 }) 143 144 #define __clear_guest_offset(hnd, off, nr) ({ \ 145 void *_d = (hnd).p; \ 146 __raw_clear_guest(_d+(off), nr); \ 147 }) 148 149 #define __copy_field_to_guest(hnd, ptr, field) ({ \ 150 const typeof(&(ptr)->field) _s = &(ptr)->field; \ 151 void *_d = &(hnd).p->field; \ 152 (void)(&(hnd).p->field == _s); \ 153 __raw_copy_to_guest(_d, _s, sizeof(*_s)); \ 154 }) 155 156 #define __copy_field_from_guest(ptr, hnd, field) ({ \ 157 const typeof(&(ptr)->field) _s = &(hnd).p->field; \ 158 typeof(&(ptr)->field) _d = &(ptr)->field; \ 159 __raw_copy_from_guest(_d, _s, sizeof(*_d)); \ 160 }) 161 162 #endif /* __ASM_X86_GUEST_ACCESS_H__ */ 163