l4re-base-25.08.0

This commit is contained in:
2025-09-12 15:55:45 +02:00
commit d959eaab98
37938 changed files with 9382688 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
provides: libvcpu
requires: l4re-util libc
maintainer: adam@os.inf.tu-dresden.de

View File

@@ -0,0 +1,4 @@
PKGDIR = .
L4DIR ?= $(PKGDIR)/../..
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,20 @@
# Libvcpu for L4Re
This package provides a library with convenience functions useful when
working with vcpus in the L4Re operating system.
# Documentation
This package is part of the L4Re operating system. For documentation and
build instructions see the
[L4Re wiki](https://kernkonzept.com/L4Re/guides/l4re).
# Contributions
We welcome contributions. Please see our contributors guide on
[how to contribute](https://kernkonzept.com/L4Re/contributing/l4re).
# License
Detailed licensing and copyright information can be found in
the [LICENSE](LICENSE.spdx) file.

View File

@@ -0,0 +1,29 @@
# Security Policy
This document outlines security procedures for the open-source projects of the
L4Re Operating System Framework as found on https://github.com/kernkonzept.
# Reporting a vulnerability
Security is very important to us and we take all security vulnerabilities
seriously. Thank you for improving the security of our open source software. If
you have discovered a security issue, we appreciate your efforts and your
responsible disclosure.
Please report a security vulnerability by sending an encrypted email to our
security team using our [public
key](https://www.kernkonzept.com/dl/security-at-kernkonzept.pub)
to **security@kernkonzept.com**. The fingerprint of our public key is
````
C4DC 2909 A22E D080 C012 5373 4055 CBA2 A4FD 855B
````
Please include the following in your report:
* A description of the vulnerability
* Steps to reproduce the vulnerability
A member of Kernkonzept's security team will confirm the vulnerability,
determine its impact, and develop a fix. The fix will be applied to the master
branch, tested, and released.

View File

@@ -0,0 +1 @@
INPUT += l4/vcpu

View File

@@ -0,0 +1,25 @@
/**
* \internal
* \file
*/
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
L4_CV L4_INLINE
int
l4vcpu_is_irq_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return vcpu->r.trapno == 0xfe;
}
L4_CV L4_INLINE
int
l4vcpu_is_page_fault_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return vcpu->r.trapno == 0xe;
}

View File

@@ -0,0 +1,25 @@
/**
* \internal
* \file
*/
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
L4_CV L4_INLINE
int
l4vcpu_is_irq_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return (vcpu->r.err >> 26) == 0x3f;
}
L4_CV L4_INLINE
int
l4vcpu_is_page_fault_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return ((vcpu->r.err >> 26) & 0x30) == 0x20;
}

View File

@@ -0,0 +1,21 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
L4_CV L4_INLINE
int
l4vcpu_is_irq_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return (vcpu->r.err >> 26) == 0x3f;
}
L4_CV L4_INLINE
int
l4vcpu_is_page_fault_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return ((vcpu->r.err >> 26) & 0x30) == 0x20;
}

View File

@@ -0,0 +1,23 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
L4_CV L4_INLINE
int
l4vcpu_is_irq_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return ((vcpu->r.cause >> 2) & 0x1f) == 0;
}
L4_CV L4_INLINE
int
l4vcpu_is_page_fault_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
unsigned x = (vcpu->r.cause >> 2) & 0x1f;
return ((1 <= x) && (x <= 3)) || ((19 <= x) && (x <= 20));
}

View File

@@ -0,0 +1,29 @@
/**
* \internal
* \file
*/
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#warning This file needs to be implemented.
L4_CV L4_INLINE
int
l4vcpu_is_irq_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
(void)vcpu;
return 0; // TBD
}
L4_CV L4_INLINE
int
l4vcpu_is_page_fault_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
(void)vcpu;
return 0; // TBD
}

View File

@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright (C) 2021, 2024 Kernkonzept GmbH.
* Author(s): Georg Kotheimer <georg.kotheimer@kernkonzept.com>
*/
#pragma once
L4_CV L4_INLINE
int
l4vcpu_is_irq_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return vcpu->r.cause == L4_riscv_ec_l4_ipc_upcall;
}
L4_CV L4_INLINE
int
l4vcpu_is_page_fault_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
switch(vcpu->r.cause)
{
case L4_riscv_exc_inst_page_fault:
case L4_riscv_exc_load_page_fault:
case L4_riscv_exc_store_page_fault:
return 1;
default:
return 0;
}
}

