1 #include "xc_sr_common_x86.h"
2 
write_x86_tsc_info(struct xc_sr_context * ctx)3 int write_x86_tsc_info(struct xc_sr_context *ctx)
4 {
5     xc_interface *xch = ctx->xch;
6     struct xc_sr_rec_x86_tsc_info tsc = {};
7     struct xc_sr_record rec = {
8         .type = REC_TYPE_X86_TSC_INFO,
9         .length = sizeof(tsc),
10         .data = &tsc,
11     };
12 
13     if ( xc_domain_get_tsc_info(xch, ctx->domid, &tsc.mode,
14                                 &tsc.nsec, &tsc.khz, &tsc.incarnation) < 0 )
15     {
16         PERROR("Unable to obtain TSC information");
17         return -1;
18     }
19 
20     return write_record(ctx, &rec);
21 }
22 
handle_x86_tsc_info(struct xc_sr_context * ctx,struct xc_sr_record * rec)23 int handle_x86_tsc_info(struct xc_sr_context *ctx, struct xc_sr_record *rec)
24 {
25     xc_interface *xch = ctx->xch;
26     struct xc_sr_rec_x86_tsc_info *tsc = rec->data;
27 
28     if ( rec->length != sizeof(*tsc) )
29     {
30         ERROR("X86_TSC_INFO record wrong size: length %u, expected %zu",
31               rec->length, sizeof(*tsc));
32         return -1;
33     }
34 
35     if ( xc_domain_set_tsc_info(xch, ctx->domid, tsc->mode,
36                                 tsc->nsec, tsc->khz, tsc->incarnation) )
37     {
38         PERROR("Unable to set TSC information");
39         return -1;
40     }
41 
42     return 0;
43 }
44 
write_x86_cpu_policy_records(struct xc_sr_context * ctx)45 int write_x86_cpu_policy_records(struct xc_sr_context *ctx)
46 {
47     xc_interface *xch = ctx->xch;
48     struct xc_sr_record cpuid = { .type = REC_TYPE_X86_CPUID_POLICY, };
49     struct xc_sr_record msrs  = { .type = REC_TYPE_X86_MSR_POLICY, };
50     uint32_t nr_leaves = 0, nr_msrs = 0;
51     int rc;
52 
53     if ( xc_get_cpu_policy_size(xch, &nr_leaves, &nr_msrs) < 0 )
54     {
55         PERROR("Unable to get CPU Policy size");
56         return -1;
57     }
58 
59     cpuid.data = malloc(nr_leaves * sizeof(xen_cpuid_leaf_t));
60     msrs.data  = malloc(nr_msrs   * sizeof(xen_msr_entry_t));
61     if ( !cpuid.data || !msrs.data )
62     {
63         ERROR("Cannot allocate memory for CPU Policy");
64         rc = -1;
65         goto out;
66     }
67 
68     if ( xc_get_domain_cpu_policy(xch, ctx->domid, &nr_leaves, cpuid.data,
69                                   &nr_msrs, msrs.data) )
70     {
71         PERROR("Unable to get d%d CPU Policy", ctx->domid);
72         rc = -1;
73         goto out;
74     }
75 
76     cpuid.length = nr_leaves * sizeof(xen_cpuid_leaf_t);
77     if ( cpuid.length )
78     {
79         rc = write_record(ctx, &cpuid);
80         if ( rc )
81             goto out;
82     }
83 
84     msrs.length = nr_msrs * sizeof(xen_msr_entry_t);
85     if ( msrs.length )
86         rc = write_record(ctx, &msrs);
87 
88  out:
89     free(cpuid.data);
90     free(msrs.data);
91 
92     return rc;
93 }
94 
handle_x86_cpuid_policy(struct xc_sr_context * ctx,struct xc_sr_record * rec)95 int handle_x86_cpuid_policy(struct xc_sr_context *ctx, struct xc_sr_record *rec)
96 {
97     xc_interface *xch = ctx->xch;
98     int rc;
99 
100     if ( rec->length == 0 ||
101          rec->length % sizeof(xen_cpuid_leaf_t) != 0 )
102     {
103         ERROR("X86_CPUID_POLICY size %u should be multiple of %zu",
104               rec->length, sizeof(xen_cpuid_leaf_t));
105         return -1;
106     }
107 
108     rc = update_blob(&ctx->x86.restore.cpuid, rec->data, rec->length);
109     if ( rc )
110         ERROR("Unable to allocate %u bytes for X86_CPUID_POLICY", rec->length);
111 
112     return rc;
113 }
114 
handle_x86_msr_policy(struct xc_sr_context * ctx,struct xc_sr_record * rec)115 int handle_x86_msr_policy(struct xc_sr_context *ctx, struct xc_sr_record *rec)
116 {
117     xc_interface *xch = ctx->xch;
118     int rc;
119 
120     if ( rec->length == 0 ||
121          rec->length % sizeof(xen_msr_entry_t) != 0 )
122     {
123         ERROR("X86_MSR_POLICY size %u should be multiple of %zu",
124               rec->length, sizeof(xen_cpuid_leaf_t));
125         return -1;
126     }
127 
128     rc = update_blob(&ctx->x86.restore.msr, rec->data, rec->length);
129     if ( rc )
130         ERROR("Unable to allocate %u bytes for X86_MSR_POLICY", rec->length);
131 
132     return rc;
133 }
134 
x86_static_data_complete(struct xc_sr_context * ctx,unsigned int * missing)135 int x86_static_data_complete(struct xc_sr_context *ctx, unsigned int *missing)
136 {
137     xc_interface *xch = ctx->xch;
138     uint32_t nr_leaves = 0, nr_msrs = 0;
139     uint32_t err_l = ~0, err_s = ~0, err_m = ~0;
140 
141     if ( ctx->x86.restore.cpuid.ptr )
142         nr_leaves = ctx->x86.restore.cpuid.size / sizeof(xen_cpuid_leaf_t);
143     else
144         *missing |= XGR_SDD_MISSING_CPUID;
145 
146     if ( ctx->x86.restore.msr.ptr )
147         nr_msrs = ctx->x86.restore.msr.size / sizeof(xen_msr_entry_t);
148     else
149         *missing |= XGR_SDD_MISSING_MSR;
150 
151     if ( (nr_leaves || nr_msrs) &&
152          xc_set_domain_cpu_policy(xch, ctx->domid,
153                                   nr_leaves, ctx->x86.restore.cpuid.ptr,
154                                   nr_msrs,   ctx->x86.restore.msr.ptr,
155                                   &err_l, &err_s, &err_m) )
156     {
157         PERROR("Failed to set CPUID policy: leaf %08x, subleaf %08x, msr %08x",
158                err_l, err_s, err_m);
159         return -1;
160     }
161 
162     return 0;
163 }
164 
165 /*
166  * Local variables:
167  * mode: C
168  * c-file-style: "BSD"
169  * c-basic-offset: 4
170  * tab-width: 4
171  * indent-tabs-mode: nil
172  * End:
173  */
174