1 /******************************************************************************
2  * domain.c
3  *
4  */
5 
6 EMIT_FILE;
7 
8 #include <xen/lib.h>
9 #include <xen/sched.h>
10 #include <xen/domain.h>
11 #include <xen/guest_access.h>
12 #include <xen/hypercall.h>
13 #include <compat/vcpu.h>
14 
15 #define xen_vcpu_set_periodic_timer vcpu_set_periodic_timer
16 CHECK_vcpu_set_periodic_timer;
17 #undef xen_vcpu_set_periodic_timer
18 
19 #define xen_vcpu_info vcpu_info
20 CHECK_SIZE_(struct, vcpu_info);
21 #undef xen_vcpu_info
22 
23 #define xen_vcpu_register_vcpu_info vcpu_register_vcpu_info
24 CHECK_vcpu_register_vcpu_info;
25 #undef xen_vcpu_register_vcpu_info
26 
27 #ifdef CONFIG_HVM
28 
29 #include <compat/hvm/hvm_vcpu.h>
30 
31 #define xen_vcpu_hvm_context vcpu_hvm_context
32 #define xen_vcpu_hvm_x86_32 vcpu_hvm_x86_32
33 #define xen_vcpu_hvm_x86_64 vcpu_hvm_x86_64
34 CHECK_vcpu_hvm_context;
35 #undef xen_vcpu_hvm_x86_64
36 #undef xen_vcpu_hvm_x86_32
37 #undef xen_vcpu_hvm_context
38 
39 #endif
40 
compat_common_vcpu_op(int cmd,struct vcpu * v,XEN_GUEST_HANDLE_PARAM (void)arg)41 int compat_common_vcpu_op(int cmd, struct vcpu *v,
42                           XEN_GUEST_HANDLE_PARAM(void) arg)
43 {
44     int rc = 0;
45     struct domain *d = current->domain;
46     unsigned int vcpuid = v->vcpu_id;
47 
48     switch ( cmd )
49     {
50     case VCPUOP_initialise:
51     {
52         if ( is_pv_domain(d) && v->vcpu_info_area.map == &dummy_vcpu_info )
53             return -EINVAL;
54 
55 #ifdef CONFIG_HVM
56         if ( is_hvm_vcpu(v) )
57         {
58             struct vcpu_hvm_context ctxt;
59 
60             if ( copy_from_guest(&ctxt, arg, 1) )
61                 return -EFAULT;
62 
63             domain_lock(d);
64             rc = v->is_initialised ? -EEXIST : arch_set_info_hvm_guest(v, &ctxt);
65             domain_unlock(d);
66         }
67         else
68 #endif
69         {
70             struct compat_vcpu_guest_context *ctxt;
71 
72             if ( (ctxt = xmalloc(struct compat_vcpu_guest_context)) == NULL )
73                 return -ENOMEM;
74 
75             if ( copy_from_guest(ctxt, arg, 1) )
76             {
77                 xfree(ctxt);
78                 return -EFAULT;
79             }
80 
81             domain_lock(d);
82             rc = v->is_initialised ? -EEXIST : arch_set_info_guest(v, ctxt);
83             domain_unlock(d);
84 
85             xfree(ctxt);
86         }
87 
88         if ( rc == -ERESTART )
89             rc = hypercall_create_continuation(__HYPERVISOR_vcpu_op, "iih",
90                                                cmd, vcpuid, arg);
91 
92         break;
93     }
94 
95     case VCPUOP_up:
96     case VCPUOP_down:
97     case VCPUOP_is_up:
98     case VCPUOP_set_periodic_timer:
99     case VCPUOP_stop_periodic_timer:
100     case VCPUOP_stop_singleshot_timer:
101     case VCPUOP_register_vcpu_info:
102         rc = common_vcpu_op(cmd, v, arg);
103         break;
104 
105     case VCPUOP_get_runstate_info:
106     {
107         union {
108             struct vcpu_runstate_info nat;
109             struct compat_vcpu_runstate_info cmp;
110         } runstate;
111 
112         vcpu_runstate_get(v, &runstate.nat);
113         xlat_vcpu_runstate_info(&runstate.nat);
114         if ( copy_to_guest(arg, &runstate.cmp, 1) )
115             rc = -EFAULT;
116         break;
117     }
118 
119     case VCPUOP_set_singleshot_timer:
120     {
121         struct compat_vcpu_set_singleshot_timer cmp;
122         struct vcpu_set_singleshot_timer *nat;
123 
124         if ( copy_from_guest(&cmp, arg, 1) )
125             return -EFAULT;
126         nat = COMPAT_ARG_XLAT_VIRT_BASE;
127         XLAT_vcpu_set_singleshot_timer(nat, &cmp);
128         rc = do_vcpu_op(cmd, vcpuid, guest_handle_from_ptr(nat, void));
129         break;
130     }
131 
132     default:
133         rc = -ENOSYS;
134         break;
135     }
136 
137     return rc;
138 }
139 
140 /*
141  * Local variables:
142  * mode: C
143  * c-file-style: "BSD"
144  * c-basic-offset: 4
145  * tab-width: 4
146  * indent-tabs-mode: nil
147  * End:
148  */
149