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