summaryrefslogtreecommitdiff
path: root/xen/arch/x86/include/asm/hvm/save.h
blob: 9d838c48e357f3ca690b97108d2096e0306faf1b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * save.h: HVM support routines for save/restore
 */

#ifndef __XEN_HVM_SAVE_H__
#define __XEN_HVM_SAVE_H__

#include <xen/types.h>
#include <xen/init.h>
#include <public/xen.h>
#include <public/hvm/save.h>

/* Marshalling and unmarshalling uses a buffer with size and cursor. */
typedef struct hvm_domain_context {
    uint32_t cur;
    uint32_t size;
    uint8_t *data;
} hvm_domain_context_t;

/* Marshalling an entry: check space and fill in the header */
int _hvm_init_entry(struct hvm_domain_context *h,
                    uint16_t tc, uint16_t inst, uint32_t len);

/* Marshalling: copy the contents in a type-safe way */
void _hvm_write_entry(struct hvm_domain_context *h,
                      void *src, uint32_t src_len);

/* Marshalling: init and copy; evaluates to zero on success */
#define hvm_save_entry(_x, _inst, _h, _src) ({                  \
    int r;                                                      \
    r = _hvm_init_entry((_h), HVM_SAVE_CODE(_x),                \
                        (_inst), HVM_SAVE_LENGTH(_x));          \
    if ( r == 0 )                                               \
        _hvm_write_entry((_h), (_src), HVM_SAVE_LENGTH(_x));    \
    r; })

/* Unmarshalling: test an entry's size and typecode and record the instance */
int _hvm_check_entry(struct hvm_domain_context *h, 
                     uint16_t type, uint32_t len, bool_t strict_length);

/* Unmarshalling: copy the contents in a type-safe way */
void _hvm_read_entry(struct hvm_domain_context *h,
                     void *dest, uint32_t dest_len);

/*
 * Unmarshalling: check, then copy. Evaluates to zero on success. This load
 * function requires the save entry to be the same size as the dest structure.
 */
#define _hvm_load_entry(_x, _h, _dst, _strict) ({                       \
    int r;                                                              \
    struct hvm_save_descriptor *desc                                    \
        = (struct hvm_save_descriptor *)&(_h)->data[(_h)->cur];         \
    if ( (r = _hvm_check_entry((_h), HVM_SAVE_CODE(_x),                 \
               HVM_SAVE_LENGTH(_x), (_strict))) == 0 )                  \
    {                                                                   \
        _hvm_read_entry((_h), (_dst), HVM_SAVE_LENGTH(_x));             \
        if ( HVM_SAVE_HAS_COMPAT(_x) &&                                 \
             desc->length != HVM_SAVE_LENGTH(_x) )                      \
            r = HVM_SAVE_FIX_COMPAT(_x, (_dst), desc->length);          \
    }                                                                   \
    else if (HVM_SAVE_HAS_COMPAT(_x)                                    \
             && (r = _hvm_check_entry((_h), HVM_SAVE_CODE(_x),          \
                       HVM_SAVE_LENGTH_COMPAT(_x), (_strict))) == 0 ) { \
        _hvm_read_entry((_h), (_dst), HVM_SAVE_LENGTH_COMPAT(_x));      \
        r = HVM_SAVE_FIX_COMPAT(_x, (_dst), desc->length);              \
    }                                                                   \
    r; })

#define hvm_load_entry(_x, _h, _dst)            \
    _hvm_load_entry(_x, _h, _dst, 1)
#define hvm_load_entry_zeroextend(_x, _h, _dst) \
    _hvm_load_entry(_x, _h, _dst, 0)

/* Unmarshalling: what is the instance ID of the next entry? */
static inline unsigned int hvm_load_instance(const struct hvm_domain_context *h)
{
    const struct hvm_save_descriptor *d = (const void *)&h->data[h->cur];

    return d->instance;
}

/* Handler types for different types of save-file entry. 
 * The save handler may save multiple instances of a type into the buffer;
 * the load handler will be called once for each instance found when
 * restoring.  Both return non-zero on error. */
typedef int (*hvm_save_handler) (struct vcpu *v,
                                 hvm_domain_context_t *h);
typedef int (*hvm_load_handler) (struct domain *d,
                                 hvm_domain_context_t *h);

/* Init-time function to declare a pair of handlers for a type,
 * and the maximum buffer space needed to save this type of state */
void hvm_register_savevm(uint16_t typecode,
                         const char *name, 
                         hvm_save_handler save_state,
                         hvm_load_handler load_state,
                         size_t size, int kind);

/* The space needed for saving can be per-domain or per-vcpu: */
#define HVMSR_PER_DOM  0
#define HVMSR_PER_VCPU 1

/* Syntactic sugar around that function: specify the max number of
 * saves, and this calculates the size of buffer needed */
#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load, _num, _k)             \
static int __init cf_check __hvm_register_##_x##_save_and_restore(void)   \
{                                                                         \
    hvm_register_savevm(HVM_SAVE_CODE(_x),                                \
                        #_x,                                              \
                        &_save,                                           \
                        &_load,                                           \
                        (_num) * (HVM_SAVE_LENGTH(_x)                     \
                                  + sizeof (struct hvm_save_descriptor)), \
                        _k);                                              \
    return 0;                                                             \
}                                                                         \
__initcall(__hvm_register_##_x##_save_and_restore);


/* Entry points for saving and restoring HVM domain state */
size_t hvm_save_size(struct domain *d);
int hvm_save(struct domain *d, hvm_domain_context_t *h);
int hvm_save_one(struct domain *d, unsigned int typecode, unsigned int instance,
                 XEN_GUEST_HANDLE_64(uint8) handle, uint64_t *bufsz);
int hvm_load(struct domain *d, hvm_domain_context_t *h);

/* Arch-specific definitions. */
struct hvm_save_header;
void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr);
int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr);

#endif /* __XEN_HVM_SAVE_H__ */