Refactor to start integrating frequency measurement and portability
- added preliminary tests of frequency measurements - refactored the signature of calibrate function to parametrize hash function - various cleanup
This commit is contained in:
parent
b7e8aff723
commit
fb926dfe2a
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -33,6 +33,7 @@ name = "cache_utils"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"polling_serial 0.1.0",
|
"polling_serial 0.1.0",
|
||||||
"static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -88,7 +89,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.68"
|
version = "0.2.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -115,7 +116,7 @@ dependencies = [
|
|||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -190,7 +191,7 @@ dependencies = [
|
|||||||
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
||||||
"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
||||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
"checksum libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
|
"checksum libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
|
||||||
"checksum linked_list_allocator 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5825aea823c659d0fdcdbe8c9b78baf56f3a10365d783db874f6d360df72626f"
|
"checksum linked_list_allocator 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5825aea823c659d0fdcdbe8c9b78baf56f3a10365d783db874f6d360df72626f"
|
||||||
"checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b"
|
"checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b"
|
||||||
"checksum nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
|
"checksum nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
|
||||||
|
@ -14,10 +14,10 @@ static_assertions = "1.1.0"
|
|||||||
itertools = { version = "0.9.0", default-features = false }
|
itertools = { version = "0.9.0", default-features = false }
|
||||||
|
|
||||||
nix = { version = "0.17.0", optional = true }
|
nix = { version = "0.17.0", optional = true }
|
||||||
|
libc = { version = "0.2.69", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
std = ["nix", "itertools/use_std"]
|
std = ["nix", "itertools/use_std", "libc"]
|
||||||
no_std = ["polling_serial", "vga_buffer"]
|
no_std = ["polling_serial", "vga_buffer"]
|
||||||
|
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
|
64
cache_utils/src/bin/frequency_test.rs
Normal file
64
cache_utils/src/bin/frequency_test.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use cache_utils::frequency::get_freq_cpufreq_kernel;
|
||||||
|
use cache_utils::rdtsc_fence;
|
||||||
|
use libc::sched_getcpu;
|
||||||
|
use nix::sched::{sched_setaffinity, CpuSet};
|
||||||
|
use nix::unistd::Pid;
|
||||||
|
use static_assertions::_core::time::Duration;
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
const NUM_SAMPLE: i32 = 1000000;
|
||||||
|
const NUM_SAMPLE_SLEEP: i32 = 10000;
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut core = CpuSet::new();
|
||||||
|
core.set(unsafe { sched_getcpu() } as usize).unwrap();
|
||||||
|
|
||||||
|
sched_setaffinity(Pid::from_raw(0), &core);
|
||||||
|
let t0_pre = unsafe { rdtsc_fence() };
|
||||||
|
let start = Instant::now();
|
||||||
|
let t0_post = unsafe { rdtsc_fence() };
|
||||||
|
|
||||||
|
let mut tsc = t0_post;
|
||||||
|
|
||||||
|
println!("TSC,Freq");
|
||||||
|
for i in 0..NUM_SAMPLE {
|
||||||
|
//let t1 = unsafe { rdtsc_fence() };
|
||||||
|
let frequency = get_freq_cpufreq_kernel();
|
||||||
|
let t2 = unsafe { rdtsc_fence() };
|
||||||
|
let delta = t2 - tsc;
|
||||||
|
tsc = t2;
|
||||||
|
if let Ok(freq) = frequency {
|
||||||
|
println!("{},{}", delta, freq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Idling");
|
||||||
|
for i in 0..NUM_SAMPLE_SLEEP {
|
||||||
|
sleep(Duration::from_micros(1000));
|
||||||
|
let frequency = get_freq_cpufreq_kernel();
|
||||||
|
let t2 = unsafe { rdtsc_fence() };
|
||||||
|
let delta = t2 - tsc;
|
||||||
|
tsc = t2;
|
||||||
|
if let Ok(freq) = frequency {
|
||||||
|
println!("{},{}", delta, freq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tf_pre = unsafe { rdtsc_fence() };
|
||||||
|
let elapsed = start.elapsed();
|
||||||
|
let tf_post = unsafe { rdtsc_fence() };
|
||||||
|
println!(
|
||||||
|
"Time elapsed: {} us, number of tsc tick: {} - {} - {}",
|
||||||
|
elapsed.as_micros(),
|
||||||
|
tf_pre - t0_pre,
|
||||||
|
(tf_pre - t0_pre + tf_post - t0_post) / 2,
|
||||||
|
tf_post - t0_post
|
||||||
|
);
|
||||||
|
eprintln!(
|
||||||
|
"Time elapsed: {} us, number of tsc tick: {} - {} - {}",
|
||||||
|
elapsed.as_micros(),
|
||||||
|
tf_pre - t0_pre,
|
||||||
|
(tf_pre - t0_pre + tf_post - t0_post) / 2,
|
||||||
|
tf_post - t0_post
|
||||||
|
);
|
||||||
|
}
|
@ -14,6 +14,12 @@ pub enum Verbosity {
|
|||||||
Debug,
|
Debug,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct HistParams {
|
||||||
|
iterations: u32,
|
||||||
|
bucket_size: usize,
|
||||||
|
bucket_number: usize,
|
||||||
|
}
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use crate::calibration::Verbosity::*;
|
use crate::calibration::Verbosity::*;
|
||||||
use crate::complex_addressing::AddressHasher;
|
use crate::complex_addressing::AddressHasher;
|
||||||
@ -165,7 +171,7 @@ pub fn calibrate_flush(
|
|||||||
panic!("not aligned nicely");
|
panic!("not aligned nicely");
|
||||||
}
|
}
|
||||||
|
|
||||||
calibrate_impl(
|
calibrate_impl_fixed_freq(
|
||||||
pointer,
|
pointer,
|
||||||
cache_line_size,
|
cache_line_size,
|
||||||
array.len() as isize,
|
array.len() as isize,
|
||||||
@ -181,10 +187,13 @@ pub fn calibrate_flush(
|
|||||||
display_name: "clflush miss",
|
display_name: "clflush miss",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
CFLUSH_BUCKET_NUMBER,
|
HistParams {
|
||||||
CFLUSH_BUCKET_SIZE,
|
bucket_number: CFLUSH_BUCKET_NUMBER,
|
||||||
CFLUSH_NUM_ITER,
|
bucket_size: CFLUSH_BUCKET_SIZE,
|
||||||
|
iterations: CFLUSH_NUM_ITER,
|
||||||
|
},
|
||||||
verbose_level,
|
verbose_level,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,39 +222,41 @@ pub unsafe fn calibrate(
|
|||||||
num_iterations: u32,
|
num_iterations: u32,
|
||||||
verbosity_level: Verbosity,
|
verbosity_level: Verbosity,
|
||||||
) -> Vec<CalibrateResult> {
|
) -> Vec<CalibrateResult> {
|
||||||
calibrate_impl(
|
calibrate_impl_fixed_freq(
|
||||||
p,
|
p,
|
||||||
increment,
|
increment,
|
||||||
len,
|
len,
|
||||||
operations,
|
operations,
|
||||||
buckets_num,
|
HistParams {
|
||||||
|
bucket_number: buckets_num,
|
||||||
bucket_size,
|
bucket_size,
|
||||||
num_iterations,
|
iterations: num_iterations,
|
||||||
|
},
|
||||||
verbosity_level,
|
verbosity_level,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const SPURIOUS_THRESHOLD: u32 = 1;
|
const SPURIOUS_THRESHOLD: u32 = 1;
|
||||||
fn calibrate_impl(
|
fn calibrate_impl_fixed_freq(
|
||||||
p: *const u8,
|
p: *const u8,
|
||||||
increment: usize,
|
increment: usize,
|
||||||
len: isize,
|
len: isize,
|
||||||
operations: &[CalibrateOperation],
|
operations: &[CalibrateOperation],
|
||||||
buckets_num: usize,
|
hist_params: HistParams,
|
||||||
bucket_size: usize,
|
|
||||||
num_iterations: u32,
|
|
||||||
verbosity_level: Verbosity,
|
verbosity_level: Verbosity,
|
||||||
|
hasher: Option<&AddressHasher>,
|
||||||
) -> Vec<CalibrateResult> {
|
) -> Vec<CalibrateResult> {
|
||||||
// TODO : adapt this to detect CPU generation and grab the correct masks.
|
// TODO : adapt this to detect CPU generation and grab the correct masks.
|
||||||
// These are the skylake masks.
|
// These are the skylake masks.
|
||||||
let masks: [usize; 3] = [
|
/*let masks: [usize; 3] = [
|
||||||
0b1111_0011_0011_0011_0010_0100_1100_0100_000000,
|
0b1111_0011_0011_0011_0010_0100_1100_0100_000000,
|
||||||
0b1011_1010_1101_0111_1110_1010_1010_0010_000000,
|
0b1011_1010_1101_0111_1110_1010_1010_0010_000000,
|
||||||
0b0110_1101_0111_1101_0101_1101_0101_0001_000000,
|
0b0110_1101_0111_1101_0101_1101_0101_0001_000000,
|
||||||
];
|
];
|
||||||
|
|
||||||
let hasher = AddressHasher::new(&masks);
|
let hasher = AddressHasher::new(&masks);
|
||||||
|
*/
|
||||||
if verbosity_level >= Thresholds {
|
if verbosity_level >= Thresholds {
|
||||||
println!(
|
println!(
|
||||||
"Calibrating {}...",
|
"Calibrating {}...",
|
||||||
@ -256,12 +267,16 @@ fn calibrate_impl(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let to_bucket = |time: u64| -> usize { time as usize / bucket_size };
|
let to_bucket = |time: u64| -> usize { time as usize / hist_params.bucket_size };
|
||||||
let from_bucket = |bucket: usize| -> u64 { (bucket * bucket_size) as u64 };
|
let from_bucket = |bucket: usize| -> u64 { (bucket * hist_params.bucket_size) as u64 };
|
||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
if verbosity_level >= Thresholds {
|
if verbosity_level >= Thresholds {
|
||||||
|
print!("CSV: address, ");
|
||||||
|
if hasher.is_some() {
|
||||||
|
print!("hash, ");
|
||||||
|
}
|
||||||
println!(
|
println!(
|
||||||
"CSV: address, hash, {} min, {} median, {} max",
|
"{} min, {} median, {} max",
|
||||||
operations
|
operations
|
||||||
.iter()
|
.iter()
|
||||||
.map(|operation| operation.name)
|
.map(|operation| operation.name)
|
||||||
@ -277,8 +292,12 @@ fn calibrate_impl(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if verbosity_level >= RawResult {
|
if verbosity_level >= RawResult {
|
||||||
|
print!("RESULT:address,");
|
||||||
|
if hasher.is_some() {
|
||||||
|
print!("hash,");
|
||||||
|
}
|
||||||
println!(
|
println!(
|
||||||
"RESULT:address,hash,time,{}",
|
"time,{}",
|
||||||
operations
|
operations
|
||||||
.iter()
|
.iter()
|
||||||
.map(|operation| operation.name)
|
.map(|operation| operation.name)
|
||||||
@ -288,10 +307,14 @@ fn calibrate_impl(
|
|||||||
|
|
||||||
for i in (0..len).step_by(increment) {
|
for i in (0..len).step_by(increment) {
|
||||||
let pointer = unsafe { p.offset(i) };
|
let pointer = unsafe { p.offset(i) };
|
||||||
let hash = hasher.hash(pointer as usize);
|
let hash = hasher.map(|h| h.hash(pointer as usize));
|
||||||
|
|
||||||
if verbosity_level >= Thresholds {
|
if verbosity_level >= Thresholds {
|
||||||
println!("Calibration for {:p} (hash: {:x})", pointer, hash);
|
print!("Calibration for {:p}", pointer);
|
||||||
|
if let Some(h) = hash {
|
||||||
|
print!(" (hash: {:x})", h)
|
||||||
|
}
|
||||||
|
println!();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO add some useful impl to CalibrateResults
|
// TODO add some useful impl to CalibrateResults
|
||||||
@ -305,10 +328,10 @@ fn calibrate_impl(
|
|||||||
calibrate_result.histogram.reserve(operations.len());
|
calibrate_result.histogram.reserve(operations.len());
|
||||||
|
|
||||||
for op in operations {
|
for op in operations {
|
||||||
let mut hist = vec![0; buckets_num];
|
let mut hist = vec![0; hist_params.bucket_number];
|
||||||
for _ in 0..num_iterations {
|
for _ in 0..hist_params.iterations {
|
||||||
let time = unsafe { (op.op)(pointer) };
|
let time = unsafe { (op.op)(pointer) };
|
||||||
let bucket = min(buckets_num - 1, to_bucket(time));
|
let bucket = min(hist_params.bucket_number - 1, to_bucket(time));
|
||||||
hist[bucket] += 1;
|
hist[bucket] += 1;
|
||||||
}
|
}
|
||||||
calibrate_result.histogram.push(hist);
|
calibrate_result.histogram.push(hist);
|
||||||
@ -319,12 +342,16 @@ fn calibrate_impl(
|
|||||||
let median_thresholds: Vec<u32> = calibrate_result
|
let median_thresholds: Vec<u32> = calibrate_result
|
||||||
.histogram
|
.histogram
|
||||||
.iter()
|
.iter()
|
||||||
.map(|h| (num_iterations - h[buckets_num - 1]) / 2)
|
.map(|h| (hist_params.iterations - h[hist_params.bucket_number - 1]) / 2)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
for j in 0..buckets_num - 1 {
|
for j in 0..hist_params.bucket_number - 1 {
|
||||||
if verbosity_level >= RawResult {
|
if verbosity_level >= RawResult {
|
||||||
print!("RESULT:{:p},{:x},{}", pointer, hash, from_bucket(j));
|
print!("RESULT:{:p},", pointer);
|
||||||
|
if let Some(h) = hash {
|
||||||
|
print!("{:x},", h);
|
||||||
|
}
|
||||||
|
print!("{}", from_bucket(j));
|
||||||
}
|
}
|
||||||
// ignore the last bucket : spurious context switches etc.
|
// ignore the last bucket : spurious context switches etc.
|
||||||
for op in 0..operations.len() {
|
for op in 0..operations.len() {
|
||||||
@ -367,10 +394,12 @@ fn calibrate_impl(
|
|||||||
calibrate_result.max[j]
|
calibrate_result.max[j]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
print!("CSV: {:p}, ", pointer);
|
||||||
|
if let Some(h) = hash {
|
||||||
|
print!("{:x}, ", h)
|
||||||
|
}
|
||||||
println!(
|
println!(
|
||||||
"CSV: {:p}, {:x}, {}, {}, {}",
|
"{}, {}, {}",
|
||||||
pointer,
|
|
||||||
hash,
|
|
||||||
calibrate_result.min.iter().format(", "),
|
calibrate_result.min.iter().format(", "),
|
||||||
calibrate_result.median.iter().format(", "),
|
calibrate_result.median.iter().format(", "),
|
||||||
calibrate_result.max.iter().format(", ")
|
calibrate_result.max.iter().format(", ")
|
||||||
@ -392,7 +421,7 @@ pub fn calibrate_L3_miss_hit(
|
|||||||
}
|
}
|
||||||
let pointer = (&array[0]) as *const u8;
|
let pointer = (&array[0]) as *const u8;
|
||||||
|
|
||||||
let r = calibrate_impl(
|
let r = calibrate_impl_fixed_freq(
|
||||||
pointer,
|
pointer,
|
||||||
cache_line_size,
|
cache_line_size,
|
||||||
array.len() as isize,
|
array.len() as isize,
|
||||||
@ -401,10 +430,13 @@ pub fn calibrate_L3_miss_hit(
|
|||||||
name: "l3_hit",
|
name: "l3_hit",
|
||||||
display_name: "L3 hit",
|
display_name: "L3 hit",
|
||||||
}],
|
}],
|
||||||
512,
|
HistParams {
|
||||||
2,
|
bucket_number: 512,
|
||||||
1 << 11,
|
bucket_size: 2,
|
||||||
|
iterations: 1 << 11,
|
||||||
|
},
|
||||||
verbose_level,
|
verbose_level,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
r.into_iter().next().unwrap()
|
r.into_iter().next().unwrap()
|
||||||
|
67
cache_utils/src/frequency.rs
Normal file
67
cache_utils/src/frequency.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
use crate::frequency::Error::{Unimplemented, UnsupportedPlatform};
|
||||||
|
|
||||||
|
use crate::rdtsc_fence;
|
||||||
|
#[cfg(all(target_os = "linux", feature = "std"))]
|
||||||
|
use libc::sched_getcpu;
|
||||||
|
#[cfg(all(target_os = "linux", feature = "std"))]
|
||||||
|
use std::convert::TryInto;
|
||||||
|
#[cfg(all(target_os = "linux", feature = "std"))]
|
||||||
|
use std::os::raw::{c_uint, c_ulong};
|
||||||
|
|
||||||
|
pub enum Error {
|
||||||
|
InsufficentPrivileges,
|
||||||
|
UnsupportedPlatform,
|
||||||
|
Unimplemented,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(target_os = "linux", feature = "std"))]
|
||||||
|
#[link(name = "cpupower")]
|
||||||
|
extern "C" {
|
||||||
|
//unsigned long cpufreq_get_freq_kernel(unsigned int cpu);
|
||||||
|
fn cpufreq_get_freq_kernel(cpu: c_uint) -> c_ulong;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_freq_cpufreq_kernel() -> Result<u64, Error> {
|
||||||
|
// TODO Add memorization
|
||||||
|
return match unsafe { sched_getcpu() }.try_into() {
|
||||||
|
Ok(cpu) => Ok(unsafe { cpufreq_get_freq_kernel(cpu) }),
|
||||||
|
Err(e) => Err(Unimplemented),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_frequency() -> Result<u64, Error> {
|
||||||
|
if cfg!(target_os = "linux") && cfg!(feature = "std") {
|
||||||
|
return get_freq_cpufreq_kernel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg!(target_os = "none") {
|
||||||
|
// TODO check CPL
|
||||||
|
// if sufficient privileges use rdmsr
|
||||||
|
// Otherwise return insufficent privileges
|
||||||
|
return Err(Unimplemented);
|
||||||
|
}
|
||||||
|
Err(UnsupportedPlatform)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_frequency_change_period(period: u64) -> Result<u64, Error> {
|
||||||
|
let mut t: u64 = 0;
|
||||||
|
let mut freq: u64 = 0;
|
||||||
|
let mut last_freq_change: u64 = 0;
|
||||||
|
for _ in 0..period {
|
||||||
|
let f = get_frequency();
|
||||||
|
let time = unsafe { rdtsc_fence() };
|
||||||
|
match f {
|
||||||
|
Ok(f) => {
|
||||||
|
if f != freq {
|
||||||
|
t += time - last_freq_change;
|
||||||
|
last_freq_change = time;
|
||||||
|
freq = f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(t / period);
|
||||||
|
}
|
@ -19,6 +19,8 @@ pub mod complex_addressing;
|
|||||||
pub mod mmap;
|
pub mod mmap;
|
||||||
pub mod prefetcher;
|
pub mod prefetcher;
|
||||||
|
|
||||||
|
pub mod frequency;
|
||||||
|
|
||||||
use core::arch::x86_64 as arch_x86;
|
use core::arch::x86_64 as arch_x86;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ use core::panic::PanicInfo;
|
|||||||
use polling_serial::{serial_print, serial_println};
|
use polling_serial::{serial_print, serial_println};
|
||||||
use vga_buffer::println;
|
use vga_buffer::println;
|
||||||
|
|
||||||
|
|
||||||
use bootloader::{entry_point, BootInfo};
|
use bootloader::{entry_point, BootInfo};
|
||||||
|
|
||||||
entry_point!(test_kernel_main);
|
entry_point!(test_kernel_main);
|
||||||
|
@ -27,5 +27,4 @@ fn should_fail() {
|
|||||||
fn panic(_info: &PanicInfo) -> ! {
|
fn panic(_info: &PanicInfo) -> ! {
|
||||||
serial_println!("[ok]");
|
serial_println!("[ok]");
|
||||||
exit_qemu(QemuExitCode::Success);
|
exit_qemu(QemuExitCode::Success);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use polling_serial::{serial_print, serial_println};
|
use polling_serial::{serial_print, serial_println};
|
||||||
use vga_buffer::{println};
|
use vga_buffer::println;
|
||||||
use volatile::Volatile;
|
use volatile::Volatile;
|
||||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user