Browse Source

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>
master
Caleb Schlossin 2 months ago
committed by Harsh Prateek Bora
parent
commit
0b74dd1d80
No known key found for this signature in database GPG Key ID: 4544E994F9D68FBB
  1. 55
      hw/ppc/pnv_occ.c
  2. 4
      include/hw/ppc/pnv_occ.h

55
hw/ppc/pnv_occ.c

@ -195,6 +195,49 @@ static const TypeInfo pnv_occ_power8_type_info = {
#define P9_OCB_OCI_OCCMISC_CLEAR 0x6081
#define P9_OCB_OCI_OCCMISC_OR 0x6082
/* OCC scratch registers for flag setting */
#define P9_OCCFLG0 0x60ac
#define P9_OCCFLG7_OR 0x60c3
enum ScomType {
SCOM_TYPE_RW = 0,
SCOM_TYPE_WO_CLEAR = 1,
SCOM_TYPE_WO_OR = 2,
};
static void rw_occ_flag_regs(PnvOCC *occ, uint32_t offset, bool read,
uint64_t *val)
{
int flag_num;
int flag_type;
/*
* Each OCCFLG register has SCOM0 - RW, SCOM1 - WO_CLEAR, SCOM2 - WO_OR
* hence divide by 3 to get flag index and mod 3 to get SCOM type.
*/
flag_num = (offset - P9_OCCFLG0) / 3;
flag_type = (offset - P9_OCCFLG0) % 3;
if (read) {
if (flag_type) {
qemu_log_mask(LOG_GUEST_ERROR, "OCC: Write only register: Ox%"
PRIx32 "\n", offset);
return;
}
*val = occ->occflags[flag_num];
} else {
switch (flag_type) {
case SCOM_TYPE_RW:
occ->occflags[flag_num] = *val;
break;
case SCOM_TYPE_WO_CLEAR:
occ->occflags[flag_num] &= ~(*val);
break;
case SCOM_TYPE_WO_OR:
occ->occflags[flag_num] |= *val;
}
}
}
static uint64_t pnv_occ_power9_xscom_read(void *opaque, hwaddr addr,
unsigned size)
@ -207,8 +250,11 @@ static uint64_t pnv_occ_power9_xscom_read(void *opaque, hwaddr addr,
case P9_OCB_OCI_OCCMISC:
val = occ->occmisc;
break;
case P9_OCCFLG0 ... P9_OCCFLG7_OR:
rw_occ_flag_regs(occ, offset, 1, &val);
break;
default:
qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register read: Ox%"
HWADDR_PRIx "\n", addr >> 3);
}
return val;
@ -229,9 +275,12 @@ static void pnv_occ_power9_xscom_write(void *opaque, hwaddr addr,
break;
case P9_OCB_OCI_OCCMISC:
pnv_occ_set_misc(occ, val);
break;
break;
case P9_OCCFLG0 ... P9_OCCFLG7_OR:
rw_occ_flag_regs(occ, offset, 0, &val);
break;
default:
qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register: Ox%"
qemu_log_mask(LOG_UNIMP, "OCC Unimplemented register write: Ox%"
HWADDR_PRIx "\n", addr >> 3);
}
}

4
include/hw/ppc/pnv_occ.h

@ -47,6 +47,10 @@ struct PnvOCC {
/* OCC Misc interrupt */
uint64_t occmisc;
/* OCC Flags */
#define NR_FLAG_REGS 8
uint32_t occflags[NR_FLAG_REGS];
qemu_irq psi_irq;
/* OCCs operate on regions of HOMER memory */

Loading…
Cancel
Save