blob: 2918a80469110f3677d1ed9a46bf5db70da497a7 [file] [log] [blame]
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
*
* Authors:
* Anup Patel <anup.patel@wdc.com>
*/
#include <sbi/riscv_asm.h>
#include <sbi/riscv_encoding.h>
#include <sbi/sbi_bits.h>
#include <sbi/sbi_console.h>
#include <sbi/sbi_emulate_csr.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_timer.h>
int sbi_emulate_csr_read(int csr_num,
u32 hartid, ulong mstatus,
struct sbi_scratch *scratch,
ulong *csr_val)
{
ulong cen = -1UL;
if (EXTRACT_FIELD(mstatus, MSTATUS_MPP) == PRV_U)
cen = csr_read(scounteren);
switch (csr_num) {
case CSR_CYCLE:
if (!((cen >> (CSR_CYCLE - CSR_CYCLE)) & 1))
return -1;
*csr_val = csr_read(mcycle);
break;
case CSR_TIME:
if (!((cen >> (CSR_TIME - CSR_CYCLE)) & 1))
return -1;
*csr_val = sbi_timer_value(scratch);
break;
case CSR_INSTRET:
if (!((cen >> (CSR_INSTRET - CSR_CYCLE)) & 1))
return -1;
*csr_val = csr_read(minstret);
break;
case CSR_MHPMCOUNTER3:
if (!((cen >> (3 + CSR_MHPMCOUNTER3 - CSR_MHPMCOUNTER3)) & 1))
return -1;
*csr_val = csr_read(mhpmcounter3);
break;
case CSR_MHPMCOUNTER4:
if (!((cen >> (3 + CSR_MHPMCOUNTER4 - CSR_MHPMCOUNTER3)) & 1))
return -1;
*csr_val = csr_read(mhpmcounter4);
break;
#if __riscv_xlen == 32
case CSR_CYCLEH:
if (!((cen >> (CSR_CYCLE - CSR_CYCLE)) & 1))
return -1;
*csr_val = csr_read(mcycleh);
break;
case CSR_TIMEH:
if (!((cen >> (CSR_TIME - CSR_CYCLE)) & 1))
return -1;
*csr_val = sbi_timer_value(scratch);
*csr_val = *csr_val >> 32;
break;
case CSR_INSTRETH:
if (!((cen >> (CSR_INSTRET - CSR_CYCLE)) & 1))
return -1;
*csr_val = csr_read(minstreth);
break;
case CSR_MHPMCOUNTER3H:
if (!((cen >> (3 + CSR_MHPMCOUNTER3 - CSR_MHPMCOUNTER3)) & 1))
return -1;
*csr_val = csr_read(mhpmcounter3h);
break;
case CSR_MHPMCOUNTER4H:
if (!((cen >> (3 + CSR_MHPMCOUNTER4 - CSR_MHPMCOUNTER3)) & 1))
return -1;
*csr_val = csr_read(mhpmcounter4h);
break;
#endif
case CSR_MHPMEVENT3:
*csr_val = csr_read(mhpmevent3);
break;
case CSR_MHPMEVENT4:
*csr_val = csr_read(mhpmevent4);
break;
default:
sbi_printf("%s: hartid%d: invalid csr_num=0x%x\n",
__func__, hartid, csr_num);
return SBI_ENOTSUPP;
};
return 0;
}
int sbi_emulate_csr_write(int csr_num,
u32 hartid, ulong mstatus,
struct sbi_scratch *scratch,
ulong csr_val)
{
switch (csr_num) {
case CSR_CYCLE:
csr_write(mcycle, csr_val);
break;
case CSR_INSTRET:
csr_write(minstret, csr_val);
break;
case CSR_MHPMCOUNTER3:
csr_write(mhpmcounter3, csr_val);
break;
case CSR_MHPMCOUNTER4:
csr_write(mhpmcounter4, csr_val);
break;
#if __riscv_xlen == 32
case CSR_CYCLEH:
csr_write(mcycleh, csr_val);
break;
case CSR_INSTRETH:
csr_write(minstreth, csr_val);
break;
case CSR_MHPMCOUNTER3H:
csr_write(mhpmcounter3h, csr_val);
break;
case CSR_MHPMCOUNTER4H:
csr_write(mhpmcounter4h, csr_val);
break;
#endif
case CSR_MHPMEVENT3:
csr_write(mhpmevent3, csr_val);
break;
case CSR_MHPMEVENT4:
csr_write(mhpmevent4, csr_val);
break;
default:
sbi_printf("%s: hartid%d: invalid csr_num=0x%x\n",
__func__, hartid, csr_num);
return SBI_ENOTSUPP;
};
return 0;
}