ppc/pnv: Add OCC FLAG registers
OCCFLG are scratch registers that can be shared with OCC firmware. Log reads and writes to the registers as a reminder when we run into more OCC code. Add RW, WO_CLEAR and WO_OR SCOM Type enums in pnv_occ.c Reviewed-by: Chalapathi V <chalapathi.v@linux.ibm.com> Reviewed-by: Glenn Miles <milesg@linux.ibm.com> Reviewed-by: Aditya Gupta <adityag@linux.ibm.com> Signed-off-by: Chalapathi V <chalapathi.v@linux.ibm.com> Signed-off-by: Caleb Schlossin <calebs@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20260210134647.2050821-4-calebs@linux.ibm.com Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
Caleb Schlossin committed
Feb 10, 2026 at 07:46 UTC
0b74dd1d8054dfff56562ccc6cedc869cebac623
2 files changed
+56
-3
hw/ppc/pnv_occ.c
+52
-3
@@ -195,6 +195,49 @@ static const TypeInfo pnv_occ_power8_type_info = {
195
#define P9_OCB_OCI_OCCMISC_CLEAR 0x6081
196
#define P9_OCB_OCI_OCCMISC_OR 0x6082
197
198
+/* OCC scratch registers for flag setting */
199
+#define P9_OCCFLG0 0x60ac
200
+#define P9_OCCFLG7_OR 0x60c3
201
+
202
+enum ScomType {
203
+ SCOM_TYPE_RW = 0,
204
+ SCOM_TYPE_WO_CLEAR = 1,
205
+ SCOM_TYPE_WO_OR = 2,
206
+};
207
+
208
+static void rw_occ_flag_regs(PnvOCC *occ, uint32_t offset, bool read,
209
+ uint64_t *val)
210
+{
211
+ int flag_num;
212
+ int flag_type;
213
+
214
+ /*
215
+ * Each OCCFLG register has SCOM0 - RW, SCOM1 - WO_CLEAR, SCOM2 - WO_OR
216
+ * hence divide by 3 to get flag index and mod 3 to get SCOM type.
217
+ */
218
+ flag_num = (offset - P9_OCCFLG0) / 3;
219
+ flag_type = (offset - P9_OCCFLG0) % 3;
220
+
221
+ if (read) {
222
+ if (flag_type) {
223
+ qemu_log_mask(LOG_GUEST_ERROR, "OCC: Write only register: Ox%"
224
+ PRIx32 "\n", offset);
225
+ return;
226
+ }
227
+ *val = occ->occflags[flag_num];
228
+ } else {
229
+ switch (flag_type) {
230
+ case SCOM_TYPE_RW:
231
+ occ->occflags[flag_num] = *val;
232
+ break;
233
+ case SCOM_TYPE_WO_CLEAR:
234
+ occ->occflags[flag_num] &= ~(*val);
235
+ break;
236
+ case SCOM_TYPE_WO_OR:
237
+ occ->occflags[flag_num] |= *val;
238
+ }
239
+ }
240
+}
241
242
static uint64_t pnv_occ_power9_xscom_read(void *opaque, hwaddr addr,
243
unsigned size)
@@ -207,8 +250,11 @@ static uint64_t pnv_occ_power9_xscom_read(void *opaque, hwaddr addr,
250
case P9_OCB_OCI_OCCMISC:
251
val = occ->occmisc;
252
break;
253
+ case P9_OCCFLG0 ... P9_OCCFLG7_OR:
254
+ rw_occ_flag_regs(occ, offset, 1, &val);
255
+ break;
256
default:
211
- qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
257
+ qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register read: Ox%"
258
HWADDR_PRIx "\n", addr >> 3);
259
}
260
return val;
@@ -229,9 +275,12 @@ static void pnv_occ_power9_xscom_write(void *opaque, hwaddr addr,
275
break;
276
case P9_OCB_OCI_OCCMISC:
277
pnv_occ_set_misc(occ, val);
232
- break;
278
+ break;
279
+ case P9_OCCFLG0 ... P9_OCCFLG7_OR:
280
+ rw_occ_flag_regs(occ, offset, 0, &val);
281
+ break;
282
default:
234
- qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
283
+ qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register write: Ox%"
284
HWADDR_PRIx "\n", addr >> 3);
285
}
286
}
include/hw/ppc/pnv_occ.h
+4
@@ -47,6 +47,10 @@ struct PnvOCC {
47
/* OCC Misc interrupt */
48
uint64_t occmisc;
49
50
+ /* OCC Flags */
51
+#define NR_FLAG_REGS 8
52
+ uint32_t occflags[NR_FLAG_REGS];
53
+
54
qemu_irq psi_irq;
55
56
/* OCCs operate on regions of HOMER memory */