1 #include <assert.h>
2
3 #include "xc_sr_common.h"
4
5 #include <xen-tools/libs.h>
6
7 static const char *const dhdr_types[] =
8 {
9 [DHDR_TYPE_X86_PV] = "x86 PV",
10 [DHDR_TYPE_X86_HVM] = "x86 HVM",
11 };
12
dhdr_type_to_str(uint32_t type)13 const char *dhdr_type_to_str(uint32_t type)
14 {
15 if ( type < ARRAY_SIZE(dhdr_types) && dhdr_types[type] )
16 return dhdr_types[type];
17
18 return "Reserved";
19 }
20
21 static const char *const mandatory_rec_types[] =
22 {
23 [REC_TYPE_END] = "End",
24 [REC_TYPE_PAGE_DATA] = "Page data",
25 [REC_TYPE_X86_PV_INFO] = "x86 PV info",
26 [REC_TYPE_X86_PV_P2M_FRAMES] = "x86 PV P2M frames",
27 [REC_TYPE_X86_PV_VCPU_BASIC] = "x86 PV vcpu basic",
28 [REC_TYPE_X86_PV_VCPU_EXTENDED] = "x86 PV vcpu extended",
29 [REC_TYPE_X86_PV_VCPU_XSAVE] = "x86 PV vcpu xsave",
30 [REC_TYPE_SHARED_INFO] = "Shared info",
31 [REC_TYPE_X86_TSC_INFO] = "x86 TSC info",
32 [REC_TYPE_HVM_CONTEXT] = "HVM context",
33 [REC_TYPE_HVM_PARAMS] = "HVM params",
34 [REC_TYPE_TOOLSTACK] = "Toolstack",
35 [REC_TYPE_X86_PV_VCPU_MSRS] = "x86 PV vcpu msrs",
36 [REC_TYPE_VERIFY] = "Verify",
37 [REC_TYPE_CHECKPOINT] = "Checkpoint",
38 [REC_TYPE_CHECKPOINT_DIRTY_PFN_LIST] = "Checkpoint dirty pfn list",
39 [REC_TYPE_STATIC_DATA_END] = "Static data end",
40 [REC_TYPE_X86_CPUID_POLICY] = "x86 CPUID policy",
41 [REC_TYPE_X86_MSR_POLICY] = "x86 MSR policy",
42 };
43
rec_type_to_str(uint32_t type)44 const char *rec_type_to_str(uint32_t type)
45 {
46 if ( !(type & REC_TYPE_OPTIONAL) )
47 {
48 if ( (type < ARRAY_SIZE(mandatory_rec_types)) &&
49 (mandatory_rec_types[type]) )
50 return mandatory_rec_types[type];
51 }
52
53 return "Reserved";
54 }
55
write_split_record(struct xc_sr_context * ctx,struct xc_sr_record * rec,void * buf,size_t sz)56 int write_split_record(struct xc_sr_context *ctx, struct xc_sr_record *rec,
57 void *buf, size_t sz)
58 {
59 static const char zeroes[(1u << REC_ALIGN_ORDER) - 1] = { 0 };
60
61 xc_interface *xch = ctx->xch;
62 typeof(rec->length) combined_length = rec->length + sz;
63 size_t record_length = ROUNDUP(combined_length, REC_ALIGN_ORDER);
64 struct iovec parts[] = {
65 { &rec->type, sizeof(rec->type) },
66 { &combined_length, sizeof(combined_length) },
67 { rec->data, rec->length },
68 { buf, sz },
69 { (void *)zeroes, record_length - combined_length },
70 };
71
72 if ( record_length > REC_LENGTH_MAX )
73 {
74 ERROR("Record (0x%08x, %s) length %#zx exceeds max (%#x)", rec->type,
75 rec_type_to_str(rec->type), record_length, REC_LENGTH_MAX);
76 return -1;
77 }
78
79 if ( rec->length )
80 assert(rec->data);
81 if ( sz )
82 assert(buf);
83
84 if ( writev_exact(ctx->fd, parts, ARRAY_SIZE(parts)) )
85 goto err;
86
87 return 0;
88
89 err:
90 PERROR("Unable to write record to stream");
91 return -1;
92 }
93
read_record(struct xc_sr_context * ctx,int fd,struct xc_sr_record * rec)94 int read_record(struct xc_sr_context *ctx, int fd, struct xc_sr_record *rec)
95 {
96 xc_interface *xch = ctx->xch;
97 struct xc_sr_rhdr rhdr;
98 size_t datasz;
99
100 if ( read_exact(fd, &rhdr, sizeof(rhdr)) )
101 {
102 PERROR("Failed to read Record Header from stream");
103 return -1;
104 }
105
106 if ( rhdr.length > REC_LENGTH_MAX )
107 {
108 ERROR("Record (0x%08x, %s) length %#x exceeds max (%#x)", rhdr.type,
109 rec_type_to_str(rhdr.type), rhdr.length, REC_LENGTH_MAX);
110 return -1;
111 }
112
113 datasz = ROUNDUP(rhdr.length, REC_ALIGN_ORDER);
114
115 if ( datasz )
116 {
117 rec->data = malloc(datasz);
118
119 if ( !rec->data )
120 {
121 ERROR("Unable to allocate %zu bytes for record data (0x%08x, %s)",
122 datasz, rhdr.type, rec_type_to_str(rhdr.type));
123 return -1;
124 }
125
126 if ( read_exact(fd, rec->data, datasz) )
127 {
128 free(rec->data);
129 rec->data = NULL;
130 PERROR("Failed to read %zu bytes of data for record (0x%08x, %s)",
131 datasz, rhdr.type, rec_type_to_str(rhdr.type));
132 return -1;
133 }
134 }
135 else
136 rec->data = NULL;
137
138 rec->type = rhdr.type;
139 rec->length = rhdr.length;
140
141 return 0;
142 };
143
build_assertions(void)144 static void __attribute__((unused)) build_assertions(void)
145 {
146 BUILD_BUG_ON(sizeof(struct xc_sr_ihdr) != 24);
147 BUILD_BUG_ON(sizeof(struct xc_sr_dhdr) != 16);
148 BUILD_BUG_ON(sizeof(struct xc_sr_rhdr) != 8);
149
150 BUILD_BUG_ON(sizeof(struct xc_sr_rec_page_data_header) != 8);
151 BUILD_BUG_ON(sizeof(struct xc_sr_rec_x86_pv_info) != 8);
152 BUILD_BUG_ON(sizeof(struct xc_sr_rec_x86_pv_p2m_frames) != 8);
153 BUILD_BUG_ON(sizeof(struct xc_sr_rec_x86_pv_vcpu_hdr) != 8);
154 BUILD_BUG_ON(sizeof(struct xc_sr_rec_x86_tsc_info) != 24);
155 BUILD_BUG_ON(sizeof(struct xc_sr_rec_hvm_params_entry) != 16);
156 BUILD_BUG_ON(sizeof(struct xc_sr_rec_hvm_params) != 8);
157 }
158
159 /*
160 * Local variables:
161 * mode: C
162 * c-file-style: "BSD"
163 * c-basic-offset: 4
164 * tab-width: 4
165 * indent-tabs-mode: nil
166 * End:
167 */
168