From b15e1cbf4903b36c65ac21095e71d081b9f723f0 Mon Sep 17 00:00:00 2001 From: Nick Hudson Date: Sat, 30 Aug 2025 06:57:23 +0000 Subject: [PATCH 10/13] timer interupts work --- accel/nvmm/nvmm-all.c | 6 ++ include/system/nvmm.h | 1 + target/arm/nvmm/nvmm.c | 150 ++++++++++++++++++++++++++-------------- target/i386/nvmm/nvmm.c | 6 ++ 4 files changed, 111 insertions(+), 52 deletions(-) diff --git a/accel/nvmm/nvmm-all.c b/accel/nvmm/nvmm-all.c index 4b66414f96..fa778e9624 100644 --- a/accel/nvmm/nvmm-all.c +++ b/accel/nvmm/nvmm-all.c @@ -417,6 +417,12 @@ nvmm_accel_init(AccelState *as, MachineState *ms) memory_listener_register(&nvmm_memory_listener, &address_space_memory); ram_block_notifier_add(&nvmm_ram_notifier); + ret = nvmm_arch_init(); + if (ret) { + error_report("NVMM: Architecture initialisation failed, ret=%d", ret); + return ret; + } + printf("NetBSD Virtual Machine Monitor accelerator is operational\n"); return 0; } diff --git a/include/system/nvmm.h b/include/system/nvmm.h index 8e5730e9f6..e419dd9144 100644 --- a/include/system/nvmm.h +++ b/include/system/nvmm.h @@ -40,6 +40,7 @@ void nvmm_init_cpu_signals(void); extern struct nvmm_assist_callbacks nvmm_callbacks; /* MD: target//nvmm/nvmm.c */ +int nvmm_arch_init(void); int nvmm_init_vcpu(CPUState *cpu); void nvmm_destroy_vcpu(CPUState *cpu); void nvmm_get_registers(CPUState *cpu); diff --git a/target/arm/nvmm/nvmm.c b/target/arm/nvmm/nvmm.c index d5f0459f8f..71572c2408 100644 --- a/target/arm/nvmm/nvmm.c +++ b/target/arm/nvmm/nvmm.c @@ -15,6 +15,7 @@ #include "system/nvmm.h" #include "system/cpus.h" #include "system/runstate.h" +#include "hw/irq.h" #include "qemu/main-loop.h" #include "qemu/error-report.h" #include "qapi/error.h" @@ -32,6 +33,11 @@ struct AccelCPUState { bool stop; }; +struct NVMMState { + uint64_t vtimer_offset; +// QTAILQ_HEAD(, nvmm_sw_breakpoint) nvmm_sw_breakpoints; +} nvmm_aarch64_global_state; + struct nvmm_sreg_match { int group; #define SREG_GROUP_SPR 0 @@ -329,6 +335,9 @@ static struct nvmm_sreg_match nvmm_sreg_match[] = { { SREG_GROUP_SPR, NVMM_AARCH64_SPR_VBAR_EL1, ENCODE_SYSREG( 12, 0, 3, 0, 0) }, }; + + + /* QEMU -> NVMM */ void nvmm_set_registers(CPUState *cpu) @@ -447,6 +456,31 @@ nvmm_get_registers(CPUState *cpu) } + + +static uint64_t nvmm_vtimer_val_raw(void) +{ + /* + * mach_absolute_time() returns the vtimer value without the VM + * offset that we define. Add our own offset on top. + */ + return 0; +// return mach_absolute_time() - nvmm_state->vtimer_offset; +} + +static uint64_t nvmm_vtimer_val(void) +{ +#if 0 + if (!runstate_is_running()) { + /* VM is paused, the vtimer value is in vtimer.vtimer_val */ + return vtimer.vtimer_val; + } +#endif + return nvmm_vtimer_val_raw(); +} + + + /* * Called before the VCPU is run. We inject events generated by the I/O * thread. @@ -490,7 +524,6 @@ nvmm_vcpu_pre_run(CPUState *cpu) has_event = true; } - if (has_event) { ret = nvmm_vcpu_inject(mach, vcpu); if (ret == -1) { @@ -549,41 +582,44 @@ nvmm_handle_halted(struct nvmm_machine *mach, CPUState *cpu, return ret; } + static void nvmm_wfi(CPUState *cpu) { + ARMCPU *arm_cpu = ARM_CPU(cpu); + AccelCPUState *qcpu = cpu->accel; + struct nvmm_vcpu *vcpu = &qcpu->vcpu; + struct nvmm_aarch64_state *state = vcpu->state; +// struct timespec ts; +// hv_return_t r; +// uint64_t ctl; +// uint64_t cval; + int64_t ticks_to_sleep; + uint64_t seconds; + uint64_t nanos; + uint32_t cntfrq; + + // ARMCPU *arm_cpu = ARM_CPU(cpu); +// CPUArchState *env = cpu_env(cpu); // &cpu->env; +// struct nvmm_machine *mach = get_nvmm_mach(); + if (cpu->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIQ)) { /* Interrupt pending, no need to wait */ return; } -// qatomic_mb_set(&cpu->thread_kicked, false); -// qemu_mutex_unlock_iothread(); -// pselect(0, 0, 0, 0, NULL, &cpu->hvf->unblock_ipi_mask); -// qemu_mutex_lock_iothread(); - - - -#if 0 - - - - - r = hv_vcpu_get_sys_reg(cpu->accel->fd, HV_SYS_REG_CNTV_CTL_EL0, &ctl); - assert_hvf_ok(r); - + uint32_t ctl = state->sprs[NVMM_AARCH64_SPR_CNTV_CTL_EL0]; if (!(ctl & 1) || (ctl & 2)) { /* Timer disabled or masked, just wait for an IPI. */ - hvf_wait_for_ipi(cpu, NULL); +// nvmm_wait_for_ipi(cpu, NULL); return; } - r = hv_vcpu_get_sys_reg(cpu->accel->fd, HV_SYS_REG_CNTV_CVAL_EL0, &cval); - assert_hvf_ok(r); + uint64_t cval = state->sprs[NVMM_AARCH64_SPR_CNTV_CTL_EL0]; - ticks_to_sleep = cval - hvf_vtimer_val(); + ticks_to_sleep = cval - nvmm_vtimer_val(); if (ticks_to_sleep < 0) { return; } @@ -593,6 +629,7 @@ nvmm_wfi(CPUState *cpu) ticks_to_sleep -= muldiv64(seconds, NANOSECONDS_PER_SECOND, cntfrq); nanos = ticks_to_sleep * cntfrq; + // XXXNH update /* * Don't sleep for less than the time a context switch would take, * so that we can satisfy fast timer requests on the same CPU. @@ -602,18 +639,8 @@ nvmm_wfi(CPUState *cpu) return; } - ts = (struct timespec) { seconds, nanos }; - hvf_wait_for_ipi(cpu, &ts); -#endif - - - - - - - - - +// ts = (struct timespec) { seconds, nanos }; +// nvmm_wait_for_ipi(cpu, &ts); } int @@ -641,7 +668,9 @@ fprintf(stderr, "%s:%d irq\n", __func__, __LINE__); } if (cpu->halted) { - return EXCP_HLT; + cpu->exception_index = EXCP_HLT; + qatomic_set(&cpu->exit_request, false); + return 0; } bql_unlock(); @@ -665,21 +694,6 @@ fprintf(stderr, "%s:%d irq\n", __func__, __LINE__); break; } -#if 0 - //XXXXXXXXXX: nvmm cannot send multiple events at the same time? - if (cpu->interrupt_request & CPU_INTERRUPT_FIQ) { - vcpu->event->type = NVMM_VCPU_EVENT_FIQ; - nvmm_vcpu_inject(mach, vcpu); - cpu->halted = false; -fprintf(stderr, "%s:%d fiq\n", __func__, __LINE__); - } - if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { - vcpu->event->type = NVMM_VCPU_EVENT_IRQ; - nvmm_vcpu_inject(mach, vcpu); - cpu->halted = false; -fprintf(stderr, "%s:%d irq\n", __func__, __LINE__); - } -#endif nvmm_vcpu_pre_run(cpu); if (qatomic_read(&cpu->exit_request)) { @@ -690,7 +704,6 @@ fprintf(stderr, "%s:%d irq\n", __func__, __LINE__); #endif } - //XXXNH wtf? /* Read exit_request before the kernel reads the immediate exit flag */ smp_rmb(); ret = nvmm_vcpu_run(mach, vcpu); @@ -702,8 +715,24 @@ fprintf(stderr, "%s:%d irq\n", __func__, __LINE__); nvmm_vcpu_post_run(cpu, exit); + // ret = 0;??? switch (exit->reason) { case NVMM_VCPU_EXIT_NONE: + break; + case NVMM_VCPU_EXIT_IRQ: + // Set vtimer / other in virtual gic + //switched_level = cpu->device_irq_level ^ run->s.regs.device_irq_level; + + bql_lock(); + if (exit->exitstate.vtimer) { + ARMCPU *arm_cpu = ARM_CPU(cpu); + + qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); + // inject + cpu->interrupt_request |= CPU_INTERRUPT_HARD; + } + bql_unlock(); + break; case NVMM_VCPU_EXIT_STOPPED: /* @@ -747,10 +776,14 @@ fprintf(stderr, "%s:%d irq\n", __func__, __LINE__); cpu->exception_index = EXCP_INTERRUPT; ret = 1; break; + // XXXNH + // case NVMM_VCPU_EXIT_PPI: + // qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); + // default: error_report("NVMM: Unexpected VM exit code" - " 0x%lx [hw=0x%lx, esr=0x%lx]", - exit->reason, exit->u.inv.hwcode, exit->esr); + " 0x%lx [esr=0x%lx]", + exit->reason, exit->esr); nvmm_get_registers(cpu); bql_lock(); qemu_system_guest_panicked(cpu_get_crash_info(cpu)); @@ -810,7 +843,7 @@ nvmm_sreg_init(CPUState *cpu) { ARMCPU *arm_cpu = ARM_CPU(cpu); CPUArchState *env = cpu_env(cpu); - AccelCPUState *qcpu = cpu->accel; +// AccelCPUState *qcpu = cpu->accel; uint32_t sregs_match_len = ARRAY_SIZE(nvmm_sreg_match); uint32_t sregs_cnt = 0; @@ -853,6 +886,19 @@ nvmm_sreg_init(CPUState *cpu) } +int +nvmm_arch_init(void) +{ +// nvmm_aarch64_global_state->vtimer_offset = mach_absolute_time(); +// vmstate_register(NULL, 0, &vmstate_nvmm_vtimer, &vtimer); +// qemu_add_vm_change_state_handler(nvmm_vm_state_change, &vtimer); + +// nvmm_arm_init_debug(); + + return 0; +} + + typedef struct ARMHostCPUFeatures { ARMISARegisters isar; uint64_t features; diff --git a/target/i386/nvmm/nvmm.c b/target/i386/nvmm/nvmm.c index 03c4854080..e9db3a1f9b 100644 --- a/target/i386/nvmm/nvmm.c +++ b/target/i386/nvmm/nvmm.c @@ -782,6 +782,12 @@ nvmm_init_cpu_signals(void) pthread_sigmask(SIG_SETMASK, &set, NULL); } +int +nvmm_arch_init(void) +{ + return 0; +} + int nvmm_init_vcpu(CPUState *cpu) { -- 2.54.0 (Apple Git-157)