qemu

Форк
0
/
s390-stattrib-kvm.c 
203 строки · 6.3 Кб
1
/*
2
 * s390 storage attributes device -- KVM object
3
 *
4
 * Copyright 2016 IBM Corp.
5
 * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
6
 *
7
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
8
 * your option) any later version. See the COPYING file in the top-level
9
 * directory.
10
 */
11

12
#include "qemu/osdep.h"
13
#include "hw/boards.h"
14
#include "migration/qemu-file.h"
15
#include "hw/s390x/storage-attributes.h"
16
#include "qemu/error-report.h"
17
#include "sysemu/kvm.h"
18
#include "exec/ram_addr.h"
19
#include "kvm/kvm_s390x.h"
20
#include "qapi/error.h"
21

22
Object *kvm_s390_stattrib_create(void)
23
{
24
    if (kvm_enabled() &&
25
                kvm_check_extension(kvm_state, KVM_CAP_S390_CMMA_MIGRATION)) {
26
        return object_new(TYPE_KVM_S390_STATTRIB);
27
    }
28
    return NULL;
29
}
30

31
static void kvm_s390_stattrib_instance_init(Object *obj)
32
{
33
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(obj);
34

35
    sas->still_dirty = 0;
36
}
37

38
static int kvm_s390_stattrib_read_helper(S390StAttribState *sa,
39
                                         uint64_t *start_gfn,
40
                                         uint32_t count,
41
                                         uint8_t *values,
42
                                         uint32_t flags)
43
{
44
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
45
    int r;
46
    struct kvm_s390_cmma_log clog = {
47
        .values = (uint64_t)values,
48
        .start_gfn = *start_gfn,
49
        .count = count,
50
        .flags = flags,
51
    };
52

53
    r = kvm_vm_ioctl(kvm_state, KVM_S390_GET_CMMA_BITS, &clog);
54
    if (r < 0) {
55
        error_report("KVM_S390_GET_CMMA_BITS failed: %s", strerror(-r));
56
        return r;
57
    }
58

59
    *start_gfn = clog.start_gfn;
60
    sas->still_dirty = clog.remaining;
61
    return clog.count;
62
}
63

64
static int kvm_s390_stattrib_get_stattr(S390StAttribState *sa,
65
                                        uint64_t *start_gfn,
66
                                        uint32_t count,
67
                                        uint8_t *values)
68
{
69
    return kvm_s390_stattrib_read_helper(sa, start_gfn, count, values, 0);
70
}
71

72
static int kvm_s390_stattrib_peek_stattr(S390StAttribState *sa,
73
                                         uint64_t start_gfn,
74
                                         uint32_t count,
75
                                         uint8_t *values)
76
{
77
    return kvm_s390_stattrib_read_helper(sa, &start_gfn, count, values,
78
                                         KVM_S390_CMMA_PEEK);
79
}
80

81
static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa,
82
                                        uint64_t start_gfn,
83
                                        uint32_t count,
84
                                        uint8_t *values)
85
{
86
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
87
    MachineState *machine = MACHINE(qdev_get_machine());
88
    unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
89

90
    if (start_gfn + count > max) {
91
        error_report("Out of memory bounds when setting storage attributes");
92
        return -1;
93
    }
94
    if (!sas->incoming_buffer) {
95
        sas->incoming_buffer = g_malloc0(max);
96
    }
97

98
    memcpy(sas->incoming_buffer + start_gfn, values, count);
99

100
    return 0;
101
}
102

103
static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
104
{
105
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
106
    MachineState *machine = MACHINE(qdev_get_machine());
107
    unsigned long max = machine->ram_size / TARGET_PAGE_SIZE;
108
    /* We do not need to reach the maximum buffer size allowed */
109
    unsigned long cx, len = KVM_S390_SKEYS_MAX / 2;
110
    int r;
111
    struct kvm_s390_cmma_log clog = {
112
        .flags = 0,
113
        .mask = ~0ULL,
114
    };
115

116
    if (sas->incoming_buffer) {
117
        for (cx = 0; cx + len <= max; cx += len) {
118
            clog.start_gfn = cx;
119
            clog.count = len;
120
            clog.values = (uint64_t)(sas->incoming_buffer + cx);
121
            r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
122
            if (r) {
123
                error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
124
                return;
125
            }
126
        }
127
        if (cx < max) {
128
            clog.start_gfn = cx;
129
            clog.count = max - cx;
130
            clog.values = (uint64_t)(sas->incoming_buffer + cx);
131
            r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
132
            if (r) {
133
                error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
134
            }
135
        }
136
        g_free(sas->incoming_buffer);
137
        sas->incoming_buffer = NULL;
138
    }
139
}
140

141
static int kvm_s390_stattrib_set_migrationmode(S390StAttribState *sa, bool val,
142
                                               Error **errp)
143
{
144
    struct kvm_device_attr attr = {
145
        .group = KVM_S390_VM_MIGRATION,
146
        .attr = val,
147
        .addr = 0,
148
    };
149
    int r;
150

151
    r = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
152
    if (r) {
153
        error_setg_errno(errp, -r, "setting KVM_S390_VM_MIGRATION failed");
154
    }
155
    return r;
156
}
157

158
static long long kvm_s390_stattrib_get_dirtycount(S390StAttribState *sa)
159
{
160
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
161
    uint8_t val[8];
162

163
    kvm_s390_stattrib_peek_stattr(sa, 0, 1, val);
164
    return sas->still_dirty;
165
}
166

167
static int kvm_s390_stattrib_get_active(S390StAttribState *sa)
168
{
169
    return kvm_s390_cmma_active() && sa->migration_enabled;
170
}
171

172
static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data)
173
{
174
    S390StAttribClass *sac = S390_STATTRIB_CLASS(oc);
175
    DeviceClass *dc = DEVICE_CLASS(oc);
176

177
    sac->get_stattr = kvm_s390_stattrib_get_stattr;
178
    sac->peek_stattr = kvm_s390_stattrib_peek_stattr;
179
    sac->set_stattr = kvm_s390_stattrib_set_stattr;
180
    sac->set_migrationmode = kvm_s390_stattrib_set_migrationmode;
181
    sac->get_dirtycount = kvm_s390_stattrib_get_dirtycount;
182
    sac->synchronize = kvm_s390_stattrib_synchronize;
183
    sac->get_active = kvm_s390_stattrib_get_active;
184

185
    /* Reason: Can only be instantiated one time (internally) */
186
    dc->user_creatable = false;
187
}
188

189
static const TypeInfo kvm_s390_stattrib_info = {
190
    .name          = TYPE_KVM_S390_STATTRIB,
191
    .parent        = TYPE_S390_STATTRIB,
192
    .instance_init = kvm_s390_stattrib_instance_init,
193
    .instance_size = sizeof(KVMS390StAttribState),
194
    .class_init    = kvm_s390_stattrib_class_init,
195
    .class_size    = sizeof(S390StAttribClass),
196
};
197

198
static void kvm_s390_stattrib_register_types(void)
199
{
200
    type_register_static(&kvm_s390_stattrib_info);
201
}
202

203
type_init(kvm_s390_stattrib_register_types)
204

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.