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 /* Cast 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 /* Cast a XEN_GUEST_HANDLE_PARAM to XEN_GUEST_HANDLE */ 66 #define guest_handle_from_param(hnd, type) ({ \ 67 /* type checking: make sure that the pointers inside \ 68 * XEN_GUEST_HANDLE and XEN_GUEST_HANDLE_PARAM are of \ 69 * the same type, then return hnd */ \ 70 (void)((typeof(&(hnd).p)) 0 == \ 71 (typeof(&((XEN_GUEST_HANDLE_PARAM(type)) {}).p)) 0); \ 72 (hnd); \ 73 }) 74 75 #define guest_handle_for_field(hnd, type, fld) \ 76 ((XEN_GUEST_HANDLE(type)) { &(hnd).p->fld }) 77 78 #define guest_handle_from_ptr(ptr, type) \ 79 ((XEN_GUEST_HANDLE_PARAM(type)) { (type *)ptr }) 80 #define const_guest_handle_from_ptr(ptr, type) \ 81 ((XEN_GUEST_HANDLE_PARAM(const_##type)) { (const type *)ptr }) 82 83 /* 84 * Copy an array of objects to guest context via a guest handle, 85 * specifying an offset into the guest array. 86 */ 87 #define copy_to_guest_offset(hnd, off, ptr, nr) ({ \ 88 const typeof(*(ptr)) *_s = (ptr); \ 89 char (*_d)[sizeof(*_s)] = (void *)(hnd).p; \ 90 ((void)((hnd).p == (ptr))); \ 91 raw_copy_to_guest(_d+(off), _s, sizeof(*_s)*(nr)); \ 92 }) 93 94 /* 95 * Copy an array of objects from guest context via a guest handle, 96 * specifying an offset into the guest array. 97 */ 98 #define copy_from_guest_offset(ptr, hnd, off, nr) ({ \ 99 const typeof(*(ptr)) *_s = (hnd).p; \ 100 typeof(*(ptr)) *_d = (ptr); \ 101 raw_copy_from_guest(_d, _s+(off), sizeof(*_d)*(nr));\ 102 }) 103 104 #define clear_guest_offset(hnd, off, nr) ({ \ 105 void *_d = (hnd).p; \ 106 raw_clear_guest(_d+(off), nr); \ 107 }) 108 109 /* Copy sub-field of a structure to guest context via a guest handle. */ 110 #define copy_field_to_guest(hnd, ptr, field) ({ \ 111 const typeof(&(ptr)->field) _s = &(ptr)->field; \ 112 void *_d = &(hnd).p->field; \ 113 ((void)(&(hnd).p->field == &(ptr)->field)); \ 114 raw_copy_to_guest(_d, _s, sizeof(*_s)); \ 115 }) 116 117 /* Copy sub-field of a structure from guest context via a guest handle. */ 118 #define copy_field_from_guest(ptr, hnd, field) ({ \ 119 const typeof(&(ptr)->field) _s = &(hnd).p->field; \ 120 typeof(&(ptr)->field) _d = &(ptr)->field; \ 121 raw_copy_from_guest(_d, _s, sizeof(*_d)); \ 122 }) 123 124 /* 125 * Pre-validate a guest handle. 126 * Allows use of faster __copy_* functions. 127 */ 128 #define guest_handle_okay(hnd, nr) \ 129 (paging_mode_external(current->domain) || \ 130 array_access_ok((hnd).p, (nr), sizeof(*(hnd).p))) 131 #define guest_handle_subrange_okay(hnd, first, last) \ 132 (paging_mode_external(current->domain) || \ 133 array_access_ok((hnd).p + (first), \ 134 (last)-(first)+1, \ 135 sizeof(*(hnd).p))) 136 137 #define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \ 138 const typeof(*(ptr)) *_s = (ptr); \ 139 char (*_d)[sizeof(*_s)] = (void *)(hnd).p; \ 140 ((void)((hnd).p == (ptr))); \ 141 __raw_copy_to_guest(_d+(off), _s, sizeof(*_s)*(nr));\ 142 }) 143 144 #define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \ 145 const typeof(*(ptr)) *_s = (hnd).p; \ 146 typeof(*(ptr)) *_d = (ptr); \ 147 __raw_copy_from_guest(_d, _s+(off), sizeof(*_d)*(nr));\ 148 }) 149 150 #define __clear_guest_offset(hnd, off, nr) ({ \ 151 void *_d = (hnd).p; \ 152 __raw_clear_guest(_d+(off), nr); \ 153 }) 154 155 #define __copy_field_to_guest(hnd, ptr, field) ({ \ 156 const typeof(&(ptr)->field) _s = &(ptr)->field; \ 157 void *_d = &(hnd).p->field; \ 158 ((void)(&(hnd).p->field == &(ptr)->field)); \ 159 __raw_copy_to_guest(_d, _s, sizeof(*_s)); \ 160 }) 161 162 #define __copy_field_from_guest(ptr, hnd, field) ({ \ 163 const typeof(&(ptr)->field) _s = &(hnd).p->field; \ 164 typeof(&(ptr)->field) _d = &(ptr)->field; \ 165 __raw_copy_from_guest(_d, _s, sizeof(*_d)); \ 166 }) 167 168 #endif /* __ASM_X86_GUEST_ACCESS_H__ */ 169