#include #define CONFIG_64BIT #include "kvm_util.h" #include "riscv/arch_timer.h" static unsigned long timer_freq; static unsigned int irq_fired; void mdelay(unsigned long msecs) { while (msecs--) udelay(1000); } static void guest_irq_handler(struct ex_regs *regs) { GUEST_PRINTF("%s\n", __func__); GUEST_ASSERT_EQ(regs->cause & ~CAUSE_IRQ_FLAG, IRQ_S_TIMER); irq_fired = 1; csr_write(CSR_STIMECMP, -1); while (csr_read(CSR_SIP) & IE_TIE) cpu_relax(); } static void guest_code(void) { GUEST_PRINTF("stage 1\n"); mdelay(1000); GUEST_ASSERT_EQ(irq_fired, 0); GUEST_PRINTF("stage 2\n"); timer_set_next_cval_ms(500); mdelay(1000); GUEST_ASSERT_EQ(irq_fired, 1); irq_fired = 0; GUEST_PRINTF("stage 3\n"); csr_clear(CSR_SIE, IE_TIE); timer_set_next_cval_ms(500); mdelay(1000); GUEST_ASSERT_EQ(irq_fired, 0); GUEST_PRINTF("stage 4\n"); csr_set(CSR_SIE, IE_TIE); mdelay(1); GUEST_ASSERT_EQ(irq_fired, 1); irq_fired = 0; GUEST_PRINTF("stage 5\n"); csr_clear(CSR_SSTATUS, SR_IE); timer_set_next_cval_ms(500); mdelay(1000); GUEST_ASSERT_EQ(irq_fired, 0); GUEST_PRINTF("stage 6\n"); csr_set(CSR_SSTATUS, SR_IE); mdelay(1); GUEST_ASSERT_EQ(irq_fired, 1); irq_fired = 0; GUEST_PRINTF("guest done\n"); GUEST_DONE(); } int main(void) { struct kvm_vcpu *vcpu; struct kvm_vm *vm; struct ucall uc; uint64_t val; int done = 0; vm = vm_create_with_one_vcpu(&vcpu, guest_code); vm_init_vector_tables(vm); vm_install_interrupt_handler(vm, guest_irq_handler); vcpu_init_vector_tables(vcpu); vcpu_set_reg(vcpu, RISCV_CSR_REG(sstatus), SR_IE); vcpu_set_reg(vcpu, RISCV_CSR_REG(sie), IE_TIE); vcpu_get_reg(vcpu, RISCV_TIMER_REG(frequency), &timer_freq); sync_global_to_guest(vm, timer_freq); vcpu_get_reg(vcpu, RISCV_TIMER_REG(compare), &val); assert(val == -1); while (!done) { vcpu_run(vcpu); switch (get_ucall(vcpu, &uc)) { case UCALL_PRINTF: printf("%s", uc.buffer); break; case UCALL_DONE: printf("Done.\n"); done = 1; break; } } }