Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/domctl.c
Line
Count
Source (jump to first uncovered line)
1
/******************************************************************************
2
 * Arch-specific domctl.c
3
 *
4
 * Copyright (c) 2002-2006, K A Fraser
5
 */
6
7
#include <xen/types.h>
8
#include <xen/lib.h>
9
#include <xen/mm.h>
10
#include <xen/guest_access.h>
11
#include <xen/compat.h>
12
#include <xen/pci.h>
13
#include <public/domctl.h>
14
#include <xen/sched.h>
15
#include <xen/domain.h>
16
#include <xen/event.h>
17
#include <xen/domain_page.h>
18
#include <asm/msr.h>
19
#include <xen/trace.h>
20
#include <xen/console.h>
21
#include <xen/iocap.h>
22
#include <xen/paging.h>
23
#include <asm/irq.h>
24
#include <asm/hvm/hvm.h>
25
#include <asm/hvm/support.h>
26
#include <asm/hvm/cacheattr.h>
27
#include <asm/processor.h>
28
#include <asm/acpi.h> /* for hvm_acpi_power_button */
29
#include <xen/hypercall.h> /* for arch_do_domctl */
30
#include <xsm/xsm.h>
31
#include <xen/iommu.h>
32
#include <xen/vm_event.h>
33
#include <public/vm_event.h>
34
#include <asm/mem_sharing.h>
35
#include <asm/xstate.h>
36
#include <asm/debugger.h>
37
#include <asm/psr.h>
38
#include <asm/cpuid.h>
39
40
static int gdbsx_guest_mem_io(domid_t domid, struct xen_domctl_gdbsx_memio *iop)
41
0
{
42
0
    void * __user gva = (void *)iop->gva, * __user uva = (void *)iop->uva;
43
0
44
0
    iop->remain = dbg_rw_mem(gva, uva, iop->len, domid,
45
0
                             !!iop->gwr, iop->pgd3val);
46
0
47
0
    return iop->remain ? -EFAULT : 0;
48
0
}
49
50
static int update_domain_cpuid_info(struct domain *d,
51
                                    const struct xen_domctl_cpuid *ctl)
52
0
{
53
0
    struct cpuid_policy *p = d->arch.cpuid;
54
0
    const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx };
55
0
    int old_vendor = p->x86_vendor;
56
0
57
0
    /*
58
0
     * Skip update for leaves we don't care about.  This avoids the overhead
59
0
     * of recalculate_cpuid_policy() and making d->arch.cpuids[] needlessly
60
0
     * longer to search.
61
0
     */
62
0
    switch ( ctl->input[0] )
63
0
    {
64
0
    case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1:
65
0
        if ( ctl->input[0] == 4 &&
66
0
             ctl->input[1] >= ARRAY_SIZE(p->cache.raw) )
67
0
            return 0;
68
0
69
0
        if ( ctl->input[0] == 7 &&
70
0
             ctl->input[1] >= ARRAY_SIZE(p->feat.raw) )
71
0
            return 0;
72
0
73
0
        BUILD_BUG_ON(ARRAY_SIZE(p->xstate.raw) < 2);
74
0
        if ( ctl->input[0] == XSTATE_CPUID &&
75
0
             ctl->input[1] != 1 ) /* Everything else automatically calculated. */
76
0
            return 0;
77
0
        break;
78
0
79
0
    case 0x40000000: case 0x40000100:
80
0
        /* Only care about the max_leaf limit. */
81
0
82
0
    case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1:
83
0
        break;
84
0
85
0
    default:
86
0
        return 0;
87
0
    }
88
0
89
0
    /* Insert ctl data into cpuid_policy. */
90
0
    switch ( ctl->input[0] )
91
0
    {
92
0
    case 0x00000000 ... ARRAY_SIZE(p->basic.raw) - 1:
93
0
        switch ( ctl->input[0] )
94
0
        {
95
0
        case 4:
96
0
            p->cache.raw[ctl->input[1]] = leaf;
97
0
            break;
98
0
99
0
        case 7:
100
0
            p->feat.raw[ctl->input[1]] = leaf;
101
0
            break;
102
0
103
0
        case XSTATE_CPUID:
104
0
            p->xstate.raw[ctl->input[1]] = leaf;
105
0
            break;
106
0
107
0
        default:
108
0
            p->basic.raw[ctl->input[0]] = leaf;
109
0
            break;
110
0
        }
111
0
        break;
112
0
113
0
    case 0x40000000:
114
0
        p->hv_limit = ctl->eax;
115
0
        break;
116
0
117
0
    case 0x40000100:
118
0
        p->hv2_limit = ctl->eax;
119
0
        break;
120
0
121
0
    case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1:
122
0
        p->extd.raw[ctl->input[0] - 0x80000000] = leaf;
123
0
        break;
124
0
    }
125
0
126
0
    recalculate_cpuid_policy(d);
127
0
128
0
    switch ( ctl->input[0] )
129
0
    {
130
0
    case 0:
131
0
        if ( is_hvm_domain(d) && (p->x86_vendor != old_vendor) )
132
0
        {
133
0
            struct vcpu *v;
134
0
135
0
            for_each_vcpu( d, v )
136
0
                hvm_update_guest_vendor(v);
137
0
        }
138
0
        break;
139
0
140
0
    case 1:
141
0
        if ( is_pv_domain(d) && ((levelling_caps & LCAP_1cd) == LCAP_1cd) )
142
0
        {
143
0
            uint64_t mask = cpuidmask_defaults._1cd;
144
0
            uint32_t ecx = p->basic._1c;
145
0
            uint32_t edx = p->basic._1d;
146
0
147
0
            /*
148
0
             * Must expose hosts HTT and X2APIC value so a guest using native
149
0
             * CPUID can correctly interpret other leaves which cannot be
150
0
             * masked.
151
0
             */
152
0
            if ( cpu_has_x2apic )
153
0
                ecx |= cpufeat_mask(X86_FEATURE_X2APIC);
154
0
            if ( cpu_has_htt )
155
0
                edx |= cpufeat_mask(X86_FEATURE_HTT);
156
0
157
0
            switch ( boot_cpu_data.x86_vendor )
158
0
            {
159
0
            case X86_VENDOR_INTEL:
160
0
                /*
161
0
                 * Intel masking MSRs are documented as AND masks.
162
0
                 * Experimentally, they are applied after OSXSAVE and APIC
163
0
                 * are fast-forwarded from real hardware state.
164
0
                 */
165
0
                mask &= ((uint64_t)edx << 32) | ecx;
166
0
167
0
                if ( ecx & cpufeat_mask(X86_FEATURE_XSAVE) )
168
0
                    ecx = cpufeat_mask(X86_FEATURE_OSXSAVE);
169
0
                else
170
0
                    ecx = 0;
171
0
                edx = cpufeat_mask(X86_FEATURE_APIC);
172
0
173
0
                mask |= ((uint64_t)edx << 32) | ecx;
174
0
                break;
175
0
176
0
            case X86_VENDOR_AMD:
177
0
                mask &= ((uint64_t)ecx << 32) | edx;
178
0
179
0
                /*
180
0
                 * AMD masking MSRs are documented as overrides.
181
0
                 * Experimentally, fast-forwarding of the OSXSAVE and APIC
182
0
                 * bits from real hardware state only occurs if the MSR has
183
0
                 * the respective bits set.
184
0
                 */
185
0
                if ( ecx & cpufeat_mask(X86_FEATURE_XSAVE) )
186
0
                    ecx = cpufeat_mask(X86_FEATURE_OSXSAVE);
187
0
                else
188
0
                    ecx = 0;
189
0
                edx = cpufeat_mask(X86_FEATURE_APIC);
190
0
191
0
                mask |= ((uint64_t)ecx << 32) | edx;
192
0
                break;
193
0
            }
194
0
195
0
            d->arch.pv_domain.cpuidmasks->_1cd = mask;
196
0
        }
197
0
        break;
198
0
199
0
    case 6:
200
0
        if ( is_pv_domain(d) && ((levelling_caps & LCAP_6c) == LCAP_6c) )
201
0
        {
202
0
            uint64_t mask = cpuidmask_defaults._6c;
203
0
204
0
            if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
205
0
                mask &= (~0ULL << 32) | ctl->ecx;
206
0
207
0
            d->arch.pv_domain.cpuidmasks->_6c = mask;
208
0
        }
209
0
        break;
210
0
211
0
    case 7:
212
0
        if ( ctl->input[1] != 0 )
213
0
            break;
214
0
215
0
        if ( is_pv_domain(d) && ((levelling_caps & LCAP_7ab0) == LCAP_7ab0) )
216
0
        {
217
0
            uint64_t mask = cpuidmask_defaults._7ab0;
218
0
            uint32_t eax = ctl->eax;
219
0
            uint32_t ebx = p->feat._7b0;
220
0
221
0
            if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
222
0
                mask &= ((uint64_t)eax << 32) | ebx;
223
0
224
0
            d->arch.pv_domain.cpuidmasks->_7ab0 = mask;
225
0
        }
226
0
        break;
227
0
228
0
    case 0xa:
229
0
        if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
230
0
            break;
231
0
232
0
        /* If PMU version is zero then the guest doesn't have VPMU */
233
0
        if ( p->basic.pmu_version == 0 )
234
0
        {
235
0
            struct vcpu *v;
236
0
237
0
            for_each_vcpu ( d, v )
238
0
                vpmu_destroy(v);
239
0
        }
240
0
        break;
241
0
242
0
    case 0xd:
243
0
        if ( ctl->input[1] != 1 )
244
0
            break;
245
0
246
0
        if ( is_pv_domain(d) && ((levelling_caps & LCAP_Da1) == LCAP_Da1) )
247
0
        {
248
0
            uint64_t mask = cpuidmask_defaults.Da1;
249
0
            uint32_t eax = p->xstate.Da1;
250
0
251
0
            if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
252
0
                mask &= (~0ULL << 32) | eax;
253
0
254
0
            d->arch.pv_domain.cpuidmasks->Da1 = mask;
255
0
        }
256
0
        break;
257
0
258
0
    case 0x80000001:
259
0
        if ( is_pv_domain(d) && ((levelling_caps & LCAP_e1cd) == LCAP_e1cd) )
260
0
        {
261
0
            uint64_t mask = cpuidmask_defaults.e1cd;
262
0
            uint32_t ecx = p->extd.e1c;
263
0
            uint32_t edx = p->extd.e1d;
264
0
265
0
            /*
266
0
             * Must expose hosts CMP_LEGACY value so a guest using native
267
0
             * CPUID can correctly interpret other leaves which cannot be
268
0
             * masked.
269
0
             */
270
0
            if ( cpu_has_cmp_legacy )
271
0
                ecx |= cpufeat_mask(X86_FEATURE_CMP_LEGACY);
272
0
273
0
            /* If not emulating AMD, clear the duplicated features in e1d. */
274
0
            if ( p->x86_vendor != X86_VENDOR_AMD )
275
0
                edx &= ~CPUID_COMMON_1D_FEATURES;
276
0
277
0
            switch ( boot_cpu_data.x86_vendor )
278
0
            {
279
0
            case X86_VENDOR_INTEL:
280
0
                mask &= ((uint64_t)edx << 32) | ecx;
281
0
                break;
282
0
283
0
            case X86_VENDOR_AMD:
284
0
                mask &= ((uint64_t)ecx << 32) | edx;
285
0
286
0
                /*
287
0
                 * Fast-forward bits - Must be set in the masking MSR for
288
0
                 * fast-forwarding to occur in hardware.
289
0
                 */
290
0
                ecx = 0;
291
0
                edx = cpufeat_mask(X86_FEATURE_APIC);
292
0
293
0
                mask |= ((uint64_t)ecx << 32) | edx;
294
0
                break;
295
0
            }
296
0
297
0
            d->arch.pv_domain.cpuidmasks->e1cd = mask;
298
0
        }
299
0
        break;
300
0
    }
