Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/acpi/power.c
Line
Count
Source (jump to first uncovered line)
1
/* drivers/acpi/sleep/power.c - PM core functionality for Xen
2
 *
3
 * Copyrights from Linux side:
4
 * Copyright (c) 2000-2003 Patrick Mochel
5
 * Copyright (C) 2001-2003 Pavel Machek <pavel@suse.cz>
6
 * Copyright (c) 2003 Open Source Development Lab
7
 * Copyright (c) 2004 David Shaohua Li <shaohua.li@intel.com>
8
 * Copyright (c) 2005 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
9
 *
10
 * Slimmed with Xen specific support.
11
 */
12
13
#include <asm/io.h>
14
#include <xen/acpi.h>
15
#include <xen/errno.h>
16
#include <xen/iocap.h>
17
#include <xen/sched.h>
18
#include <asm/acpi.h>
19
#include <asm/irq.h>
20
#include <asm/init.h>
21
#include <xen/spinlock.h>
22
#include <xen/sched.h>
23
#include <xen/domain.h>
24
#include <xen/console.h>
25
#include <xen/iommu.h>
26
#include <xen/cpu.h>
27
#include <public/platform.h>
28
#include <asm/tboot.h>
29
#include <asm/apic.h>
30
#include <asm/io_apic.h>
31
#include <acpi/cpufreq/cpufreq.h>
32
33
uint32_t system_reset_counter = 1;
34
35
static char __initdata opt_acpi_sleep[20];
36
string_param("acpi_sleep", opt_acpi_sleep);
37
38
static u8 sleep_states[ACPI_S_STATE_COUNT];
39
static DEFINE_SPINLOCK(pm_lock);
40
41
struct acpi_sleep_info acpi_sinfo;
42
43
void do_suspend_lowlevel(void);
44
45
enum dev_power_saved
46
{
47
    SAVED_NONE,
48
    SAVED_CONSOLE,
49
    SAVED_TIME,
50
    SAVED_I8259A,
51
    SAVED_IOAPIC,
52
    SAVED_IOMMU,
53
    SAVED_LAPIC,
54
    SAVED_ALL,
55
};
56
57
static int device_power_down(void)
58
0
{
59
0
    if ( console_suspend() )
60
0
        return SAVED_NONE;
61
0
62
0
    if ( time_suspend() )
63
0
        return SAVED_CONSOLE;
64
0
65
0
    if ( i8259A_suspend() )
66
0
        return SAVED_TIME;
67
0
68
0
    /* ioapic_suspend cannot fail */
69
0
    ioapic_suspend();
70
0
71
0
    if ( iommu_suspend() )
72
0
        return SAVED_IOAPIC;
73
0
74
0
    if ( lapic_suspend() )
75
0
        return SAVED_IOMMU;
76
0
77
0
    return SAVED_ALL;
78
0
}
79
80
static void device_power_up(enum dev_power_saved saved)
81
0
{
82
0
    switch ( saved )
83
0
    {
84
0
    case SAVED_ALL:
85
0
    case SAVED_LAPIC:
86
0
        lapic_resume();
87
0
        /* fall through */
88
0
    case SAVED_IOMMU:
89
0
        iommu_resume();
90
0
        /* fall through */
91
0
    case SAVED_IOAPIC:
92
0
        ioapic_resume();
93
0
        /* fall through */
94
0
    case SAVED_I8259A:
95
0
        i8259A_resume();
96
0
        /* fall through */
97
0
    case SAVED_TIME:
98
0
        time_resume();
99
0
        /* fall through */
100
0
    case SAVED_CONSOLE:
101
0
        console_resume();
102
0
        /* fall through */
103
0
    case SAVED_NONE:
104
0
        break;
105
0
    default:
106
0
        BUG();
107
0
        break;
108
0
    }
109
0
}
110
111
static void freeze_domains(void)
112
0
{
113
0
    struct domain *d;
114
0
115
0
    rcu_read_lock(&domlist_read_lock);
116
0
    /*
117
0
     * Note that we iterate in order of domain-id. Hence we will pause dom0
118
0
     * first which is required for correctness (as only dom0 can add domains to
119
0
     * the domain list). Otherwise we could miss concurrently-created domains.
120
0
     */
121
0
    for_each_domain ( d )
122
0
        domain_pause(d);
123
0
    rcu_read_unlock(&domlist_read_lock);
124
0
}
125
126
static void thaw_domains(void)
127
0
{
128
0
    struct domain *d;
129
0
130
0
    rcu_read_lock(&domlist_read_lock);
131
0
    for_each_domain ( d )
132
0
    {
133
0
        restore_vcpu_affinity(d);
134
0
        domain_unpause(d);
135
0
    }
136
0
    rcu_read_unlock(&domlist_read_lock);
137
0
}
138
139
static void acpi_sleep_prepare(u32 state)
140
0
{
141
0
    void *wakeup_vector_va;
142
0
143
0
    if ( state != ACPI_STATE_S3 )
144
0
        return;
145
0
146
0
    wakeup_vector_va = __acpi_map_table(
147
0
        acpi_sinfo.wakeup_vector, sizeof(uint64_t));
148
0
149
0
    /* TBoot will set resume vector itself (when it is safe to do so). */
150
0
    if ( tboot_in_measured_env() )
151
0
        return;
152
0
153
0
    if ( acpi_sinfo.vector_width == 32 )
154
0
        *(uint32_t *)wakeup_vector_va = bootsym_phys(wakeup_start);
155
0
    else
156
0
        *(uint64_t *)wakeup_vector_va = bootsym_phys(wakeup_start);
157
0
}
158
159
0
static void acpi_sleep_post(u32 state) {}
160
161
/* Main interface to do xen specific suspend/resume */
162
static int enter_state(u32 state)
163
0
{
164
0
    unsigned long flags;
165
0
    int error;
166
0
    unsigned long cr4;
167
0
168
0
    if ( (state <= ACPI_STATE_S0) || (state > ACPI_S_STATES_MAX) )
169
0
        return -EINVAL;
170
0
171
0
    if ( !spin_trylock(&pm_lock) )
172
0
        return -EBUSY;
173
0
174
0
    BUG_ON(system_state != SYS_STATE_active);
175
0
    system_state = SYS_STATE_suspend;
176
0
177
0
    printk(XENLOG_INFO "Preparing system for ACPI S%d state.\n", state);
178
0
179
0
    freeze_domains();
180
0
181
0
    acpi_dmar_reinstate();
182
0
183
0
    if ( (error = disable_nonboot_cpus()) )
184
0
    {
185
0
        system_state = SYS_STATE_resume;
186
0
        goto enable_cpu;
187
0
    }
188
0
189
0
    cpufreq_del_cpu(0);
190
0
191
0
    hvm_cpu_down();
192
0
193
0
    acpi_sleep_prepare(state);
194
0
195
0
    console_start_sync();
196
0
    printk("Entering ACPI S%d state.\n", state);
197
0
198
0
    local_irq_save(flags);
199
0
    spin_debug_disable();
200
0
201
0
    if ( (error = device_power_down()) != SAVED_ALL )
202
0
    {
203
0
        printk(XENLOG_ERR "Some devices failed to power down.");
204
0
        system_state = SYS_STATE_resume;
205
0
        device_power_up(error);
206
0
        error = -EIO;
207
0
        goto done;
208
0
    }
209
0
    else
210
0
        error = 0;
211
0
212
0
    ACPI_FLUSH_CPU_CACHE();
213
0
214
0
    switch ( state )
215
0
    {
216
0
    case ACPI_STATE_S3:
217
0
        do_suspend_lowlevel();
218
0
        system_reset_counter++;
219
0
        error = tboot_s3_resume();
220
0
        break;
221
0
    case ACPI_STATE_S5:
222
0
        acpi_enter_sleep_state(ACPI_STATE_S5);
223
0
        break;
224
0
    default:
225
0
        error = -EINVAL;
226
0
        break;
227
0
    }
228
0
229
0
    system_state = SYS_STATE_resume;
230
0
231
0
    /* Restore CR4 and EFER from cached values. */
232
0
    cr4 = read_cr4();
233
0
    write_cr4(cr4 & ~X86_CR4_MCE);
234
0
    write_efer(read_efer());
235
0
236
0
    device_power_up(SAVED_ALL);
237
0
238
0
    mcheck_init(&boot_cpu_data, false);
239
0
    write_cr4(cr4);
240
0
241
0
    printk(XENLOG_INFO "Finishing wakeup from ACPI S%d state.\n", state);
242
0
243
0
    if ( (state == ACPI_STATE_S3) && error )
244
0
        tboot_s3_error(error);
245
0
246
0
 done:
247
0
    spin_debug_enable();
248
0
    local_irq_restore(flags);
249
0
    console_end_sync();
250
0
    acpi_sleep_post(state);
251
0
    if ( hvm_cpu_up() )
252
0
        BUG();
253
0
254
0
 enable_cpu:
255
0
    cpufreq_add_cpu(0);
256
0
    microcode_resume_cpu(0);
257
0
    rcu_barrier();
258
0
    mtrr_aps_sync_begin();
259
0
    enable_nonboot_cpus();
260
0
    mtrr_aps_sync_end();
261
0
    adjust_vtd_irq_affinities();
262
0
    acpi_dmar_zap();
263
0
    thaw_domains();
264
0
    system_state = SYS_STATE_active;
265
0
    spin_unlock(&pm_lock);
266
0
    return error;
267
0
}
268
269
static long enter_state_helper(void *data)
270
0
{
271
0
    struct acpi_sleep_info *sinfo = (struct acpi_sleep_info *)data;
272
0
    return enter_state(sinfo->sleep_state);
273
0
}
274
275
/*
276
 * Dom0 issues this hypercall in place of writing pm1a_cnt. Xen then
277
 * takes over the control and put the system into sleep state really.
278
 */
