forked from QubesOS/qubes-vmm-xen
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpatch-0005-xen-cpupool-simplify-suspend-resume-handling.patch
228 lines (216 loc) · 7.48 KB
/
patch-0005-xen-cpupool-simplify-suspend-resume-handling.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
From 6d54ec93842934303db0e81d462ab8aaaca1fd3d Mon Sep 17 00:00:00 2001
From: Juergen Gross <[email protected]>
Date: Tue, 2 Apr 2019 07:34:56 +0200
Subject: [PATCH 5/9] xen/cpupool: simplify suspend/resume handling
Instead of removing cpus temporarily from cpupools during
suspend/resume only remove cpus finally which didn't come up when
resuming.
Signed-off-by: Juergen Gross <[email protected]>
Reviewed-by: George Dunlap <[email protected]>
Reviewed-by: Dario Faggioli <[email protected]>
(cherry picked from commit 6870ea9d1fad6fbe27cf3ce5fe093be709ad2668)
---
xen/common/cpupool.c | 131 +++++++++++++++----------------------
xen/include/xen/sched-if.h | 1 -
2 files changed, 52 insertions(+), 80 deletions(-)
diff --git a/xen/common/cpupool.c b/xen/common/cpupool.c
index 1e8edcbd5794..cae19fda6e11 100644
--- a/xen/common/cpupool.c
+++ b/xen/common/cpupool.c
@@ -47,12 +47,6 @@ static struct cpupool *alloc_cpupool_struct(void)
xfree(c);
c = NULL;
}
- else if ( !zalloc_cpumask_var(&c->cpu_suspended) )
- {
- free_cpumask_var(c->cpu_valid);
- xfree(c);
- c = NULL;
- }
return c;
}
@@ -60,10 +54,7 @@ static struct cpupool *alloc_cpupool_struct(void)
static void free_cpupool_struct(struct cpupool *c)
{
if ( c )
- {
- free_cpumask_var(c->cpu_suspended);
free_cpumask_var(c->cpu_valid);
- }
xfree(c);
}
@@ -477,10 +468,6 @@ void cpupool_rm_domain(struct domain *d)
/*
* Called to add a cpu to a pool. CPUs being hot-plugged are added to pool0,
* as they must have been in there when unplugged.
- *
- * If, on the other hand, we are adding CPUs because we are resuming (e.g.,
- * after ACPI S3) we put the cpu back in the pool where it was in prior when
- * we suspended.
*/
static int cpupool_cpu_add(unsigned int cpu)
{
@@ -490,42 +477,15 @@ static int cpupool_cpu_add(unsigned int cpu)
cpumask_clear_cpu(cpu, &cpupool_locked_cpus);
cpumask_set_cpu(cpu, &cpupool_free_cpus);
- if ( system_state == SYS_STATE_suspend || system_state == SYS_STATE_resume )
- {
- struct cpupool **c;
-
- for_each_cpupool(c)
- {
- if ( cpumask_test_cpu(cpu, (*c)->cpu_suspended ) )
- {
- ret = cpupool_assign_cpu_locked(*c, cpu);
- if ( ret )
- goto out;
- cpumask_clear_cpu(cpu, (*c)->cpu_suspended);
- break;
- }
- }
+ /*
+ * If we are not resuming, we are hot-plugging cpu, and in which case
+ * we add it to pool0, as it certainly was there when hot-unplagged
+ * (or unplugging would have failed) and that is the default behavior
+ * anyway.
+ */
+ per_cpu(cpupool, cpu) = NULL;
+ ret = cpupool_assign_cpu_locked(cpupool0, cpu);
- /*
- * Either cpu has been found as suspended in a pool, and added back
- * there, or it stayed free (if it did not belong to any pool when
- * suspending), and we don't want to do anything.
- */
- ASSERT(cpumask_test_cpu(cpu, &cpupool_free_cpus) ||
- cpumask_test_cpu(cpu, (*c)->cpu_valid));
- }
- else
- {
- /*
- * If we are not resuming, we are hot-plugging cpu, and in which case
- * we add it to pool0, as it certainly was there when hot-unplagged
- * (or unplugging would have failed) and that is the default behavior
- * anyway.
- */
- per_cpu(cpupool, cpu) = NULL;
- ret = cpupool_assign_cpu_locked(cpupool0, cpu);
- }
- out:
spin_unlock(&cpupool_lock);
return ret;
@@ -535,42 +495,14 @@ static int cpupool_cpu_add(unsigned int cpu)
* Called to remove a CPU from a pool. The CPU is locked, to forbid removing
* it from pool0. In fact, if we want to hot-unplug a CPU, it must belong to
* pool0, or we fail.
- *
- * However, if we are suspending (e.g., to ACPI S3), we mark the CPU in such
- * a way that it can be put back in its pool when resuming.
*/
static int cpupool_cpu_remove(unsigned int cpu)
{
int ret = -ENODEV;
spin_lock(&cpupool_lock);
- if ( system_state == SYS_STATE_suspend )
- {
- struct cpupool **c;
-
- for_each_cpupool(c)
- {
- if ( cpumask_test_cpu(cpu, (*c)->cpu_valid ) )
- {
- cpumask_set_cpu(cpu, (*c)->cpu_suspended);
- cpumask_clear_cpu(cpu, (*c)->cpu_valid);
- break;
- }
- }
- /*
- * Either we found cpu in a pool, or it must be free (if it has been
- * hot-unplagged, then we must have found it in pool0). It is, of
- * course, fine to suspend or shutdown with CPUs not assigned to a
- * pool, and (in case of suspend) they will stay free when resuming.
- */
- ASSERT(cpumask_test_cpu(cpu, &cpupool_free_cpus) ||
- cpumask_test_cpu(cpu, (*c)->cpu_suspended));
- ASSERT(cpumask_test_cpu(cpu, &cpu_online_map) ||
- cpumask_test_cpu(cpu, cpupool0->cpu_suspended));
- ret = 0;
- }
- else if ( cpumask_test_cpu(cpu, cpupool0->cpu_valid) )
+ if ( cpumask_test_cpu(cpu, cpupool0->cpu_valid) )
{
/*
* If we are not suspending, we are hot-unplugging cpu, and that is
@@ -587,6 +519,41 @@ static int cpupool_cpu_remove(unsigned int cpu)
return ret;
}
+/*
+ * Called during resume for all cpus which didn't come up again. The cpu must
+ * be removed from the cpupool it is assigned to. In case a cpupool will be
+ * left without cpu we move all domains of that cpupool to cpupool0.
+ */
+static void cpupool_cpu_remove_forced(unsigned int cpu)
+{
+ struct cpupool **c;
+ struct domain *d;
+
+ spin_lock(&cpupool_lock);
+
+ if ( cpumask_test_cpu(cpu, &cpupool_free_cpus) )
+ cpumask_clear_cpu(cpu, &cpupool_free_cpus);
+ else
+ {
+ for_each_cpupool(c)
+ {
+ if ( cpumask_test_cpu(cpu, (*c)->cpu_valid) )
+ {
+ cpumask_clear_cpu(cpu, (*c)->cpu_valid);
+ if ( cpumask_weight((*c)->cpu_valid) == 0 )
+ {
+ if ( *c == cpupool0 )
+ panic("No cpu left in cpupool0\n");
+ for_each_domain_in_cpupool(d, *c)
+ cpupool_move_domain_locked(d, cpupool0);
+ }
+ }
+ }
+ }
+
+ spin_unlock(&cpupool_lock);
+}
+
/*
* do cpupool related sysctl operations
*/
@@ -779,10 +746,16 @@ static int cpu_callback(
{
case CPU_DOWN_FAILED:
case CPU_ONLINE:
- rc = cpupool_cpu_add(cpu);
+ if ( system_state <= SYS_STATE_active )
+ rc = cpupool_cpu_add(cpu);
break;
case CPU_DOWN_PREPARE:
- rc = cpupool_cpu_remove(cpu);
+ /* Suspend/Resume don't change assignments of cpus to cpupools. */
+ if ( system_state <= SYS_STATE_active )
+ rc = cpupool_cpu_remove(cpu);
+ break;
+ case CPU_RESUME_FAILED:
+ cpupool_cpu_remove_forced(cpu);
break;
default:
break;
diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h
index bc0e794b0f86..4d7a19295684 100644
--- a/xen/include/xen/sched-if.h
+++ b/xen/include/xen/sched-if.h
@@ -181,7 +181,6 @@ struct cpupool
{
int cpupool_id;
cpumask_var_t cpu_valid; /* all cpus assigned to pool */
- cpumask_var_t cpu_suspended; /* cpus in S3 that should be in this pool */
struct cpupool *next;
unsigned int n_dom;
struct scheduler *sched;
--
2.26.2