301
0
302
0
    return 0;
303
0
}
304
305
static int vcpu_set_vmce(struct vcpu *v,
306
                         const struct xen_domctl_ext_vcpucontext *evc)
307
0
{
308
0
    /*
309
0
     * Sizes of vMCE parameters used by the current and past versions
310
0
     * of Xen in descending order. If vMCE parameters are extended,
311
0
     * remember to add the old size to this array by VMCE_SIZE().
312
0
     */
313
0
#define VMCE_SIZE(field) \
314
0
    (offsetof(typeof(evc->vmce), field) + sizeof(evc->vmce.field))
315
0
316
0
    static const unsigned int valid_sizes[] = {
317
0
        sizeof(evc->vmce),
318
0
        VMCE_SIZE(mci_ctl2_bank1),
319
0
        VMCE_SIZE(caps),
320
0
    };
321
0
#undef VMCE_SIZE
322
0
323
0
    struct hvm_vmce_vcpu vmce = { };
324
0
    unsigned int evc_vmce_size =
325
0
        min(evc->size - offsetof(typeof(*evc), vmce), sizeof(evc->vmce));
326
0
    unsigned int i = 0;
327
0
328
0
    BUILD_BUG_ON(offsetof(typeof(*evc), mcg_cap) !=
329
0
                 offsetof(typeof(*evc), vmce.caps));
330
0
    BUILD_BUG_ON(sizeof(evc->mcg_cap) != sizeof(evc->vmce.caps));
331
0
332
0
    while ( i < ARRAY_SIZE(valid_sizes) && evc_vmce_size < valid_sizes[i] )
333
0
        ++i;
334
0
335
0
    if ( i == ARRAY_SIZE(valid_sizes) )
336
0
        return 0;
337
0
338
0
    memcpy(&vmce, &evc->vmce, valid_sizes[i]);
339
0
340
0
    return vmce_restore_vcpu(v, &vmce);
341
0
}
342
343
void arch_get_domain_info(const struct domain *d,
344
                          struct xen_domctl_getdomaininfo *info)