279
int acpi_enter_sleep(struct xenpf_enter_acpi_sleep *sleep)
280
0
{
281
0
    if ( sleep->flags & XENPF_ACPI_SLEEP_EXTENDED )
282
0
    {
283
0
        if ( !acpi_sinfo.sleep_control.address ||
284
0
             !acpi_sinfo.sleep_status.address )
285
0
            return -EPERM;
286
0
287
0
        if ( sleep->flags & ~XENPF_ACPI_SLEEP_EXTENDED )
288
0
            return -EINVAL;
289
0
290
0
        if ( sleep->val_a > ACPI_SLEEP_TYPE_MAX ||
291
0
             (sleep->val_b != ACPI_SLEEP_TYPE_INVALID &&
292
0
              sleep->val_b > ACPI_SLEEP_TYPE_MAX) )
293
0
            return -ERANGE;
294
0
295
0
        acpi_sinfo.sleep_type_a = sleep->val_a;
296
0
        acpi_sinfo.sleep_type_b = sleep->val_b;
297
0
298
0
        acpi_sinfo.sleep_extended = 1;
299
0
    }
300
0
301
0
    else if ( !acpi_sinfo.pm1a_cnt_blk.address )
302
0
        return -EPERM;
303
0
304
0
    /* Sanity check */
305
0
    else if ( sleep->val_b &&
306
0
              ((sleep->val_a ^ sleep->val_b) & ACPI_BITMASK_SLEEP_ENABLE) )
307
0
    {
308
0
        gdprintk(XENLOG_ERR, "Mismatched pm1a/pm1b setting\n");
309
0
        return -EINVAL;
310
0
    }
311
0
312
0
    else if ( sleep->flags )
313
0
        return -EINVAL;
314
0
315
0
    else
316
0
    {
317
0
        acpi_sinfo.pm1a_cnt_val = sleep->val_a;
318
0
        acpi_sinfo.pm1b_cnt_val = sleep->val_b;
319
0
        acpi_sinfo.sleep_extended = 0;
320
0
    }
321
0
322
0
    acpi_sinfo.sleep_state = sleep->sleep_state;
323
0
324
0
    return continue_hypercall_on_cpu(0, enter_state_helper, &acpi_sinfo);
325
0
}
326
327
static int acpi_get_wake_status(void)
328
0
{
329
0
    uint32_t val;
330
0
    acpi_status status;
331
0
332
0
    if ( acpi_sinfo.sleep_extended )
333
0
    {
334
0
        status = acpi_hw_register_read(ACPI_REGISTER_SLEEP_STATUS, &val);
335
0
336
0
        return ACPI_FAILURE(status) ? 0 : val & ACPI_X_WAKE_STATUS;
337
0
    }
338
0
339
0
    /* Wake status is the 15th bit of PM1 status register. (ACPI spec 3.0) */
340
0
    status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &val);
