Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry pick changes from main to release/0.20 #4067

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions include/bpf_helper_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,3 +473,25 @@ EBPF_HELPER(size_t, bpf_strnlen_s, (const char* str, size_t str_size));
#define memcpy_s bpf_memcpy
#define memmove_s bpf_memmove
#endif

/**
* @brief Return time elapsed since boot in milliseconds including time while suspended.
* This function uses a lower resolution clock source than bpf_ktime_get_boot_ns, but is faster.
*
* @return Time elapsed since boot in milliseconds.
*/
EBPF_HELPER(uint64_t, bpf_ktime_get_boot_ms, ());
#ifndef __doxygen
#define bpf_ktime_get_boot_ms ((bpf_ktime_get_boot_ms_t)BPF_FUNC_ktime_get_boot_ms)
#endif

/**
* @brief Return time elapsed since boot in milliseconds excluding time while suspended.
* This function uses a lower resolution clock source than bpf_ktime_get_ns, but is faster.
*
* @return Time elapsed since boot in milliseconds.
*/
EBPF_HELPER(uint64_t, bpf_ktime_get_ms, ());
#ifndef __doxygen
#define bpf_ktime_get_ms ((bpf_ktime_get_ms_t)BPF_FUNC_ktime_get_ms)
#endif
2 changes: 2 additions & 0 deletions include/ebpf_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ typedef enum
BPF_FUNC_strncpy_s = 27, ///< \ref bpf_strncpy_s
BPF_FUNC_strncat_s = 28, ///< \ref bpf_strncat_s
BPF_FUNC_strnlen_s = 29, ///< \ref bpf_strnlen_s
BPF_FUNC_ktime_get_boot_ms = 30, ///< \ref bpf_ktime_get_boot_ms
BPF_FUNC_ktime_get_ms = 31, ///< \ref bpf_ktime_get_ms
} ebpf_helper_id_t;

// Cross-platform BPF program types.
Expand Down
32 changes: 28 additions & 4 deletions libs/execution_context/ebpf_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ _ebpf_core_memmove(
_In_reads_(source_length) const void* source,
size_t source_length);

static uint64_t
_ebpf_core_get_time_since_boot_ms();

static uint64_t
_ebpf_core_get_time_ms();

#define EBPF_CORE_GLOBAL_HELPER_EXTENSION_VERSION 0

static ebpf_program_type_descriptor_t _ebpf_global_helper_program_descriptor = {
Expand Down Expand Up @@ -144,6 +150,8 @@ static const void* _ebpf_general_helpers[] = {
(void*)&_ebpf_core_strncpy_s,
(void*)&_ebpf_core_strncat_s,
(void*)&_ebpf_core_strlen_s,
(void*)&_ebpf_core_get_time_since_boot_ms,
(void*)&_ebpf_core_get_time_ms,
};

static const ebpf_helper_function_addresses_t _ebpf_global_helper_function_dispatch_table = {
Expand Down Expand Up @@ -2257,17 +2265,33 @@ _ebpf_core_random_uint32()
static uint64_t
_ebpf_core_get_time_since_boot_ns()
{
// ebpf_query_time_since_boot_precise returns time elapsed since
// cxplat_query_time_since_boot_precise returns time elapsed since
// boot in units of 100 ns.
return ebpf_query_time_since_boot_precise(true) * EBPF_NS_PER_FILETIME;
return cxplat_query_time_since_boot_precise(true) * EBPF_NS_PER_FILETIME;
}

static uint64_t
_ebpf_core_get_time_ns()
{
// ebpf_query_time_since_boot_precise returns time elapsed since
// cxplat_query_time_since_boot_precise returns time elapsed since
// boot in units of 100 ns.
return cxplat_query_time_since_boot_precise(false) * EBPF_NS_PER_FILETIME;
}

static uint64_t
_ebpf_core_get_time_since_boot_ms()
{
// cxplat_query_time_since_boot_approximate returns time elapsed since
// boot in units of 100 ns.
return cxplat_query_time_since_boot_approximate(true) / EBPF_FILETIME_PER_MS;
}

static uint64_t
_ebpf_core_get_time_ms()
{
// cxplat_query_time_since_boot_approximate returns time elapsed since
// boot in units of 100 ns.
return ebpf_query_time_since_boot_precise(false) * EBPF_NS_PER_FILETIME;
return cxplat_query_time_since_boot_approximate(false) / EBPF_FILETIME_PER_MS;
}

static uint64_t
Expand Down
6 changes: 6 additions & 0 deletions libs/execution_context/ebpf_general_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ ebpf_helper_function_prototype_t ebpf_core_helper_function_prototype_array[] = {
EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM,
EBPF_ARGUMENT_TYPE_CONST_SIZE_OR_ZERO,
}},
{EBPF_HELPER_FUNCTION_PROTOTYPE_HEADER,
BPF_FUNC_ktime_get_boot_ms,
"bpf_ktime_get_boot_ms",
EBPF_RETURN_TYPE_INTEGER,
{0}},
{EBPF_HELPER_FUNCTION_PROTOTYPE_HEADER, BPF_FUNC_ktime_get_ms, "bpf_ktime_get_ms", EBPF_RETURN_TYPE_INTEGER, {0}},
};