345
4
{
346
4
    if ( paging_mode_hap(d) )
347
4
        info->flags |= XEN_DOMINF_hap;
348
4
}
349
350
0
#define MAX_IOPORTS 0x10000
351
352
long arch_do_domctl(
353
    struct xen_domctl *domctl, struct domain *d,
354
    XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
355
0
{
356
0
    struct vcpu *curr = current;
357
0
    struct domain *currd = curr->domain;
358
0
    long ret = 0;
359
0
    bool copyback = false;
360
0
    unsigned long i;
361
0
362
0
    switch ( domctl->cmd )
363
0
    {
364
0
365
0
    case XEN_DOMCTL_shadow_op:
366
0
        ret = paging_domctl(d, &domctl->u.shadow_op, u_domctl, 0);
367
0
        if ( ret == -ERESTART )
368
0
            return hypercall_create_continuation(__HYPERVISOR_arch_1,
369
0
                                                 "h", u_domctl);
370
0
        copyback = true;
371
0
        break;
372
0
373
0
    case XEN_DOMCTL_ioport_permission:
374
0
    {
375
0
        unsigned int fp = domctl->u.ioport_permission.first_port;
376
0
        unsigned int np = domctl->u.ioport_permission.nr_ports;
377
0
        int allow = domctl->u.ioport_permission.allow_access;
378
0
379
0
        if ( (fp + np) <= fp || (fp + np) > MAX_IOPORTS )
380
0
            ret = -EINVAL;
381
0
        else if ( !ioports_access_permitted(currd, fp, fp + np - 1) ||
382
0
                  xsm_ioport_permission(XSM_HOOK, d, fp, fp + np - 1, allow) )
383
0
            ret = -EPERM;
384
0
        else if ( allow )
385
0
            ret = ioports_permit_access(d, fp, fp + np - 1);
386
0
        else
387
0
            ret = ioports_deny_access(d, fp, fp + np - 1);
388
0
        if ( !ret )
389
0
            memory_type_changed(d);
390
0
        break;
391
0
    }
392
0
393
0
    case XEN_DOMCTL_getmemlist:
394
0
    {
395
0
        unsigned long max_pfns = domctl->u.getmemlist.max_pfns;
396
0
        uint64_t mfn;
397
0
        struct page_info *page;
398
0
399
0
        if ( unlikely(d->is_dying) )
400
0
        {
401
0
            ret = -EINVAL;
402
0
            break;
403
0
        }
404
0
405
0
        /*
406
0
         * XSA-74: This sub-hypercall is broken in several ways:
407
0
         * - lock order inversion (p2m locks inside page_alloc_lock)
408
0
         * - no preemption on huge max_pfns input
409
0
         * - not (re-)checking d->is_dying with page_alloc_lock held
410
0
         * - not honoring start_pfn input (which libxc also doesn't set)
411
0
         * Additionally it is rather useless, as the result is stale by the
412
0
         * time the caller gets to look at it.
413
0
         * As it only has a single, non-production consumer (xen-mceinj),
414
0
         * rather than trying to fix it we restrict it for the time being.
415
0
         */
416
0
        if ( /* No nested locks inside copy_to_guest_offset(). */
417
0
             paging_mode_external(currd) ||
418
0
             /* Arbitrary limit capping processing time. */
419
0
             max_pfns > GB(4) / PAGE_SIZE )
420
0
        {
421
0
            ret = -EOPNOTSUPP;
422
0
            break;
423
0
        }
424
0
425
0
        spin_lock(&d->page_alloc_lock);
426
0
427
0
        ret = i = 0;
428
0
        page_list_for_each(page, &d->page_list)
429
0
        {
430
0
            if ( i >= max_pfns )
431
0
                break;
432
0
            mfn = page_to_mfn(page);
433
0
            if ( copy_to_guest_offset(domctl->u.getmemlist.buffer,
434
0
                                      i, &mfn, 1) )
435
0
            {
436
0
                ret = -EFAULT;
437
0
                break;
438
0
            }
439
0
      ++i;
440
0
    }
441
0
442
0
        spin_unlock(&d->page_alloc_lock);
443
0
444
0
        domctl->u.getmemlist.num_pfns = i;
445
0
        copyback = true;
446
0
        break;
447
0
    }
448
0
449
0
    case XEN_DOMCTL_getpageframeinfo3:
450
0
    {
451
0
        unsigned int num = domctl->u.getpageframeinfo3.num;
452
0
        unsigned int width = has_32bit_shinfo(currd) ? 4 : 8;
453
0
454
0
        /* Games to allow this code block to handle a compat guest. */
455
0
        void __user *guest_handle = domctl->u.getpageframeinfo3.array.p;
456
0
457
0
        if ( unlikely(num > 1024) ||
458
0
             unlikely(num != domctl->u.getpageframeinfo3.num) )
459
0
        {
460
0
            ret = -E2BIG;
461
0
            break;
462
0
        }
463
0
464
0
        for ( i = 0; i < num; ++i )
465
0
        {
466
0
            unsigned long gfn = 0, type = 0;
467
0
            struct page_info *page;
468
0
            p2m_type_t t;
469
0
470
0
            if ( raw_copy_from_guest(&gfn, guest_handle + (i * width), width) )
471
0
            {
472
0
                ret = -EFAULT;
473
0
                break;
474
0
            }
475
0
476
0
            page = get_page_from_gfn(d, gfn, &t, P2M_ALLOC);
477
0
478
0
            if ( unlikely(!page) ||
479
0
                 unlikely(is_xen_heap_page(page)) )
480
0
            {
481
0
                if ( unlikely(p2m_is_broken(t)) )
482
0
                    type = XEN_DOMCTL_PFINFO_BROKEN;
483
0
                else
484
0
                    type = XEN_DOMCTL_PFINFO_XTAB;
485
0
            }
486
0
            else
487
0
            {
488
0
                switch( page->u.inuse.type_info & PGT_type_mask )
489
0
                {
490
0
                case PGT_l1_page_table:
491
0
                    type = XEN_DOMCTL_PFINFO_L1TAB;
492
0
                    break;
493
0
                case PGT_l2_page_table:
494
0
                    type = XEN_DOMCTL_PFINFO_L2TAB;
495
0
                    break;
496
0
                case PGT_l3_page_table:
497
0
                    type = XEN_DOMCTL_PFINFO_L3TAB;
498
0
                    break;
499
0
                case PGT_l4_page_table:
500
0
                    type = XEN_DOMCTL_PFINFO_L4TAB;
501
0
                    break;
502
0
                }
503
0
504
0
                if ( page->u.inuse.type_info & PGT_pinned )
505
0
                    type |= XEN_DOMCTL_PFINFO_LPINTAB;
506
0
507
0
                if ( page->count_info & PGC_broken )
508
0
                    type = XEN_DOMCTL_PFINFO_BROKEN;
509
0
            }
510
0
511
0
            if ( page )
512
0
                put_page(page);
513
0
514
0
            if ( __raw_copy_to_guest(guest_handle + (i * width), &type, width) )
515
0
            {
516
0
                ret = -EFAULT;
517
0
                break;
518
0
            }
519
0
        }
520
0
521
0
        break;
522
0
    }
523
0
524
0
    case XEN_DOMCTL_hypercall_init:
525
0
    {
526
0
        unsigned long gmfn = domctl->u.hypercall_init.gmfn;
527
0
        struct page_info *page;
528
0
        void *hypercall_page;
529
0
530
0
        page = get_page_from_gfn(d, gmfn, NULL, P2M_ALLOC);
531
0
532
0
        if ( !page || !get_page_type(page, PGT_writable_page) )
533
0
        {
534
0
            if ( page )
535
0
            {
536
0
                ret = -EPERM;
537
0
                put_page(page);
538
0
            }
539
0
            else
540
0
                ret = -EINVAL;
541
0
            break;
542
0
        }
543
0
544
0
        hypercall_page = __map_domain_page(page);
545
0
        hypercall_page_initialise(d, hypercall_page);
546
0
        unmap_domain_page(hypercall_page);
547
0
548
0
        put_page_and_type(page);
549
0
        break;
550
0
    }
551
0
552
0
    case XEN_DOMCTL_sethvmcontext:
553
0
    {
554
0
        struct hvm_domain_context c = { .size = domctl->u.hvmcontext.size };
555
0
556
0
        ret = -EINVAL;
557
0
        if ( (d == currd) || /* no domain_pause() */
558
0
             !is_hvm_domain(d) )
559
0
            goto sethvmcontext_out;
560
0
561
0
        ret = -ENOMEM;
562
0
        if ( (c.data = xmalloc_bytes(c.size)) == NULL )
563
0
            goto sethvmcontext_out;
564
0
565
0
        ret = -EFAULT;
566
0
        if ( copy_from_guest(c.data, domctl->u.hvmcontext.buffer, c.size) != 0 )
567
0
            goto sethvmcontext_out;
568
0
569
0
        domain_pause(d);
570
0
        ret = hvm_load(d, &c);
571
0
        domain_unpause(d);
572
0
573
0
    sethvmcontext_out:
574
0
        xfree(c.data);
575
0
        break;
576
0
    }
577
0
578
0
    case XEN_DOMCTL_gethvmcontext:
579
0
    {
580
0
        struct hvm_domain_context c = { 0 };
581
0
582
0
        ret = -EINVAL;
583
0
        if ( (d == currd) || /* no domain_pause() */
584
0
             !is_hvm_domain(d) )
585
0
            goto gethvmcontext_out;
586
0
587
0
        c.size = hvm_save_size(d);
588
0
589
0
        if ( guest_handle_is_null(domctl->u.hvmcontext.buffer) )
590
0
        {
591
0
            /* Client is querying for the correct buffer size */
592
0
            domctl->u.hvmcontext.size = c.size;
593
0
            ret = 0;
594
0
            goto gethvmcontext_out;
595
0
        }
596
0
597
0
        /* Check that the client has a big enough buffer */
598
0
        ret = -ENOSPC;
599
0
        if ( domctl->u.hvmcontext.size < c.size )
600
0
            goto gethvmcontext_out;
601
0
602
0
        /* Allocate our own marshalling buffer */
603
0
        ret = -ENOMEM;
604
0
        if ( (c.data = xmalloc_bytes(c.size)) == NULL )
605
0
            goto gethvmcontext_out;
606
0
607
0
        domain_pause(d);
608
0
        ret = hvm_save(d, &c);
609
0
        domain_unpause(d);
610
0
611
0
        domctl->u.hvmcontext.size = c.cur;
612
0
        if ( copy_to_guest(domctl->u.hvmcontext.buffer, c.data, c.size) != 0 )
613
0
            ret = -EFAULT;
614
0
615
0
    gethvmcontext_out:
616
0
        copyback = true;
617
0
        xfree(c.data);
618
0
        break;
619
0
    }
620
0
621
0
    case XEN_DOMCTL_gethvmcontext_partial:
622
0
        ret = -EINVAL;
623
0
        if ( (d == currd) || /* no domain_pause() */
624
0
             !is_hvm_domain(d) )
625
0
            break;
626
0
627
0
        domain_pause(d);
628
0
        ret = hvm_save_one(d, domctl->u.hvmcontext_partial.type,
629
0
                           domctl->u.hvmcontext_partial.instance,
630
0
                           domctl->u.hvmcontext_partial.buffer,
631
0
                           &domctl->u.hvmcontext_partial.bufsz);
632
0
        domain_unpause(d);
633
0
634
0
        if ( !ret )
635
0
            copyback = true;
636
0
        break;
637
0
638
0
    case XEN_DOMCTL_set_address_size:
639
0
        if ( ((domctl->u.address_size.size == 64) && !d->arch.is_32bit_pv) ||
640
0
             ((domctl->u.address_size.size == 32) && d->arch.is_32bit_pv) )
641
0
            ret = 0;
642
0
        else if ( domctl->u.address_size.size == 32 )
643
0
            ret = switch_compat(d);
644
0
        else
645
0
            ret = -EINVAL;
646
0
        break;
647
0
648
0
    case XEN_DOMCTL_get_address_size:
649
0
        domctl->u.address_size.size = is_pv_32bit_domain(d) ? 32 :
650
0
                                                              BITS_PER_LONG;
651
0
        copyback = true;
652
0
        break;
653
0
654
0
    case XEN_DOMCTL_set_machine_address_size:
655
0
        if ( d->tot_pages > 0 )
656
0
            ret = -EBUSY;
657
0
        else
658
0
            d->arch.physaddr_bitsize = domctl->u.address_size.size;
659
0
        break;
660
0
661
0
    case XEN_DOMCTL_get_machine_address_size:
662
0
        domctl->u.address_size.size = d->arch.physaddr_bitsize;
663
0
        copyback = true;
664
0
        break;
665
0
666
0
    case XEN_DOMCTL_sendtrigger:
667
0
    {
668
0
        struct vcpu *v;
669
0
670
0
        ret = -ESRCH;
671
0
        if ( domctl->u.sendtrigger.vcpu >= d->max_vcpus ||
672
0
             (v = d->vcpu[domctl->u.sendtrigger.vcpu]) == NULL )
673
0
            break;
674
0
675
0
        switch ( domctl->u.sendtrigger.trigger )
676
0
        {
677
0
        case XEN_DOMCTL_SENDTRIGGER_NMI:
678
0
            ret = 0;
679
0
            if ( !test_and_set_bool(v->nmi_pending) )
680
0
                vcpu_kick(v);
681
0
            break;
682
0
683
0
        case XEN_DOMCTL_SENDTRIGGER_POWER:
684
0
            ret = -EINVAL;
685
0
            if ( is_hvm_domain(d) )
686
0
            {
687
0
                ret = 0;
688
0
                hvm_acpi_power_button(d);
689
0
            }
690
0
            break;
691
0
692
0
        case XEN_DOMCTL_SENDTRIGGER_SLEEP:
693
0
            ret = -EINVAL;
694
0
            if ( is_hvm_domain(d) )
695
0
            {
696
0
                ret = 0;
697
0
                hvm_acpi_sleep_button(d);
698
0
            }
699
0
            break;
700
0
701
0
        default:
702
0
            ret = -ENOSYS;
703
0
        }
704
0
        break;
705
0
    }
706
0
707
0
    case XEN_DOMCTL_bind_pt_irq:
708
0
    {
709
0
        struct xen_domctl_bind_pt_irq *bind = &domctl->u.bind_pt_irq;
710
0
        int irq;
711
0
712
0
        ret = -EINVAL;
713
0
        if ( !is_hvm_domain(d) )
714
0
            break;
715
0
716
0
        ret = xsm_bind_pt_irq(XSM_HOOK, d, bind);
717
0
        if ( ret )
718
0
            break;
719
0
720
0
        irq = domain_pirq_to_irq(d, bind->machine_irq);
721
0
        ret = -EPERM;
722
0
        if ( irq <= 0 || !irq_access_permitted(currd, irq) )
723
0
            break;
724
0
725
0
        ret = -ESRCH;
726
0
        if ( iommu_enabled )
727
0
        {
728
0
            pcidevs_lock();
729
0
            ret = pt_irq_create_bind(d, bind);
730
0
            pcidevs_unlock();
731
0
        }
732
0
        if ( ret < 0 )
733
0
            printk(XENLOG_G_ERR "pt_irq_create_bind failed (%ld) for dom%d\n",
734
0
                   ret, d->domain_id);
735
0
        break;
736
0
    }
737
0
738
0
    case XEN_DOMCTL_unbind_pt_irq:
739
0
    {
740
0
        struct xen_domctl_bind_pt_irq *bind = &domctl->u.bind_pt_irq;
741
0
        int irq = domain_pirq_to_irq(d, bind->machine_irq);
742
0
743
0
        ret = -EPERM;
744
0
        if ( irq <= 0 || !irq_access_permitted(currd, irq) )
745
0
            break;
746
0
747
0
        ret = xsm_unbind_pt_irq(XSM_HOOK, d, bind);
748
0
        if ( ret )
749
0
            break;
750
0
751
0
        if ( iommu_enabled )
752
0
        {
753
0
            pcidevs_lock();
754
0
            ret = pt_irq_destroy_bind(d, bind);
755
0
            pcidevs_unlock();
756
0
        }
757
0
        if ( ret < 0 )
758
0
            printk(XENLOG_G_ERR "pt_irq_destroy_bind failed (%ld) for dom%d\n",
759
0
                   ret, d->domain_id);
760
0
        break;
761
0
    }
762
0
763
0
    case XEN_DOMCTL_ioport_mapping:
764
0
    {
765
0
        unsigned int fgp = domctl->u.ioport_mapping.first_gport;
766
0
        unsigned int fmp = domctl->u.ioport_mapping.first_mport;
767
0
        unsigned int np = domctl->u.ioport_mapping.nr_ports;
768
0
        unsigned int add = domctl->u.ioport_mapping.add_mapping;
769
0
        struct hvm_domain *hvm_domain;
770
0
        struct g2m_ioport *g2m_ioport;
771
0
        int found = 0;
772
0
773
0
        ret = -EOPNOTSUPP;
774
0
        if ( !is_hvm_domain(d) )
775
0
        {
776
0
            printk(XENLOG_G_ERR "ioport_map against non-HVM domain\n");
777
0
            break;
778
0
        }
779
0
780
0
        ret = -EINVAL;
781
0
        if ( ((fgp | fmp | (np - 1)) >= MAX_IOPORTS) ||
782
0
            ((fgp + np) > MAX_IOPORTS) || ((fmp + np) > MAX_IOPORTS) )
783
0
        {
784
0
            printk(XENLOG_G_ERR
785
0
                   "ioport_map:invalid:dom%d gport=%x mport=%x nr=%x\n",
786
0
                   domctl->domain, fgp, fmp, np);
787
0
            break;
788
0
        }
789
0
790
0
        ret = -EPERM;
791
0
        if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) )
792
0
            break;
793
0
794
0
        ret = xsm_ioport_mapping(XSM_HOOK, d, fmp, fmp + np - 1, add);
795
0
        if ( ret )
796
0
            break;
797
0
798
0
        hvm_domain = &d->arch.hvm_domain;
799
0
        if ( add )
800
0
        {
801
0
            printk(XENLOG_G_INFO
802
0
                   "ioport_map:add: dom%d gport=%x mport=%x nr=%x\n",
803
0
                   d->domain_id, fgp, fmp, np);
804
0
805
0
            list_for_each_entry(g2m_ioport, &hvm_domain->g2m_ioport_list, list)
806
0
                if (g2m_ioport->mport == fmp )
807
0
                {
808
0
                    g2m_ioport->gport = fgp;
809
0
                    g2m_ioport->np = np;
810
0
                    found = 1;
811
0
                    break;
812
0
                }
813
0
            if ( !found )
814
0
            {
815
0
                g2m_ioport = xmalloc(struct g2m_ioport);
816
0
                if ( !g2m_ioport )
817
0
                    ret = -ENOMEM;
818
0
            }
819
0
            if ( !found && !ret )
820
0
            {
821
0
                g2m_ioport->gport = fgp;
822
0
                g2m_ioport->mport = fmp;
823
0
                g2m_ioport->np = np;
824
0
                list_add_tail(&g2m_ioport->list, &hvm_domain->g2m_ioport_list);
825
0
            }
826
0
            if ( !ret )
827
0
                ret = ioports_permit_access(d, fmp, fmp + np - 1);
828
0
            if ( ret && !found && g2m_ioport )
829
0
            {
830
0
                list_del(&g2m_ioport->list);
831
0
                xfree(g2m_ioport);
832
0
            }
833
0
        }
834
0
        else
835
0
        {
836
0
            printk(XENLOG_G_INFO
837
0
                   "ioport_map:remove: dom%d gport=%x mport=%x nr=%x\n",
838
0
                   d->domain_id, fgp, fmp, np);
839
0
            list_for_each_entry(g2m_ioport, &hvm_domain->g2m_ioport_list, list)
840
0
                if ( g2m_ioport->mport == fmp )
841
0
                {
842
0
                    list_del(&g2m_ioport->list);
843
0
                    xfree(g2m_ioport);
844
0
                    break;
845
0
                }
846
0
            ret = ioports_deny_access(d, fmp, fmp + np - 1);
847
0
            if ( ret && is_hardware_domain(currd) )
848
0
                printk(XENLOG_ERR
849
0
                       "ioport_map: error %ld denying dom%d access to [%x,%x]\n",
850
0
                       ret, d->domain_id, fmp, fmp + np - 1);
851
0
        }
852
0
        if ( !ret )
853
0
            memory_type_changed(d);
854
0
        break;
855
0
    }
856
0
857
0
    case XEN_DOMCTL_pin_mem_cacheattr:
858
0
        ret = hvm_set_mem_pinned_cacheattr(
859
0
            d, domctl->u.pin_mem_cacheattr.start,
860
0
            domctl->u.pin_mem_cacheattr.end,
861
0
            domctl->u.pin_mem_cacheattr.type);
862
0
        break;
863
0
864
0
    case XEN_DOMCTL_set_ext_vcpucontext:
865
0
    case XEN_DOMCTL_get_ext_vcpucontext:
866
0
    {
867
0
        struct xen_domctl_ext_vcpucontext *evc = &domctl->u.ext_vcpucontext;
868
0
        struct vcpu *v;
869
0
870
0
        ret = -ESRCH;
871
0
        if ( (evc->vcpu >= d->max_vcpus) ||
872
0
             ((v = d->vcpu[evc->vcpu]) == NULL) )
873
0
            break;
874
0
875
0
        if ( domctl->cmd == XEN_DOMCTL_get_ext_vcpucontext )
876
0
        {
877
0
            if ( v == curr ) /* no vcpu_pause() */
878
0
                break;
879
0
880
0
            evc->size = sizeof(*evc);
881
0
882
0
            vcpu_pause(v);
883
0
884
0
            if ( is_pv_domain(d) )
885
0
            {
886
0
                evc->sysenter_callback_cs      =
887
0
                    v->arch.pv_vcpu.sysenter_callback_cs;
888
0
                evc->sysenter_callback_eip     =
889
0
                    v->arch.pv_vcpu.sysenter_callback_eip;
890
0
                evc->sysenter_disables_events  =
891
0
                    v->arch.pv_vcpu.sysenter_disables_events;
892
0
                evc->syscall32_callback_cs     =
893
0
                    v->arch.pv_vcpu.syscall32_callback_cs;
894
0
                evc->syscall32_callback_eip    =
895
0
                    v->arch.pv_vcpu.syscall32_callback_eip;
896
0
                evc->syscall32_disables_events =
897
0
                    v->arch.pv_vcpu.syscall32_disables_events;
898
0
            }
899
0
            else
900
0
            {
901
0
                evc->sysenter_callback_cs      = 0;
902
0
                evc->sysenter_callback_eip     = 0;
903
0
                evc->sysenter_disables_events  = 0;
904
0
                evc->syscall32_callback_cs     = 0;
905
0
                evc->syscall32_callback_eip    = 0;
906
0
                evc->syscall32_disables_events = 0;
907
0
            }
908
0
            evc->vmce.caps = v->arch.vmce.mcg_cap;
909
0
            evc->vmce.mci_ctl2_bank0 = v->arch.vmce.bank[0].mci_ctl2;
910
0
            evc->vmce.mci_ctl2_bank1 = v->arch.vmce.bank[1].mci_ctl2;
911
0
            evc->vmce.mcg_ext_ctl = v->arch.vmce.mcg_ext_ctl;
912
0
913
0
            ret = 0;
914
0
            vcpu_unpause(v);
915
0
            copyback = true;
916
0
        }
917
0
        else
918
0
        {
919
0
            if ( d == currd ) /* no domain_pause() */
920
0
                break;
921
0
            ret = -EINVAL;
922
0
            if ( evc->size < offsetof(typeof(*evc), vmce) )
923
0
                break;
924
0
            if ( is_pv_domain(d) )
925
0
            {
926
0
                if ( !is_canonical_address(evc->sysenter_callback_eip) ||
927
0
                     !is_canonical_address(evc->syscall32_callback_eip) )
928
0
                    break;
929
0
                domain_pause(d);
930
0
                fixup_guest_code_selector(d, evc->sysenter_callback_cs);
931
0
                v->arch.pv_vcpu.sysenter_callback_cs      =
932
0
                    evc->sysenter_callback_cs;
933
0
                v->arch.pv_vcpu.sysenter_callback_eip     =
934
0
                    evc->sysenter_callback_eip;
935
0
                v->arch.pv_vcpu.sysenter_disables_events  =
936
0
                    evc->sysenter_disables_events;
937
0
                fixup_guest_code_selector(d, evc->syscall32_callback_cs);
938
0
                v->arch.pv_vcpu.syscall32_callback_cs     =
939
0
                    evc->syscall32_callback_cs;
940
0
                v->arch.pv_vcpu.syscall32_callback_eip    =
941
0
                    evc->syscall32_callback_eip;
942
0
                v->arch.pv_vcpu.syscall32_disables_events =
943
0
                    evc->syscall32_disables_events;
944
0
            }
945
0
            else if ( (evc->sysenter_callback_cs & ~3) ||
946
0
                      evc->sysenter_callback_eip ||
947
0
                      (evc->syscall32_callback_cs & ~3) ||
948
0
                      evc->syscall32_callback_eip )
949
0
                break;
950
0
            else
951
0
                domain_pause(d);
952
0
953
0
            ret = vcpu_set_vmce(v, evc);
954
0
955
0
            domain_unpause(d);
956
0
        }
957
0
        break;
958
0
    }
959
0
960
0
    case XEN_DOMCTL_set_cpuid:
961
0
        if ( d == currd ) /* no domain_pause() */
962
0
            ret = -EINVAL;
963
0
        else if ( d->creation_finished )
964
0
            ret = -EEXIST; /* No changing once the domain is running. */
965
0
        else
966
0
        {
967
0
            domain_pause(d);
968
0
            ret = update_domain_cpuid_info(d, &domctl->u.cpuid);
969
0
            domain_unpause(d);
970
0
        }
971
0
        break;
972
0
973
0
    case XEN_DOMCTL_gettscinfo:
974
0
        if ( d == currd ) /* no domain_pause() */
975
0
            ret = -EINVAL;
976
0
        else
977
0
        {
978
0
            domain_pause(d);
979
0
            tsc_get_info(d, &domctl->u.tsc_info.tsc_mode,
980
0
                         &domctl->u.tsc_info.elapsed_nsec,
981
0
                         &domctl->u.tsc_info.gtsc_khz,
982
0
                         &domctl->u.tsc_info.incarnation);
983
0
            domain_unpause(d);
984
0
            copyback = true;
985
0
        }
986
0
        break;
987
0
988
0
    case XEN_DOMCTL_settscinfo:
989
0
        if ( d == currd ) /* no domain_pause() */
990
0
            ret = -EINVAL;
991
0
        else
992
0
        {
993
0
            domain_pause(d);
994
0
            tsc_set_info(d, domctl->u.tsc_info.tsc_mode,
995
0
                         domctl->u.tsc_info.elapsed_nsec,
996
0
                         domctl->u.tsc_info.gtsc_khz,
997
0
                         domctl->u.tsc_info.incarnation);
998
0
            domain_unpause(d);
999
0
        }
1000
0
        break;
1001
0
1002
0
    case XEN_DOMCTL_suppress_spurious_page_faults:
1003
0
        d->arch.suppress_spurious_page_faults = 1;
1004
0
        break;
1005
0
1006
0
    case XEN_DOMCTL_debug_op:
1007
0
    {
1008
0
        struct vcpu *v;
1009
0
1010
0
        ret = -EINVAL;
1011
0
        if ( (domctl->u.debug_op.vcpu >= d->max_vcpus) ||
1012
0
             ((v = d->vcpu[domctl->u.debug_op.vcpu]) == NULL) )
1013
0
            break;
1014
0
1015
0
        ret = -EINVAL;
1016
0
        if ( (v == curr) || /* no vcpu_pause() */
1017
0
             !is_hvm_domain(d) )
1018
0
            break;
1019
0
1020
0
        ret = hvm_debug_op(v, domctl->u.debug_op.op);
1021
0
        break;
1022
0
    }
1023
0
1024
0
    case XEN_DOMCTL_gdbsx_guestmemio:
1025
0
        domctl->u.gdbsx_guest_memio.remain = domctl->u.gdbsx_guest_memio.len;
1026
0
        ret = gdbsx_guest_mem_io(domctl->domain, &domctl->u.gdbsx_guest_memio);
1027
0
        if ( !ret )
1028
0
           copyback = true;
1029
0
        break;
1030
0
1031
0
    case XEN_DOMCTL_gdbsx_pausevcpu:
1032
0
    {
1033
0
        struct vcpu *v;
1034
0
1035
0
        ret = -EBUSY;
1036
0
        if ( !d->controller_pause_count )
1037
0
            break;
1038
0
        ret = -EINVAL;
1039
0
        if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= d->max_vcpus ||
1040
0
             (v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == NULL )
1041
0
            break;
1042
0
        ret = vcpu_pause_by_systemcontroller(v);
1043
0
        break;
1044
0
    }
1045
0
1046
0
    case XEN_DOMCTL_gdbsx_unpausevcpu:
1047
0
    {
1048
0
        struct vcpu *v;
1049
0
1050
0
        ret = -EBUSY;
1051
0
        if ( !d->controller_pause_count )
1052
0
            break;
1053
0
        ret = -EINVAL;
1054
0
        if ( domctl->u.gdbsx_pauseunp_vcpu.vcpu >= d->max_vcpus ||
1055
0
             (v = d->vcpu[domctl->u.gdbsx_pauseunp_vcpu.vcpu]) == NULL )
1056
0
            break;
1057
0
        ret = vcpu_unpause_by_systemcontroller(v);
1058
0
        if ( ret == -EINVAL )
1059
0
            printk(XENLOG_G_WARNING
1060
0
                   "WARN: d%d attempting to unpause %pv which is not paused\n",
1061
0
                   currd->domain_id, v);
1062
0
        break;
1063
0
    }
1064
0
1065
0
    case XEN_DOMCTL_gdbsx_domstatus:
1066
0
    {
1067
0
        struct vcpu *v;
1068
0
1069
0
        domctl->u.gdbsx_domstatus.vcpu_id = -1;
1070
0
        domctl->u.gdbsx_domstatus.paused = d->controller_pause_count > 0;
1071
0
        if ( domctl->u.gdbsx_domstatus.paused )
1072
0
        {
1073
0
            for_each_vcpu ( d, v )
1074
0
            {
1075
0
                if ( v->arch.gdbsx_vcpu_event )
1076
0
                {
1077
0
                    domctl->u.gdbsx_domstatus.vcpu_id = v->vcpu_id;
1078
0
                    domctl->u.gdbsx_domstatus.vcpu_ev =
1079
0
                        v->arch.gdbsx_vcpu_event;
1080
0
                    v->arch.gdbsx_vcpu_event = 0;
1081
0
                    break;
1082
0
                }
1083
0
            }
1084
0
        }
1085
0
        copyback = true;
1086
0
        break;
1087
0
    }
1088
0
1089
0
    case XEN_DOMCTL_setvcpuextstate:
1090
0
    case XEN_DOMCTL_getvcpuextstate:
1091
0
    {
1092
0
        struct xen_domctl_vcpuextstate *evc = &domctl->u.vcpuextstate;
1093
0
        struct vcpu *v;
1094
0
        uint32_t offset = 0;
1095
0
1096
0
#define PV_XSAVE_HDR_SIZE (2 * sizeof(uint64_t))
1097
0
#define PV_XSAVE_SIZE(xcr0) (PV_XSAVE_HDR_SIZE + xstate_ctxt_size(xcr0))
1098
0
1099
0
        ret = -ESRCH;
1100
0
        if ( (evc->vcpu >= d->max_vcpus) ||
1101
0
             ((v = d->vcpu[evc->vcpu]) == NULL) )
1102
0
            goto vcpuextstate_out;
1103
0
1104
0
        ret = -EINVAL;
1105
0
        if ( v == curr ) /* no vcpu_pause() */
1106
0
            goto vcpuextstate_out;
1107
0
1108
0
        if ( domctl->cmd == XEN_DOMCTL_getvcpuextstate )
1109
0
        {
1110
0
            unsigned int size;
1111
0
1112
0
            ret = 0;
1113
0
1114
0
            if ( (!evc->size && !evc->xfeature_mask) ||
1115
0
                 guest_handle_is_null(evc->buffer) )
1116
0
            {
1117
0
                /*
1118
0
                 * A query for the size of buffer to use.  Must return the
1119
0
                 * maximum size we ever might hand back to userspace, bearing
1120
0
                 * in mind that the vcpu might increase its xcr0_accum between
1121
0
                 * this query for size, and the following query for data.
1122
0
                 */
1123
0
                evc->xfeature_mask = xfeature_mask;
1124
0
                evc->size = PV_XSAVE_SIZE(xfeature_mask);
1125
0
                goto vcpuextstate_out;
1126
0
            }
1127
0
1128
0
            vcpu_pause(v);
1129
0
            size = PV_XSAVE_SIZE(v->arch.xcr0_accum);
1130
0
1131
0
            if ( evc->size < size || evc->xfeature_mask != xfeature_mask )
1132
0
                ret = -EINVAL;
1133
0
1134
0
            if ( !ret && copy_to_guest_offset(evc->buffer, offset,
1135
0
                                              (void *)&v->arch.xcr0,
1136
0
                                              sizeof(v->arch.xcr0)) )
1137
0
                ret = -EFAULT;
1138
0
1139
0
            offset += sizeof(v->arch.xcr0);
1140
0
            if ( !ret && copy_to_guest_offset(evc->buffer, offset,
1141
0
                                              (void *)&v->arch.xcr0_accum,
1142
0
                                              sizeof(v->arch.xcr0_accum)) )
1143
0
                ret = -EFAULT;
1144
0
1145
0
            offset += sizeof(v->arch.xcr0_accum);
1146
0
1147
0
            /* Serialise xsave state, if there is any. */
1148
0
            if ( !ret && size > PV_XSAVE_HDR_SIZE )
1149
0
            {
1150
0
                unsigned int xsave_size = size - PV_XSAVE_HDR_SIZE;
1151
0
                void *xsave_area = xmalloc_bytes(xsave_size);
1152
0
1153
0
                if ( !xsave_area )
1154
0
                {
1155
0
                    ret = -ENOMEM;
1156
0
                    vcpu_unpause(v);
1157
0
                    goto vcpuextstate_out;
1158
0
                }
1159
0
1160
0
                expand_xsave_states(v, xsave_area, xsave_size);
1161
0
1162
0
                if ( copy_to_guest_offset(evc->buffer, offset, xsave_area,
1163
0
                                          xsave_size) )
1164
0
                     ret = -EFAULT;
1165
0
                xfree(xsave_area);
1166
0
           }
1167
0
1168
0
            vcpu_unpause(v);
1169
0
1170
0
            /* Specify how much data we actually wrote into the buffer. */
1171
0
            if ( !ret )
1172
0
                evc->size = size;
1173
0
        }
1174
0
        else
1175
0
        {
1176
0
            void *receive_buf;
1177
0
            uint64_t _xcr0, _xcr0_accum;
1178
0
            const struct xsave_struct *_xsave_area;
1179
0
1180
0
            ret = -EINVAL;
1181
0
            if ( evc->size < PV_XSAVE_HDR_SIZE ||
1182
0
                 evc->size > PV_XSAVE_SIZE(xfeature_mask) )
1183
0
                goto vcpuextstate_out;
1184
0
1185
0
            receive_buf = xmalloc_bytes(evc->size);
1186
0
            if ( !receive_buf )
1187
0
            {
1188
0
                ret = -ENOMEM;
1189
0
                goto vcpuextstate_out;
1190
0
            }
1191
0
            if ( copy_from_guest_offset(receive_buf, domctl->u.vcpuextstate.buffer,
1192
0
                                        offset, evc->size) )
1193
0
            {
1194
0
                ret = -EFAULT;
1195
0
                xfree(receive_buf);
1196
0
                goto vcpuextstate_out;
1197
0
            }
1198
0
1199
0
            _xcr0 = *(uint64_t *)receive_buf;
1200
0
            _xcr0_accum = *(uint64_t *)(receive_buf + sizeof(uint64_t));
1201
0
            _xsave_area = receive_buf + PV_XSAVE_HDR_SIZE;
1202
0
1203
0
            if ( _xcr0_accum )
1204
0
            {
1205
0
                if ( evc->size >= PV_XSAVE_HDR_SIZE + XSTATE_AREA_MIN_SIZE )
1206
0
                    ret = validate_xstate(_xcr0, _xcr0_accum,
1207
0
                                          &_xsave_area->xsave_hdr);
1208
0
            }
1209
0
            else if ( !_xcr0 )
1210
0
                ret = 0;
1211
0
            if ( ret )
1212
0
            {
1213
0
                xfree(receive_buf);
1214
0
                goto vcpuextstate_out;
1215
0
            }
1216
0
1217
0
            if ( evc->size == PV_XSAVE_HDR_SIZE )
1218
0
                ; /* Nothing to restore. */
1219
0
            else if ( evc->size < PV_XSAVE_HDR_SIZE + XSTATE_AREA_MIN_SIZE )
1220
0
                ret = -EINVAL; /* Can't be legitimate data. */
1221
0
            else if ( xsave_area_compressed(_xsave_area) )
1222
0
                ret = -EOPNOTSUPP; /* Don't support compressed data. */
1223
0
            else if ( evc->size != PV_XSAVE_SIZE(_xcr0_accum) )
1224
0
                ret = -EINVAL; /* Not legitimate data. */
1225
0
            else
1226
0
            {
1227
0
                vcpu_pause(v);
1228
0
                v->arch.xcr0 = _xcr0;
1229
0
                v->arch.xcr0_accum = _xcr0_accum;
1230
0
                if ( _xcr0_accum & XSTATE_NONLAZY )
1231
0
                    v->arch.nonlazy_xstate_used = 1;
1232
0
                compress_xsave_states(v, _xsave_area,
1233
0
                                      evc->size - PV_XSAVE_HDR_SIZE);
1234
0
                vcpu_unpause(v);
1235
0
            }
1236
0
1237
0
            xfree(receive_buf);
1238
0
        }
1239
0
1240
0
#undef PV_XSAVE_HDR_SIZE
1241
0
#undef PV_XSAVE_SIZE
1242
0
1243
0
    vcpuextstate_out:
1244
0
        if ( domctl->cmd == XEN_DOMCTL_getvcpuextstate )
1245
0
            copyback = true;
1246
0
        break;
1247
0
    }
1248
0
1249
0
    case XEN_DOMCTL_mem_sharing_op:
1250
0
        ret = mem_sharing_domctl(d, &domctl->u.mem_sharing_op);
1251
0
        break;
1252
0
1253
0
#if P2M_AUDIT
1254
0
    case XEN_DOMCTL_audit_p2m:
1255
0
        if ( d == currd )
1256
0
            ret = -EPERM;
1257
0
        else
1258
0
        {
1259
0
            audit_p2m(d,
1260
0
                      &domctl->u.audit_p2m.orphans,
1261
0
                      &domctl->u.audit_p2m.m2p_bad,
1262
0
                      &domctl->u.audit_p2m.p2m_bad);
1263
0
            copyback = true;
1264
0
        }
1265
0
        break;
1266
0
#endif /* P2M_AUDIT */
1267
0
1268
0
    case XEN_DOMCTL_set_broken_page_p2m:
1269
0
    {
1270
0
        p2m_type_t pt;
1271
0
        unsigned long pfn = domctl->u.set_broken_page_p2m.pfn;
1272
0
        mfn_t mfn = get_gfn_query(d, pfn, &pt);
1273
0
1274
0
        if ( unlikely(!mfn_valid(mfn)) || unlikely(!p2m_is_ram(pt)) )
1275
0
            ret = -EINVAL;
1276
0
        else
1277
0
            ret = p2m_change_type_one(d, pfn, pt, p2m_ram_broken);
1278
0
1279
0
        put_gfn(d, pfn);
1280
0
        break;
1281
0
    }
1282
0
1283
0
    case XEN_DOMCTL_get_vcpu_msrs:
1284
0
    case XEN_DOMCTL_set_vcpu_msrs:
1285
0
    {
1286
0
        struct xen_domctl_vcpu_msrs *vmsrs = &domctl->u.vcpu_msrs;
1287
0
        struct xen_domctl_vcpu_msr msr;
1288
0
        struct vcpu *v;
1289
0
        uint32_t nr_msrs = 0;
1290
0
1291
0
        ret = -ESRCH;
1292
0
        if ( (vmsrs->vcpu >= d->max_vcpus) ||
1293
0
             ((v = d->vcpu[vmsrs->vcpu]) == NULL) )
1294
0
            break;
1295
0
1296
0
        ret = -EINVAL;
1297
0
        if ( (v == curr) || /* no vcpu_pause() */
1298
0
             !is_pv_domain(d) )
1299
0
            break;
1300
0
1301
0
        /* Count maximum number of optional msrs. */
1302
0
        if ( boot_cpu_has(X86_FEATURE_DBEXT) )
1303
0
            nr_msrs += 4;
1304
0
1305
0
        if ( domctl->cmd == XEN_DOMCTL_get_vcpu_msrs )
1306
0
        {
1307
0
            ret = 0; copyback = true;
1308
0
1309
0
            /* NULL guest handle is a request for max size. */
1310
0
            if ( guest_handle_is_null(vmsrs->msrs) )
1311
0
                vmsrs->msr_count = nr_msrs;
1312
0
            else
1313
0
            {
1314
0
                i = 0;
1315
0
1316
0
                vcpu_pause(v);
1317
0
1318
0
                if ( boot_cpu_has(X86_FEATURE_DBEXT) )
1319
0
                {
1320
0
                    unsigned int j;
1321
0
1322
0
                    if ( v->arch.pv_vcpu.dr_mask[0] )
1323
0
                    {
1324
0
                        if ( i < vmsrs->msr_count && !ret )
1325
0
                        {
1326
0
                            msr.index = MSR_AMD64_DR0_ADDRESS_MASK;
1327
0
                            msr.reserved = 0;
1328
0
                            msr.value = v->arch.pv_vcpu.dr_mask[0];
1329
0
                            if ( copy_to_guest_offset(vmsrs->msrs, i, &msr, 1) )
1330
0
                                ret = -EFAULT;
1331
0
                        }
1332
0
                        ++i;
1333
0
                    }
1334
0
1335
0
                    for ( j = 0; j < 3; ++j )
1336
0
                    {
1337
0
                        if ( !v->arch.pv_vcpu.dr_mask[1 + j] )
1338
0
                            continue;
1339
0
                        if ( i < vmsrs->msr_count && !ret )
1340
0
                        {
1341
0
                            msr.index = MSR_AMD64_DR1_ADDRESS_MASK + j;
1342
0
                            msr.reserved = 0;
1343
0
                            msr.value = v->arch.pv_vcpu.dr_mask[1 + j];
1344
0
                            if ( copy_to_guest_offset(vmsrs->msrs, i, &msr, 1) )
1345
0
                                ret = -EFAULT;
1346
0
                        }
1347
0
                        ++i;
1348
0
                    }
1349
0
                }
1350
0
1351
0
                vcpu_unpause(v);
1352
0
1353
0
                if ( i > vmsrs->msr_count && !ret )
1354
0
                    ret = -ENOBUFS;
1355
0
                vmsrs->msr_count = i;
1356
0
            }
1357
0
        }
1358
0
        else
1359
0
        {
1360
0
            ret = -EINVAL;
1361
0
            if ( vmsrs->msr_count > nr_msrs )
1362
0
                break;
1363
0
1364
0
            vcpu_pause(v);
1365
0
1366
0
            for ( i = 0; i < vmsrs->msr_count; ++i )
1367
0
            {
1368
0
                ret = -EFAULT;
1369
0
                if ( copy_from_guest_offset(&msr, vmsrs->msrs, i, 1) )
1370
0
                    break;
1371
0
1372
0
                ret = -EINVAL;
1373
0
                if ( msr.reserved )
1374
0
                    break;
1375
0
1376
0
                switch ( msr.index )
1377
0
                {
1378
0
                case MSR_AMD64_DR0_ADDRESS_MASK:
1379
0
                    if ( !boot_cpu_has(X86_FEATURE_DBEXT) ||
1380
0
                         (msr.value >> 32) )
1381
0
                        break;
1382
0
                    v->arch.pv_vcpu.dr_mask[0] = msr.value;
1383
0
                    continue;
1384
0
1385
0
                case MSR_AMD64_DR1_ADDRESS_MASK ...
1386
0
                    MSR_AMD64_DR3_ADDRESS_MASK:
1387
0
                    if ( !boot_cpu_has(X86_FEATURE_DBEXT) ||
1388
0
                         (msr.value >> 32) )
1389
0
                        break;
1390
0
                    msr.index -= MSR_AMD64_DR1_ADDRESS_MASK - 1;
1391
0
                    v->arch.pv_vcpu.dr_mask[msr.index] = msr.value;
1392
0
                    continue;
1393
0
                }
1394
0
                break;
1395
0
            }
1396
0
1397
0
            vcpu_unpause(v);
1398
0
1399
0
            if ( i == vmsrs->msr_count )
1400
0
                ret = 0;
1401
0
            else
1402
0
            {
1403
0
                vmsrs->msr_count = i;
1404
0
                copyback = true;
1405
0
            }
1406
0
        }
1407
0
        break;
1408
0
    }
1409
0
1410
0
    case XEN_DOMCTL_psr_cmt_op:
1411
0
        if ( !psr_cmt_enabled() )
1412
0
        {
1413
0
            ret = -ENODEV;
1414
0
            break;
1415
0
        }
1416
0
1417
0
        switch ( domctl->u.psr_cmt_op.cmd )
1418
0
        {
1419
0
        case XEN_DOMCTL_PSR_CMT_OP_ATTACH:
1420
0
            ret = psr_alloc_rmid(d);
1421
0
            break;
1422
0
1423
0
        case XEN_DOMCTL_PSR_CMT_OP_DETACH:
1424
0
            if ( d->arch.psr_rmid > 0 )
1425
0
                psr_free_rmid(d);
1426
0
            else
1427
0
                ret = -ENOENT;
1428
0
            break;
1429
0
1430
0
        case XEN_DOMCTL_PSR_CMT_OP_QUERY_RMID:
1431
0
            domctl->u.psr_cmt_op.data = d->arch.psr_rmid;
1432
0
            copyback = true;
1433
0
            break;
1434
0
1435
0
        default:
1436
0
            ret = -ENOSYS;
1437
0
            break;
1438
0
        }
1439
0
        break;
1440
0
1441
0
    case XEN_DOMCTL_psr_cat_op:
1442
0
        switch ( domctl->u.psr_cat_op.cmd )
1443
0
        {
1444
0
            uint32_t val32;
1445
0
1446
0
        case XEN_DOMCTL_PSR_CAT_OP_SET_L3_CBM:
1447
0
            ret = psr_set_val(d, domctl->u.psr_cat_op.target,
1448
0
                              domctl->u.psr_cat_op.data,
1449
0
                              PSR_CBM_TYPE_L3);
1450
0
            break;
1451
0
1452
0
        case XEN_DOMCTL_PSR_CAT_OP_SET_L3_CODE:
1453
0
            ret = psr_set_val(d, domctl->u.psr_cat_op.target,
1454
0
                              domctl->u.psr_cat_op.data,
1455
0
                              PSR_CBM_TYPE_L3_CODE);
1456
0
            break;
1457
0
1458
0
        case XEN_DOMCTL_PSR_CAT_OP_SET_L3_DATA:
1459
0
            ret = psr_set_val(d, domctl->u.psr_cat_op.target,
1460
0
                              domctl->u.psr_cat_op.data,
1461
0
                              PSR_CBM_TYPE_L3_DATA);
1462
0
            break;
1463
0
1464
0
        case XEN_DOMCTL_PSR_CAT_OP_SET_L2_CBM:
1465
0
            ret = psr_set_val(d, domctl->u.psr_cat_op.target,
1466
0
                              domctl->u.psr_cat_op.data,
1467
0
                              PSR_CBM_TYPE_L2);
1468
0
            break;
1469
0
1470
0
        case XEN_DOMCTL_PSR_CAT_OP_GET_L3_CBM:
1471
0
            ret = psr_get_val(d, domctl->u.psr_cat_op.target,
1472
0
                              &val32, PSR_CBM_TYPE_L3);
1473
0
            domctl->u.psr_cat_op.data = val32;
1474
0
            copyback = true;
1475
0
            break;
1476
0
1477
0
        case XEN_DOMCTL_PSR_CAT_OP_GET_L3_CODE:
1478
0
            ret = psr_get_val(d, domctl->u.psr_cat_op.target,
1479
0
                              &val32, PSR_CBM_TYPE_L3_CODE);
1480
0
            domctl->u.psr_cat_op.data = val32;
1481
0
            copyback = true;
1482
0
            break;
1483
0
1484
0
        case XEN_DOMCTL_PSR_CAT_OP_GET_L3_DATA:
1485
0
            ret = psr_get_val(d, domctl->u.psr_cat_op.target,
1486
0
                              &val32, PSR_CBM_TYPE_L3_DATA);
1487
0
            domctl->u.psr_cat_op.data = val32;
1488
0
            copyback = true;
1489
0
            break;
1490
0
1491
0
        case XEN_DOMCTL_PSR_CAT_OP_GET_L2_CBM:
1492
0
            ret = psr_get_val(d, domctl->u.psr_cat_op.target,
1493
0
                              &val32, PSR_CBM_TYPE_L2);
1494
0
            domctl->u.psr_cat_op.data = val32;
1495
0
            copyback = true;
1496
0
            break;
1497
0
1498
0
        default:
1499
0
            ret = -EOPNOTSUPP;
1500
0
            break;
1501
0
        }
1502
0
        break;
1503
0
1504
0
    case XEN_DOMCTL_disable_migrate:
1505
0
        d->disable_migrate = domctl->u.disable_migrate.disable;
1506
0
        recalculate_cpuid_policy(d);
1507
0
        break;
1508
0
1509
0
    default:
1510
0
        ret = iommu_do_domctl(domctl, d, u_domctl);
1511
0
        break;
1512
0
    }
