hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/arch/powerpc/kernel/paca.c
....@@ -1,22 +1,22 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * c 2001 PPC 64 Team, IBM Corp
3
- *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License
6
- * as published by the Free Software Foundation; either version
7
- * 2 of the License, or (at your option) any later version.
84 */
95
106 #include <linux/smp.h>
117 #include <linux/export.h>
128 #include <linux/memblock.h>
139 #include <linux/sched/task.h>
10
+#include <linux/numa.h>
11
+#include <linux/pgtable.h>
1412
1513 #include <asm/lppaca.h>
1614 #include <asm/paca.h>
1715 #include <asm/sections.h>
18
-#include <asm/pgtable.h>
1916 #include <asm/kexec.h>
17
+#include <asm/svm.h>
18
+#include <asm/ultravisor.h>
19
+#include <asm/rtas.h>
2020
2121 #include "setup.h"
2222
....@@ -27,7 +27,7 @@
2727 static void *__init alloc_paca_data(unsigned long size, unsigned long align,
2828 unsigned long limit, int cpu)
2929 {
30
- unsigned long pa;
30
+ void *ptr;
3131 int nid;
3232
3333 /*
....@@ -36,26 +36,68 @@
3636 * which will put its paca in the right place.
3737 */
3838 if (cpu == boot_cpuid) {
39
- nid = -1;
39
+ nid = NUMA_NO_NODE;
4040 memblock_set_bottom_up(true);
4141 } else {
4242 nid = early_cpu_to_node(cpu);
4343 }
4444
45
- pa = memblock_alloc_base_nid(size, align, limit, nid, MEMBLOCK_NONE);
46
- if (!pa) {
47
- pa = memblock_alloc_base(size, align, limit);
48
- if (!pa)
49
- panic("cannot allocate paca data");
50
- }
45
+ ptr = memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,
46
+ limit, nid);
47
+ if (!ptr)
48
+ panic("cannot allocate paca data");
5149
5250 if (cpu == boot_cpuid)
5351 memblock_set_bottom_up(false);
5452
55
- return __va(pa);
53
+ return ptr;
5654 }
5755
5856 #ifdef CONFIG_PPC_PSERIES
57
+
58
+#define LPPACA_SIZE 0x400
59
+
60
+static void *__init alloc_shared_lppaca(unsigned long size, unsigned long limit,
61
+ int cpu)
62
+{
63
+ size_t shared_lppaca_total_size = PAGE_ALIGN(nr_cpu_ids * LPPACA_SIZE);
64
+ static unsigned long shared_lppaca_size;
65
+ static void *shared_lppaca;
66
+ void *ptr;
67
+
68
+ if (!shared_lppaca) {
69
+ memblock_set_bottom_up(true);
70
+
71
+ /*
72
+ * See Documentation/powerpc/ultravisor.rst for more details.
73
+ *
74
+ * UV/HV data sharing is in PAGE_SIZE granularity. In order to
75
+ * minimize the number of pages shared, align the allocation to
76
+ * PAGE_SIZE.
77
+ */
78
+ shared_lppaca =
79
+ memblock_alloc_try_nid(shared_lppaca_total_size,
80
+ PAGE_SIZE, MEMBLOCK_LOW_LIMIT,
81
+ limit, NUMA_NO_NODE);
82
+ if (!shared_lppaca)
83
+ panic("cannot allocate shared data");
84
+
85
+ memblock_set_bottom_up(false);
86
+ uv_share_page(PHYS_PFN(__pa(shared_lppaca)),
87
+ shared_lppaca_total_size >> PAGE_SHIFT);
88
+ }
89
+
90
+ ptr = shared_lppaca + shared_lppaca_size;
91
+ shared_lppaca_size += size;
92
+
93
+ /*
94
+ * This is very early in boot, so no harm done if the kernel crashes at
95
+ * this point.
96
+ */
97
+ BUG_ON(shared_lppaca_size > shared_lppaca_total_size);
98
+
99
+ return ptr;
100
+}
59101
60102 /*
61103 * See asm/lppaca.h for more detail.
....@@ -70,7 +112,7 @@
70112
71113 *lppaca = (struct lppaca) {
72114 .desc = cpu_to_be32(0xd397d781), /* "LpPa" */
73
- .size = cpu_to_be16(0x400),
115
+ .size = cpu_to_be16(LPPACA_SIZE),
74116 .fpregs_in_use = 1,
75117 .slb_count = cpu_to_be16(64),
76118 .vmxregs_in_use = 0,
....@@ -80,19 +122,22 @@
80122 static struct lppaca * __init new_lppaca(int cpu, unsigned long limit)
81123 {
82124 struct lppaca *lp;
83
- size_t size = 0x400;
84125
85
- BUILD_BUG_ON(size < sizeof(struct lppaca));
126
+ BUILD_BUG_ON(sizeof(struct lppaca) > LPPACA_SIZE);
86127
87128 if (early_cpu_has_feature(CPU_FTR_HVMODE))
88129 return NULL;
89130
90
- lp = alloc_paca_data(size, 0x400, limit, cpu);
131
+ if (is_secure_guest())
132
+ lp = alloc_shared_lppaca(LPPACA_SIZE, limit, cpu);
133
+ else
134
+ lp = alloc_paca_data(LPPACA_SIZE, 0x400, limit, cpu);
135
+
91136 init_lppaca(lp);
92137
93138 return lp;
94139 }
95
-#endif /* CONFIG_PPC_BOOK3S */
140
+#endif /* CONFIG_PPC_PSERIES */
96141
97142 #ifdef CONFIG_PPC_BOOK3S_64
98143
....@@ -118,7 +163,6 @@
118163 }
119164
120165 s = alloc_paca_data(sizeof(*s), L1_CACHE_BYTES, limit, cpu);
121
- memset(s, 0, sizeof(*s));
122166
123167 s->persistent = cpu_to_be32(SLB_NUM_BOLTED);
124168 s->buffer_length = cpu_to_be32(sizeof(*s));
....@@ -127,6 +171,30 @@
127171 }
128172
129173 #endif /* CONFIG_PPC_BOOK3S_64 */
174
+
175
+#ifdef CONFIG_PPC_PSERIES
176
+/**
177
+ * new_rtas_args() - Allocates rtas args
178
+ * @cpu: CPU number
179
+ * @limit: Memory limit for this allocation
180
+ *
181
+ * Allocates a struct rtas_args and return it's pointer,
182
+ * if not in Hypervisor mode
183
+ *
184
+ * Return: Pointer to allocated rtas_args
185
+ * NULL if CPU in Hypervisor Mode
186
+ */
187
+static struct rtas_args * __init new_rtas_args(int cpu, unsigned long limit)
188
+{
189
+ limit = min_t(unsigned long, limit, RTAS_INSTANTIATE_MAX);
190
+
191
+ if (early_cpu_has_feature(CPU_FTR_HVMODE))
192
+ return NULL;
193
+
194
+ return alloc_paca_data(sizeof(struct rtas_args), L1_CACHE_BYTES,
195
+ limit, cpu);
196
+}
197
+#endif /* CONFIG_PPC_PSERIES */
130198
131199 /* The Paca is an array with one entry per processor. Each contains an
132200 * lppaca, which contains the information shared between the
....@@ -166,6 +234,10 @@
166234 /* For now -- if we have threads this will be adjusted later */
167235 new_paca->tcd_ptr = &new_paca->tcd;
168236 #endif
237
+
238
+#ifdef CONFIG_PPC_PSERIES
239
+ new_paca->rtas_args_reentrant = NULL;
240
+#endif
169241 }
170242
171243 /* Put the paca pointer into r13 and SPRG_PACA */
....@@ -178,11 +250,15 @@
178250 /* On Book3E, initialize the TLB miss exception frames */
179251 mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb);
180252 #else
181
- /* In HV mode, we setup both HPACA and PACA to avoid problems
253
+ /*
254
+ * In HV mode, we setup both HPACA and PACA to avoid problems
182255 * if we do a GET_PACA() before the feature fixups have been
183
- * applied
256
+ * applied.
257
+ *
258
+ * Normally you should test against CPU_FTR_HVMODE, but CPU features
259
+ * are not yet set up when we first reach here.
184260 */
185
- if (early_cpu_has_feature(CPU_FTR_HVMODE))
261
+ if (mfmsr() & MSR_HV)
186262 mtspr(SPRN_SPRG_HPACA, local_paca);
187263 #endif
188264 mtspr(SPRN_SPRG_PACA, local_paca);
....@@ -198,7 +274,11 @@
198274 paca_nr_cpu_ids = nr_cpu_ids;
199275
200276 paca_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids;
201
- paca_ptrs = __va(memblock_alloc(paca_ptrs_size, 0));
277
+ paca_ptrs = memblock_alloc_raw(paca_ptrs_size, SMP_CACHE_BYTES);
278
+ if (!paca_ptrs)
279
+ panic("Failed to allocate %d bytes for paca pointers\n",
280
+ paca_ptrs_size);
281
+
202282 memset(paca_ptrs, 0x88, paca_ptrs_size);
203283 }
204284
....@@ -222,7 +302,6 @@
222302 paca = alloc_paca_data(sizeof(struct paca_struct), L1_CACHE_BYTES,
223303 limit, cpu);
224304 paca_ptrs[cpu] = paca;
225
- memset(paca, 0, sizeof(struct paca_struct));
226305
227306 initialise_paca(paca, cpu);
228307 #ifdef CONFIG_PPC_PSERIES
....@@ -230,6 +309,9 @@
230309 #endif
231310 #ifdef CONFIG_PPC_BOOK3S_64
232311 paca->slb_shadow_ptr = new_slb_shadow(cpu, limit);
312
+#endif
313
+#ifdef CONFIG_PPC_PSERIES
314
+ paca->rtas_args_reentrant = new_rtas_args(cpu, limit);
233315 #endif
234316 paca_struct_size += sizeof(struct paca_struct);
235317 }
....@@ -266,12 +348,12 @@
266348
267349 get_paca()->mm_ctx_id = context->id;
268350 #ifdef CONFIG_PPC_MM_SLICES
269
- VM_BUG_ON(!mm->context.slb_addr_limit);
270
- get_paca()->mm_ctx_slb_addr_limit = mm->context.slb_addr_limit;
271
- memcpy(&get_paca()->mm_ctx_low_slices_psize,
272
- &context->low_slices_psize, sizeof(context->low_slices_psize));
273
- memcpy(&get_paca()->mm_ctx_high_slices_psize,
274
- &context->high_slices_psize, TASK_SLICE_ARRAY_SZ(mm));
351
+ VM_BUG_ON(!mm_ctx_slb_addr_limit(context));
352
+ get_paca()->mm_ctx_slb_addr_limit = mm_ctx_slb_addr_limit(context);
353
+ memcpy(&get_paca()->mm_ctx_low_slices_psize, mm_ctx_low_slices(context),
354
+ LOW_SLICE_ARRAY_SZ);
355
+ memcpy(&get_paca()->mm_ctx_high_slices_psize, mm_ctx_high_slices(context),
356
+ TASK_SLICE_ARRAY_SZ(context));
275357 #else /* CONFIG_PPC_MM_SLICES */
276358 get_paca()->mm_ctx_user_psize = context->user_psize;
277359 get_paca()->mm_ctx_sllp = context->sllp;