Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/acpi/lib.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  lib.c - Architecture-Specific Low-Level ACPI Support
3
 *
4
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20
 */
21
22
#include <xen/errno.h>
23
#include <xen/init.h>
24
#include <xen/acpi.h>
25
#include <asm/apic.h>
26
#include <asm/fixmap.h>
27
28
u32 __read_mostly acpi_smi_cmd;
29
u8 __read_mostly acpi_enable_value;
30
u8 __read_mostly acpi_disable_value;
31
32
u32 __read_mostly x86_acpiid_to_apicid[MAX_MADT_ENTRIES] =
33
    {[0 ... MAX_MADT_ENTRIES - 1] = BAD_APICID };
34
35
/*
36
 * Important Safety Note:  The fixed ACPI page numbers are *subtracted*
37
 * from the fixed base.  That's why we start at FIX_ACPI_END and
38
 * count idx down while incrementing the phys address.
39
 */
40
char *__acpi_map_table(paddr_t phys, unsigned long size)
41
27
{
42
27
  unsigned long base, offset, mapped_size;
43
27
  int idx;
44
27
45
27
  /* XEN: RAM holes above 1MB are not permanently mapped. */
46
27
  if ((phys + size) <= (1 * 1024 * 1024))
47
5
    return __va(phys);
48
27
49
22
  offset = phys & (PAGE_SIZE - 1);
50
22
  mapped_size = PAGE_SIZE - offset;
51
22
  set_fixmap(FIX_ACPI_END, phys);
52
22
  base = fix_to_virt(FIX_ACPI_END);
53
22
54
22
  /*
55
22
   * Most cases can be covered by the below.
56
22
   */
57
22
  idx = FIX_ACPI_END;
58
22
  while (mapped_size < size) {
59
0
    if (--idx < FIX_ACPI_BEGIN)
60
0
      return NULL; /* cannot handle this */
61
0
    phys += PAGE_SIZE;
62
0
    set_fixmap(idx, phys);
63
0
    mapped_size += PAGE_SIZE;
64
0
  }
65
22
66
22
  return ((char *) base + offset);
67
22
}
68
69
unsigned int acpi_get_processor_id(unsigned int cpu)
70
0
{
71
0
  unsigned int acpiid, apicid;
72
0
73
0
  if ((apicid = x86_cpu_to_apicid[cpu]) == BAD_APICID)
74
0
    return INVALID_ACPIID;
75
0
76
0
  for (acpiid = 0; acpiid < ARRAY_SIZE(x86_acpiid_to_apicid); acpiid++)
77
0
    if (x86_acpiid_to_apicid[acpiid] == apicid)
78
0
      return acpiid;
79
0
80
0
  return INVALID_ACPIID;
81
0
}
82
83
static void get_mwait_ecx(void *info)
84
0
{
85
0
  *(u32 *)info = cpuid_ecx(CPUID_MWAIT_LEAF);
86
0
}
87
88
int arch_acpi_set_pdc_bits(u32 acpi_id, u32 *pdc, u32 mask)
89
0
{
90
0
  unsigned int cpu = get_cpu_id(acpi_id);
91
0
  struct cpuinfo_x86 *c;
92
0
  u32 ecx;
93
0
94
0
  if (!(acpi_id + 1))
95
0
    c = &boot_cpu_data;
96
0
  else if (cpu >= nr_cpu_ids || !cpu_online(cpu))
97
0
    return -EINVAL;
98
0
  else
99
0
    c = cpu_data + cpu;
100
0
101
0
  pdc[2] |= ACPI_PDC_C_CAPABILITY_SMP & mask;
102
0
103
0
  if (cpu_has(c, X86_FEATURE_EIST))
104
0
    pdc[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP & mask;
105
0
106
0
  if (cpu_has(c, X86_FEATURE_ACPI))
107
0
    pdc[2] |= ACPI_PDC_T_FFH & mask;
108
0
109
0
  /*
110
0
   * If mwait/monitor or its break-on-interrupt extension are
111
0
   * unsupported, Cx_FFH will be disabled.
112
0
   */
113
0
  if (!cpu_has(c, X86_FEATURE_MONITOR) ||
114
0
      c->cpuid_level < CPUID_MWAIT_LEAF)
115
0
    ecx = 0;
116
0
  else if (c == &boot_cpu_data || cpu == smp_processor_id())
117
0
    ecx = cpuid_ecx(CPUID_MWAIT_LEAF);
118
0
  else
119
0
    on_selected_cpus(cpumask_of(cpu), get_mwait_ecx, &ecx, 1);
120
0
  if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
121
0
      !(ecx & CPUID5_ECX_INTERRUPT_BREAK))
122
0
    pdc[2] &= ~(ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH);
123
0
124
0
  return 0;
125
0
}