1513
0
1514
0
    if ( copyback && __copy_to_guest(u_domctl, domctl, 1) )
1515
0
        ret = -EFAULT;
1516
0
1517
0
    return ret;
1518
0
}
1519
1520
#define xen_vcpu_guest_context vcpu_guest_context
1521
#define fpu_ctxt fpu_ctxt.x
1522
CHECK_FIELD_(struct, vcpu_guest_context, fpu_ctxt);
1523
#undef fpu_ctxt
1524
#undef xen_vcpu_guest_context
1525
1526
void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
1527
0
{
1528
0
    unsigned int i;
1529
0
    const struct domain *d = v->domain;
1530
0
    bool compat = is_pv_32bit_domain(d);
1531
0
#define c(fld) (!compat ? (c.nat->fld) : (c.cmp->fld))
1532
0
1533
0
    memcpy(&c.nat->fpu_ctxt, v->arch.fpu_ctxt, sizeof(c.nat->fpu_ctxt));
1534
0
    c(flags = v->arch.vgc_flags & ~(VGCF_i387_valid|VGCF_in_kernel));
1535
0
    if ( v->fpu_initialised )
1536
0
        c(flags |= VGCF_i387_valid);
1537
0
    if ( !(v->pause_flags & VPF_down) )
1538
0
        c(flags |= VGCF_online);
1539
0
    if ( !compat )
1540
0
    {
1541
0
        memcpy(&c.nat->user_regs, &v->arch.user_regs, sizeof(c.nat->user_regs));
1542
0
        if ( is_pv_domain(d) )
1543
0
            memcpy(c.nat->trap_ctxt, v->arch.pv_vcpu.trap_ctxt,
1544
0
                   sizeof(c.nat->trap_ctxt));
1545
0
    }
1546
0
    else
1547
0
    {
1548
0
        XLAT_cpu_user_regs(&c.cmp->user_regs, &v->arch.user_regs);
1549
0
        if ( is_pv_domain(d) )
1550
0
        {
1551
0
            for ( i = 0; i < ARRAY_SIZE(c.cmp->trap_ctxt); ++i )
1552
0
                XLAT_trap_info(c.cmp->trap_ctxt + i,
1553
0
                               v->arch.pv_vcpu.trap_ctxt + i);
1554
0
        }
1555
0
    }
1556
0
1557
0
    for ( i = 0; i < ARRAY_SIZE(v->arch.debugreg); ++i )
1558
0
        c(debugreg[i] = v->arch.debugreg[i]);
1559
0
1560
0
    if ( is_hvm_domain(d) )
1561
0
    {
1562
0
        struct segment_register sreg;
1563
0
1564
0
        c.nat->ctrlreg[0] = v->arch.hvm_vcpu.guest_cr[0];
1565
0
        c.nat->ctrlreg[2] = v->arch.hvm_vcpu.guest_cr[2];
1566
0
        c.nat->ctrlreg[3] = v->arch.hvm_vcpu.guest_cr[3];
1567
0
        c.nat->ctrlreg[4] = v->arch.hvm_vcpu.guest_cr[4];
1568
0
        hvm_get_segment_register(v, x86_seg_cs, &sreg);
1569
0
        c.nat->user_regs.cs = sreg.sel;
1570
0
        hvm_get_segment_register(v, x86_seg_ss, &sreg);
1571
0
        c.nat->user_regs.ss = sreg.sel;
1572
0
        hvm_get_segment_register(v, x86_seg_ds, &sreg);
1573
0
        c.nat->user_regs.ds = sreg.sel;
1574
0
        hvm_get_segment_register(v, x86_seg_es, &sreg);
1575
0
        c.nat->user_regs.es = sreg.sel;
1576
0
        hvm_get_segment_register(v, x86_seg_fs, &sreg);
1577
0
        c.nat->user_regs.fs = sreg.sel;
1578
0
        c.nat->fs_base = sreg.base;
1579
0
        hvm_get_segment_register(v, x86_seg_gs, &sreg);
1580
0
        c.nat->user_regs.gs = sreg.sel;
1581
0
        if ( ring_0(&c.nat->user_regs) )
1582
0
        {
1583
0
            c.nat->gs_base_kernel = sreg.base;
1584
0
            c.nat->gs_base_user = hvm_get_shadow_gs_base(v);
1585
0
        }
1586
0
        else
1587
0
        {
1588
0
            c.nat->gs_base_user = sreg.base;
1589
0
            c.nat->gs_base_kernel = hvm_get_shadow_gs_base(v);
1590
0
        }
1591
0
    }
1592
0
    else
1593
0
    {
1594
0
        c(ldt_base = v->arch.pv_vcpu.ldt_base);
1595
0
        c(ldt_ents = v->arch.pv_vcpu.ldt_ents);
1596
0
        for ( i = 0; i < ARRAY_SIZE(v->arch.pv_vcpu.gdt_frames); ++i )
1597
0
            c(gdt_frames[i] = v->arch.pv_vcpu.gdt_frames[i]);
1598
0
        BUILD_BUG_ON(ARRAY_SIZE(c.nat->gdt_frames) !=
1599
0
                     ARRAY_SIZE(c.cmp->gdt_frames));
1600
0
        for ( ; i < ARRAY_SIZE(c.nat->gdt_frames); ++i )
1601
0
            c(gdt_frames[i] = 0);
1602
0
        c(gdt_ents = v->arch.pv_vcpu.gdt_ents);
1603
0
        c(kernel_ss = v->arch.pv_vcpu.kernel_ss);
1604
0
        c(kernel_sp = v->arch.pv_vcpu.kernel_sp);
1605
0
        for ( i = 0; i < ARRAY_SIZE(v->arch.pv_vcpu.ctrlreg); ++i )
1606
0
            c(ctrlreg[i] = v->arch.pv_vcpu.ctrlreg[i]);
1607
0
        c(event_callback_eip = v->arch.pv_vcpu.event_callback_eip);
1608
0
        c(failsafe_callback_eip = v->arch.pv_vcpu.failsafe_callback_eip);
1609
0
        if ( !compat )
1610
0
        {
1611
0
            c.nat->syscall_callback_eip = v->arch.pv_vcpu.syscall_callback_eip;
1612
0
            c.nat->fs_base = v->arch.pv_vcpu.fs_base;
1613
0
            c.nat->gs_base_kernel = v->arch.pv_vcpu.gs_base_kernel;
1614
0
            c.nat->gs_base_user = v->arch.pv_vcpu.gs_base_user;
1615
0
        }
1616
0
        else
1617
0
        {
1618
0
            c(event_callback_cs = v->arch.pv_vcpu.event_callback_cs);
1619
0
            c(failsafe_callback_cs = v->arch.pv_vcpu.failsafe_callback_cs);
1620
0
        }
1621
0
1622
0
        /* IOPL privileges are virtualised: merge back into returned eflags. */
1623
0
        BUG_ON((c(user_regs.eflags) & X86_EFLAGS_IOPL) != 0);
1624
0
        c(user_regs.eflags |= v->arch.pv_vcpu.iopl);
1625
0
1626
0
        if ( !compat )
1627
0
        {
1628
0
            c.nat->ctrlreg[3] = xen_pfn_to_cr3(
1629
0
                pagetable_get_pfn(v->arch.guest_table));
1630
0
            c.nat->ctrlreg[1] =
1631
0
                pagetable_is_null(v->arch.guest_table_user) ? 0
1632
0
                : xen_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table_user));
1633
0
1634
0
            /* Merge shadow DR7 bits into real DR7. */
1635
0
            c.nat->debugreg[7] |= c.nat->debugreg[5];
1636
0
            c.nat->debugreg[5] = 0;
1637
0
        }
1638
0
        else
1639
0
        {
1640
0
            const l4_pgentry_t *l4e =
1641
0
                map_domain_page(pagetable_get_mfn(v->arch.guest_table));
1642
0
1643
0
            c.cmp->ctrlreg[3] = compat_pfn_to_cr3(l4e_get_pfn(*l4e));
1644
0
            unmap_domain_page(l4e);
1645
0
1646
0
            /* Merge shadow DR7 bits into real DR7. */
1647
0
            c.cmp->debugreg[7] |= c.cmp->debugreg[5];
1648
0
            c.cmp->debugreg[5] = 0;
1649
0
        }
1650
0
1651
0
        if ( guest_kernel_mode(v, &v->arch.user_regs) )
1652
0
            c(flags |= VGCF_in_kernel);
1653
0
    }
1654
0
1655
0
    c(vm_assist = d->vm_assist);
1656
0
#undef c
1657
0
}
1658
1659
/*
1660
 * Local variables:
1661
 * mode: C
1662
 * c-file-style: "BSD"
1663
 * c-basic-offset: 4
1664
 * tab-width: 4
1665
 * indent-tabs-mode: nil
1666
 * End:
1667
 */