1
0
mirror of https://github.com/openbsd/src.git synced 2026-04-27 15:46:02 +00:00

regress: Test vmmcall raises #UD

On AMD/SVM the hypervisor will inject #UD when userland tries to
execute the vmmcall instruction.  Same holds for vmgexit which is
encode as "rep vmmcall".

On Intel/VMX vmmcall and vmgexit are invalid instructions, so the
CPU will raise #UD.

ok mlarkin@
This commit is contained in:
hshoexer
2026-02-16 13:08:57 +00:00
parent c7faaa76b4
commit dac3ac0915
3 changed files with 111 additions and 1 deletions

View File

@@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.5 2026/02/16 13:05:14 hshoexer Exp $
# $OpenBSD: Makefile,v 1.6 2026/02/16 13:08:57 hshoexer Exp $
.if ${MACHINE_ARCH} == "amd64"
SUBDIR += ddb
@@ -6,6 +6,7 @@ SUBDIR += dump_tables
SUBDIR += fpu
SUBDIR += seves_mmio
SUBDIR += vmcall
SUBDIR += vmmcall
SUBDIR += vmm
.elif make(regress) || make(all)

View File

@@ -0,0 +1,29 @@
# $OpenBSD: Makefile,v 1.1 2026/02/16 13:08:57 hshoexer Exp $
.if "${MACHINE_ARCH}" != amd64
regress:
# MACHINE_ARCH is not amd64
@echo SKIPPED
.else
PROGS = vmmcall
WARNINGS = yes
REGRESS_TARGETS = run-regress-vmmcall
run-regress-vmmcall: vmmcall
./vmmcall vmmcall
./vmmcall vmgexit
.if ! (make(clean) || make(cleandir) || make(obj))
.include <bsd.own.mk>
VMMODE != /sbin/sysctl -n machdep.vmmode
HYPVERVISOR!= /sbin/sysctl -n hw.vendor
# Only run test on vmm(4) guests
.if "${VMMODE}" == "host" || "${HYPVERVISOR}" != "OpenBSD"
REGRESS_SKIP_TARGETS = ${REGRESS_TARGETS}
.endif
.endif
.endif
.include <bsd.regress.mk>

View File

@@ -0,0 +1,80 @@
/* $OpenBSD: vmmcall.c,v 1.1 2026/02/16 13:08:57 hshoexer Exp $ */
/*
* Copyright (c) 2025 Hans-Joerg Hoexer <hshoexer@yerbouti.franken.de>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void
handler(int sig, siginfo_t *sip, void *ctx)
{
printf("signo %d, code %d, errno %d\n", sip->si_signo, sip->si_code,
sip->si_errno);
if (sig != SIGILL)
errx(1, "expected SIGILL: %d", sig);
if (sip->si_code != ILL_PRVOPC)
errx(1, "expected ILL_PRVOPC: %d", sip->si_code);
exit(0);
}
__dead static void
usage(void)
{
fprintf(stderr, "usage: %s vmmcall | vmgexit\n",
getprogname());
exit(2);
}
int
main(int argc, char **argv)
{
struct sigaction sa;
int n;
if (argc != 2)
usage();
if (strcmp(argv[1], "vmmcall") == 0)
n = 0;
else if (strcmp(argv[1], "vmgexit") == 0)
n = 1;
else
usage();
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = handler;
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGILL, &sa, NULL) == -1)
err(2, "sigaction");
switch (n) {
case 0:
asm volatile("vmmcall");
break;
case 1:
/* vmgexit is encode as "rep; vmmcall" */
asm volatile("rep; vmmcall");
break;
}
errx(1, "expected signal");
return (0);
}