Skip to content

Commit

Permalink
ref(csr): Adapt csr access to be done through functions
Browse files Browse the repository at this point in the history
ISO C forbids braced-groups within expressions which was used in the
CSRR macro. We use the same strategy as in arm code, by generating
static functions accessors for each CSR

Signed-off-by: Miguel Silva <[email protected]>
  • Loading branch information
miguelafsilva5 authored and josecm committed May 22, 2024
1 parent 6fac282 commit 6935959
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 62 deletions.
62 changes: 52 additions & 10 deletions src/arch/riscv/inc/arch/csrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,16 +217,58 @@

#ifndef __ASSEMBLER__

#define CSRR(csr) \
({ \
unsigned long _temp; \
__asm__ volatile("csrr %0, " XSTR(csr) "\n\r" : "=r"(_temp)::"memory"); \
_temp; \
})

#define CSRW(csr, rs) __asm__ volatile("csrw " XSTR(csr) ", %0\n\r" ::"rK"(rs) : "memory")
#define CSRS(csr, rs) __asm__ volatile("csrs " XSTR(csr) ", %0\n\r" ::"rK"(rs) : "memory")
#define CSRC(csr, rs) __asm__ volatile("csrc " XSTR(csr) ", %0\n\r" ::"rK"(rs) : "memory")
#define CSRS_GEN_ACCESSORS_NAMED(csr_name, csr_id) \
static inline unsigned long csrs_##csr_name##_read(void) \
{ \
unsigned long csr_value; \
__asm__ volatile("csrr %0," XSTR(csr_id) : "=r"(csr_value)::"memory"); \
return csr_value; \
} \
static inline void csrs_##csr_name##_write(unsigned long csr_value) \
{ \
__asm__ volatile("csrw " XSTR(csr_id) ",%0" ::"r"(csr_value) : "memory"); \
} \
static inline void csrs_##csr_name##_set(unsigned long csr_value) \
{ \
__asm__ volatile("csrs " XSTR(csr_id) ",%0" ::"r"(csr_value) : "memory"); \
} \
static inline void csrs_##csr_name##_clear(unsigned long csr_value) \
{ \
__asm__ volatile("csrc " XSTR(csr_id) ",%0" ::"r"(csr_value) : "memory"); \
}

#define CSRS_GEN_ACCESSORS(csr) CSRS_GEN_ACCESSORS_NAMED(csr, csr)

CSRS_GEN_ACCESSORS(sstatus)
CSRS_GEN_ACCESSORS(sscratch)
CSRS_GEN_ACCESSORS(scause)
CSRS_GEN_ACCESSORS(stval)
CSRS_GEN_ACCESSORS(sepc)
CSRS_GEN_ACCESSORS(sie)
CSRS_GEN_ACCESSORS(sip)
CSRS_GEN_ACCESSORS(satp)

CSRS_GEN_ACCESSORS_NAMED(hstatus, CSR_HSTATUS)
CSRS_GEN_ACCESSORS_NAMED(hgatp, CSR_HGATP)
CSRS_GEN_ACCESSORS_NAMED(htinst, CSR_HTINST)
CSRS_GEN_ACCESSORS_NAMED(htval, CSR_HTVAL)
CSRS_GEN_ACCESSORS_NAMED(hideleg, CSR_HIDELEG)
CSRS_GEN_ACCESSORS_NAMED(hedeleg, CSR_HEDELEG)
CSRS_GEN_ACCESSORS_NAMED(hcounteren, CSR_HCOUNTEREN)
CSRS_GEN_ACCESSORS_NAMED(stimecmp, CSR_STIMECMP)
CSRS_GEN_ACCESSORS_NAMED(vstimecmp, CSR_VSTIMECMP)
CSRS_GEN_ACCESSORS_NAMED(henvcfg, CSR_HENVCFG)
CSRS_GEN_ACCESSORS_NAMED(vsstatus, CSR_VSSTATUS)
CSRS_GEN_ACCESSORS_NAMED(vstvec, CSR_VSTVEC)
CSRS_GEN_ACCESSORS_NAMED(vsscratch, CSR_VSSCRATCH)
CSRS_GEN_ACCESSORS_NAMED(vsepc, CSR_VSEPC)
CSRS_GEN_ACCESSORS_NAMED(vscause, CSR_VSCAUSE)
CSRS_GEN_ACCESSORS_NAMED(vstval, CSR_VSTVAL)
CSRS_GEN_ACCESSORS_NAMED(vsatp, CSR_VSATP)
CSRS_GEN_ACCESSORS_NAMED(hvip, CSR_HVIP)
CSRS_GEN_ACCESSORS_NAMED(vsie, CSR_VSIE)
CSRS_GEN_ACCESSORS_NAMED(htimedelta, CSR_HTIMEDELTA)
CSRS_GEN_ACCESSORS_NAMED(hie, CSR_HIE)

