Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Dec 2014 10:56:38 +0200
From:      Ivan Klymenko <fidaj@ukr.net>
To:        svn-src-all@freebsd.org
Subject:   Re: svn commit: r276428 - in head: lib/libvmmapi sys/amd64/include sys/amd64/vmm sys/amd64/vmm/io sys/modules/vmm usr.sbin/bhyve usr.sbin/bhyvectl
Message-ID:  <20141231105638.15336969@nonamehost.local>
In-Reply-To: <201412302219.sBUMJZ1x094872@svn.freebsd.org>
References:  <201412302219.sBUMJZ1x094872@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
=D0=92 Tue, 30 Dec 2014 22:19:35 +0000 (UTC)
Neel Natu <neel@FreeBSD.org> =D0=BF=D0=B8=D1=88=D0=B5=D1=82:

> Author: neel
> Date: Tue Dec 30 22:19:34 2014
> New Revision: 276428
> URL: https://svnweb.freebsd.org/changeset/base/276428
>=20
> Log:
>   Replace bhyve's minimal RTC emulation with a fully featured one in
> vmm.ko.=20
>   The new RTC emulation supports all interrupt modes: periodic,
> update ended and alarm. It is also capable of maintaining the
> date/time and NVRAM contents across virtual machine reset. Also, the
> date/time fields can now be modified by the guest.
>  =20
>   Since bhyve now emulates both the PIT and the RTC there is no need
> for "Legacy Replacement Routing" in the HPET so get rid of it.
>  =20
>   The RTC device state can be inspected via bhyvectl as follows:
>   bhyvectl --vm=3Dvm --get-rtc-time
>   bhyvectl --vm=3Dvm --set-rtc-time=3D<unix_time_secs>
>   bhyvectl --vm=3Dvm --rtc-nvram-offset=3D<offset> --get-rtc-nvram
>   bhyvectl --vm=3Dvm --rtc-nvram-offset=3D<offset> --set-rtc-nvram=3D<val=
ue>
>  =20
>   Reviewed by:	tychon
>   Discussed with:	grehan
>   Differential Revision:	https://reviews.freebsd.org/D1385
>   MFC after:	2 weeks
>=20
> Added:
>   head/sys/amd64/vmm/io/vrtc.c   (contents, props changed)
>   head/sys/amd64/vmm/io/vrtc.h   (contents, props changed)
> Modified:
>   head/lib/libvmmapi/vmmapi.c
>   head/lib/libvmmapi/vmmapi.h
>   head/sys/amd64/include/vmm.h
>   head/sys/amd64/include/vmm_dev.h
>   head/sys/amd64/vmm/io/vhpet.c
>   head/sys/amd64/vmm/vmm.c
>   head/sys/amd64/vmm/vmm_dev.c
>   head/sys/amd64/vmm/vmm_ioport.c
>   head/sys/modules/vmm/Makefile
>   head/usr.sbin/bhyve/rtc.c
>   head/usr.sbin/bhyvectl/bhyvectl.c
>=20
> Modified: head/lib/libvmmapi/vmmapi.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/lib/libvmmapi/vmmapi.c	Tue Dec 30 22:04:24
> 2014	(r276427) +++ head/lib/libvmmapi/vmmapi.c	Tue Dec
> 30 22:19:34 2014	(r276428) @@ -1146,3 +1146,55 @@
> vm_set_intinfo(struct vmctx *ctx, int vc error =3D ioctl(ctx->fd,
> VM_SET_INTINFO, &vmii); return (error);
>  }
> +
> +int
> +vm_rtc_write(struct vmctx *ctx, int offset, uint8_t value)
> +{
> +	struct vm_rtc_data rtcdata;
> +	int error;
> +
> +	bzero(&rtcdata, sizeof(struct vm_rtc_data));
> +	rtcdata.offset =3D offset;
> +	rtcdata.value =3D value;
> +	error =3D ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata);
> +	return (error);
> +}
> +
> +int
> +vm_rtc_read(struct vmctx *ctx, int offset, uint8_t *retval)
> +{
> +	struct vm_rtc_data rtcdata;
> +	int error;
> +
> +	bzero(&rtcdata, sizeof(struct vm_rtc_data));
> +	rtcdata.offset =3D offset;
> +	error =3D ioctl(ctx->fd, VM_RTC_READ, &rtcdata);
> +	if (error =3D=3D 0)
> +		*retval =3D rtcdata.value;
> +	return (error);
> +}
> +
> +int
> +vm_rtc_settime(struct vmctx *ctx, time_t secs)
> +{
> +	struct vm_rtc_time rtctime;
> +	int error;
> +
> +	bzero(&rtctime, sizeof(struct vm_rtc_time));
> +	rtctime.secs =3D secs;
> +	error =3D ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime);
> +	return (error);
> +}
> +
> +int
> +vm_rtc_gettime(struct vmctx *ctx, time_t *secs)
> +{
> +	struct vm_rtc_time rtctime;
> +	int error;
> +
> +	bzero(&rtctime, sizeof(struct vm_rtc_time));
> +	error =3D ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime);
> +	if (error =3D=3D 0)
> +		*secs =3D rtctime.secs;
> +	return (error);
> +}
>=20
> Modified: head/lib/libvmmapi/vmmapi.h
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/lib/libvmmapi/vmmapi.h	Tue Dec 30 22:04:24
> 2014	(r276427) +++ head/lib/libvmmapi/vmmapi.h	Tue Dec
> 30 22:19:34 2014	(r276428) @@ -133,6 +133,12 @@ void
> vm_copyin(struct vmctx *ctx, int vc void	vm_copyout(struct
> vmctx *ctx, int vcpu, const void *host_src, struct iovec *guest_iov,
> size_t len);=20
> +/* RTC */
> +int	vm_rtc_write(struct vmctx *ctx, int offset, uint8_t
> value); +int	vm_rtc_read(struct vmctx *ctx, int offset,
> uint8_t *retval); +int	vm_rtc_settime(struct vmctx *ctx,
> time_t secs); +int	vm_rtc_gettime(struct vmctx *ctx, time_t
> *secs); +
>  /* Reset vcpu register state */
>  int	vcpu_reset(struct vmctx *ctx, int vcpu);
> =20
>=20
> Modified: head/sys/amd64/include/vmm.h
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/sys/amd64/include/vmm.h	Tue Dec 30 22:04:24
> 2014	(r276427) +++ head/sys/amd64/include/vmm.h	Tue Dec
> 30 22:19:34 2014	(r276428) @@ -286,6 +286,7 @@ int
> vm_unassign_pptdev(struct vm *vm, in struct vatpic *vm_atpic(struct
> vm *vm); struct vatpit *vm_atpit(struct vm *vm);
>  struct vpmtmr *vm_pmtmr(struct vm *vm);
> +struct vrtc *vm_rtc(struct vm *vm);
> =20
>  /*
>   * Inject exception 'vme' into the guest vcpu. This function returns
> 0 on
>=20
> Modified: head/sys/amd64/include/vmm_dev.h
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/sys/amd64/include/vmm_dev.h	Tue Dec 30 22:04:24
> 2014	(r276427) +++ head/sys/amd64/include/vmm_dev.h	Tue
> Dec 30 22:19:34 2014	(r276428) @@ -195,6 +195,15 @@ struct
> vm_intinfo { uint64_t	info2;
>  };
> =20
> +struct vm_rtc_time {
> +	time_t		secs;
> +};
> +
> +struct vm_rtc_data {
> +	int		offset;
> +	uint8_t		value;
> +};
> +
>  enum {
>  	/* general routines */
>  	IOCNUM_ABIVERS =3D 0,
> @@ -254,6 +263,12 @@ enum {
>  	/* vm_cpuset */
>  	IOCNUM_ACTIVATE_CPU =3D 90,
>  	IOCNUM_GET_CPUSET =3D 91,
> +
> +	/* RTC */
> +	IOCNUM_RTC_READ =3D 100,
> +	IOCNUM_RTC_WRITE =3D 101,
> +	IOCNUM_RTC_SETTIME =3D 102,
> +	IOCNUM_RTC_GETTIME =3D 103,
>  };
> =20
>  #define	VM_RUN		\
> @@ -336,4 +351,12 @@ enum {
>  	_IOW('v', IOCNUM_SET_INTINFO, struct vm_intinfo)
>  #define	VM_GET_INTINFO	\
>  	_IOWR('v', IOCNUM_GET_INTINFO, struct vm_intinfo)
> +#define VM_RTC_WRITE \
> +	_IOW('v', IOCNUM_RTC_WRITE, struct vm_rtc_data)
> +#define VM_RTC_READ \
> +	_IOWR('v', IOCNUM_RTC_READ, struct vm_rtc_data)
> +#define VM_RTC_SETTIME	\
> +	_IOW('v', IOCNUM_RTC_SETTIME, struct vm_rtc_time)
> +#define VM_RTC_GETTIME	\
> +	_IOR('v', IOCNUM_RTC_GETTIME, struct vm_rtc_time)
>  #endif
>=20
> Modified: head/sys/amd64/vmm/io/vhpet.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/sys/amd64/vmm/io/vhpet.c	Tue Dec 30 22:04:24
> 2014	(r276427) +++ head/sys/amd64/vmm/io/vhpet.c	Tue
> Dec 30 22:19:34 2014	(r276428) @@ -104,7 +104,6 @@
> vhpet_capabilities(void) uint64_t cap =3D 0;
> =20
>  	cap |=3D 0x8086 << 16;			/* vendor id */
> -	cap |=3D HPET_CAP_LEG_RT;			/* legacy
> routing capable */ cap |=3D (VHPET_NUM_TIMERS - 1) << 8;	/*
> number of timers */ cap |=3D 1;				/*
> revision */ cap &=3D ~HPET_CAP_COUNT_SIZE;		/* 32-bit
> timer */ @@ -127,15 +126,6 @@ vhpet_timer_msi_enabled(struct vhpet *vh
>  {
>  	const uint64_t msi_enable =3D HPET_TCAP_FSB_INT_DEL |
> HPET_TCNF_FSB_EN;=20
> -	/*
> -	 * LegacyReplacement Route configuration takes precedence
> over MSI
> -	 * for timers 0 and 1.
> -	 */
> -	if (n =3D=3D 0 || n =3D=3D 1) {
> -		if (vhpet->config & HPET_CNF_LEG_RT)
> -			return (false);
> -	}
> -
>  	if ((vhpet->timer[n].cap_config & msi_enable) =3D=3D msi_enable)
>  		return (true);
>  	else
> @@ -152,41 +142,9 @@ vhpet_timer_ioapic_pin(struct vhpet *vhp
>  	if (vhpet_timer_msi_enabled(vhpet, n))
>  		return (0);
> =20
> -	if (vhpet->config & HPET_CNF_LEG_RT) {
> -		/*
> -		 * In "legacy routing" timers 0 and 1 are connected
> to
> -		 * ioapic pins 2 and 8 respectively.
> -		 */
> -		switch (n) {
> -		case 0:
> -			return (2);
> -		case 1:
> -			return (8);
> -		}
> -	}
> -
>  	return ((vhpet->timer[n].cap_config & HPET_TCNF_INT_ROUTE)
> >> 9); }
> =20
> -static __inline int
> -vhpet_timer_atpic_pin(struct vhpet *vhpet, int n)
> -{
> -	if (vhpet->config & HPET_CNF_LEG_RT) {
> -		/*
> -		 * In "legacy routing" timers 0 and 1 are connected
> to
> -		 * 8259 master pin 0 and slave pin 0 respectively.
> -		 */
> -		switch (n) {
> -		case 0:
> -			return (0);
> -		case 1:
> -			return (8);
> -		}
> -	}
> -
> -	return (-1);
> -}
> -
>  static uint32_t
>  vhpet_counter(struct vhpet *vhpet, sbintime_t *nowptr)
>  {
> @@ -216,17 +174,12 @@ vhpet_counter(struct vhpet *vhpet, sbint
>  static void
>  vhpet_timer_clear_isr(struct vhpet *vhpet, int n)
>  {
> -	int pin, legacy_pin;
> +	int pin;
> =20
>  	if (vhpet->isr & (1 << n)) {
>  		pin =3D vhpet_timer_ioapic_pin(vhpet, n);
>  		KASSERT(pin !=3D 0, ("vhpet timer %d irq incorrectly
> routed", n)); vioapic_deassert_irq(vhpet->vm, pin);
> -
> -		legacy_pin =3D vhpet_timer_atpic_pin(vhpet, n);
> -		if (legacy_pin !=3D -1)
> -			vatpic_deassert_irq(vhpet->vm, legacy_pin);
> -
>  		vhpet->isr &=3D ~(1 << n);
>  	}
>  }
> @@ -252,12 +205,6 @@ vhpet_timer_edge_trig(struct vhpet *vhpe
>  	KASSERT(!vhpet_timer_msi_enabled(vhpet, n),
> ("vhpet_timer_edge_trig: " "timer %d is using MSI", n));
> =20
> -	/* The legacy replacement interrupts are always edge
> triggered */
> -	if (vhpet->config & HPET_CNF_LEG_RT) {
> -		if (n =3D=3D 0 || n =3D=3D 1)
> -			return (true);
> -	}
> -
>  	if ((vhpet->timer[n].cap_config & HPET_TCNF_INT_TYPE) =3D=3D 0)
>  		return (true);
>  	else
> @@ -267,7 +214,7 @@ vhpet_timer_edge_trig(struct vhpet *vhpe
>  static void
>  vhpet_timer_interrupt(struct vhpet *vhpet, int n)
>  {
> -	int pin, legacy_pin;
> +	int pin;
> =20
>  	/* If interrupts are not enabled for this timer then just
> return. */ if (!vhpet_timer_interrupt_enabled(vhpet, n))
> @@ -293,17 +240,11 @@ vhpet_timer_interrupt(struct vhpet *vhpe
>  		return;
>  	}
> =20
> -	legacy_pin =3D vhpet_timer_atpic_pin(vhpet, n);
> -
>  	if (vhpet_timer_edge_trig(vhpet, n)) {
>  		vioapic_pulse_irq(vhpet->vm, pin);
> -		if (legacy_pin !=3D -1)
> -			vatpic_pulse_irq(vhpet->vm, legacy_pin);
>  	} else {
>  		vhpet->isr |=3D 1 << n;
>  		vioapic_assert_irq(vhpet->vm, pin);
> -		if (legacy_pin !=3D -1)
> -			vatpic_assert_irq(vhpet->vm, legacy_pin);
>  	}
>  }
> =20
> @@ -579,6 +520,13 @@ vhpet_mmio_write(void *vm, int vcpuid, u
>  		counter =3D vhpet_counter(vhpet, nowptr);
>  		oldval =3D vhpet->config;
>  		update_register(&vhpet->config, data, mask);
> +
> +		/*
> +		 * LegacyReplacement Routing is not supported so
> clear the
> +		 * bit explicitly.
> +		 */
> +		vhpet->config &=3D ~HPET_CNF_LEG_RT;
> +
>  		if ((oldval ^ vhpet->config) & HPET_CNF_ENABLE) {
>  			if (vhpet_counter_enabled(vhpet)) {
>  				vhpet_start_counting(vhpet);
>=20
> Added: head/sys/amd64/vmm/io/vrtc.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- /dev/null	00:00:00 1970	(empty, because file is
> newly added) +++ head/sys/amd64/vmm/io/vrtc.c	Tue Dec 30
> 22:19:34 2014	(r276428) @@ -0,0 +1,952 @@
> +/*-
> + * Copyright (c) 2014, Neel Natu (neel@freebsd.org)
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above
> copyright
> + *    notice, this list of conditions and the following disclaimer
> in the
> + *    documentation and/or other materials provided with the
> distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
> OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
> TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
> USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/queue.h>
> +#include <sys/cpuset.h>
> +#include <sys/kernel.h>
> +#include <sys/malloc.h>
> +#include <sys/lock.h>
> +#include <sys/mutex.h>
> +#include <sys/clock.h>
> +#include <sys/sysctl.h>
> +
> +#include <machine/vmm.h>
> +
> +#include <isa/rtc.h>
> +
> +#include "vmm_ktr.h"
> +#include "vatpic.h"
> +#include "vioapic.h"
> +#include "vrtc.h"
> +
> +/* Register layout of the RTC */
> +struct rtcdev {
> +	uint8_t	sec;
> +	uint8_t	alarm_sec;
> +	uint8_t	min;
> +	uint8_t	alarm_min;
> +	uint8_t	hour;
> +	uint8_t	alarm_hour;
> +	uint8_t	day_of_week;
> +	uint8_t	day_of_month;
> +	uint8_t	month;
> +	uint8_t	year;
> +	uint8_t	reg_a;
> +	uint8_t	reg_b;
> +	uint8_t	reg_c;
> +	uint8_t	reg_d;
> +	uint8_t	nvram[128 - 14];
> +} __packed;
> +CTASSERT(sizeof(struct rtcdev) =3D=3D 128);
> +
> +struct vrtc {
> +	struct vm	*vm;
> +	struct mtx	mtx;
> +	struct callout	callout;
> +	u_int		addr;		/* RTC register to
> read or write */
> +	sbintime_t	base_uptime;
> +	time_t		base_rtctime;
> +	struct rtcdev	rtcdev;
> +};
> +
> +#define	VRTC_LOCK(vrtc)
> mtx_lock(&((vrtc)->mtx)) +#define	VRTC_UNLOCK(vrtc)
> mtx_unlock(&((vrtc)->mtx)) +#define	VRTC_LOCKED(vrtc)
> mtx_owned(&((vrtc)->mtx)) +
> +/*
> + * RTC time is considered "broken" if:
> + * - RTC updates are halted by the guest
> + * - RTC date/time fields have invalid values
> + */
> +#define	VRTC_BROKEN_TIME	((time_t)-1)
> +
> +#define	RTC_IRQ			8
> +#define	RTCSB_BIN		0x04
> +#define	RTCSB_ALL_INTRS		(RTCSB_UINTR |
> RTCSB_AINTR | RTCSB_PINTR) +#define	rtc_halted(vrtc)
> ((vrtc->rtcdev.reg_b & RTCSB_HALT) !=3D 0) +#define
> aintr_enabled(vrtc)	(((vrtc)->rtcdev.reg_b & RTCSB_AINTR) !=3D
> 0) +#define	pintr_enabled(vrtc)	(((vrtc)->rtcdev.reg_b
> & RTCSB_PINTR) !=3D 0) +#define	uintr_enabled(vrtc)
> (((vrtc)->rtcdev.reg_b & RTCSB_UINTR) !=3D 0) + +static void
> vrtc_callout_handler(void *arg); +static void vrtc_set_reg_c(struct
> vrtc *vrtc, uint8_t newval); +
> +static MALLOC_DEFINE(M_VRTC, "vrtc", "bhyve virtual rtc");
> +
> +SYSCTL_DECL(_hw_vmm);
> +SYSCTL_NODE(_hw_vmm, OID_AUTO, vrtc, CTLFLAG_RW, NULL, NULL);
> +
> +static int rtc_flag_broken_time =3D 1;
> +SYSCTL_INT(_hw_vmm_vrtc, OID_AUTO, flag_broken_time, CTLFLAG_RDTUN,
> +    &rtc_flag_broken_time, 0, "Stop guest when invalid RTC time is
> detected"); +
> +static __inline bool
> +divider_enabled(int reg_a)
> +{
> +	/*
> +	 * The RTC is counting only when dividers are not held in
> reset.
> +	 */
> +	return ((reg_a & 0x70) =3D=3D 0x20);
> +}
> +
> +static __inline bool
> +update_enabled(struct vrtc *vrtc)
> +{
> +	/*
> +	 * RTC date/time can be updated only if:
> +	 * - divider is not held in reset
> +	 * - guest has not disabled updates
> +	 * - the date/time fields have valid contents
> +	 */
> +	if (!divider_enabled(vrtc->rtcdev.reg_a))
> +		return (false);
> +
> +	if (rtc_halted(vrtc))
> +		return (false);
> +
> +	if (vrtc->base_rtctime =3D=3D VRTC_BROKEN_TIME)
> +		return (false);
> +
> +	return (true);
> +}
> +
> +static time_t
> +vrtc_curtime(struct vrtc *vrtc)
> +{
> +	sbintime_t now, delta;
> +	time_t t;
> +
> +	KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked",
> __func__)); +
> +	t =3D vrtc->base_rtctime;
> +	if (update_enabled(vrtc)) {
> +		now =3D sbinuptime();
> +		delta =3D now - vrtc->base_uptime;
> +		KASSERT(delta >=3D 0, ("vrtc_curtime: uptime went
> backwards: "
> +		    "%#lx to %#lx", vrtc->base_uptime, now));
> +		t +=3D delta / SBT_1S;
> +	}
> +	return (t);
> +}
> +
> +static __inline uint8_t
> +rtcset(struct rtcdev *rtc, int val)
> +{
> +
> +	KASSERT(val >=3D 0 && val < 100, ("%s: invalid bin2bcd index
> %d",
> +	    __func__, val));
> +
> +	return ((rtc->reg_b & RTCSB_BIN) ? val : bin2bcd_data[val]);
> +}
> +
> +static void
> +secs_to_rtc(time_t rtctime, struct vrtc *vrtc, int force_update)
> +{
> +	struct clocktime ct;
> +	struct timespec ts;
> +	struct rtcdev *rtc;
> +	int hour;
> +
> +	KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked",
> __func__)); +
> +	if (rtctime < 0) {
> +		KASSERT(rtctime =3D=3D VRTC_BROKEN_TIME,
> +		    ("%s: invalid vrtc time %#lx", __func__,
> rtctime));
> +		return;
> +	}
> +
> +	/*
> +	 * If the RTC is halted then the guest has "ownership" of the
> +	 * date/time fields. Don't update the RTC date/time fields in
> +	 * this case (unless forced).
> +	 */
> +	if (rtc_halted(vrtc) && !force_update)
> +		return;
> +
> +	ts.tv_sec =3D rtctime;
> +	ts.tv_nsec =3D 0;
> +	clock_ts_to_ct(&ts, &ct);
> +
> +	KASSERT(ct.sec >=3D 0 && ct.sec <=3D 59, ("invalid clocktime sec
> %d",
> +	    ct.sec));
> +	KASSERT(ct.min >=3D 0 && ct.min <=3D 59, ("invalid clocktime min
> %d",
> +	    ct.min));
> +	KASSERT(ct.hour >=3D 0 && ct.hour <=3D 23, ("invalid clocktime
> hour %d",
> +	    ct.hour));
> +	KASSERT(ct.dow >=3D 0 && ct.dow <=3D 6, ("invalid clocktime wday
> %d",
> +	    ct.dow));
> +	KASSERT(ct.day >=3D 1 && ct.day <=3D 31, ("invalid clocktime
> mday %d",
> +	    ct.day));
> +	KASSERT(ct.mon >=3D 1 && ct.mon <=3D 12, ("invalid clocktime
> month %d",
> +	    ct.mon));
> +	KASSERT(ct.year >=3D POSIX_BASE_YEAR, ("invalid clocktime year
> %d",
> +	    ct.year));
> +
> +	rtc =3D &vrtc->rtcdev;
> +	rtc->sec =3D rtcset(rtc, ct.sec);
> +	rtc->min =3D rtcset(rtc, ct.min);
> +
> +	hour =3D ct.hour;
> +	if ((rtc->reg_b & RTCSB_24HR) =3D=3D 0)
> +		hour =3D (hour % 12) + 1;	    /* convert to a
> 12-hour format */ +
> +	rtc->hour =3D rtcset(rtc, hour);
> +
> +	if ((rtc->reg_b & RTCSB_24HR) =3D=3D 0 && ct.hour >=3D 12)
> +		rtc->hour |=3D 0x80;	    /* set MSB to indicate
> PM */ +
> +	rtc->day_of_week =3D rtcset(rtc, ct.dow + 1);
> +	rtc->day_of_month =3D rtcset(rtc, ct.day);
> +	rtc->month =3D rtcset(rtc, ct.mon);
> +	rtc->year =3D rtcset(rtc, ct.year % 100);
> +}
> +
> +static int
> +rtcget(struct rtcdev *rtc, int val, int *retval)
> +{
> +	uint8_t upper, lower;
> +
> +	if (rtc->reg_b & RTCSB_BIN) {
> +		*retval =3D val;
> +		return (0);
> +	}
> +
> +	lower =3D val & 0xf;
> +	upper =3D (val >> 4) & 0xf;
> +
> +	if (lower > 9 || upper > 9)
> +		return (-1);
> +
> +	*retval =3D upper * 10 + lower;
> +	return (0);
> +}
> +
> +static time_t
> +rtc_to_secs(struct vrtc *vrtc)
> +{
> +	struct clocktime ct;
> +	struct timespec ts;
> +	struct rtcdev *rtc;
> +	struct vm *vm;
> +	int error, hour, pm, year;
> +
> +	KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked",
> __func__)); +
> +	vm =3D vrtc->vm;
> +	rtc =3D &vrtc->rtcdev;
> +
> +	bzero(&ct, sizeof(struct clocktime));
> +
> +	error =3D rtcget(rtc, rtc->sec, &ct.sec);
> +	if (error || ct.sec < 0 || ct.sec > 59) {
> +		VM_CTR2(vm, "Invalid RTC sec %#x/%d", rtc->sec,
> ct.sec);
> +		goto fail;
> +	}
> +
> +	error =3D rtcget(rtc, rtc->min, &ct.min);
> +	if (error || ct.min < 0 || ct.min > 59) {
> +		VM_CTR2(vm, "Invalid RTC min %#x/%d", rtc->min,
> ct.min);
> +		goto fail;
> +	}
> +
> +	pm =3D 0;
> +	hour =3D rtc->hour;
> +	if ((rtc->reg_b & RTCSB_24HR) =3D=3D 0) {
> +		if (hour & 0x80) {
> +			hour &=3D ~0x80;
> +			pm =3D 1;
> +		}
> +	}
> +	error =3D rtcget(rtc, hour, &ct.hour);
> +	if ((rtc->reg_b & RTCSB_24HR) =3D=3D 0) {
> +		ct.hour -=3D 1;
> +		if (pm)
> +			ct.hour +=3D 12;
> +	}
> +
> +	if (error || ct.hour < 0 || ct.hour > 23) {
> +		VM_CTR2(vm, "Invalid RTC hour %#x/%d", rtc->hour,
> ct.hour);
> +		goto fail;
> +	}
> +
> +	/*
> +	 * Ignore 'rtc->dow' because some guests like Linux don't
> bother
> +	 * setting it at all while others like OpenBSD/i386 set it
> incorrectly.=20
> +	 *
> +	 * clock_ct_to_ts() does not depend on 'ct.dow' anyways so
> ignore it.
> +	 */
> +	ct.dow =3D -1;
> +
> +	error =3D rtcget(rtc, rtc->day_of_month, &ct.day);
> +	if (error || ct.day < 1 || ct.day > 31) {
> +		VM_CTR2(vm, "Invalid RTC mday %#x/%d",
> rtc->day_of_month,
> +		    ct.day);
> +		goto fail;
> +	}
> +
> +	error =3D rtcget(rtc, rtc->month, &ct.mon);
> +	if (error || ct.mon < 1 || ct.mon > 12) {
> +		VM_CTR2(vm, "Invalid RTC month %#x/%d", rtc->month,
> ct.mon);
> +		goto fail;
> +	}
> +
> +	error =3D rtcget(rtc, rtc->year, &year);
> +	if (error || year < 0 || year > 99) {
> +		VM_CTR2(vm, "Invalid RTC year %#x/%d", rtc->year,
> year);
> +		goto fail;
> +	}
> +	if (year >=3D 70)
> +		ct.year =3D 1900 + year;
> +	else
> +		ct.year =3D 2000 + year;
> +
> +	error =3D clock_ct_to_ts(&ct, &ts);
> +	if (error || ts.tv_sec < 0) {
> +		VM_CTR3(vm, "Invalid RTC clocktime.date
> %04d-%02d-%02d",
> +		    ct.year, ct.mon, ct.day);
> +		VM_CTR3(vm, "Invalid RTC clocktime.time
> %02d:%02d:%02d",
> +		    ct.hour, ct.min, ct.sec);
> +		goto fail;
> +	}
> +	return (ts.tv_sec);		/* success */
> +fail:
> +	return (VRTC_BROKEN_TIME);	/* failure */
> +}
> +
> +static int
> +vrtc_time_update(struct vrtc *vrtc, time_t newtime)
> +{
> +	struct rtcdev *rtc;
> +	time_t oldtime;
> +	uint8_t alarm_sec, alarm_min, alarm_hour;
> +
> +	KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked",
> __func__)); +
> +	rtc =3D &vrtc->rtcdev;
> +	alarm_sec =3D rtc->alarm_sec;
> +	alarm_min =3D rtc->alarm_min;
> +	alarm_hour =3D rtc->alarm_hour;
> +
> +	oldtime =3D vrtc->base_rtctime;
> +	VM_CTR2(vrtc->vm, "Updating RTC time from %#lx to %#lx",
> +	    oldtime, newtime);
> +
> +	if (newtime =3D=3D oldtime)
> +		return (0);
> +
> +	/*
> +	 * If 'newtime' indicates that RTC updates are disabled then
> just
> +	 * record that and return. There is no need to do alarm
> interrupt
> +	 * processing or update 'base_uptime' in this case.
> +	 */
> +	if (newtime =3D=3D VRTC_BROKEN_TIME) {
> +		vrtc->base_rtctime =3D VRTC_BROKEN_TIME;
> +		return (0);
> +	}
> +
> +	/*
> +	 * Return an error if RTC updates are halted by the guest.
> +	 */
> +	if (rtc_halted(vrtc)) {
> +		VM_CTR0(vrtc->vm, "RTC update halted by guest");
> +		return (EBUSY);
> +	}
> +
> +	do {
> +		/*
> +		 * If the alarm interrupt is enabled and 'oldtime'
> is valid
> +		 * then visit all the seconds between 'oldtime' and
> 'newtime'
> +		 * to check for the alarm condition.
> +		 *
> +		 * Otherwise move the RTC time forward directly to
> 'newtime'.
> +		 */
> +		if (aintr_enabled(vrtc) && oldtime !=3D
> VRTC_BROKEN_TIME)
> +			vrtc->base_rtctime++;
> +		else
> +			vrtc->base_rtctime =3D newtime;
> +
> +		if (aintr_enabled(vrtc)) {
> +			/*
> +			 * Update the RTC date/time fields before
> checking
> +			 * if the alarm conditions are satisfied.
> +			 */
> +			secs_to_rtc(vrtc->base_rtctime, vrtc, 0);
> +
> +			if ((alarm_sec >=3D 0xC0 || alarm_sec =3D=3D
> rtc->sec) &&
> +			    (alarm_min >=3D 0xC0 || alarm_min =3D=3D
> rtc->min) &&
> +			    (alarm_hour >=3D 0xC0 || alarm_hour =3D=3D
> rtc->hour)) {
> +				vrtc_set_reg_c(vrtc, rtc->reg_c |
> RTCIR_ALARM);
> +			}
> +		}
> +	} while (vrtc->base_rtctime !=3D newtime);
> +
> +	if (uintr_enabled(vrtc))
> +		vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_UPDATE);
> +
> +	vrtc->base_uptime =3D sbinuptime();
> +
> +	return (0);
> +}
> +
> +static sbintime_t
> +vrtc_freq(struct vrtc *vrtc)
> +{
> +	int ratesel;
> +
> +	static sbintime_t pf[16] =3D {
> +		0,
> +		SBT_1S / 256,
> +		SBT_1S / 128,
> +		SBT_1S / 8192,
> +		SBT_1S / 4096,
> +		SBT_1S / 2048,
> +		SBT_1S / 1024,
> +		SBT_1S / 512,
> +		SBT_1S / 256,
> +		SBT_1S / 128,
> +		SBT_1S / 64,
> +		SBT_1S / 32,
> +		SBT_1S / 16,
> +		SBT_1S / 8,
> +		SBT_1S / 4,
> +		SBT_1S / 2,
> +	};
> +
> +	KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked",
> __func__)); +
> +	/*
> +	 * If both periodic and alarm interrupts are enabled then
> use the
> +	 * periodic frequency to drive the callout. The minimum
> periodic
> +	 * frequency (2 Hz) is higher than the alarm frequency (1
> Hz) so
> +	 * piggyback the alarm on top of it. The same argument
> applies to
> +	 * the update interrupt.
> +	 */
> +	if (pintr_enabled(vrtc) &&
> divider_enabled(vrtc->rtcdev.reg_a)) {
> +		ratesel =3D vrtc->rtcdev.reg_a & 0xf;
> +		return (pf[ratesel]);
> +	} else if (aintr_enabled(vrtc) && update_enabled(vrtc)) {
> +		return (SBT_1S);
> +	} else if (uintr_enabled(vrtc) && update_enabled(vrtc)) {
> +		return (SBT_1S);
> +	} else {
> +		return (0);
> +	}
> +}
> +
> +static void
> +vrtc_callout_reset(struct vrtc *vrtc, sbintime_t freqsbt)
> +{
> +
> +	KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked",
> __func__)); +
> +	if (freqsbt =3D=3D 0) {
> +		if (callout_active(&vrtc->callout)) {
> +			VM_CTR0(vrtc->vm, "RTC callout stopped");
> +			callout_stop(&vrtc->callout);
> +		}
> +		return;
> +	}
> +	VM_CTR1(vrtc->vm, "RTC callout frequency %d hz", SBT_1S /
> freqsbt);
> +	callout_reset_sbt(&vrtc->callout, freqsbt, 0,
> vrtc_callout_handler,
> +	    vrtc, 0);
> +}
> +
> +static void
> +vrtc_callout_handler(void *arg)
> +{
> +	struct vrtc *vrtc =3D arg;
> +	sbintime_t freqsbt;
> +	time_t rtctime;
> +	int error;
> +
> +	VM_CTR0(vrtc->vm, "vrtc callout fired");
> +
> +	VRTC_LOCK(vrtc);
> +	if (callout_pending(&vrtc->callout))	/* callout was
> reset */
> +		goto done;
> +
> +	if (!callout_active(&vrtc->callout))	/* callout was
> stopped */
> +		goto done;
> +
> +	callout_deactivate(&vrtc->callout);
> +
> +	KASSERT((vrtc->rtcdev.reg_b & RTCSB_ALL_INTRS) !=3D 0,
> +	    ("gratuitous vrtc callout"));
> +
> +	if (pintr_enabled(vrtc))
> +		vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c |
> RTCIR_PERIOD); +
> +	if (aintr_enabled(vrtc) || uintr_enabled(vrtc)) {
> +		rtctime =3D vrtc_curtime(vrtc);
> +		error =3D vrtc_time_update(vrtc, rtctime);
> +		KASSERT(error =3D=3D 0, ("%s: vrtc_time_update error %d",
> +		    __func__, error));
> +	}
> +
> +	freqsbt =3D vrtc_freq(vrtc);
> +	KASSERT(freqsbt !=3D 0, ("%s: vrtc frequency cannot be zero",
> __func__));
> +	vrtc_callout_reset(vrtc, freqsbt);
> +done:
> +	VRTC_UNLOCK(vrtc);
> +}
> +
> +static __inline void
> +vrtc_callout_check(struct vrtc *vrtc, sbintime_t freq)
> +{
> +	int active;
> +
> +	active =3D callout_active(&vrtc->callout) ? 1 : 0;
> +	KASSERT((freq =3D=3D 0 && !active) || (freq !=3D 0 && active),
> +	    ("vrtc callout %s with frequency %#lx",
> +	    active ? "active" : "inactive", freq));
> +}
> +
> +static void
> +vrtc_set_reg_c(struct vrtc *vrtc, uint8_t newval)
> +{
> +	struct rtcdev *rtc;
> +	int oldirqf, newirqf;
> +	uint8_t oldval, changed;
> +
> +	KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked",
> __func__)); +
> +	rtc =3D &vrtc->rtcdev;
> +	newval &=3D RTCIR_ALARM | RTCIR_PERIOD | RTCIR_UPDATE;
> +
> +	oldirqf =3D rtc->reg_c & RTCIR_INT;
> +	if ((aintr_enabled(vrtc) && (newval & RTCIR_ALARM) !=3D 0) ||
> +	    (pintr_enabled(vrtc) && (newval & RTCIR_PERIOD) !=3D 0) ||
> +	    (uintr_enabled(vrtc) && (newval & RTCIR_UPDATE) !=3D 0)) {
> +		newirqf =3D RTCIR_INT;
> +	} else {
> +		newirqf =3D 0;
> +	}
> +
> +	oldval =3D rtc->reg_c;
> +	rtc->reg_c =3D newirqf | newval;
> +	changed =3D oldval ^ rtc->reg_c;
> +	if (changed) {
> +		VM_CTR2(vrtc->vm, "RTC reg_c changed from %#x to
> %#x",
> +		    oldval, rtc->reg_c);
> +	}
> +
> +	if (!oldirqf && newirqf) {
> +		VM_CTR1(vrtc->vm, "RTC irq %d asserted", RTC_IRQ);
> +		vatpic_pulse_irq(vrtc->vm, RTC_IRQ);
> +		vioapic_pulse_irq(vrtc->vm, RTC_IRQ);
> +	} else if (oldirqf && !newirqf) {
> +		VM_CTR1(vrtc->vm, "RTC irq %d deasserted", RTC_IRQ);
> +	}
> +}
> +
> +static int
> +vrtc_set_reg_b(struct vrtc *vrtc, uint8_t newval)
> +{
> +	struct rtcdev *rtc;
> +	sbintime_t oldfreq, newfreq;
> +	time_t curtime, rtctime;
> +	int error;
> +	uint8_t oldval, changed;
> +
> +	KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked",
> __func__)); +
> +	rtc =3D &vrtc->rtcdev;
> +	oldval =3D rtc->reg_b;
> +	oldfreq =3D vrtc_freq(vrtc);
> +
> +	rtc->reg_b =3D newval;
> +	changed =3D oldval ^ newval;
> +	if (changed) {
> +		VM_CTR2(vrtc->vm, "RTC reg_b changed from %#x to
> %#x",
> +		    oldval, newval);
> +	}
> +
> +	if (changed & RTCSB_HALT) {
> +		if ((newval & RTCSB_HALT) =3D=3D 0) {
> +			rtctime =3D rtc_to_secs(vrtc);
> +			if (rtctime =3D=3D VRTC_BROKEN_TIME) {
> +				/*
> +				 * Stop updating the RTC if the
> date/time
> +				 * programmed by the guest is not
> correct.
> +				 */
> +				VM_CTR0(vrtc->vm, "Invalid RTC
> date/time "
> +				    "programming detected");
> +
> +				if (rtc_flag_broken_time)
> +					return (-1);
> +			}
> +		} else {
> +			curtime =3D vrtc_curtime(vrtc);
> +			KASSERT(curtime =3D=3D vrtc->base_rtctime, ("%s:
> mismatch "
> +			    "between vrtc basetime (%#lx) and
> curtime (%#lx)",
> +			    __func__, vrtc->base_rtctime, curtime));
> +
> +			/*
> +			 * Force a refresh of the RTC date/time
> fields so
> +			 * they reflect the time right before the
> guest set
> +			 * the HALT bit.
> +			 */
> +			secs_to_rtc(curtime, vrtc, 1);
> +
> +			/*
> +			 * Updates are halted so mark 'base_rtctime'
> to denote
> +			 * that the RTC date/time is in flux.
> +			 */
> +			rtctime =3D VRTC_BROKEN_TIME;
> +			rtc->reg_b &=3D ~RTCSB_UINTR;
> +		}
> +		error =3D vrtc_time_update(vrtc, rtctime);
> +		KASSERT(error =3D=3D 0, ("vrtc_time_update error %d",
> error));
> +	}
> +
> +	/*
> +	 * Side effect of changes to the interrupt enable bits.
> +	 */
> +	if (changed & RTCSB_ALL_INTRS)
> +		vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c);
> +
> +	/*
> +	 * Change the callout frequency if it has changed.
> +	 */
> +	newfreq =3D vrtc_freq(vrtc);
> +	if (newfreq !=3D oldfreq)
> +		vrtc_callout_reset(vrtc, newfreq);
> +	else
> +		vrtc_callout_check(vrtc, newfreq);
> +
> +	/*
> +	 * The side effect of bits that control the RTC date/time
> format
> +	 * is handled lazily when those fields are actually read.
> +	 */
> +	return (0);
> +}
> +
> +static void
> +vrtc_set_reg_a(struct vrtc *vrtc, uint8_t newval)
> +{
> +	sbintime_t oldfreq, newfreq;
> +	uint8_t oldval, changed;
> +
> +	KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked",
> __func__)); +
> +	newval &=3D ~RTCSA_TUP;
> +	oldval =3D vrtc->rtcdev.reg_a;
> +	oldfreq =3D vrtc_freq(vrtc);
> +
> +	if (divider_enabled(oldval) && !divider_enabled(newval)) {
> +		VM_CTR2(vrtc->vm, "RTC divider held in reset at
> %#lx/%#lx",
> +		    vrtc->base_rtctime, vrtc->base_uptime);
> +	} else if (!divider_enabled(oldval) &&
> divider_enabled(newval)) {
> +		/*
> +		 * If the dividers are coming out of reset then
> update
> +		 * 'base_uptime' before this happens. This is done to
> +		 * maintain the illusion that the RTC date/time was
> frozen
> +		 * while the dividers were disabled.
> +		 */
> +		vrtc->base_uptime =3D sbinuptime();
> +		VM_CTR2(vrtc->vm, "RTC divider out of reset at
> %#lx/%#lx",
> +		    vrtc->base_rtctime, vrtc->base_uptime);
> +	} else {
> +		/* NOTHING */
> +	}
> +
> +	vrtc->rtcdev.reg_a =3D newval;
> +	changed =3D oldval ^ newval;
> +	if (changed) {
> +		VM_CTR2(vrtc->vm, "RTC reg_a changed from %#x to
> %#x",
> +		    oldval, newval);
> +	}
> +
> +	/*
> +	 * Side effect of changes to rate select and divider enable
> bits.
> +	 */
> +	newfreq =3D vrtc_freq(vrtc);
> +	if (newfreq !=3D oldfreq)
> +		vrtc_callout_reset(vrtc, newfreq);
> +	else
> +		vrtc_callout_check(vrtc, newfreq);
> +}
> +
> +int
> +vrtc_set_time(struct vm *vm, time_t secs)
> +{
> +	struct vrtc *vrtc;
> +	int error;
> +
> +	vrtc =3D vm_rtc(vm);
> +	VRTC_LOCK(vrtc);
> +	error =3D vrtc_time_update(vrtc, secs);
> +	VRTC_UNLOCK(vrtc);
> +
> +	if (error) {
> +		VM_CTR2(vrtc->vm, "Error %d setting RTC time to
> %#lx", error,
> +		    secs);
> +	} else {
> +		VM_CTR1(vrtc->vm, "RTC time set to %#lx", secs);
> +	}
> +
> +	return (error);
> +}
> +
> +time_t
> +vrtc_get_time(struct vm *vm)
> +{
> +	struct vrtc *vrtc;
> +	time_t t;
> +
> +	vrtc =3D vm_rtc(vm);
> +	VRTC_LOCK(vrtc);
> +	t =3D vrtc_curtime(vrtc);
> +	VRTC_UNLOCK(vrtc);
> +
>=20
> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
> _______________________________________________
> svn-src-all@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/svn-src-all
> To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"


...
/usr/local/libexec/ccache/world/cc -target x86_64-unknown-freebsd11.0  -O2 =
-pipe -O3 -fvectorize -fslp-vectorize -fblocks -march=3Dnative -mmmx -msse =
-msse2 -msse3 -mssse3 -mavx -maes -mpclmul -funroll-loops -march=3Dnative  =
-Wall -I/usr/src/lib/libvgl -std=3Dgnu99 -fstack-protector -Wsystem-headers=
 -Werror -Wall -Wno-format-y2k -Wno-uninitialized -Wno-pointer-sign -Wno-em=
pty-body -Wno-string-plus-int -Wno-unused-const-variable -Wno-tautological-=
compare -Wno-unused-value -Wno-parentheses-equality -Wno-unused-function -W=
no-enum-conversion -Wno-switch -Wno-switch-enum -Wno-knr-promoted-parameter=
 -Qunused-arguments -c /usr/src/lib/libvgl/simple.c -o simple.o
--- all_subdir_libvmmapi ---
/usr/src/lib/libvmmapi/vmmapi.c:1153:21: error: variable has incomplete typ=
e 'struct vm_rtc_data'
        struct vm_rtc_data rtcdata;
                           ^
/usr/src/lib/libvmmapi/vmmapi.c:1153:9: note: forward declaration of 'struc=
t vm_rtc_data'
        struct vm_rtc_data rtcdata;
               ^
/usr/src/lib/libvmmapi/vmmapi.c:1159:25: error: use of undeclared identifie=
r 'VM_RTC_WRITE'
        error =3D ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata);
                               ^
