tools/ocaml: Introduce xenctrl ABI build-time checks

c/s f089fddd94 broke the Ocaml ABI by renumering
XEN_SYSCTL_PHYSCAP_directio without adjusting the Ocaml
physinfo_cap_flag enumeration.

Add build machinery which will check the ABI correspondence.

This will result in a compile time failure whenever constants get
renumbered/added without a compatible adjustment to the Ocaml ABI.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Christian Lindig <christian.lindig@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <Andrew.Cooper3@citrix.com>
This commit is contained in:
Ian Jackson committed 2019-09-10 14:44:33 +01:00
1 parent 7b7bab4bce
commit 006a69d25c
5 files changed
+145 -20

No files matched your search

+1
View File
@@ -392,6 +392,7 @@ tools/ocaml/libs/xentoollog/_xtl_levels.*
tools/ocaml/libs/xentoollog/xentoollog.ml
tools/ocaml/libs/xentoollog/xentoollog.mli
tools/ocaml/libs/xs/paths.ml
tools/ocaml/libs/xc/xenctrl_abi_check.h
tools/ocaml/xenstored/_paths.h
tools/ocaml/xenstored/oxenstored
tools/ocaml/xenstored/oxenstored.conf
+7
View File
@@ -31,4 +31,11 @@ install: $(LIBS) META
uninstall:
$(OCAMLFIND) remove -destdir $(OCAMLDESTDIR) xenctrl
xenctrl_stubs.o: xenctrl_abi_check.h
xenctrl_abi_check.h: abi-check xenctrl_stubs.c xenctrl.ml
$(PERL) -w $^ >$@.tmp && mv -f $@.tmp $@
GENERATED_FILES += xenctrl_abi_check.h
include $(TOPLEVEL)/Makefile.rules
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
our %enums;
@ARGV == 2 or die;
our ($c, $o) = @ARGV;
open STDIN, "<", $c or die $!;
our $cline = -1;
our $ei;
while (<>) {
if ($cline == -1) {
if (m/c_bitmap_to_ocaml_list/) {
$cline = 0;
$ei = { };
}
} else {
$cline++;
m{^\s+/\* \s+ ! \s+ (.*?) \s* \*/\s*$}x or die "$cline $_ ?";
my @vals = split /\s+/, $1;
if ($cline == 1 && !@vals) {
$cline = -1;
} elsif ($cline == 1 && @vals == 3) {
$ei->{$_} = shift @vals foreach qw(OType OPrefix Mangle);
} elsif ($cline == 2 && @vals == 3) {
$ei->{$_} = shift @vals foreach qw(CPrefix CFinal CFinalHow);
die if $enums{ $ei->{OType} };
$enums{ $ei->{OType} } = $ei;
$cline = -1;
} else {
die "$_ ?";
}
}
}
sub expect ($$) {
printf "BUILD_BUG_ON( %-30s != %-10s );\n", @_ or die $!;
}
open STDIN, "<", $o or die $!;
my $cval;
$ei = undef;
my $bitnum = 0;
while (<>) {
if (!$ei) {
if (m{^type \s+ (\w+) \s* \= \s* $/}x && $enums{$1}) {
$ei = $enums{$1};
$cval = '';
$bitnum = 0;
}
} else {
if (m{^\s+ \| \s* $ei->{OPrefix} (\w+) \s*$}x) {
$cval = $1;
if ($ei->{Mangle} eq 'lc') {
$cval = lc $cval;
} elsif ($ei->{Mangle} eq 'none') {
} else {
die;
}
$cval = $ei->{CPrefix}.$cval;
expect($cval, "(1u << $bitnum)");
$bitnum++;
} elsif (m/^\w|\{/) {
if ($ei->{CFinalHow} eq 'max') {
expect($ei->{CFinal}, "(1u << ".($bitnum-1).")");
} elsif ($ei->{CFinalHow} eq 'all') {
expect($ei->{CFinal}, "(1u << $bitnum)-1u");
} else {
die Dumper($ei)." ?";
}
$ei = undef;
} elsif (!m{\S}) {
} else {
die "$_ ?";
}
}
}
close STDOUT or die $!;
+49 -20
View File
@@ -32,6 +32,7 @@
#define XC_WANT_COMPAT_MAP_FOREIGN_API
#include <xenctrl.h>
#include <xen-tools/libs.h>
#include "mmap_stubs.h"
@@ -119,6 +120,39 @@ static void domain_handle_of_uuid_string(xen_domain_handle_t h,
#undef X
}
/*
* Various fields which are a bitmap in the C ABI are converted to lists of
* integers in the Ocaml ABI for more idiomatic handling.
*/
static value c_bitmap_to_ocaml_list
/* ! */
/*
* All calls to this function must be in a form suitable
* for xenctrl_abi_check. The parsing there is ad-hoc.
*/
(unsigned int bitmap)
{
CAMLparam0();
CAMLlocal2(list, tmp);
#include "xenctrl_abi_check.h"
list = tmp = Val_emptylist;
for ( unsigned int i = 0; bitmap; i++, bitmap >>= 1 )
{
if ( !(bitmap & 1) )
continue;
tmp = caml_alloc_small(2, Tag_cons);
Field(tmp, 0) = Val_int(i);
Field(tmp, 1) = list;
list = tmp;
}
CAMLreturn(list);
}
CAMLprim value stub_xc_domain_create(value xch, value config)
{
CAMLparam2(xch, config);
@@ -315,16 +349,13 @@ static value alloc_domaininfo(xc_domaininfo_t * info)
Store_field(result, 15, tmp);
#if defined(__i386__) || defined(__x86_64__)
/* emulation_flags: x86_arch_emulation_flags list; */
tmp = emul_list = Val_emptylist;
for (i = 0; i < 10; i++) {
if ((info->arch_config.emulation_flags >> i) & 1) {
tmp = caml_alloc_small(2, Tag_cons);
Field(tmp, 0) = Val_int(i);
Field(tmp, 1) = emul_list;
emul_list = tmp;
}
}
/*
* emulation_flags: x86_arch_emulation_flags list;
*/
emul_list = c_bitmap_to_ocaml_list
/* ! x86_arch_emulation_flags X86_EMU_ none */
/* ! XEN_X86_EMU_ XEN_X86_EMU_ALL all */
(info->arch_config.emulation_flags);
/* xen_x86_arch_domainconfig */
x86_arch_config = caml_alloc_tuple(1);
@@ -635,7 +666,7 @@ CAMLprim value stub_xc_send_debug_keys(value xch, value keys)
CAMLprim value stub_xc_physinfo(value xch)
{
CAMLparam1(xch);
CAMLlocal3(physinfo, cap_list, tmp);
CAMLlocal2(physinfo, cap_list);
xc_physinfo_t c_physinfo;
int r;
@@ -646,15 +677,13 @@ CAMLprim value stub_xc_physinfo(value xch)
if (r)
failwith_xc(_H(xch));
tmp = cap_list = Val_emptylist;
for (r = 0; r < 2; r++) {
if ((c_physinfo.capabilities >> r) & 1) {
tmp = caml_alloc_small(2, Tag_cons);
Field(tmp, 0) = Val_int(r);
Field(tmp, 1) = cap_list;
cap_list = tmp;
}
}
/*
* capabilities: physinfo_cap_flag list;
*/
cap_list = c_bitmap_to_ocaml_list
/* ! physinfo_cap_flag CAP_ lc */
/* ! XEN_SYSCTL_PHYSCAP_ XEN_SYSCTL_PHYSCAP_MAX max */
(c_physinfo.capabilities);
physinfo = caml_alloc_tuple(10);
Store_field(physinfo, 0, Val_int(c_physinfo.threads_per_core));
+4
View File
@@ -90,6 +90,10 @@ struct xen_sysctl_tbuf_op {
/* The platform supports direct access to I/O devices with IOMMU. */
#define _XEN_SYSCTL_PHYSCAP_directio 2
#define XEN_SYSCTL_PHYSCAP_directio (1u<<_XEN_SYSCTL_PHYSCAP_directio)
/* Max XEN_SYSCTL_PHYSCAP_* constant. Used for ABI checking. */
#define XEN_SYSCTL_PHYSCAP_MAX XEN_SYSCTL_PHYSCAP_directio
struct xen_sysctl_physinfo {
uint32_t threads_per_core;
uint32_t cores_per_socket;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.