configurable interrupt sources
This commit is contained in:
parent
288abeb6bf
commit
740ce09d31
@ -1,33 +1,34 @@
|
||||
kernel,main_function,input_symbol,input_size,return_function,select_task
|
||||
mpeg2,mpeg2_main,mpeg2_oldorgframe,90112,mpeg2_return,NONE
|
||||
audiobeam,audiobeam_main,audiobeam_input,11520,audiobeam_return,NONE
|
||||
epic,epic_main,epic_image,4096,epic_return,NONE
|
||||
dijkstra,dijkstra_main,dijkstra_AdjMatrix,10000,dijkstra_return,NONE
|
||||
fft,fft_main,fft_twidtable,2046,fft_return,NONE
|
||||
bsort,bsort_main,bsort_Array,400,bsort_return,NONE
|
||||
insertsort,insertsort_main,insertsort_a,400,insertsort_return,NONE
|
||||
g723_enc,g723_enc_main,g723_enc_INPUT,1024,g723_enc_return,NONE
|
||||
rijndael_dec,rijndael_dec_main,rijndael_dec_data,32768,rijndael_dec_return,NONE
|
||||
rijndael_enc,rijndael_enc_main,rijndael_enc_data,31369,rijndael_enc_return,NONE
|
||||
huff_dec,huff_dec_main,huff_dec_encoded,419,huff_dec_return,NONE
|
||||
huff_enc,huff_enc_main,huff_enc_plaintext,600,huff_enc_return,NONE
|
||||
gsm_enc,gsm_enc_main,gsm_enc_pcmdata,6400,gsm_enc_return,NONE
|
||||
tmr,main,FUZZ_INPUT,32,trigger_Qemu_break,NONE
|
||||
tacle_rtos,prvStage0,FUZZ_INPUT,604,trigger_Qemu_break,NONE
|
||||
lift,main_lift,FUZZ_INPUT,100,trigger_Qemu_break,NONE
|
||||
waters,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||
watersv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||
waterspart,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||
waterspartv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||
waters_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||
watersv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||
waterspart_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||
waterspartv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129
|
||||
micro_branchless,main_branchless,FUZZ_INPUT,4,trigger_Qemu_break,NONE
|
||||
micro_int,main_int,FUZZ_INPUT,16,trigger_Qemu_break,NONE
|
||||
micro_longint,main_micro_longint,FUZZ_INPUT,16,trigger_Qemu_break,NONE
|
||||
minimal,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,NONE
|
||||
gen3,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,NONE
|
||||
interact,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,NONE
|
||||
interact_int,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,NONE
|
||||
release,main_release,FUZZ_INPUT,4096,trigger_Qemu_break,T3
|
||||
kernel,main_function,input_symbol,input_size,return_function,select_task,interrupts
|
||||
mpeg2,mpeg2_main,mpeg2_oldorgframe,90112,mpeg2_return,NONE,0#1000
|
||||
audiobeam,audiobeam_main,audiobeam_input,11520,audiobeam_return,NONE,0#1000
|
||||
epic,epic_main,epic_image,4096,epic_return,NONE,0#1000
|
||||
dijkstra,dijkstra_main,dijkstra_AdjMatrix,10000,dijkstra_return,NONE,0#1000
|
||||
fft,fft_main,fft_twidtable,2046,fft_return,NONE,0#1000
|
||||
bsort,bsort_main,bsort_Array,400,bsort_return,NONE,0#1000
|
||||
insertsort,insertsort_main,insertsort_a,400,insertsort_return,NONE,0#1000
|
||||
g723_enc,g723_enc_main,g723_enc_INPUT,1024,g723_enc_return,NONE,0#1000
|
||||
rijndael_dec,rijndael_dec_main,rijndael_dec_data,32768,rijndael_dec_return,NONE,0#1000
|
||||
rijndael_enc,rijndael_enc_main,rijndael_enc_data,31369,rijndael_enc_return,NONE,0#1000
|
||||
huff_dec,huff_dec_main,huff_dec_encoded,419,huff_dec_return,NONE,0#1000
|
||||
huff_enc,huff_enc_main,huff_enc_plaintext,600,huff_enc_return,NONE,0#1000
|
||||
gsm_enc,gsm_enc_main,gsm_enc_pcmdata,6400,gsm_enc_return,NONE,0#1000
|
||||
tmr,main,FUZZ_INPUT,32,trigger_Qemu_break,NONE,0#1000
|
||||
tacle_rtos,prvStage0,FUZZ_INPUT,604,trigger_Qemu_break,NONE,0#1000
|
||||
lift,main_lift,FUZZ_INPUT,100,trigger_Qemu_break,NONE,0#1000
|
||||
waters,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||
watersv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||
waterspart,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||
waterspartv2,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||
waters_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||
watersv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||
waterspart_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||
waterspartv2_int,main_waters,FUZZ_INPUT,4096,trigger_Qemu_break,1129,0#1000
|
||||
micro_branchless,main_branchless,FUZZ_INPUT,4,trigger_Qemu_break,NONE,0#1000
|
||||
micro_int,main_int,FUZZ_INPUT,16,trigger_Qemu_break,NONE,0#1000
|
||||
micro_longint,main_micro_longint,FUZZ_INPUT,16,trigger_Qemu_break,NONE,0#1000
|
||||
minimal,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,NONE,0#1000
|
||||
gen3,main_minimal,FUZZ_INPUT,4096,trigger_Qemu_break,NONE,0#1000
|
||||
interact,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,NONE,0#1000
|
||||
interact_int,main_interact,FUZZ_INPUT,4096,trigger_Qemu_break,NONE,0#1000
|
||||
release,main_release,FUZZ_INPUT,4096,trigger_Qemu_break,T3,0#10000;1#1000;2#2000;3#3000
|
||||
|
||||
|
|
@ -89,4 +89,27 @@ pub fn set_env_from_config(kernel : &PathBuf, path : &PathBuf) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_interrupt_config(kernel : &PathBuf, path : &PathBuf) -> Vec<(usize,u32)>{
|
||||
let is_csv = path.as_path().extension().map_or(false, |x| x=="csv");
|
||||
if !is_csv {
|
||||
panic!("Interrupt config must be inside a CSV file");
|
||||
} else {
|
||||
let mut reader = csv::Reader::from_path(path).expect("CSV read from config failed");
|
||||
let p = kernel.as_path();
|
||||
let stem = p.file_stem().expect("Kernel filename error").to_str().unwrap();
|
||||
for r in reader.records() {
|
||||
let rec = r.expect("CSV entry error");
|
||||
if stem == &rec[0] {
|
||||
let ret = rec[6].split(';').map(|x| {
|
||||
let pair = x.split_once('#').expect("Interrupt config error");
|
||||
(pair.0.parse().expect("Interrupt config error"), pair.1.parse().expect("Interrupt config error"))
|
||||
}).collect();
|
||||
println!("Interrupt config {:?}", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Vec::new();
|
||||
}
|
@ -21,7 +21,7 @@ use crate::{
|
||||
qemustate::QemuStateRestoreHelper
|
||||
},
|
||||
systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol, QemuSystemStateHelper}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}},
|
||||
systemstate::mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, MINIMUM_INTER_ARRIVAL_TIME},
|
||||
systemstate::mutational::{input_bytes_to_interrupt_times, InterruptShiftStage},
|
||||
};
|
||||
use std::time::SystemTime;
|
||||
use petgraph::dot::Dot;
|
||||
@ -164,6 +164,7 @@ log::set_max_level(log::LevelFilter::Info);
|
||||
SimpleStderrLogger::set_logger().unwrap();
|
||||
let cli = Cli::parse();
|
||||
set_env_from_config(&cli.kernel, &cli.config);
|
||||
let interrupt_config = crate::cli::get_interrupt_config(&cli.kernel, &cli.config);
|
||||
unsafe {FUZZ_START_TIMESTAMP = SystemTime::now();}
|
||||
if cli.dump_name.is_none() && (cli.dump_times || cli.dump_cases || cli.dump_traces || cli.dump_graph) {
|
||||
panic!("Dump name not give but dump is requested");
|
||||
@ -272,6 +273,18 @@ let api_ranges : Vec<_> = api_ranges.into_iter().collect();
|
||||
#[cfg(feature = "observe_systemstate")]
|
||||
let isr_ranges : Vec<_> = isr_ranges.into_iter().collect();
|
||||
|
||||
/// Setup the interrupt inputs. Noop if interrupts are not fuzzed
|
||||
fn setup_interrupt_inputs(mut input : MultipartInput<BytesInput>, interrupt_config : &Vec<(usize,u32)>) -> MultipartInput<BytesInput> {
|
||||
#[cfg(feature = "fuzz_int")]
|
||||
for (i,_) in interrupt_config {
|
||||
let name = format!("interrupts_{}",i);
|
||||
if input.parts_by_name(&name).next().is_none() {
|
||||
input.add_part(name, BytesInput::new([0; MAX_NUM_INTERRUPT*4].to_vec()));
|
||||
}
|
||||
}
|
||||
input
|
||||
}
|
||||
|
||||
// Client setup ================================================================================
|
||||
|
||||
let run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
@ -331,10 +344,14 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
unsafe {
|
||||
#[cfg(feature = "fuzz_int")]
|
||||
{
|
||||
let time_bytes = input.parts_by_name("interrupts").next().map(|x| x.1.bytes()).unwrap_or(&[0u8; MAX_NUM_INTERRUPT*4]);
|
||||
let t = input_bytes_to_interrupt_times(time_bytes);
|
||||
for i in 0..t.len() {libafl_interrupt_offsets[0][i]=t[i];}
|
||||
libafl_num_interrupts[0]=t.len();
|
||||
for &c in &interrupt_config {
|
||||
let (i,_) = c;
|
||||
let name = format!("interrupts_{}",i);
|
||||
let input_bytes = input.parts_by_name(&name).next().map(|x| x.1.bytes()).unwrap_or(&[0u8; MAX_NUM_INTERRUPT*4]);
|
||||
let t = input_bytes_to_interrupt_times(input_bytes, c);
|
||||
for j in 0..t.len() {libafl_interrupt_offsets[i][j]=t[j];}
|
||||
libafl_num_interrupts[i]=t.len();
|
||||
}
|
||||
|
||||
// println!("Load: {:?}", libafl_interrupt_offsets[0..libafl_num_interrupts].to_vec());
|
||||
}
|
||||
@ -502,7 +519,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
let stages = (systemstate::report::SchedulerStatsStage::default(),());
|
||||
let mut stages = (StdMutationalStage::new(mutator), stages);
|
||||
#[cfg(feature = "fuzz_int")]
|
||||
let mut stages = (InterruptShiftStage::new(), stages);
|
||||
let mut stages = (InterruptShiftStage::new(&interrupt_config), stages);
|
||||
|
||||
if let Commands::Showmap { input } = cli.command.clone() {
|
||||
let s = input.as_os_str();
|
||||
@ -519,7 +536,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
println!("Interpreting input file as raw input");
|
||||
MultipartInput::from([("interrupts",BytesInput::new([0; MAX_NUM_INTERRUPT].to_vec())),("bytes",BytesInput::new(input.as_os_str().as_encoded_bytes().to_vec()))])
|
||||
setup_interrupt_inputs(MultipartInput::from([("bytes",BytesInput::new(input.as_os_str().as_encoded_bytes().to_vec()))]), &interrupt_config)
|
||||
}
|
||||
};
|
||||
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, show_input)
|
||||
@ -533,7 +550,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
for _ in 0..100 {
|
||||
let inp1 = BytesInput::new(vec![rng.gen::<u8>(); MAX_NUM_INTERRUPT*4]);
|
||||
let inp2 = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
|
||||
let inp = MultipartInput::from([("interrupts",inp1),("bytes",inp2)]);
|
||||
let inp = setup_interrupt_inputs(MultipartInput::from([("bytes",inp2)]), &interrupt_config);
|
||||
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
|
||||
}
|
||||
}
|
||||
@ -576,7 +593,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
// libafl's generator is too slow
|
||||
let inp1 = BytesInput::new(vec![rng.gen::<u8>(); MAX_NUM_INTERRUPT*4]);
|
||||
let inp2 = BytesInput::new(vec![rng.gen::<u8>(); MAX_INPUT_SIZE]);
|
||||
let inp = MultipartInput::from([("interrupts",inp1),("bytes",inp2)]);
|
||||
let inp = setup_interrupt_inputs(MultipartInput::from([("bytes",inp2)]), &interrupt_config);
|
||||
fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, inp).unwrap();
|
||||
}
|
||||
}} else {
|
||||
|
@ -19,13 +19,13 @@ use std::borrow::Cow;
|
||||
|
||||
use super::stg::{STGEdge, STGNode};
|
||||
|
||||
pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC;
|
||||
// pub static mut MINIMUM_INTER_ARRIVAL_TIME : u32 = 1000 /*us*/ * QEMU_ISNS_PER_USEC;
|
||||
// one isn per 2**4 ns
|
||||
// virtual insn/sec 62500000 = 1/16 GHz
|
||||
// 1ms = 62500 insn
|
||||
// 1us = 62.5 insn
|
||||
|
||||
pub fn input_bytes_to_interrupt_times(buf: &[u8]) -> Vec<u32> {
|
||||
pub fn input_bytes_to_interrupt_times(buf: &[u8], config: (usize,u32)) -> Vec<u32> {
|
||||
let len = buf.len();
|
||||
let mut start_tick : u32 = 0;
|
||||
let mut ret = Vec::with_capacity(DO_NUM_INTERRUPT);
|
||||
@ -45,8 +45,8 @@ pub fn input_bytes_to_interrupt_times(buf: &[u8]) -> Vec<u32> {
|
||||
for i in 0..ret.len() {
|
||||
if ret[i]==0 {continue;}
|
||||
for j in i+1..ret.len()-1 {
|
||||
if ret[j]-ret[i] < unsafe{MINIMUM_INTER_ARRIVAL_TIME} {
|
||||
ret[j] = u32::saturating_add(ret[i],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||
if ret[j]-ret[i] < config.1 as u32 * QEMU_ISNS_PER_USEC {
|
||||
ret[j] = u32::saturating_add(ret[i],config.1 * QEMU_ISNS_PER_USEC);
|
||||
} else {break;}
|
||||
}
|
||||
}
|
||||
@ -70,11 +70,11 @@ fn is_candidate_for_new_branches(graph: &DiGraph<STGNode, STGEdge>, node: NodeIn
|
||||
|
||||
// TODO: this can be much more efficient, if the graph stored snapshots of the state and input progress was tracked
|
||||
/// Determines if a given node in the state transition graph (STG) is a candidate for introducing new branches.
|
||||
pub fn try_force_new_branches(interrupt_ticks : &[u32], fbs: &STGFeedbackState, meta: &STGNodeMetadata) -> Option<Vec<u32>> {
|
||||
pub fn try_force_new_branches(interrupt_ticks : &[u32], fbs: &STGFeedbackState, meta: &STGNodeMetadata, config: (usize, u32)) -> Option<Vec<u32>> {
|
||||
let mut new = false;
|
||||
let mut new_interrupt_times = Vec::new();
|
||||
for (num,&interrupt_time) in interrupt_ticks.iter().enumerate() {
|
||||
let lower_bound = if num==0 {FIRST_INT} else {interrupt_ticks[num-1].saturating_add(unsafe{MINIMUM_INTER_ARRIVAL_TIME})};
|
||||
let lower_bound = if num==0 {FIRST_INT} else {interrupt_ticks[num-1].saturating_add(config.1 * QEMU_ISNS_PER_USEC)};
|
||||
let next = if interrupt_ticks.len()>num {interrupt_ticks[num+1]} else {u32::MAX};
|
||||
for exec_interval in meta.intervals.iter().filter(|x| x.start_tick >= lower_bound as u64 && x.start_tick < next as u64) {
|
||||
if !(exec_interval.start_capture.0==CaptureEvent::ISRStart) { // shortcut to skip interrupt handers without node lookup
|
||||
@ -98,6 +98,7 @@ pub fn try_force_new_branches(interrupt_ticks : &[u32], fbs: &STGFeedbackState,
|
||||
pub struct InterruptShiftStage<E, EM, Z> {
|
||||
#[allow(clippy::type_complexity)]
|
||||
phantom: PhantomData<(E, EM, Z)>,
|
||||
interrup_config: Vec<(usize,u32)>
|
||||
}
|
||||
|
||||
impl<E, EM, Z> InterruptShiftStage<E, EM, Z>
|
||||
@ -107,8 +108,8 @@ where
|
||||
Z: Evaluator<E, EM>,
|
||||
Z::State: MaybeHasClientPerfMonitor + HasCorpus + HasRand,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self { phantom: PhantomData }
|
||||
pub fn new(config : &Vec<(usize,u32)>) -> Self {
|
||||
Self { phantom: PhantomData, interrup_config: config.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,20 +134,26 @@ where
|
||||
let mut myrand = StdRand::new();
|
||||
myrand.set_seed(state.rand_mut().next());
|
||||
|
||||
|
||||
let mut loopcount = 0;
|
||||
let mut loopbound = 50;
|
||||
loop {
|
||||
let interrup_config = match myrand.choose(&self.interrup_config) {
|
||||
Some(s) => s,
|
||||
Option::None => return Ok(())
|
||||
};
|
||||
let name = format!("interrupts_{}", interrup_config.0);
|
||||
// manager.log(state, LogSeverity::Info, format!("Mutation {}/{}", loopbound, loopcount))?;
|
||||
loopbound-=1;
|
||||
let current_case = state.current_testcase()?;
|
||||
let old_input = current_case.input().as_ref().unwrap();
|
||||
let old_interrupt_times = old_input.parts_by_name("interrupts").next();
|
||||
let old_interrupt_times = old_input.parts_by_name(&name).next();
|
||||
let mut new_input = old_input.clone();
|
||||
|
||||
let mut new_interrupt_times : &mut I = if new_input.parts_by_name("interrupts").next().is_some() {
|
||||
new_input.parts_by_name_mut("interrupts").next().unwrap()
|
||||
let mut new_interrupt_times : &mut I = if new_input.parts_by_name(&name).next().is_some() {
|
||||
new_input.parts_by_name_mut(&name).next().unwrap()
|
||||
} else {
|
||||
new_input.add_part(String::from("interrupts"), I::default()); new_input.parts_by_name_mut("interrupts").next().unwrap()
|
||||
new_input.add_part(String::from(&name), I::default()); new_input.parts_by_name_mut(&name).next().unwrap()
|
||||
}.1;
|
||||
let mut do_rerun = false;
|
||||
// if state.rand_mut().between(1, 100) <= 50 // only attempt the mutation half of the time
|
||||
@ -156,7 +163,7 @@ where
|
||||
let mut interrupt_offsets : [u32; MAX_NUM_INTERRUPT] = [u32::MAX; MAX_NUM_INTERRUPT];
|
||||
let mut num_interrupts : usize = 0;
|
||||
{
|
||||
let t = input_bytes_to_interrupt_times(new_interrupt_times.bytes());
|
||||
let t = input_bytes_to_interrupt_times(new_interrupt_times.bytes(), *interrup_config);
|
||||
for i in 0..t.len() {interrupt_offsets[i]=t[i];}
|
||||
num_interrupts=t.len();
|
||||
}
|
||||
@ -180,7 +187,7 @@ where
|
||||
let maxtick : u64 = hist.1.0;
|
||||
// let maxtick : u64 = (_input.exec_time().expect("No duration found").as_nanos() >> 4).try_into().unwrap();
|
||||
let mut numbers : Vec<u32> = vec![];
|
||||
for i in 0..myrand.between(0,2*min(MAX_NUM_INTERRUPT, maxtick as usize / unsafe{MINIMUM_INTER_ARRIVAL_TIME as usize})) {
|
||||
for i in 0..myrand.between(0,2*min(MAX_NUM_INTERRUPT, maxtick as usize / (interrup_config.1 as usize * QEMU_ISNS_PER_USEC as usize))) {
|
||||
prefix.push(u32::to_le_bytes(myrand.between(0, min(maxtick, u32::MAX as u64) as usize).try_into().expect("ticks > u32")));
|
||||
}
|
||||
}
|
||||
@ -194,7 +201,7 @@ where
|
||||
}
|
||||
};
|
||||
if let Some(meta) = current_case.metadata_map().get::<STGNodeMetadata>() {
|
||||
if let Some(t) = try_force_new_branches(&interrupt_offsets, feedbackstate, meta) {
|
||||
if let Some(t) = try_force_new_branches(&interrupt_offsets, feedbackstate, meta, *interrup_config) {
|
||||
do_rerun = true;
|
||||
for i in 0..t.len() {
|
||||
if i<num_interrupts {
|
||||
@ -280,10 +287,10 @@ where
|
||||
let mut lb = FIRST_INT;
|
||||
let mut ub : u32 = marks[marks.len()-1].0.end_tick.try_into().expect("ticks > u32");
|
||||
if i > 0 {
|
||||
lb = u32::saturating_add(interrupt_offsets[i-1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||
lb = u32::saturating_add(interrupt_offsets[i-1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||
}
|
||||
if i < num_interrupts-1 {
|
||||
ub = u32::saturating_sub(interrupt_offsets[i+1],unsafe{MINIMUM_INTER_ARRIVAL_TIME});
|
||||
ub = u32::saturating_sub(interrupt_offsets[i+1], interrup_config.1 * QEMU_ISNS_PER_USEC);
|
||||
}
|
||||
// get old hit and handler
|
||||
let old_hit = marks.iter().filter(
|
||||
|
Loading…
x
Reference in New Issue
Block a user