freebsd-dev/sys/xen/hypervisor.h
Roger Pau Monné a231723cc0 xen/console: Introduce a new console driver for Xen guest
The current Xen console driver is crashing very quickly when using it on
an ARM guest. This is because the console lock is recursive and it may
lead to recursion on the tty lock and/or corrupt the ring pointer.

Furthermore, the console lock is not always taken where it should be and has
to be released too early because of the way the console has been designed.

Over the years, code has been modified to support various new features but
the driver has not been reworked.

This new driver has been rewritten with the idea of only having a small set
of specific function to write either via the shared ring or the hypercall
interface.

Note that HVM support has been left aside for now because it requires
additional features which are not yet supported. A follow-up patch will be
sent with HVM guest support.

List of items that may be good to have but not mandatory:
 - Avoid to flush for each character written when using the tty
 - Support multiple consoles

Submitted by:		Julien Grall <julien.grall@citrix.com>
Reviewed by:		royger
Differential Revision:	https://reviews.freebsd.org/D3698
Sponsored by:		Citrix Systems R&D
2015-10-08 16:39:43 +00:00

155 lines
3.3 KiB
C

/******************************************************************************
* hypervisor.h
*
* Linux-specific hypervisor handling.
*
* Copyright (c) 2002, K A Fraser
*
* $FreeBSD$
*/
#ifndef __XEN_HYPERVISOR_H__
#define __XEN_HYPERVISOR_H__
#ifdef XENHVM
#define is_running_on_xen() (HYPERVISOR_shared_info != NULL)
#else
#define is_running_on_xen() 1
#endif
#ifdef PAE
#ifndef CONFIG_X86_PAE
#define CONFIG_X86_PAE
#endif
#endif
#include <sys/cdefs.h>
#include <sys/systm.h>
#include <xen/interface/xen.h>
#include <xen/interface/platform.h>
#include <xen/interface/event_channel.h>
#include <xen/interface/physdev.h>
#include <xen/interface/sched.h>
#include <xen/interface/callback.h>
#include <xen/interface/memory.h>
#include <machine/xen/hypercall.h>
#if defined(__amd64__)
#define MULTI_UVMFLAGS_INDEX 2
#define MULTI_UVMDOMID_INDEX 3
#else
#define MULTI_UVMFLAGS_INDEX 3
#define MULTI_UVMDOMID_INDEX 4
#endif
#ifdef CONFIG_XEN_PRIVILEGED_GUEST
#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN)
#else
#define is_initial_xendomain() 0
#endif
extern start_info_t *xen_start_info;
extern uint64_t get_system_time(int ticks);
static inline int
HYPERVISOR_console_write(const char *str, int count)
{
return HYPERVISOR_console_io(CONSOLEIO_write, count, str);
}
static inline void HYPERVISOR_crash(void) __dead2;
static inline int
HYPERVISOR_yield(void)
{
int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
#if CONFIG_XEN_COMPAT <= 0x030002
if (rc == -ENOXENSYS)
rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
#endif
return (rc);
}
static inline int
HYPERVISOR_block(
void)
{
int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
#if CONFIG_XEN_COMPAT <= 0x030002
if (rc == -ENOXENSYS)
rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
#endif
return (rc);
}
static inline void
HYPERVISOR_shutdown(unsigned int reason)
{
struct sched_shutdown sched_shutdown = {
.reason = reason
};
HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
#if CONFIG_XEN_COMPAT <= 0x030002
HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);
#endif
}
static inline void
HYPERVISOR_crash(void)
{
HYPERVISOR_shutdown(SHUTDOWN_crash);
/* NEVER REACHED */
for (;;) ; /* eliminate noreturn error */
}
/* Transfer control to hypervisor until an event is detected on one */
/* of the specified ports or the specified number of ticks elapse */
static inline int
HYPERVISOR_poll(
evtchn_port_t *ports, unsigned int nr_ports, int ticks)
{
int rc;
struct sched_poll sched_poll = {
.nr_ports = nr_ports,
.timeout = get_system_time(ticks)
};
set_xen_guest_handle(sched_poll.ports, ports);
rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
#if CONFIG_XEN_COMPAT <= 0x030002
if (rc == -ENOXENSYS)
rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
#endif
return (rc);
}
static inline void
MULTI_update_va_mapping(
multicall_entry_t *mcl, unsigned long va,
uint64_t new_val, unsigned long flags)
{
mcl->op = __HYPERVISOR_update_va_mapping;
mcl->args[0] = va;
#if defined(__amd64__)
mcl->args[1] = new_val;
#elif defined(PAE)
mcl->args[1] = (uint32_t)(new_val & 0xffffffff) ;
mcl->args[2] = (uint32_t)(new_val >> 32);
#else
mcl->args[1] = new_val;
mcl->args[2] = 0;
#endif
mcl->args[MULTI_UVMFLAGS_INDEX] = flags;
}
#endif /* __XEN_HYPERVISOR_H__ */