#endif /* __ASSEMBLER__ */

Expand Down
24 changes: 12 additions & 12 deletions src/arch/riscv/interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void interrupts_arch_init()
/**
* Enable external interrupts.
*/
CSRS(sie, SIE_SEIE);
csrs_sie_set(SIE_SEIE);
}

void interrupts_arch_ipi_send(cpuid_t target_cpu, irqid_t ipi_id)
Expand All @@ -48,25 +48,25 @@ void interrupts_arch_ipi_send(cpuid_t target_cpu, irqid_t ipi_id)
void interrupts_arch_cpu_enable(bool en)
{
if (en) {
CSRS(sstatus, SSTATUS_SIE_BIT);
csrs_sstatus_set(SSTATUS_SIE_BIT);
} else {
CSRC(sstatus, SSTATUS_SIE_BIT);
csrs_sstatus_clear(SSTATUS_SIE_BIT);
}
}

void interrupts_arch_enable(irqid_t int_id, bool en)
{
if (int_id == SOFT_INT_ID) {
if (en) {
CSRS(sie, SIE_SSIE);
csrs_sie_set(SIE_SSIE);
} else {
CSRC(sie, SIE_SSIE);
csrs_sie_clear(SIE_SSIE);
}
} else if (int_id == TIMR_INT_ID) {
if (en) {
CSRS(sie, SIE_STIE);
csrs_sie_set(SIE_STIE);
} else {
CSRC(sie, SIE_STIE);
csrs_sie_clear(SIE_STIE);
}
} else {
irqc_config_irq(int_id, en);
Expand All @@ -75,11 +75,11 @@ void interrupts_arch_enable(irqid_t int_id, bool en)

void interrupts_arch_handle()
{
unsigned long _scause = CSRR(scause);
unsigned long _scause = csrs_scause_read();

switch (_scause) {
case SCAUSE_CODE_SSI:
CSRC(sip, SIP_SSIP);
csrs_sip_clear(SIP_SSIP);
interrupts_handle(SOFT_INT_ID);
break;
case SCAUSE_CODE_STI:
Expand All @@ -104,9 +104,9 @@ void interrupts_arch_handle()
bool interrupts_arch_check(irqid_t int_id)
{
if (int_id == SOFT_INT_ID) {
return CSRR(sip) & SIP_SSIP;
return csrs_sip_read() & SIP_SSIP;
} else if (int_id == TIMR_INT_ID) {
return CSRR(sip) & SIP_STIP;
return csrs_sip_read() & SIP_STIP;
} else {
return irqc_get_pend(int_id);
}
Expand All @@ -115,7 +115,7 @@ bool interrupts_arch_check(irqid_t int_id)
void interrupts_arch_clear(irqid_t int_id)
{
if (int_id == SOFT_INT_ID) {
CSRC(sip, SIP_SSIP);
csrs_sip_clear(SIP_SSIP);
} else if (int_id == TIMR_INT_ID) {
/**
* It is not actually possible to clear timer by software.
Expand Down
4 changes: 2 additions & 2 deletions src/arch/riscv/irqc/aia/vaplic.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,9 @@ static void vaplic_update_hart_line(struct vcpu* vcpu, vcpuid_t vhart_index)
*/
if (pcpu_id == cpu()->id) {
if (vaplic_update_topi(vcpu)) {
CSRS(CSR_HVIP, HIP_VSEIP);
csrs_hvip_set(HIP_VSEIP);
} else {
CSRC(CSR_HVIP, HIP_VSEIP);
csrs_hvip_clear(HIP_VSEIP);
}
} else {
struct cpu_msg msg = { VPLIC_IPI_ID, UPDATE_HART_LINE, vhart_index };
Expand Down
4 changes: 2 additions & 2 deletions src/arch/riscv/irqc/plic/vplic.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ void vplic_update_hart_line(struct vcpu* vcpu, int vcntxt)
if (pcntxt.hart_id == cpu()->id) {
int id = vplic_next_pending(vcpu, vcntxt);
if (id != 0) {
CSRS(CSR_HVIP, HIP_VSEIP);
csrs_hvip_set(HIP_VSEIP);
} else {
CSRC(CSR_HVIP, HIP_VSEIP);
csrs_hvip_clear(HIP_VSEIP);
}
} else {
struct cpu_msg msg = { VPLIC_IPI_ID, UPDATE_HART_LINE, vcntxt };
Expand Down
12 changes: 6 additions & 6 deletions src/arch/riscv/sbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ void sbi_msg_handler(uint32_t event, uint64_t data)
{
switch (event) {
case SEND_IPI:
CSRS(CSR_HVIP, HIP_VSSIP);
csrs_hvip_set(HIP_VSSIP);
break;
case HART_START: {
spin_lock(&cpu()->vcpu->arch.sbi_ctx.lock);
Expand All @@ -204,20 +204,20 @@ struct sbiret sbi_time_handler(unsigned long fid)

uint64_t stime_value = vcpu_readreg(cpu()->vcpu, REG_A0);
if (CPU_HAS_EXTENSION(CPU_EXT_SSTC)) {
CSRW(CSR_VSTIMECMP, stime_value);
csrs_vstimecmp_write(stime_value);
} else {
sbi_set_timer(stime_value); // assumes always success
CSRC(CSR_HVIP, HIP_VSTIP);
CSRS(sie, SIE_STIE);
csrs_hvip_clear(HIP_VSTIP);
csrs_sie_set(SIE_STIE);
}

return (struct sbiret){ SBI_SUCCESS };
}

void sbi_timer_irq_handler()
{
CSRS(CSR_HVIP, HIP_VSTIP);
CSRC(sie, SIE_STIE);
csrs_hvip_set(HIP_VSTIP);
csrs_sie_clear(SIE_STIE);
}

struct sbiret sbi_ipi_handler(unsigned long fid)
Expand Down
20 changes: 10 additions & 10 deletions src/arch/riscv/sync_exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ void internal_exception_handler(unsigned long gprs[])
for (int i = 0; i < 31; i++) {
console_printk("x%d:\t\t0x%0lx\n", i, gprs[i]);
}
console_printk("sstatus:\t0x%0lx\n", CSRR(sstatus));
console_printk("stval:\t\t0x%0lx\n", CSRR(stval));
console_printk("sepc:\t\t0x%0lx\n", CSRR(sepc));
console_printk("sstatus:\t0x%0lx\n", csrs_sstatus_read());
console_printk("stval:\t\t0x%0lx\n", csrs_stval_read());
console_printk("sepc:\t\t0x%0lx\n", csrs_sepc_read());
ERROR("cpu%d internal hypervisor abort - PANIC\n", cpu()->id);
}

Expand Down Expand Up @@ -80,18 +80,18 @@ static inline bool is_pseudo_ins(uint32_t ins)

size_t guest_page_fault_handler()
{
vaddr_t addr = CSRR(CSR_HTVAL) << 2;
vaddr_t addr = csrs_htval_read() << 2;

emul_handler_t handler = vm_emul_get_mem(cpu()->vcpu->vm, addr);
if (handler != NULL) {
unsigned long ins = CSRR(CSR_HTINST);
unsigned long ins = csrs_htinst_read();
size_t ins_size;
if (ins == 0) {
/**
* If htinst does not provide information about the trap, we must read the instruction
* from the guest's memory manually.
*/
vaddr_t ins_addr = CSRR(sepc);
vaddr_t ins_addr = csrs_sepc_read();
ins = read_ins(ins_addr);
ins_size = INS_SIZE(ins);
} else if (is_pseudo_ins(ins)) {
Expand Down Expand Up @@ -119,10 +119,10 @@ size_t guest_page_fault_handler()
if (handler(&emul)) {
return ins_size;
} else {
ERROR("emulation handler failed (0x%x at 0x%x)", addr, CSRR(sepc));
ERROR("emulation handler failed (0x%x at 0x%x)", addr, csrs_sepc_read());
}
} else {
ERROR("no emulation handler for abort(0x%x at 0x%x)", addr, CSRR(sepc));
ERROR("no emulation handler for abort(0x%x at 0x%x)", addr, csrs_sepc_read());
}
}

Expand All @@ -137,9 +137,9 @@ static const size_t sync_handler_table_size = sizeof(sync_handler_table) / sizeo
void sync_exception_handler()
{
size_t pc_step = 0;
unsigned long _scause = CSRR(scause);
unsigned long _scause = csrs_scause_read();

if (!(CSRR(CSR_HSTATUS) & HSTATUS_SPV)) {
if (!(csrs_hstatus_read() & HSTATUS_SPV)) {
internal_exception_handler(&cpu()->vcpu->regs.x[0]);
}

Expand Down
29 changes: 15 additions & 14 deletions src/arch/riscv/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void vm_arch_init(struct vm* vm, const struct vm_config* config)
unsigned long hgatp = (root_pt_pa >> PAGE_SHIFT) | (HGATP_MODE_DFLT) |
((vm->id << HGATP_VMID_OFF) & HGATP_VMID_MSK);

CSRW(CSR_HGATP, hgatp);
csrs_hgatp_write(hgatp);

virqc_init(vm, &config->platform.arch.irqc);
}
Expand All @@ -34,7 +34,7 @@ void vcpu_arch_reset(struct vcpu* vcpu, vaddr_t entry)
{
memset(&vcpu->regs, 0, sizeof(struct arch_regs));

CSRW(sscratch, &vcpu->regs);
csrs_sscratch_write((uintptr_t)&vcpu->regs);

vcpu->regs.hstatus = HSTATUS_SPV | HSTATUS_VSXL_64;
vcpu->regs.sstatus = SSTATUS_SPP_BIT | SSTATUS_FS_DIRTY | SSTATUS_XS_DIRTY;
Expand All @@ -43,19 +43,20 @@ void vcpu_arch_reset(struct vcpu* vcpu, vaddr_t entry)
vcpu->regs.a1 = 0; // according to sbi it should be the dtb load address

if (CPU_HAS_EXTENSION(CPU_EXT_SSTC)) {
CSRW(CSR_VSTIMECMP, -1);
csrs_stimecmp_write(-1);
}
CSRW(CSR_HCOUNTEREN, HCOUNTEREN_TM);
CSRW(CSR_HTIMEDELTA, 0);
CSRW(CSR_VSSTATUS, SSTATUS_SD | SSTATUS_FS_DIRTY | SSTATUS_XS_DIRTY);
CSRW(CSR_HIE, 0);
CSRW(CSR_VSTVEC, 0);
CSRW(CSR_VSSCRATCH, 0);
CSRW(CSR_VSEPC, 0);
CSRW(CSR_VSCAUSE, 0);
CSRW(CSR_VSTVAL, 0);
CSRW(CSR_HVIP, 0);
CSRW(CSR_VSATP, 0);

csrs_hcounteren_write(HCOUNTEREN_TM);
csrs_htimedelta_write(0);
csrs_vsstatus_write(SSTATUS_SD | SSTATUS_FS_DIRTY | SSTATUS_XS_DIRTY);
csrs_hie_write(0);
csrs_vstvec_write(0);
csrs_vsscratch_write(0);
csrs_vsepc_write(0);
csrs_vscause_write(0);
csrs_vstval_write(0);
csrs_hvip_write(0);
csrs_vsatp_write(0);
}

unsigned long vcpu_readreg(struct vcpu* vcpu, unsigned long reg)
Expand Down
12 changes: 6 additions & 6 deletions src/arch/riscv/vmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@ void vmm_arch_init()
* Delegate all interrupts and exceptions not meant to be dealt by the hypervisor
*/

CSRW(CSR_HIDELEG, HIDELEG_VSSI | HIDELEG_VSTI | HIDELEG_VSEI);
CSRW(CSR_HEDELEG, HEDELEG_ECU | HEDELEG_IPF | HEDELEG_LPF | HEDELEG_SPF);
csrs_hideleg_write(HIDELEG_VSSI | HIDELEG_VSTI | HIDELEG_VSEI);
csrs_hedeleg_write(HEDELEG_ECU | HEDELEG_IPF | HEDELEG_LPF | HEDELEG_SPF);

/**
* Enable and sanity check presence of Sstc extension if the hypervisor was
* configured to use it (via the CPU_EXT_SSTC macro). Otherwise, make sure
* it is disabled.
*/
if (CPU_HAS_EXTENSION(CPU_EXT_SSTC)) {
CSRS(CSR_HENVCFG, HENVCFG_STCE);
bool sstc_present = (CSRR(CSR_HENVCFG) & HENVCFG_STCE) != 0;
csrs_henvcfg_set(HENVCFG_STCE);
bool sstc_present = (csrs_henvcfg_read() & HENVCFG_STCE) != 0;
if (cpu_is_master() && !sstc_present) {
ERROR("Platform configured to use Sstc extension, but extension not present.");
}
// Set stimecmp to infinity in case we enable the stimer interrupt somewhere else
// and fail to set the timer to a point in the future.
CSRS(CSR_STIMECMP, -1);
csrs_stimecmp_write(-1);
} else {
CSRC(CSR_HENVCFG, HENVCFG_STCE);
csrs_henvcfg_clear(HENVCFG_STCE);
}

/**
Expand Down

0 comments on commit 6935959

Please sign in to comment.