/usr/src/lib/libvmmapi/vmmapi.c:1166:21: error: variable has incomplete typ=
e 'struct vm_rtc_data'
        struct vm_rtc_data rtcdata;
                           ^
/usr/src/lib/libvmmapi/vmmapi.c:1166:9: note: forward declaration of 'struc=
t vm_rtc_data'
        struct vm_rtc_data rtcdata;
               ^
/usr/src/lib/libvmmapi/vmmapi.c:1171:25: error: use of undeclared identifie=
r 'VM_RTC_READ'
        error =3D ioctl(ctx->fd, VM_RTC_READ, &rtcdata);
                               ^
/usr/src/lib/libvmmapi/vmmapi.c:1180:21: error: variable has incomplete typ=
e 'struct vm_rtc_time'
        struct vm_rtc_time rtctime;
                           ^
/usr/src/lib/libvmmapi/vmmapi.c:1180:9: note: forward declaration of 'struc=
t vm_rtc_time'
        struct vm_rtc_time rtctime;
               ^
/usr/src/lib/libvmmapi/vmmapi.c:1185:25: error: use of undeclared identifie=
r 'VM_RTC_SETTIME'
        error =3D ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime);
                               ^
/usr/src/lib/libvmmapi/vmmapi.c:1192:21: error: variable has incomplete typ=
e 'struct vm_rtc_time'
        struct vm_rtc_time rtctime;
                           ^