View File

@@ -0,0 +1,25 @@
/**
* \internal
* \file
*/
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
L4_CV L4_INLINE
int
l4vcpu_is_irq_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return 0; // tbd
}
L4_CV L4_INLINE
int
l4vcpu_is_page_fault_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return 0; // tbd
}

View File

@@ -0,0 +1,25 @@
/**
* \internal
* \file
*/
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
L4_CV L4_INLINE
int
l4vcpu_is_irq_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return vcpu->r.trapno == 0xfe;
}
L4_CV L4_INLINE
int
l4vcpu_is_page_fault_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW
{
return vcpu->r.trapno == 0xe;
}

View File

@@ -0,0 +1,7 @@
PKGDIR = ..
L4DIR ?= $(PKGDIR)/../..
PKGNAME = vcpu
EXTRA_TARGET += vcpu
include $(L4DIR)/mk/include.mk

View File

@@ -0,0 +1,280 @@
// vi:se ft=cpp:
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
/**
* \file
* vCPU support library (C++ interface).
*/
#pragma once
#include <l4/re/env>
#include <l4/vcpu/vcpu.h>
namespace L4vcpu {
/**
* \brief C++ implementation of state word in the vCPU area
* \ingroup api_libvcpu
*/
class State
{
public:
State() {}
/**
* \brief Initialize state.
*
* \param v Initial state.
*/
explicit State(unsigned v) : _s(v) {}
/**
* \brief Add flags.
*
* \param bits Bits to add to the word.
*/
void add(unsigned bits) throw() { _s |= bits; }
/**
* \brief Clear flags.
*
* \param bits Bits to clear in the word.
*/
void clear(unsigned bits) throw() { _s &= ~bits; }
/**
* \brief Set flags.
*
* \param v Set the word to the value of v.
*/
void set(unsigned v) throw() { _s = v; }
private:
__typeof__(((l4_vcpu_state_t *)0)->state) _s;
};
/**
* \brief C++ implementation of the vCPU save state area
* \ingroup api_libvcpu
*/
class Vcpu : private l4_vcpu_state_t
{
public:
/**
* \brief Disable the vCPU for event delivery.
*/
void irq_disable() throw()
{ l4vcpu_irq_disable(this); }
/**
* \brief Disable the vCPU for event delivery and return previous state.
* \return IRQ state before disabling IRQs.
*/
unsigned irq_disable_save() throw()
{ return l4vcpu_irq_disable_save(this); }
l4_vcpu_state_t *s() { return this; }
l4_vcpu_state_t const *s() const { return this; }
/**
* \brief Get state word
* \return Pointer to state word in the vCPU
*/
State *state() throw()
{
static_assert(sizeof(State) == sizeof(l4_vcpu_state_t::state),
"size mismatch");
return reinterpret_cast<State *>(&(l4_vcpu_state_t::state));
}
/**
* \brief Get state word
* \return Pointer to state word in the vCPU
*/
State state() const throw()
{ return static_cast<State>(l4_vcpu_state_t::state); }
/**
* \brief Get saved_state word
* \return Pointer to saved_state word in the vCPU
*/
State *saved_state() throw()
{
static_assert(sizeof(State) == sizeof(l4_vcpu_state_t::saved_state),
"size mismatch");
return reinterpret_cast<State *>(&(l4_vcpu_state_t::saved_state));
}
/**
* \brief Get saved_state word
* \return Pointer to saved_state word in the vCPU
*/
State saved_state() const throw()
{ return static_cast<State>(l4_vcpu_state_t::saved_state); }
/**
* \brief Get sticky flags
*/
l4_uint16_t sticky_flags() const throw()
{ return l4_vcpu_state_t::sticky_flags; }
/**
* \brief Enable the vCPU for event delivery.
*
* \param utcb The UTCB to use.
* \param do_event_work_cb Call-back function that is called in case an
* event (such as an interrupt) is pending.
* \param setup_ipc Call-back function that is called before an
* IPC operation is called, and before event
* delivery is enabled.
*/
void irq_enable(l4_utcb_t *utcb, l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) throw()
{ l4vcpu_irq_enable(this, utcb, do_event_work_cb, setup_ipc); }
/**
* \brief Restore a previously saved IRQ/event state.
*
* \param s IRQ state to be restored.
* \param utcb The UTCB to use.
* \param do_event_work_cb Call-back function that is called in case an
* event (such as an interrupt) is pending.
* \param setup_ipc Call-back function that is called before an
* IPC operation is called, and before event
* delivery is enabled.
*/
void irq_restore(unsigned s, l4_utcb_t *utcb,
l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) throw()
{ l4vcpu_irq_restore(this, s, utcb, do_event_work_cb, setup_ipc); }
/**
* \brief Wait for event.
*
* \param utcb The UTCB to use.
* \param do_event_work_cb Call-back function that is called in case an
* event (such as an interrupt) is pending.
* \param setup_ipc Call-back function that is called before an
* IPC operation is called.
*
* Note that event delivery remains disabled after this function returns.
*/
void wait_for_event(l4_utcb_t *utcb, l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) throw()
{ l4vcpu_wait_for_event(this, utcb, do_event_work_cb, setup_ipc); }
/**
* \brief Set the task of the vCPU.
* \param task Task to set, defaults to invalid task.
*/
void task(L4::Cap<L4::Task> const task = L4::Cap<L4::Task>::Invalid) throw()
{ user_task = task.cap(); }
/**
* \brief Return whether the entry reason was a page fault.
* return 0 if not, !=0 otherwise.
*/
int is_page_fault_entry() const
{ return l4vcpu_is_page_fault_entry(this); }
/**
* \brief Return whether the entry reason was an IRQ/IPC message.
* return 0 if not, !=0 otherwise.
*/
int is_irq_entry() const
{ return l4vcpu_is_irq_entry(this); }
/**
* \brief Return pointer to register state.
* \return Pointer to register state.
*/
l4_vcpu_regs_t *r() throw()
{ return &(l4_vcpu_state_t::r); }
/**
* \brief Return pointer to register state.
* \return Pointer to register state.
*/
l4_vcpu_regs_t const *r() const throw()
{ return &(l4_vcpu_state_t::r); }
/**
* \brief Return pointer to IPC state.
* \return Pointer to IPC state.
*/
l4_vcpu_ipc_regs_t *i() throw()
{ return &(l4_vcpu_state_t::i); }
/**
* \brief Return pointer to IPC state.
* \return Pointer to IPC state.
*/
l4_vcpu_ipc_regs_t const *i() const throw()
{ return &(l4_vcpu_state_t::i); }
/**
* \brief Set vCPU entry stack pointer.
* \param sp Stack pointer address to set.
*
* \note The value is only used when entering from a user-task.
*/
void entry_sp(l4_umword_t sp)
{ l4_vcpu_state_t::entry_sp = sp; }
/**
* \brief Set vCPU entry instruction pointer.
* \param ip Instruction pointer address to set.
*/
void entry_ip(l4_umword_t ip)
{ l4_vcpu_state_t::entry_ip = ip; }
/**
* \brief Allocate state area for an extended vCPU.
*
* \param[out] vcpu Allocated vcpu-state area.
* \param[out] ext_state Allocated extended vcpu-state area.
* \param task Task to use for allocation, defaults to own task.
* \param rm Region manager to use for allocation defaults to
* standard region manager.
*
* \return 0 for success, error code otherwise
*/
L4_CV static int
ext_alloc(Vcpu **vcpu,
l4_addr_t *ext_state,
L4::Cap<L4::Task> task = L4Re::Env::env()->task(),
L4::Cap<L4Re::Rm> rm = L4Re::Env::env()->rm()) throw();
/**
* \brief Cast a void pointer to a class pointer.
*
* \param x Pointer.
*
* \return Pointer to Vcpu class.
*/
static inline Vcpu *cast(void *x) throw()
{ return reinterpret_cast<Vcpu *>(x); }
/**
* \brief Cast an address to a class pointer.
*
* \param x Pointer.
*
* \return Pointer to Vcpu class.
*/
static inline Vcpu *cast(l4_addr_t x) throw()
{ return reinterpret_cast<Vcpu *>(x); }
/**
* \brief Print the state of the vCPU.
*/
void print_state(const char *prefix = "") const throw()
{ l4vcpu_print_state(this, prefix); }
};
}

