/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2024 Ruslan Bukin <[email protected]>4*5* This software was developed by the University of Cambridge Computer6* Laboratory (Department of Computer Science and Technology) under Innovate7* UK project 105694, "Digital Security by Design (DSbD) Technology Platform8* Prototype".9*10* Redistribution and use in source and binary forms, with or without11* modification, are permitted provided that the following conditions12* are met:13* 1. Redistributions of source code must retain the above copyright14* notice, this list of conditions and the following disclaimer.15* 2. Redistributions in binary form must reproduce the above copyright16* notice, this list of conditions and the following disclaimer in the17* documentation and/or other materials provided with the distribution.18*19* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND20* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE21* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE22* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE23* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL24* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS25* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT27* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY28* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF29* SUCH DAMAGE.30*/3132#include <sys/param.h>33#include <sys/kernel.h>34#include <sys/lock.h>35#include <sys/mutex.h>3637#include <dev/ofw/ofw_bus.h>38#include <dev/ofw/ofw_bus_subr.h>39#include <dev/ofw/openfirm.h>4041#include <dev/vmm/vmm_vm.h>4243#include "riscv.h"4445#define VTIMER_DEFAULT_FREQ 10000004647static int48vtimer_get_timebase(uint32_t *freq)49{50phandle_t node;51int len;5253node = OF_finddevice("/cpus");54if (node == -1)55return (ENXIO);5657len = OF_getproplen(node, "timebase-frequency");58if (len != 4)59return (ENXIO);6061OF_getencprop(node, "timebase-frequency", freq, len);6263return (0);64}6566void67vtimer_cpuinit(struct hypctx *hypctx)68{69struct vtimer *vtimer;70uint32_t freq;71int error;7273vtimer = &hypctx->vtimer;74mtx_init(&vtimer->mtx, "vtimer callout mutex", NULL, MTX_DEF);75callout_init_mtx(&vtimer->callout, &vtimer->mtx, 0);7677error = vtimer_get_timebase(&freq);78if (error)79freq = VTIMER_DEFAULT_FREQ;8081vtimer->freq = freq;82}8384static void85vtimer_inject_irq_callout(void *arg)86{87struct hypctx *hypctx;88struct hyp *hyp;8990hypctx = arg;91hyp = hypctx->hyp;9293atomic_set_32(&hypctx->interrupts_pending, HVIP_VSTIP);94vcpu_notify_event(vm_vcpu(hyp->vm, hypctx->cpu_id));95}9697int98vtimer_set_timer(struct hypctx *hypctx, uint64_t next_val)99{100struct vtimer *vtimer;101sbintime_t time;102uint64_t curtime;103uint64_t delta;104105vtimer = &hypctx->vtimer;106107curtime = rdtime();108if (curtime < next_val) {109delta = next_val - curtime;110time = delta * SBT_1S / vtimer->freq;111atomic_clear_32(&hypctx->interrupts_pending, HVIP_VSTIP);112callout_reset_sbt(&vtimer->callout, time, 0,113vtimer_inject_irq_callout, hypctx, 0);114} else115atomic_set_32(&hypctx->interrupts_pending, HVIP_VSTIP);116117return (0);118}119120121