#ifdef __cplusplus
Expand Down
6 changes: 3 additions & 3 deletions libs/execution_context/ebpf_maps.c
Original file line number Diff line number Diff line change
Expand Up @@ -1224,15 +1224,15 @@ _insert_into_hot_list(_Inout_ ebpf_core_lru_map_t* map, size_t partition, _Inout
switch (key_state) {
case EBPF_LRU_KEY_UNINITIALIZED:
EBPF_LRU_ENTRY_GENERATION_PTR(map, entry)[partition] = map->partitions[partition].current_generation;
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = ebpf_query_time_since_boot_approximate(false);
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = cxplat_query_time_since_boot_approximate(false);
ebpf_list_insert_tail(
&map->partitions[partition].hot_list, &EBPF_LRU_ENTRY_LIST_ENTRY_PTR(map, entry)[partition]);
map->partitions[partition].hot_list_size++;
break;
case EBPF_LRU_KEY_COLD:
// Remove from cold list.
EBPF_LRU_ENTRY_GENERATION_PTR(map, entry)[partition] = map->partitions[partition].current_generation;
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = ebpf_query_time_since_boot_approximate(false);
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = cxplat_query_time_since_boot_approximate(false);
ebpf_list_remove_entry(&EBPF_LRU_ENTRY_LIST_ENTRY_PTR(map, entry)[partition]);
ebpf_list_insert_tail(
&map->partitions[partition].hot_list, &EBPF_LRU_ENTRY_LIST_ENTRY_PTR(map, entry)[partition]);
Expand Down Expand Up @@ -1271,7 +1271,7 @@ _initialize_lru_entry(
// Only insert into the current partition's hot list.
ebpf_lock_state_t state = ebpf_lock_lock(&map->partitions[partition].lock);
EBPF_LRU_ENTRY_GENERATION_PTR(map, entry)[partition] = map->partitions[partition].current_generation;
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = ebpf_query_time_since_boot_approximate(false);
EBPF_LRU_ENTRY_LAST_USED_TIME_PTR(map, entry)[partition] = cxplat_query_time_since_boot_approximate(false);
ebpf_list_insert_tail(&map->partitions[partition].hot_list, &EBPF_LRU_ENTRY_LIST_ENTRY_PTR(map, entry)[partition]);
map->partitions[partition].hot_list_size++;

Expand Down
8 changes: 4 additions & 4 deletions libs/execution_context/ebpf_program.c
Original file line number Diff line number Diff line change
Expand Up @@ -2454,7 +2454,7 @@ _ebpf_program_test_run_work_item(_In_ cxplat_preemptible_work_item_t* work_item,
state_stored = true;
}

uint64_t start_time = ebpf_query_time_since_boot_precise(false);
uint64_t start_time = cxplat_query_time_since_boot_precise(false);
// Use a counter instead of performing a modulus operation to determine when to start a new epoch.
// This is because the modulus operation is expensive and we want to minimize the overhead of
// the test run.
Expand All @@ -2467,7 +2467,7 @@ _ebpf_program_test_run_work_item(_In_ cxplat_preemptible_work_item_t* work_item,
ebpf_epoch_exit(&epoch_state);
if (ebpf_should_yield_processor()) {
// Compute the elapsed time since the last yield.
end_time = ebpf_query_time_since_boot_precise(false);
end_time = cxplat_query_time_since_boot_precise(false);

// Add the elapsed time to the cumulative time.
cumulative_time += end_time - start_time;
Expand All @@ -2479,7 +2479,7 @@ _ebpf_program_test_run_work_item(_In_ cxplat_preemptible_work_item_t* work_item,
old_irql = ebpf_raise_irql(context->required_irql);

// Reset the start time.
start_time = ebpf_query_time_since_boot_precise(false);
start_time = cxplat_query_time_since_boot_precise(false);
}
ebpf_epoch_enter(&epoch_state);
}
Expand All @@ -2489,7 +2489,7 @@ _ebpf_program_test_run_work_item(_In_ cxplat_preemptible_work_item_t* work_item,
break;
}
}
end_time = ebpf_query_time_since_boot_precise(false);
end_time = cxplat_query_time_since_boot_precise(false);

cumulative_time += end_time - start_time;

Expand Down
28 changes: 0 additions & 28 deletions libs/runtime/ebpf_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,34 +222,6 @@ ebpf_allocate_process_state()
return state;
}

uint64_t
ebpf_query_time_since_boot_precise(bool include_suspended_time)
{
uint64_t qpc_time;
if (include_suspended_time) {
// KeQueryUnbiasedInterruptTimePrecise returns the current interrupt-time count in 100-nanosecond units.
// Unbiased Interrupt time is the total time since boot including time spent suspended.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-kequeryunbiasedinterrupttimeprecise
return KeQueryUnbiasedInterruptTimePrecise(&qpc_time);
} else {
// KeQueryInterruptTimePrecise returns the current interrupt-time count in 100-nanosecond units.
// (Biased) Interrupt time is the total time since boot excluding time spent suspended. //
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-kequeryinterrupttimeprecise
return KeQueryInterruptTimePrecise(&qpc_time);
}
}

uint64_t
ebpf_query_time_since_boot_approximate(bool include_suspend_time)
{
if (include_suspend_time) {
ebpf_assert(!"Include suspend time not supported on this platform.");
return 0;
} else {
return KeQueryInterruptTime();
}
}

MDL*
ebpf_map_memory(size_t length)
{
Expand Down
24 changes: 1 addition & 23 deletions libs/runtime/ebpf_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ extern "C"
}

#define EBPF_NS_PER_FILETIME 100
#define EBPF_FILETIME_PER_MS 10000

typedef enum _ebpf_code_integrity_state
{
Expand Down Expand Up @@ -632,29 +633,6 @@ extern "C"
ebpf_validate_security_descriptor(
_In_ const ebpf_security_descriptor_t* security_descriptor, size_t security_descriptor_length);

/**
* @brief Return time elapsed since boot in units of 100 nanoseconds.
*
* @param[in] include_suspended_time Include time the system spent in a suspended state.
* @return Time elapsed since boot in 100 nanosecond units.
*/
EBPF_INLINE_HINT
uint64_t
ebpf_query_time_since_boot_precise(bool include_suspended_time);

/**
* @brief Return time elapsed since boot in units of 100 nanoseconds.
* This function is faster than ebpf_query_time_since_boot_precise() but may not
* be as accurate.
*
* @param[in] include_suspended_time Include time the system spent in a suspended state.
*
* @return Time elapsed since boot in 100 nanosecond units.
*/
EBPF_INLINE_HINT
uint64_t
ebpf_query_time_since_boot_approximate(bool include_suspended_time);

/**
* @brief Affinitize the current thread to a specific CPU by index and return the old affinity.
*
Expand Down
Loading
Loading