View File

@@ -0,0 +1,277 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
/**
* \file
* vCPU support library (C interface).
*/
#pragma once
#include <l4/sys/vcpu.h>
#include <l4/sys/utcb.h>
__BEGIN_DECLS
/**
* \defgroup api_libvcpu vCPU Support Library
* \brief vCPU handling functionality.
*
* This library provides convenience functionality on top of the l4sys vCPU
* interface to ease programming. It wraps commonly used code and abstracts
* architecture depends parts as far as reasonable.
*/
/**
* \defgroup api_libvcpu_ext Extended vCPU support
* \ingroup api_libvcpu
* \brief Extended vCPU handling functionality.
*/
typedef void (*l4vcpu_event_hndl_t)(l4_vcpu_state_t *vcpu);
typedef void (*l4vcpu_setup_ipc_t)(l4_utcb_t *utcb);
/**
* \brief Disable a vCPU for event delivery.
* \ingroup api_libvcpu
*
* \param vcpu Pointer to vCPU area.
*/
L4_CV L4_INLINE
void
l4vcpu_irq_disable(l4_vcpu_state_t *vcpu) L4_NOTHROW;
/**
* \brief Disable a vCPU for event delivery and return previous state.
* \ingroup api_libvcpu
*
* \param vcpu Pointer to vCPU area.
*
* \return IRQ state before disabling IRQs.
*/
L4_CV L4_INLINE
unsigned
l4vcpu_irq_disable_save(l4_vcpu_state_t *vcpu) L4_NOTHROW;
/**
* \brief Enable a vCPU for event delivery.
* \ingroup api_libvcpu
*
* \param vcpu Pointer to vCPU area.
* \param utcb Utcb pointer of the calling vCPU.
* \param do_event_work_cb Call-back function that is called in case an
* event (such as an interrupt) is pending.
* \param setup_ipc Function call-back that is called right before
* any IPC operation, and before event delivery is
* enabled.
*/
L4_CV L4_INLINE
void
l4vcpu_irq_enable(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW;
/**
* \brief Restore a previously saved IRQ/event state.
* \ingroup api_libvcpu
*
* \param vcpu Pointer to vCPU area.
* \param s IRQ state to be restored.
* \param utcb Utcb pointer of the calling vCPU.
* \param do_event_work_cb Call-back function that is called in case an
* event (such as an interrupt) is pending after
* enabling.
* \param setup_ipc Function call-back that is called right before
* any IPC operation, and before event delivery is
* enabled.
*/
L4_CV L4_INLINE
void
l4vcpu_irq_restore(l4_vcpu_state_t *vcpu, unsigned s,
l4_utcb_t *utcb,
l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW;
/**
* \internal
* \ingroup api_libvcpu
*
* \param vcpu Pointer to vCPU area.
* \param utcb Utcb pointer of the calling vCPU.
* \param to Timeout to do IPC operation with.
* \param do_event_work_cb Call-back function that is called in case an
* event (such as an interrupt) is pending after
* enabling.
* \param setup_ipc Function call-back that is called right before
* any IPC operation.
*/
L4_CV L4_INLINE
void
l4vcpu_wait(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
l4_timeout_t to,
l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW;
/**
* \brief Wait for event.
* \ingroup api_libvcpu
*
* \param vcpu Pointer to vCPU area.
* \param utcb Utcb pointer of the calling vCPU.
* \param do_event_work_cb Call-back function that is called when the vCPU
* awakes and needs to handle an event/IRQ.
* \param setup_ipc Function call-back that is called right before
* any IPC operation.
*
* Note that event delivery remains disabled after this function returns.
*/
L4_CV L4_INLINE
void
l4vcpu_wait_for_event(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW;
/**
* \brief Print the state of a vCPU.
* \ingroup api_libvcpu
*
* \param vcpu Pointer to vCPU area.
* \param prefix A prefix for each line printed.
*/
L4_CV void
l4vcpu_print_state(const l4_vcpu_state_t *vcpu, const char *prefix) L4_NOTHROW;
/**
* \internal
*/
L4_CV void
l4vcpu_print_state_arch(const l4_vcpu_state_t *vcpu, const char *prefix) L4_NOTHROW;
/**
* \brief Return whether the entry reason was an IRQ/IPC message.
* \ingroup api_libvcpu
*
* \param vcpu Pointer to vCPU area.
*
* return 0 if not, !=0 otherwise.
*/
L4_CV L4_INLINE
int
l4vcpu_is_irq_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW;
/**
* \brief Return whether the entry reason was a page fault.
* \ingroup api_libvcpu
*
* \param vcpu Pointer to vCPU area.
*
* return 0 if not, !=0 otherwise.
*/
L4_CV L4_INLINE
int
l4vcpu_is_page_fault_entry(l4_vcpu_state_t const *vcpu) L4_NOTHROW;
/**
* \brief Allocate state area for an extended vCPU.
* \ingroup api_libvcpu_ext
*
* \param[out] vcpu Allocated vcpu-state area.
* \param[out] ext_state Allocated extended vcpu-state area.
* \param task Task to use for allocation.
* \param regmgr Region manager to use for allocation.
*
* \return 0 for success, error code otherwise
*/
L4_CV int
l4vcpu_ext_alloc(l4_vcpu_state_t **vcpu, l4_addr_t *ext_state,
l4_cap_idx_t task, l4_cap_idx_t regmgr) L4_NOTHROW;
/* ===================================================================== */
/* Implementations */
#include <l4/sys/ipc.h>
#include <l4/vcpu/vcpu_arch.h>
L4_CV L4_INLINE
void
l4vcpu_irq_disable(l4_vcpu_state_t *vcpu) L4_NOTHROW
{
vcpu->state &= ~L4_VCPU_F_IRQ;
l4_barrier();
}
L4_CV L4_INLINE
unsigned
l4vcpu_irq_disable_save(l4_vcpu_state_t *vcpu) L4_NOTHROW
{
unsigned s = vcpu->state;
l4vcpu_irq_disable(vcpu);
return s;
}
L4_CV L4_INLINE
void
l4vcpu_wait(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
l4_timeout_t to,
l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW
{
l4vcpu_irq_disable(vcpu);
setup_ipc(utcb);
vcpu->i.tag = l4_ipc_wait(utcb, &vcpu->i.label, to);
if (L4_LIKELY(!l4_msgtag_has_error(vcpu->i.tag)))
do_event_work_cb(vcpu);
}
L4_CV L4_INLINE
void
l4vcpu_irq_enable(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW
{
if (!(vcpu->state & L4_VCPU_F_IRQ))
{
setup_ipc(utcb);
l4_barrier();
}
while (1)
{
vcpu->state |= L4_VCPU_F_IRQ;
l4_barrier();
if (L4_LIKELY(!(vcpu->sticky_flags & L4_VCPU_SF_IRQ_PENDING)))
break;
l4vcpu_wait(vcpu, utcb, L4_IPC_BOTH_TIMEOUT_0,
do_event_work_cb, setup_ipc);
}
}
L4_CV L4_INLINE
void
l4vcpu_irq_restore(l4_vcpu_state_t *vcpu, unsigned s,
l4_utcb_t *utcb,
l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW
{
if (s & L4_VCPU_F_IRQ)
l4vcpu_irq_enable(vcpu, utcb, do_event_work_cb, setup_ipc);
else if (vcpu->state & L4_VCPU_F_IRQ)
l4vcpu_irq_disable(vcpu);
}
L4_CV L4_INLINE
void
l4vcpu_wait_for_event(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb,
l4vcpu_event_hndl_t do_event_work_cb,
l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW
{
l4vcpu_wait(vcpu, utcb, L4_IPC_NEVER, do_event_work_cb, setup_ipc);
}
__END_DECLS

View File

@@ -0,0 +1,4 @@
PKGDIR = ..
L4DIR ?= $(PKGDIR)/../..
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,20 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#include <l4/vcpu/vcpu.h>
#include <stdio.h>
void l4vcpu_print_state_arch(l4_vcpu_state_t const *vcpu,
const char *prefix) L4_NOTHROW
{
printf("%sip=%08lx sp=%08lx trapno=%08lx\n",
prefix, vcpu->r.ip, vcpu->r.sp, vcpu->r.trapno);
printf("%sax=%08lx dx=%08lx bx=%08lx cx=%08lx\n",
prefix, vcpu->r.ax, vcpu->r.dx, vcpu->r.bx, vcpu->r.cx);
printf("%ssi=%08lx di=%08lx bp=%08lx flags=%08lx\n",
prefix, vcpu->r.si, vcpu->r.di, vcpu->r.bp, vcpu->r.flags);
}

View File

@@ -0,0 +1,25 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#include <l4/vcpu/vcpu.h>
#include <stdio.h>
void l4vcpu_print_state_arch(l4_vcpu_state_t const *vcpu,
const char *prefix) L4_NOTHROW
{
printf("%svcpu=%p ip=%08lx sp=%08lx err=%08lx label=%08lx\n",
prefix, vcpu, vcpu->r.ip, vcpu->r.sp, vcpu->r.err, vcpu->i.label);
printf("%s r0=%08lx r1=%08lx r2=%08lx r3=%08lx\n",
prefix, vcpu->r.r[0], vcpu->r.r[1], vcpu->r.r[2], vcpu->r.r[3]);
printf("%s r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n",
prefix, vcpu->r.r[4], vcpu->r.r[5], vcpu->r.r[6], vcpu->r.r[7]);
printf("%s r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n",
prefix, vcpu->r.r[8], vcpu->r.r[9], vcpu->r.r[10], vcpu->r.r[11]);
printf("%sr12=%08lx lr=%08lx flags=%08lx\n",
prefix, vcpu->r.r[12], vcpu->r.lr, vcpu->r.flags);
}

View File

@@ -0,0 +1,25 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#include <l4/vcpu/vcpu.h>
#include <stdio.h>
void l4vcpu_print_state_arch(l4_vcpu_state_t const *vcpu,
const char *prefix) L4_NOTHROW
{
printf("%svcpu=%p ip=%08lx sp=%08lx err=%08lx label=%08lx\n",
prefix, vcpu, vcpu->r.ip, vcpu->r.sp, vcpu->r.err, vcpu->i.label);
printf("%s r0=%08lx r1=%08lx r2=%08lx r3=%08lx\n",
prefix, vcpu->r.r[0], vcpu->r.r[1], vcpu->r.r[2], vcpu->r.r[3]);
printf("%s r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n",
prefix, vcpu->r.r[4], vcpu->r.r[5], vcpu->r.r[6], vcpu->r.r[7]);
printf("%s r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n",
prefix, vcpu->r.r[8], vcpu->r.r[9], vcpu->r.r[10], vcpu->r.r[11]);
printf("%sr12=%08lx lr=%08lx flags=%08lx\n",
prefix, vcpu->r.r[12], vcpu->r.r[30], vcpu->r.flags);
}

View File

@@ -0,0 +1,21 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#include <l4/vcpu/vcpu.h>
#include <stdio.h>
void l4vcpu_print_state_arch(l4_vcpu_state_t const *vcpu,
const char *prefix) L4_NOTHROW
{
printf("%svcpu=%p ip=%08lx status=%08lx cause=%08lx label=%08lx\n",
prefix, vcpu, vcpu->r.epc, vcpu->r.status, vcpu->r.cause, vcpu->i.label);
for (unsigned i = 0; i < 32; ++i)
printf("%sr[%2d]=%08lx%s", (i & 3) == 0 ? prefix : "", i, vcpu->r.r[i],
(i & 3) == 3 ? "\n" : " ");
printf("%shi=%08lx lo=%08lx\n", prefix, vcpu->r.hi, vcpu->r.lo);
}

View File

@@ -0,0 +1,17 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#include <l4/vcpu/vcpu.h>
#include <stdio.h>
void l4vcpu_print_state_arch(l4_vcpu_state_t const *vcpu,
const char *prefix) L4_NOTHROW
{
(void)vcpu;
printf("%sTBD\n", prefix);
}

View File

@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright (C) 2021, 2024 Kernkonzept GmbH.
* Author(s): Georg Kotheimer <georg.kotheimer@kernkonzept.com>
*/
#include <l4/vcpu/vcpu.h>
#include <stdio.h>
void l4vcpu_print_state_arch(l4_vcpu_state_t const *vcpu,
const char *prefix) L4_NOTHROW
{
printf("%svcpu=%p ip=%08lx status=%08lx cause=%08lx label=%08lx\n",
prefix, vcpu, vcpu->r.ip, vcpu->r.status, vcpu->r.cause, vcpu->i.label);
for (unsigned i = 0; i < 31; ++i)
printf("%sr[%2d]=%08lx%s", (i & 3) == 0 ? prefix : "", i, vcpu->r.r[i],
(i & 3) == 3 ? "\n" : " ");
}

View File

@@ -0,0 +1,25 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#include <l4/vcpu/vcpu.h>
#include <stdio.h>
void l4vcpu_print_state_arch(l4_vcpu_state_t const *vcpu,
const char *prefix) L4_NOTHROW
{
printf("%svcpu=%p ip=%08lx sp=%08lx err=%08lx label=%08lx\n",
prefix, vcpu, vcpu->r.ip, vcpu->r.sp, vcpu->r.err, vcpu->i.label);
printf("%s r0=%08lx r1=%08lx r2=%08lx r3=%08lx\n",
prefix, vcpu->r.r[0], vcpu->r.r[1], vcpu->r.r[2], vcpu->r.r[3]);
printf("%s r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n",
prefix, vcpu->r.r[4], vcpu->r.r[5], vcpu->r.r[6], vcpu->r.r[7]);
printf("%s r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n",
prefix, vcpu->r.r[8], vcpu->r.r[9], vcpu->r.r[10], vcpu->r.r[11]);
printf("%sr12=%08lx lr=%08lx flags=%08lx\n",
prefix, vcpu->r.r[12], vcpu->r.lr, vcpu->r.flags);
}

View File

@@ -0,0 +1,22 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#include <l4/vcpu/vcpu.h>
#include <stdio.h>
void l4vcpu_print_state_arch(l4_vcpu_state_t const *vcpu,
const char *prefix) L4_NOTHROW
{
printf("%sip=%08lx sp=%08lx trapno=%08lx\n",
prefix, vcpu->r.ip, vcpu->r.sp, vcpu->r.trapno);
printf("%sax=%08lx dx=%08lx bx=%08lx cx=%08lx\n",
prefix, vcpu->r.ax, vcpu->r.dx, vcpu->r.bx, vcpu->r.cx);
printf("%ssi=%08lx di=%08lx bp=%08lx flags=%08lx\n",
prefix, vcpu->r.si, vcpu->r.di, vcpu->r.bp, vcpu->r.flags);
printf("%sds=%08lx es=%08lx gs=%08lx fs=%08lx\n",
prefix, vcpu->r.ds, vcpu->r.es, vcpu->r.gs, vcpu->r.fs);
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../..
PC_FILENAME = libvcpu
TARGET = libvcpu.a libvcpu.so
SRC_CC = vcpu.cc ARCH-$(ARCH)/arch.cc
REQUIRES_LIBS := l4re-util
include $(L4DIR)/mk/lib.mk

View File

@@ -0,0 +1,62 @@
/*
* (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#include <l4/vcpu/vcpu>
#include <l4/re/util/kumem_alloc>
#include <cstdio>
#include <cstring>
L4_CV void
l4vcpu_print_state(l4_vcpu_state_t const *vcpu,
const char *prefix) L4_NOTHROW
{
printf("%svcpu=%p state=%x savedstate=%x label=%lx\n",
prefix, vcpu, vcpu->state, vcpu->saved_state, vcpu->i.label);
printf("%ssticky=%x user_task=%lx pfa=%lx\n",
prefix, vcpu->sticky_flags, vcpu->user_task << L4_CAP_SHIFT,
vcpu->r.pfa);
printf("%sentry_sp=%lx entry_ip=%lx\n",
prefix, vcpu->entry_sp, vcpu->entry_ip);
l4vcpu_print_state_arch(vcpu, prefix);
}
static int
do_l4vcpu_ext_alloc(L4vcpu::Vcpu **vcpu,
l4_addr_t *ext_state,
L4::Cap<L4::Task> task,
L4::Cap<L4Re::Rm> rm) L4_NOTHROW
{
int r;
l4_addr_t v;
if ((r = L4Re::Util::kumem_alloc(&v, 0, task, rm)))
return r;
*vcpu = L4vcpu::Vcpu::cast(v);
*ext_state = v + L4_VCPU_OFFSET_EXT_STATE;
return 0;
}
L4_CV int
l4vcpu_ext_alloc(l4_vcpu_state_t **vcpu, l4_addr_t *ext_state,
l4_cap_idx_t task, l4_cap_idx_t regmgr) L4_NOTHROW
{
L4::Cap<L4::Task> t(task);
L4::Cap<L4Re::Rm> r(regmgr);
L4vcpu::Vcpu **v = reinterpret_cast<L4vcpu::Vcpu **>(vcpu);
return do_l4vcpu_ext_alloc(v, ext_state, t, r);
}
L4_CV int
L4vcpu::Vcpu::ext_alloc(Vcpu **vcpu,
l4_addr_t *ext_state,
L4::Cap<L4::Task> task,
L4::Cap<L4Re::Rm> rm) throw()
{
return do_l4vcpu_ext_alloc(vcpu, ext_state, task, rm);
}