/usr/src/lib/libvmmapi/vmmapi.c:1192:9: note: forward declaration of 'struc=
t vm_rtc_time'
        struct vm_rtc_time rtctime;
               ^
/usr/src/lib/libvmmapi/vmmapi.c:1196:25: error: use of undeclared identifie=
r 'VM_RTC_GETTIME'
        error =3D ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime);
                               ^
8 errors generated.
*** [vmmapi.So] Error code 1

make[5]: stopped in /usr/src/lib/libvmmapi
1 error

make[5]: stopped in /usr/src/lib/libvmmapi
*** [all_subdir_libvmmapi] Error code 2

make[4]: stopped in /usr/src/lib
--- all_subdir_libunbound ---
A failure has been detected in another branch of the parallel make

make[5]: stopped in /usr/src/lib/libunbound
*** [all_subdir_libunbound] Error code 2

make[4]: stopped in /usr/src/lib
--- all_subdir_libvgl ---
A failure has been detected in another branch of the parallel make

make[5]: stopped in /usr/src/lib/libvgl
*** [all_subdir_libvgl] Error code 2

make[4]: stopped in /usr/src/lib
--- all_subdir_libstand ---
A failure has been detected in another branch of the parallel make

make[5]: stopped in /usr/src/lib/libstand
*** [all_subdir_libstand] Error code 2

make[4]: stopped in /usr/src/lib
4 errors

make[4]: stopped in /usr/src/lib
A failure has been detected in another branch of the parallel make

make[3]: stopped in /usr/src
*** [libraries] Error code 2

make[2]: stopped in /usr/src
1 error

make[2]: stopped in /usr/src
*** [_libraries] Error code 2

make[1]: stopped in /usr/src
1 error

make[1]: stopped in /usr/src
*** [buildworld] Error code 2

make: stopped in /usr/src
1 error

make: stopped in /usr/src
root@nonamehost:/usr/src #=20




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20141231105638.15336969>