From 2673484d7703feef51a50a4acc67ae8fb0d917b8 Mon Sep 17 00:00:00 2001 From: rubberhead Date: Mon, 15 Jan 2024 23:43:17 +0000 Subject: [PATCH] Init module: flush_dcache --- src/aarch64-linux-flush-dcache/.vscode-ctags | 38 ++++++++ .../.vscode/c_cpp_properties.json | 44 +++++++++ .../.vscode/settings.json | 10 ++ src/aarch64-linux-flush-dcache/mod_entry.c | 97 +++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 src/aarch64-linux-flush-dcache/.vscode-ctags create mode 100644 src/aarch64-linux-flush-dcache/.vscode/c_cpp_properties.json create mode 100644 src/aarch64-linux-flush-dcache/.vscode/settings.json create mode 100644 src/aarch64-linux-flush-dcache/mod_entry.c diff --git a/src/aarch64-linux-flush-dcache/.vscode-ctags b/src/aarch64-linux-flush-dcache/.vscode-ctags new file mode 100644 index 0000000..b35e51f --- /dev/null +++ b/src/aarch64-linux-flush-dcache/.vscode-ctags @@ -0,0 +1,38 @@ +!_TAG_EXTRA_DESCRIPTION anonymous /Include tags for non-named objects like lambda/ +!_TAG_EXTRA_DESCRIPTION fileScope /Include tags of file scope/ +!_TAG_EXTRA_DESCRIPTION pseudo /Include pseudo tags/ +!_TAG_EXTRA_DESCRIPTION subparser /Include tags generated by subparsers/ +!_TAG_FIELD_DESCRIPTION epoch /the last modified time of the input file (only for F\/file kind tag)/ +!_TAG_FIELD_DESCRIPTION file /File-restricted scoping/ +!_TAG_FIELD_DESCRIPTION input /input file/ +!_TAG_FIELD_DESCRIPTION name /tag name/ +!_TAG_FIELD_DESCRIPTION pattern /pattern/ +!_TAG_FIELD_DESCRIPTION typeref /Type and name of a variable or typedef/ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_KIND_DESCRIPTION!C d,macro /macro definitions/ +!_TAG_KIND_DESCRIPTION!C e,enumerator /enumerators (values inside an enumeration)/ +!_TAG_KIND_DESCRIPTION!C f,function /function definitions/ +!_TAG_KIND_DESCRIPTION!C g,enum /enumeration names/ +!_TAG_KIND_DESCRIPTION!C h,header /included header files/ +!_TAG_KIND_DESCRIPTION!C m,member /struct, and union members/ +!_TAG_KIND_DESCRIPTION!C s,struct /structure names/ +!_TAG_KIND_DESCRIPTION!C t,typedef /typedefs/ +!_TAG_KIND_DESCRIPTION!C u,union /union names/ +!_TAG_KIND_DESCRIPTION!C v,variable /variable definitions/ +!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ +!_TAG_OUTPUT_FILESEP slash /slash or backslash/ +!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ +!_TAG_OUTPUT_VERSION 0.0 /current.age/ +!_TAG_PARSER_VERSION!C 1.1 /current.age/ +!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/ +!_TAG_PROC_CWD /home/rubberhead/Git/00-UOE/unnamed_ba_thesis/src/aarch64-linux-flush-dcache/ // +!_TAG_PROGRAM_AUTHOR Universal Ctags Team // +!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/ +!_TAG_PROGRAM_URL https://ctags.io/ /official site/ +!_TAG_PROGRAM_VERSION 6.1.0 /v6.1.0/ +!_TAG_ROLE_DESCRIPTION!C!function foreigndecl /declared in foreign languages/ +!_TAG_ROLE_DESCRIPTION!C!header local /local header/ +!_TAG_ROLE_DESCRIPTION!C!header system /system header/ +!_TAG_ROLE_DESCRIPTION!C!macro undef /undefined/ +!_TAG_ROLE_DESCRIPTION!C!struct foreigndecl /declared in foreign languages/ diff --git a/src/aarch64-linux-flush-dcache/.vscode/c_cpp_properties.json b/src/aarch64-linux-flush-dcache/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..3690212 --- /dev/null +++ b/src/aarch64-linux-flush-dcache/.vscode/c_cpp_properties.json @@ -0,0 +1,44 @@ +{ + "configurations": [ + { + "name": "Linux-clang-arm64", + "includePath": [ + "${workspaceFolder}/**", + "/home/rubberhead/Git/linux/include", + "/home/rubberhead/Git/linux/include/uapi", + "/home/rubberhead/Git/linux/include/generated", + "/home/rubberhead/Git/linux/arch/arm64/include", + "/home/rubberhead/Git/linux/arch/arm64/include/uapi", + "/home/rubberhead/Git/linux/arch/arm64/include/generated", + "/usr/lib/gcc/aarch64-linux-gnu/13.2.0/include" + ], + "defines": [ + "__GNUC__", + "__KERNEL__" + ], + "compilerPath": "/usr/bin/clang", + "compilerArgs": [ + "-nostdinc", + "-std=gnu11" + ], + "cStandard": "gnu11", + "cppStandard": "${default}", + "browse": { + "path": [ + "${workspaceFolder}", + "/home/rubberhead/Git/linux/include", + "/home/rubberhead/Git/linux/include/uapi", + "/home/rubberhead/Git/linux/include/generated", + "/home/rubberhead/Git/linux/arch/arm64/include", + "/home/rubberhead/Git/linux/arch/arm64/include/uapi", + "/home/rubberhead/Git/linux/arch/arm64/include/generated", + "/usr/lib/gcc/aarch64-linux-gnu/13.2.0/include" + ], + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "" + }, + "intelliSenseMode": "linux-clang-arm64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/src/aarch64-linux-flush-dcache/.vscode/settings.json b/src/aarch64-linux-flush-dcache/.vscode/settings.json new file mode 100644 index 0000000..e29650f --- /dev/null +++ b/src/aarch64-linux-flush-dcache/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "C_Cpp.errorSquiggles": "enabled", + "files.associations": { + "*.h": "c", + }, + "editor.insertSpaces": false, + "editor.indentSize": "tabSize", + "editor.tabSize": 8, + "clangd.arguments": ["--compile-commands-dir=/home/rubberhead/Git/linux"] +} \ No newline at end of file diff --git a/src/aarch64-linux-flush-dcache/mod_entry.c b/src/aarch64-linux-flush-dcache/mod_entry.c new file mode 100644 index 0000000..df19ab3 --- /dev/null +++ b/src/aarch64-linux-flush-dcache/mod_entry.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* PID: The task for which page cache is to be flushed. */ +static int param_pid; +module_param_named(pid, param_pid, int, 0644); + +/* addr: The virtual memory address used to index into the page to be flushed. */ +static unsigned long param_vmaddr; +module_param_named(addr, param_vmaddr, ulong, 0644); + +static int __init flush_dcache_init(void) +{ + struct task_struct *tsk; + struct mm_struct *mm_of_tsk; + struct page *page_of_addr; + + // Get task_struct from PID, then get its mm_struct + rcu_read_lock(); + tsk = find_task_by_pid_ns(param_pid, &init_pid_ns); + if (!tsk) { + rcu_read_unlock(); + goto ret_err_no_tsk; + } + mm_of_tsk = get_task_mm(tsk); + rcu_read_unlock(); + + // No mm_struct -- may be kthread? + if (!mm_of_tsk) + goto ret_warn_kthread; + + /* Get page from mm_struct -- + * We need to pin the page i.e., have it marked as FOLL_PIN. + * Ref. Documentation/core-api/pin_user_pages.rst: + * Because we are writing to the data represented by the page -- we are + * flushing cache to dirty page, after all -- we need FOLL_PIN instead + * of *get-API. This effectively? prevents page from being evicted in + * the short term. + */ + mmap_read_lock(mm_of_tsk); + long pin_pages_retval = pin_user_pages_remote( + mm_of_tsk, param_vmaddr, 1, + FOLL_WRITE, &page_of_addr, NULL + ); // We know mmap is locked, stop asking. + if (pin_pages_retval != 1) { + mmap_read_unlock(mm_of_tsk); + goto ret_err_no_page; + } + + // Begin test. We ABSOLUTELY cannot be interrupted here... + unsigned long _eflags; + local_irq_save(_eflags); + // [TODO]: Use non-temporal instr to write directly to memory. + // This will most certainly require asm blocks... + // ...Or else, simulate a cache-incoherent DMA? + // e.g., run in qemu -> attach gdb on vmlinux -> breakpoint -> + // gdb examines physical mem -> gdb makes a silly write -> + // continue, check here. + // ...Or else, pgprot_noncached + pr_info("Before flush: cache line/memory diff: "); + flush_dcache_page(page_of_addr); + pr_info("After flush: ..."); + mmap_read_unlock(mm_of_tsk); + local_irq_restore(_eflags); + + unpin_user_pages(&page_of_addr, 1); + return 0; + +ret_warn_kthread: + pr_warn("[%s] Cannot find `tsk->mm` for PID %d. This may be a kthread.\n" + "Messing with `active_mm` may be unsafe. Exiting...", + __func__, param_pid); + return 0; +ret_err_no_tsk: + pr_err("[%s] Cannot find `task_struct` for PID %d.", + __func__, param_pid); + return -EINVAL; +ret_err_no_page: + pr_err("[%s] Cannot pin requested pages. [TODO]", __func__); + return pin_pages_retval == 0 ? -EINVAL : (int)pin_pages_retval; +} + +static void __exit flush_dcache_exit(void) +{ + pr_info("[%s] See ya~", __func__); +} + +module_init(flush_dcache_init); +module_exit(flush_dcache_exit); + +MODULE_LICENSE("GPL"); \ No newline at end of file