341
0
    if ( ACPI_FAILURE(status) )
342
0
        return 0;
343
0
344
0
    val &= ACPI_BITMASK_WAKE_STATUS;
345
0
    val >>= ACPI_BITPOSITION_WAKE_STATUS;
346
0
    return val;
347
0
}
348
349
static void tboot_sleep(u8 sleep_state)
350
0
{
351
0
    uint32_t shutdown_type;
352
0
353
0
#define TB_COPY_GAS(tbg, g)             \
354
0
    tbg.space_id = g.space_id;          \
355
0
    tbg.bit_width = g.bit_width;        \
356
0
    tbg.bit_offset = g.bit_offset;      \
357
0
    tbg.access_width = g.access_width;  \
358
0
    tbg.address = g.address;
359
0
360
0
    /* sizes are not same (due to packing) so copy each one */
361
0
    TB_COPY_GAS(g_tboot_shared->acpi_sinfo.pm1a_cnt_blk,
362
0
                acpi_sinfo.pm1a_cnt_blk);
363
0
    TB_COPY_GAS(g_tboot_shared->acpi_sinfo.pm1b_cnt_blk,
364
0
                acpi_sinfo.pm1b_cnt_blk);
365
0
    TB_COPY_GAS(g_tboot_shared->acpi_sinfo.pm1a_evt_blk,
366
0
                acpi_sinfo.pm1a_evt_blk);
367
0
    TB_COPY_GAS(g_tboot_shared->acpi_sinfo.pm1b_evt_blk,
368
0
                acpi_sinfo.pm1b_evt_blk);
369
0
    g_tboot_shared->acpi_sinfo.pm1a_cnt_val = acpi_sinfo.pm1a_cnt_val;
370
0
    g_tboot_shared->acpi_sinfo.pm1b_cnt_val = acpi_sinfo.pm1b_cnt_val;
371
0
    g_tboot_shared->acpi_sinfo.wakeup_vector = acpi_sinfo.wakeup_vector;
372
0
    g_tboot_shared->acpi_sinfo.vector_width = acpi_sinfo.vector_width;
373
0
    g_tboot_shared->acpi_sinfo.kernel_s3_resume_vector =
374
0
                                              bootsym_phys(wakeup_start);
375
0
376
0
    switch ( sleep_state )
377
0
    {
378
0
        case ACPI_STATE_S3:
379
0
            shutdown_type = TB_SHUTDOWN_S3;
380
0
            break;
381
0
        case ACPI_STATE_S4:
382
0
            shutdown_type = TB_SHUTDOWN_S4;
383
0
            break;
384
0
        case ACPI_STATE_S5:
385
0
            shutdown_type = TB_SHUTDOWN_S5;
386
0
            break;
387
0
        default:
388
0
            return;
389
0
    }
390
0
391
0
    tboot_shutdown(shutdown_type);
392
0
}
393
394
/* System is really put into sleep state by this stub */
395
acpi_status acpi_enter_sleep_state(u8 sleep_state)
396
0
{
397
0
    acpi_status status;
398
0
399
0
    if ( tboot_in_measured_env() )
400
0
    {
401
0
        tboot_sleep(sleep_state);
402
0
        printk(XENLOG_ERR "TBOOT failed entering s3 state\n");
403
0
        return_ACPI_STATUS(AE_ERROR);
404
0
    }
405
0
406
0
    ACPI_FLUSH_CPU_CACHE();
407
0
408
0
    if ( acpi_sinfo.sleep_extended )
409
0
    {
410
0
        /*
411
0
         * Set the SLP_TYP and SLP_EN bits.
412
0
         *
413
0
         * Note: We only use the first value returned by the \_Sx method
414
0
         * (acpi_sinfo.sleep_type_a) - As per ACPI specification.
415
0
         */
416
0
        u8 sleep_type_value =
417
0
            ((acpi_sinfo.sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
418
0
             ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE;
419
0
420
0
        status = acpi_hw_register_write(ACPI_REGISTER_SLEEP_CONTROL,
421
0
                                        sleep_type_value);
422
0
    }
423
0
    else
424
0
    {
425
0
        status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL,
426
0
                                        acpi_sinfo.pm1a_cnt_val);
427
0
        if ( !ACPI_FAILURE(status) && acpi_sinfo.pm1b_cnt_blk.address )
428
0
            status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL,
429
0
                                            acpi_sinfo.pm1b_cnt_val);
430
0
    }
431
0
432
0
    if ( ACPI_FAILURE(status) )
433
0
        return_ACPI_STATUS(AE_ERROR);
434
0
435
0
    /* Wait until we enter sleep state, and spin until we wake */
436
0
    while ( !acpi_get_wake_status() )
437
0
        continue;
438
0
439
0
    return_ACPI_STATUS(AE_OK);
440
0
}
441
442
static int __init acpi_sleep_init(void)
443
1
{
444
1
    int i;
445
1
    char *p = opt_acpi_sleep;
446
1
447
1
    while ( (p != NULL) && (*p != '\0') )
448
0
    {
449
0
        if ( !strncmp(p, "s3_bios", 7) )
450
0
            acpi_video_flags |= 1;
451
0
        if ( !strncmp(p, "s3_mode", 7) )
452
0
            acpi_video_flags |= 2;
453
0
        p = strchr(p, ',');
454
0
        if ( p != NULL )
455
0
            p += strspn(p, ", \t");
456
0
    }
457
1
458
1
    printk(XENLOG_INFO "ACPI sleep modes:");
459
7
    for ( i = 0; i < ACPI_S_STATE_COUNT; i++ )
460
6
    {
461
6
        if ( i == ACPI_STATE_S3 )
462
1
        {
463
1
            sleep_states[i] = 1;
464
1
            printk(" S%d", i);
465
1
        }
466
6
        else
467
5
            sleep_states[i] = 0;
468
6
    }
469
1
    printk("\n");
470
1
471
1
    return 0;
472
1
}
473
__initcall(acpi_sleep_init);