Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/common/cpu.c
Line
Count
Source (jump to first uncovered line)
1
#include <xen/cpumask.h>
2
#include <xen/cpu.h>
3
#include <xen/event.h>
4
#include <xen/init.h>
5
#include <xen/sched.h>
6
#include <xen/stop_machine.h>
7
8
unsigned int __read_mostly nr_cpu_ids = NR_CPUS;
9
#ifndef nr_cpumask_bits
10
unsigned int __read_mostly nr_cpumask_bits
11
    = BITS_TO_LONGS(NR_CPUS) * BITS_PER_LONG;
12
#endif
13
14
/*
15
 * cpu_bit_bitmap[] is a special, "compressed" data structure that
16
 * represents all NR_CPUS bits binary values of 1<<nr.
17
 *
18
 * It is used by cpumask_of() to get a constant address to a CPU
19
 * mask value that has a single bit set only.
20
 */
21
22
/* cpu_bit_bitmap[0] is empty - so we can back into it */
23
#define MASK_DECLARE_1(x) [x+1][0] = 1UL << (x)
24
#define MASK_DECLARE_2(x) MASK_DECLARE_1(x), MASK_DECLARE_1(x+1)
25
#define MASK_DECLARE_4(x) MASK_DECLARE_2(x), MASK_DECLARE_2(x+2)
26
#define MASK_DECLARE_8(x) MASK_DECLARE_4(x), MASK_DECLARE_4(x+4)
27
28
const unsigned long cpu_bit_bitmap[BITS_PER_LONG+1][BITS_TO_LONGS(NR_CPUS)] = {
29
30
    MASK_DECLARE_8(0),  MASK_DECLARE_8(8),
31
    MASK_DECLARE_8(16), MASK_DECLARE_8(24),
32
#if BITS_PER_LONG > 32
33
    MASK_DECLARE_8(32), MASK_DECLARE_8(40),
34
    MASK_DECLARE_8(48), MASK_DECLARE_8(56),
35
#endif
36
};
37
38
static DEFINE_SPINLOCK(cpu_add_remove_lock);
39
40
bool_t get_cpu_maps(void)
41
11
{
42
11
    return spin_trylock_recursive(&cpu_add_remove_lock);
43
11
}
44
45
void put_cpu_maps(void)
46
11
{
47
11
    spin_unlock_recursive(&cpu_add_remove_lock);
48
11
}
49
50
bool_t cpu_hotplug_begin(void)
51
11
{
52
11
    return get_cpu_maps();
53
11
}
54
55
void cpu_hotplug_done(void)
56
11
{
57
11
    put_cpu_maps();
58
11
}
59
60
static NOTIFIER_HEAD(cpu_chain);
61
62
void __init register_cpu_notifier(struct notifier_block *nb)
63
18
{
64
18
    if ( !spin_trylock(&cpu_add_remove_lock) )
65
0
        BUG(); /* Should never fail as we are called only during boot. */
66
18
    notifier_chain_register(&cpu_chain, nb);
67
18
    spin_unlock(&cpu_add_remove_lock);
68
18
}
69
70
static int take_cpu_down(void *unused)
71
0
{
72
0
    void *hcpu = (void *)(long)smp_processor_id();
73
0
    int notifier_rc = notifier_call_chain(&cpu_chain, CPU_DYING, hcpu, NULL);
74
0
    BUG_ON(notifier_rc != NOTIFY_DONE);
75
0
    __cpu_disable();
76
0
    return 0;
77
0
}
78
79
int cpu_down(unsigned int cpu)
80
0
{
81
0
    int err, notifier_rc;
82
0
    void *hcpu = (void *)(long)cpu;
83
0
    struct notifier_block *nb = NULL;
84
0
85
0
    if ( !cpu_hotplug_begin() )
86
0
        return -EBUSY;
87
0
88
0
    if ( (cpu >= nr_cpu_ids) || (cpu == 0) || !cpu_online(cpu) )
89
0
    {
90
0
        cpu_hotplug_done();
91
0
        return -EINVAL;
92
0
    }
93
0
94
0
    notifier_rc = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, hcpu, &nb);
95
0
    if ( notifier_rc != NOTIFY_DONE )
96
0
    {
97
0
        err = notifier_to_errno(notifier_rc);
98
0
        goto fail;
99
0
    }
