aboutsummaryrefslogtreecommitdiff
path: root/test_macros/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'test_macros/src/lib.rs')
-rw-r--r--test_macros/src/lib.rs43
1 files changed, 38 insertions, 5 deletions
diff --git a/test_macros/src/lib.rs b/test_macros/src/lib.rs
index a211112..bd89f87 100644
--- a/test_macros/src/lib.rs
+++ b/test_macros/src/lib.rs
@@ -31,8 +31,9 @@ use syn::parse::IResult;
use std::string;
use proc_macro::TokenStream;
use quote::ToTokens;
+use std::collections::HashMap;
-fn parse_kvmtest_args(args: &syn::DeriveInput) -> ((u64, u64), bool) {
+fn parse_kvmtest_args(args: &syn::DeriveInput) -> ((u64, u64), (u16, u32), bool) {
if args.ident.as_ref() != "Dummy" {
panic!("Get rid of this hack!");
}
@@ -40,6 +41,8 @@ fn parse_kvmtest_args(args: &syn::DeriveInput) -> ((u64, u64), bool) {
// If syn ever implements visitor for MetaItems, this can probably be written simpler:
let mut identity_map: bool = false;
let mut physical_memory: Vec<u64> = Vec::with_capacity(2);
+ let mut ioport_reads: Vec<u32> = vec![0,0];
+
for attr in &args.attrs {
match attr.value {
syn::MetaItem::List(ref name, ref kvmattrs) => {
@@ -59,7 +62,18 @@ fn parse_kvmtest_args(args: &syn::DeriveInput) -> ((u64, u64), bool) {
&syn::NestedMetaItem::Literal(syn::Lit::Int(n, _)) => {
physical_memory.push(n);
},
- _ => panic!("Type mismatch in ram().")
+ _ => panic!("Type mismatch in ram() arguments.")
+ }
+ }
+ }
+ "ioport" => {
+ ioport_reads.clear();
+ for (idx, innerattr) in innerattrs.iter().enumerate() {
+ match innerattr {
+ &syn::NestedMetaItem::Literal(syn::Lit::Int(n, _)) => {
+ ioport_reads.push(n as u32);
+ },
+ _ => panic!("Type mismatch in ioport() arguments.")
}
}
}
@@ -87,8 +101,11 @@ fn parse_kvmtest_args(args: &syn::DeriveInput) -> ((u64, u64), bool) {
if physical_memory.len() != 2 {
panic!("ram() takes two values (x,y)");
}
+ if ioport_reads.len() != 2 {
+ panic!("in() takes two values (x,y)");
+ }
- ((physical_memory[0], physical_memory[1]) , identity_map)
+ ((physical_memory[0], physical_memory[1]), (ioport_reads[0] as u16, ioport_reads[1]), identity_map)
}
/// Add a additional meta-data and setup functions for a KVM based test.
@@ -98,7 +115,7 @@ fn generate_kvmtest_meta_data(test_ident: &syn::Ident, args: &syn::DeriveInput)
let setup_fn_ident = syn::Ident::new(String::from(test_name) + "_setup");
let struct_ident = syn::Ident::new(String::from(test_name) + "_kvm_meta_data");
- let (physical_memory, identity_map) = parse_kvmtest_args(args);
+ let (physical_memory, ioport_reads, identity_map) = parse_kvmtest_args(args);
(struct_ident.clone(),
quote! {
@@ -108,7 +125,8 @@ fn generate_kvmtest_meta_data(test_ident: &syn::Ident, args: &syn::DeriveInput)
mbz: 0,
meta: #test_name,
identity_map: #identity_map,
- physical_memory: #physical_memory
+ physical_memory: #physical_memory,
+ ioport_reads: #ioport_reads
};
})
@@ -130,6 +148,19 @@ fn insert_meta_data_reference(struct_ident: &syn::Ident, test_block: &mut syn::B
test_block.stmts.insert(0, stmt);
}
+/// Inserts an IO out (outw) instruction at the end of the test function
+/// that writes to port 0xf4 with value 0x0. outw will cause a vmexit.
+/// This particular port, payload combination is handled as a special case
+/// in the test runner to signal that the test has completed.
+fn insert_test_shutdown(struct_ident: &syn::Ident, test_block: &mut syn::Block) {
+ let stmt_exit_test = String::from("unsafe { x86::shared::io::outw(0xf4, 0x00); }");
+ let stmt = match syn::parse::stmt(stmt_exit_test.as_str()) {
+ IResult::Done(stmt_str, stmt) => stmt,
+ IResult::Error => panic!("Unable to generate test exit instruction."),
+ };
+ test_block.stmts.push(stmt);
+}
+
#[proc_macro_attribute]
pub fn kvmattrs(args: TokenStream, input: TokenStream) -> TokenStream {
@@ -141,6 +172,7 @@ pub fn kvmattrs(args: TokenStream, input: TokenStream) -> TokenStream {
// FIXME, see also https://github.com/dtolnay/syn/issues/86
let derive_input_hack = format!("#[kvmattrs{}] struct Dummy;", args);
let args_ast = syn::parse_derive_input(&derive_input_hack).unwrap();
+ println!("1");
// Generate meta-data struct
let ident = ast.ident.clone();
@@ -150,6 +182,7 @@ pub fn kvmattrs(args: TokenStream, input: TokenStream) -> TokenStream {
match &mut ast.node {
&mut syn::ItemKind::Fn(_, _, _, _, _, ref mut block) => {
insert_meta_data_reference(&meta_data_ident, block);
+ insert_test_shutdown(&meta_data_ident, block);
}
_ => panic!("Not a function!"),
};