/*-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 "riscv.h"4243#define VTIMER_DEFAULT_FREQ 10000004445static int46vtimer_get_timebase(uint32_t *freq)47{48phandle_t node;49int len;5051node = OF_finddevice("/cpus");52if (node == -1)53return (ENXIO);5455len = OF_getproplen(node, "timebase-frequency");56if (len != 4)57return (ENXIO);5859OF_getencprop(node, "timebase-frequency", freq, len);6061return (0);62}6364void65vtimer_cpuinit(struct hypctx *hypctx)66{67struct vtimer *vtimer;68uint32_t freq;69int error;7071vtimer = &hypctx->vtimer;72mtx_init(&vtimer->mtx, "vtimer callout mutex", NULL, MTX_DEF);73callout_init_mtx(&vtimer->callout, &vtimer->mtx, 0);7475error = vtimer_get_timebase(&freq);76if (error)77freq = VTIMER_DEFAULT_FREQ;7879vtimer->freq = freq;80}8182static void83vtimer_inject_irq_callout(void *arg)84{85struct hypctx *hypctx;86struct hyp *hyp;8788hypctx = arg;89hyp = hypctx->hyp;9091atomic_set_32(&hypctx->interrupts_pending, HVIP_VSTIP);92vcpu_notify_event(vm_vcpu(hyp->vm, hypctx->cpu_id));93}9495int96vtimer_set_timer(struct hypctx *hypctx, uint64_t next_val)97{98struct vtimer *vtimer;99sbintime_t time;100uint64_t curtime;101uint64_t delta;102103vtimer = &hypctx->vtimer;104105curtime = rdtime();106if (curtime < next_val) {107delta = next_val - curtime;108time = delta * SBT_1S / vtimer->freq;109atomic_clear_32(&hypctx->interrupts_pending, HVIP_VSTIP);110callout_reset_sbt(&vtimer->callout, time, 0,111vtimer_inject_irq_callout, hypctx, 0);112} else113atomic_set_32(&hypctx->interrupts_pending, HVIP_VSTIP);114115return (0);116}117118119