100
0
101
0
    if ( (err = stop_machine_run(take_cpu_down, NULL, cpu)) < 0 )
102
0
        goto fail;
103
0
104
0
    __cpu_die(cpu);
105
0
    BUG_ON(cpu_online(cpu));
106
0
107
0
    notifier_rc = notifier_call_chain(&cpu_chain, CPU_DEAD, hcpu, NULL);
108
0
    BUG_ON(notifier_rc != NOTIFY_DONE);
109
0
110
0
    send_global_virq(VIRQ_PCPU_STATE);
111
0
    cpu_hotplug_done();
112
0
    return 0;
113
0
114
0
 fail:
115
0
    notifier_rc = notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, hcpu, &nb);
116
0
    BUG_ON(notifier_rc != NOTIFY_DONE);
117
0
    cpu_hotplug_done();
118
0
    return err;
119
0
}
120
121
int cpu_up(unsigned int cpu)
122
11
{
123
11
    int notifier_rc, err = 0;
124
11
    void *hcpu = (void *)(long)cpu;
125
11
    struct notifier_block *nb = NULL;
126
11
127
11
    if ( !cpu_hotplug_begin() )
128
0
        return -EBUSY;
129
11
130
11
    if ( (cpu >= nr_cpu_ids) || cpu_online(cpu) || !cpu_present(cpu) )
131
0
    {
132
0
        cpu_hotplug_done();
133
0
        return -EINVAL;
134
0
    }
135
11
136
11
    notifier_rc = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu, &nb);
137
11
    if ( notifier_rc != NOTIFY_DONE )
138
0
    {
139
0
        err = notifier_to_errno(notifier_rc);
140
0
        goto fail;
141
0
    }
142
11
143
11
    err = __cpu_up(cpu);
144
11
    if ( err < 0 )
145
0
        goto fail;
146
11
147
11
    notifier_rc = notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu, NULL);
148
11
    BUG_ON(notifier_rc != NOTIFY_DONE);
149
11
150
11
    send_global_virq(VIRQ_PCPU_STATE);
151
11
152
11
    cpu_hotplug_done();
153
11
    return 0;
154
11
155
0
 fail:
156
0
    notifier_rc = notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu, &nb);
157
0
    BUG_ON(notifier_rc != NOTIFY_DONE);
158
0
    cpu_hotplug_done();
159
0
    return err;
160
11
}
161
162
void notify_cpu_starting(unsigned int cpu)
163
11
{
164
11
    void *hcpu = (void *)(long)cpu;
165
11
    int notifier_rc = notifier_call_chain(
166
11
        &cpu_chain, CPU_STARTING, hcpu, NULL);
167
11
    BUG_ON(notifier_rc != NOTIFY_DONE);
168
11
}
169
170
static cpumask_t frozen_cpus;
171
172
int disable_nonboot_cpus(void)
173
0
{
174
0
    int cpu, error = 0;
175
0
176
0
    BUG_ON(smp_processor_id() != 0);
177
0
178
0
    cpumask_clear(&frozen_cpus);
179
0
180
0
    printk("Disabling non-boot CPUs ...\n");
181
0
182
0
    for_each_online_cpu ( cpu )
183
0
    {
184
0
        if ( cpu == 0 )
185
0
            continue;
186
0
187
0
        if ( (error = cpu_down(cpu)) )
188
0
        {
189
0
            printk("Error taking CPU%d down: %d\n", cpu, error);
190
0
            BUG_ON(error == -EBUSY);
191
0
            break;
192
0
        }
193
0
194
0
        __cpumask_set_cpu(cpu, &frozen_cpus);
195
0
    }
196
0
197
0
    BUG_ON(!error && (num_online_cpus() != 1));
198
0
    return error;
199
0
}
200
201
void enable_nonboot_cpus(void)
202
0
{
203
0
    int cpu, error;
204
0
205
0
    printk("Enabling non-boot CPUs  ...\n");
206
0
207
0
    for_each_cpu ( cpu, &frozen_cpus )
208
0
    {
209
0
        if ( (error = cpu_up(cpu)) )
210
0
        {
211
0
            printk("Error bringing CPU%d up: %d\n", cpu, error);
212
0
            BUG_ON(error == -EBUSY);
213
0
        }
214
0
    }
215
0
216
0
    cpumask_clear(&frozen_cpus);
217
0
}