+++ /dev/null
-From eb65003ff273a7b0488f534ebe184d3bf9f076c0 Mon Sep 17 00:00:00 2001
-From: Tamas K Lengyel <tamas.lengyel@intel.com>
-Date: Fri, 2 Feb 2024 08:27:44 -0500
-Subject: [PATCH] TSFFS
-
----
- xen/arch/x86/domctl.c | 3 +
- xen/arch/x86/hvm/hypercall.c | 48 +++++++++++--
- xen/arch/x86/hvm/vmx/vmx.c | 2 +
- xen/common/ubsan/ubsan.c | 3 +
- xen/drivers/char/console.c | 5 ++
- xen/include/xen/kfx.h | 32 +++++++++
- xen/include/xen/sched.h | 4 ++
- xen/include/xen/tsffs.h | 131 +++++++++++++++++++++++++++++++++++
- 8 files changed, 223 insertions(+), 5 deletions(-)
- create mode 100644 xen/include/xen/kfx.h
- create mode 100644 xen/include/xen/tsffs.h
-
-diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
-index 9a72d57333..8b97186331 100644
---- a/xen/arch/x86/domctl.c
-+++ b/xen/arch/x86/domctl.c
-@@ -21,6 +21,9 @@
- #include <xen/iocap.h>
- #include <xen/paging.h>
-
-+#include <xen/tsffs.h>
-+#include <xen/kfx.h>
-+
- #include <asm/gdbsx.h>
- #include <asm/irq.h>
- #include <asm/hvm/emulate.h>
-diff --git a/xen/arch/x86/hvm/hypercall.c b/xen/arch/x86/hvm/hypercall.c
-index eeb73e1aa5..cdf6a9d61f 100644
---- a/xen/arch/x86/hvm/hypercall.c
-+++ b/xen/arch/x86/hvm/hypercall.c
-@@ -11,6 +11,8 @@
- #include <xen/ioreq.h>
- #include <xen/nospec.h>
-
-+#include <xen/tsffs.h>
-+
- #include <asm/hvm/emulate.h>
- #include <asm/hvm/support.h>
- #include <asm/hvm/viridian.h>
-@@ -104,8 +106,40 @@ int hvm_hypercall(struct cpu_user_regs *regs)
- struct vcpu *curr = current;
- struct domain *currd = curr->domain;
- int mode = hvm_guest_x86_mode(curr);
-- unsigned long eax = regs->eax;
-+ unsigned long eax;
- unsigned int token;
-+ int ret;
-+
-+ struct cpu_user_regs fme = *regs;
-+ size_t _size = sizeof(struct cpu_user_regs);
-+ HARNESS_START(&fme, &_size);
-+
-+ regs->r8 = fme.r8;
-+ regs->r9 = fme.r9;
-+ regs->r10 = fme.r10;
-+ regs->r11 = fme.r11;
-+ regs->r12 = fme.r12;
-+ regs->r13 = fme.r13;
-+ regs->r14 = fme.r14;
-+ regs->r15 = fme.r15;
-+ regs->rax = fme.rax;
-+ regs->rbx = fme.rbx;
-+ regs->rcx = fme.rcx;
-+ regs->rdx = fme.rdx;
-+ regs->rsi = fme.rsi;
-+ regs->rdi = fme.rdi;
-+ regs->rip = fme.rip;
-+ regs->rsp = fme.rsp;
-+ regs->rbp = fme.rbp;
-+ regs->rflags = fme.rflags;
-+ regs->cs = fme.cs;
-+ regs->ss = fme.ss;
-+ regs->es = fme.es;
-+ regs->ds = fme.ds;
-+ regs->fs = fme.fs;
-+ regs->gs = fme.gs;
-+
-+ eax = regs->eax;
-
- switch ( mode )
- {
-@@ -123,7 +157,8 @@ int hvm_hypercall(struct cpu_user_regs *regs)
- {
- default:
- regs->rax = -EPERM;
-- return HVM_HCALL_completed;
-+ ret = HVM_HCALL_completed;
-+ goto out;
- }
- case 0:
- break;
-@@ -131,8 +166,6 @@ int hvm_hypercall(struct cpu_user_regs *regs)
-
- if ( (eax & 0x80000000U) && is_viridian_domain(currd) )
- {
-- int ret;
--
- /* See comment below. */
- token = hvmemul_cache_disable(curr);
-
-@@ -140,7 +173,7 @@ int hvm_hypercall(struct cpu_user_regs *regs)
-
- hvmemul_cache_restore(curr, token);
-
-- return ret;
-+ goto out;
- }
-
- /*
-@@ -188,7 +221,12 @@ int hvm_hypercall(struct cpu_user_regs *regs)
-
- perfc_incra(hypercalls, eax);
-
-+ HARNESS_STOP();
- return curr->hcall_preempted ? HVM_HCALL_preempted : HVM_HCALL_completed;
-+
-+ out:
-+ HARNESS_STOP();
-+ return ret;
- }
-
- enum mc_disposition hvm_do_multicall_call(struct mc_state *state)
-diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
-index 1500dca603..9e1230ee45 100644
---- a/xen/arch/x86/hvm/vmx/vmx.c
-+++ b/xen/arch/x86/hvm/vmx/vmx.c
-@@ -4780,6 +4780,8 @@ bool asmlinkage vmx_vmenter_helper(const struct cpu_user_regs *regs)
- struct hvm_vcpu_asid *p_asid;
- bool need_flush;
-
-+ HARNESS_STOP();
-+
- ASSERT(hvmemul_cache_disabled(curr));
-
- /* Shadow EPTP can't be updated here because irqs are disabled */
-diff --git a/xen/common/ubsan/ubsan.c b/xen/common/ubsan/ubsan.c
-index 5d50c10742..6f734aa473 100644
---- a/xen/common/ubsan/ubsan.c
-+++ b/xen/common/ubsan/ubsan.c
-@@ -13,6 +13,9 @@
- #include <xen/spinlock.h>
- #include <xen/percpu.h>
-
-+#include <xen/tsffs.h>
-+#include <xen/kfx.h>
-+
- #define __noreturn noreturn
- #define pr_err(...) printk(XENLOG_ERR __VA_ARGS__)
- struct xen_ubsan { int in_ubsan; };
-diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
-index dce0226e87..d7a2751bcd 100644
---- a/xen/drivers/char/console.c
-+++ b/xen/drivers/char/console.c
-@@ -33,6 +33,9 @@
- #include <xen/pv_console.h>
- #include <asm/setup.h>
-
-+#include <xen/tsffs.h>
-+#include <xen/kfx.h>
-+
- #ifdef CONFIG_X86
- #include <xen/consoled.h>
- #include <asm/guest.h>
-@@ -1269,6 +1272,8 @@ void panic(const char *fmt, ...)
- static DEFINE_SPINLOCK(lock);
- static char buf[128];
-
-+ HARNESS_ASSERT();
-+
- spin_debug_disable();
- spinlock_profile_printall('\0');
- debugtrace_dump();
-diff --git a/xen/include/xen/kfx.h b/xen/include/xen/kfx.h
-new file mode 100644
-index 0000000000..afde305796
---- /dev/null
-+++ b/xen/include/xen/kfx.h
-@@ -0,0 +1,32 @@
-+#ifndef KFX_H
-+#define KFX_H
-+
-+static inline void harness_extended(unsigned int magic, void *a, size_t s)
-+{
-+ asm volatile ("cpuid"
-+ : "=a" (magic), "=c" (magic), "=S" (magic)
-+ : "a" (magic), "c" (s), "S" (a)
-+ : "bx", "dx");
-+}
-+
-+static inline void harness(void)
-+{
-+ unsigned int tmp;
-+
-+ asm volatile ("cpuid"
-+ : "=a" (tmp)
-+ : "a" (0x13371337)
-+ : "bx", "cx", "dx");
-+}
-+
-+static inline void kfx_sink(void)
-+{
-+ unsigned int tmp;
-+
-+ asm volatile ("int3"
-+ : "=a" (tmp)
-+ : "a" (0x13371337)
-+ : "bx", "cx", "dx");
-+}
-+
-+#endif
-diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
-index 9da91e0e62..8f04f6110f 100644
---- a/xen/include/xen/sched.h
-+++ b/xen/include/xen/sched.h
-@@ -24,6 +24,7 @@
- #include <asm/current.h>
- #include <xen/vpci.h>
- #include <xen/wait.h>
-+#include <xen/tsffs.h>
- #include <public/xen.h>
- #include <public/domctl.h>
- #include <public/sysctl.h>
-@@ -792,6 +793,9 @@ void vcpu_end_shutdown_deferral(struct vcpu *v);
- void __domain_crash(struct domain *d);
- #define domain_crash(d, ...) \
- do { \
-+ HARNESS_STOP(); \
-+ __arch_harness_stop(MAGIC_ALT_0); \
-+ __arch_harness_stop(MAGIC_ALT_1); \
- if ( count_args(__VA_ARGS__) == 0 ) \
- printk(XENLOG_ERR "domain_crash called from %s:%d\n", \
- __FILE__, __LINE__); \
-diff --git a/xen/include/xen/tsffs.h b/xen/include/xen/tsffs.h
-new file mode 100644
-index 0000000000..c2afe7ace3
---- /dev/null
-+++ b/xen/include/xen/tsffs.h
-@@ -0,0 +1,131 @@
-+/// Definitions and macros for compiled-in harnessing of C and C++ target
-+/// software for the RISC-V (64-bit) architecture
-+///
-+/// Example:
-+/// ```c
-+/// #include "tsffs-gcc-x86_64.h"
-+///
-+/// int main() {
-+/// char buf[0x10];
-+/// size_t size = 0x10;
-+/// size_t *size_ptr = &size;
-+/// HARNESS_START((char *)buf, size_ptr);
-+/// int retval = YourSpecialDecoder(buf, *size_ptr);
-+/// if (!retval) {
-+/// HARNESS_ASSERT();
-+/// } else {
-+/// HARNESS_STOP();
-+/// }
-+/// }
-+/// ```
-+
-+#ifndef TSFFS_H
-+#define TSFFS_H
-+
-+/// Define common with LibFuzzer and other fuzzers to allow code that is
-+/// fuzzing-specific to be left in the codebase. See
-+/// https://llvm.org/docs/LibFuzzer.html#id35 for more information
-+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-+#define FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION (1)
-+#endif // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-+
-+/// Magic value defined by SIMICS as the "leaf" value of a CPUID instruction
-+/// that is treated as a magic instruction.
-+#define MAGIC (0x4711U)
-+/// Default magic instruction `n` value to signal the TSFFS fuzzer to start the
-+/// fuzzing loop
-+#define MAGIC_START (0x0001U)
-+/// Default magic instruction `n` value to signal the TSFFS fuzzer to stop and
-+/// reset the fuzzing loop
-+#define MAGIC_STOP (0x0002U)
-+/// Default magic instruction `n` value to signal the TSFFS fuzzer that an error
-+/// has occurred and the testcase input should be saved as a solution
-+#define MAGIC_ASSERT (0x0003U)
-+
-+/// Alternative magic numbers that can be used for start and stop events in
-+/// conjunction with setting the magic number for each event via the SIMICS or
-+/// SIMICS Python script interface
-+#define MAGIC_ALT_0 (0x0004U)
-+#define MAGIC_ALT_1 (0x0005U)
-+#define MAGIC_ALT_2 (0x0006U)
-+#define MAGIC_ALT_3 (0x0007U)
-+#define MAGIC_ALT_4 (0x0008U)
-+#define MAGIC_ALT_5 (0x0009U)
-+#define MAGIC_ALT_6 (0x000aU)
-+#define MAGIC_ALT_7 (0x000bU)
-+
-+/// Invoke the magic instruction defined by SIMICS for the x86-64 architecture
-+/// (`cpuid`) with a specific value of `n`, after setting register `rdi` to the
-+/// value of the pointer to the testcase and register `rsi` to the value of the
-+/// pointer to the testcase size. These registers are accessed by the fuzzer and
-+/// are defined per-architecture.
-+#define __cpuid_extended2(value, inout_ptr_0, inout_ptr_1) \
-+ unsigned int _a __attribute__((unused)) = 0; \
-+ __asm__ __volatile__("cpuid" \
-+ : "=a"(_a) \
-+ : "a"(value), "D"(inout_ptr_0), "S"(inout_ptr_1) \
-+ : "rbx", "rcx", "rdx");
-+
-+/// Invoke the magic instruction defined by SIMICS for the x86-64 architecture
-+/// (`cpuid`) with a specific value of `n`
-+#define __cpuid(value) \
-+ unsigned int _a __attribute__((unused)) = 0; \
-+ __asm__ __volatile__("cpuid\n\t" \
-+ : "=a"(_a) \
-+ : "a"(value) \
-+ : "rbx", "rcx", "rdx")
-+
-+/// Signal the fuzzer using a specific magic value `start` to start the fuzzing
-+/// loop at the point this macro is called. A snapshot will be taken when the
-+/// macro is called, and the maximum testcase size `*size_ptr` will be saved as
-+/// `max_testcase_size`. Each iteration of the fuzzing loop, the fuzzer input
-+/// (the "testcase") will be written to `*testcase_ptr` as if running
-+/// `memcpy(testcase_ptr, current_testcase, max_testcase_size)`, and the actual
-+/// size of the current testcase will be written to
-+/// `*size_ptr` as if running `*size_ptr = current_testcase_size`.
-+#define __arch_harness_start(start, testcase_ptr, size_ptr) \
-+ do { \
-+ unsigned int magic = (start << 0x10U) | MAGIC; \
-+ __cpuid_extended2(magic, testcase_ptr, size_ptr); \
-+ } while (0)
-+
-+/// Signal the fuzzer using the a specific magic value (`stop`) to stop and
-+/// reset to the beginning of the fuzzing loop with a "normal" stop status,
-+/// indicating no solution has occurred.
-+#define __arch_harness_stop(stop) \
-+ do { \
-+ unsigned int magic = (stop << 0x10U) | MAGIC; \
-+ __cpuid(magic); \
-+ } while (0)
-+
-+/// Signal the fuzzer using the default magic value to start the fuzzing loop at
-+/// the point this macro is called. A snapshot will be taken when the macro is
-+/// called, and the maximum testcase size `*size_ptr` will be saved as
-+/// `max_testcase_size`. Each iteration of the fuzzing loop, the fuzzer input
-+/// (the "testcase") will be written to
-+/// `*testcase_ptr` as if running `memcpy(testcase_ptr, current_testcase,
-+/// max_testcase_size)`, and the actual size of the current testcase will be
-+/// written to
-+/// `*size_ptr` as if running `*size_ptr = current_testcase_size`.
-+#define HARNESS_START(testcase_ptr, size_ptr) \
-+ do { \
-+ __arch_harness_start(MAGIC_START, testcase_ptr, size_ptr); \
-+ } while (0)
-+
-+/// Signal the fuzzer using the default magic value to stop and reset to the
-+/// beginning of the fuzzing loop with a "normal" stop status, indicating no
-+/// solution has occurred.
-+#define HARNESS_STOP() \
-+ do { \
-+ __arch_harness_stop(MAGIC_STOP); \
-+ } while (0)
-+
-+/// Signal the fuzzer using the default magic value to stop and reset to the
-+/// beginning of the fuzzing loop with a "solution" stop status, indicating some
-+/// custom error has occurred.
-+#define HARNESS_ASSERT() \
-+ do { \
-+ __arch_harness_stop(MAGIC_ASSERT); \
-+ } while (0)
-+
-+#endif // TSFFS_H
-\ No newline at end of file
---
-2.34.1
-
+// Copyright (C) 2024 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+
/// Definitions and macros for compiled-in harnessing of C and C++ target
-/// software for the RISC-V (64-bit) architecture
-///
-/// Example:
-/// ```c
-/// #include "tsffs-gcc-x86_64.h"
-///
-/// int main() {
-/// char buf[0x10];
-/// size_t size = 0x10;
-/// size_t *size_ptr = &size;
-/// HARNESS_START((char *)buf, size_ptr);
-/// int retval = YourSpecialDecoder(buf, *size_ptr);
-/// if (!retval) {
-/// HARNESS_ASSERT();
-/// } else {
-/// HARNESS_STOP();
-/// }
-/// }
-/// ```
+/// software for the x86_64 architecture.
#ifndef TSFFS_H
#define TSFFS_H
#define FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION (1)
#endif // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+/// __cpuid
+///
+/// Invoke the CPUID instruction with a specific value `value` in register
+/// `rax`.
+///
+/// # Arguments
+///
+/// - `value`: The value to load into the `rax` register before invoking the
+/// CPUID instruction
+#define __cpuid(value) \
+ unsigned int _a __attribute__((unused)) = 0; \
+ unsigned int _b __attribute__((unused)) = 0; \
+ unsigned int _c __attribute__((unused)) = 0; \
+ unsigned int _d __attribute__((unused)) = 0; \
+ __asm__ __volatile__("cpuid\n\t" \
+ : "=a"(_a), "=b"(_b), "=c"(_c), "=d"(_d) \
+ : "a"(value));
+
+/// __cpuid_extended1
+///
+/// Invoke the CPUID instruction with a specific value `value` in register
+/// `rax` and a pseudo-argument in register `rdi`.
+///
+/// # Arguments
+///
+/// - `value`: The value to load into the `rax` register before invoking the
+/// CPUID instruction
+/// - `arg0`: The value to load into the `rdi` register before invoking the
+/// CPUID instruction
+#define __cpuid_extended1(value, arg0) \
+ unsigned int _a __attribute__((unused)) = 0; \
+ unsigned int _b __attribute__((unused)) = 0; \
+ unsigned int _c __attribute__((unused)) = 0; \
+ unsigned int _d __attribute__((unused)) = 0; \
+ __asm__ __volatile__("cpuid\n\t" \
+ : "=a"(_a), "=b"(_b), "=c"(_c), "=d"(_d) \
+ : "a"(value), "D"(arg0));
+
+/// __cpuid_extended2
+///
+/// Invoke the CPUID instruction with a specific value `value` in register
+/// `rax` and a pseudo-arguments in registers `rdi` and `rsi`.
+///
+/// # Arguments
+///
+/// - `value`: The value to load into the `rax` register before invoking the
+/// CPUID instruction
+/// - `arg0`: The value to load into the `rdi` register before invoking the
+/// CPUID instruction
+/// - `arg1`: The value to load into the `rsi` register before invoking the
+/// CPUID instruction
+#define __cpuid_extended2(value, arg0, arg1) \
+ unsigned int _a __attribute__((unused)) = 0; \
+ unsigned int _b __attribute__((unused)) = 0; \
+ unsigned int _c __attribute__((unused)) = 0; \
+ unsigned int _d __attribute__((unused)) = 0; \
+ __asm__ __volatile__("cpuid\n\t" \
+ : "=a"(_a), "=b"(_b), "=c"(_c), "=d"(_d) \
+ : "a"(value), "D"(arg0), "S"(arg1));
+
+/// __cpuid_extended3
+///
+/// Invoke the CPUID instruction with a specific value `value` in register
+/// `rax` and a pseudo-arguments in registers `rdi`, `rsi`, and `rdx`.
+///
+/// # Arguments
+///
+/// - `value`: The value to load into the `rax` register before invoking the
+/// CPUID instruction
+/// - `arg0`: The value to load into the `rdi` register before invoking the
+/// CPUID instruction
+/// - `arg1`: The value to load into the `rsi` register before invoking the
+/// CPUID instruction
+/// - `arg2`: The value to load into the `rdx` register before invoking the
+/// CPUID instruction
+#define __cpuid_extended3(value, arg0, arg1, arg2) \
+ unsigned int _a __attribute__((unused)) = 0; \
+ unsigned int _b __attribute__((unused)) = 0; \
+ unsigned int _c __attribute__((unused)) = 0; \
+ unsigned int _d __attribute__((unused)) = 0; \
+ __asm__ __volatile__("cpuid\n\t" \
+ : "=a"(_a), "=b"(_b), "=c"(_c), "=d"(_d) \
+ : "a"(value), "D"(arg0), "S"(arg1), "d"(arg2));
+
+/// __cpuid_extended4
+///
+/// Invoke the CPUID instruction with a specific value `value` in register
+/// `rax` and a pseudo-arguments in registers `rdi`, `rsi`, `rdx`, and `rcx`.
+///
+/// # Arguments
+///
+/// - `value`: The value to load into the `rax` register before invoking the
+/// CPUID instruction
+/// - `arg0`: The value to load into the `rdi` register before invoking the
+/// CPUID instruction
+/// - `arg1`: The value to load into the `rsi` register before invoking the
+/// CPUID instruction
+/// - `arg2`: The value to load into the `rdx` register before invoking the
+/// CPUID instruction
+/// - `arg3`: The value to load into the `rcx` register before invoking the
+/// CPUID instruction
+#define __cpuid_extended4(value, arg0, arg1, arg2, arg3) \
+ unsigned int _a __attribute__((unused)) = 0; \
+ unsigned int _b __attribute__((unused)) = 0; \
+ unsigned int _c __attribute__((unused)) = 0; \
+ unsigned int _d __attribute__((unused)) = 0; \
+ __asm__ __volatile__("cpuid\n\t" \
+ : "=a"(_a), "=b"(_b), "=c"(_c), "=d"(_d) \
+ : "a"(value), "D"(arg0), "S"(arg1), "d"(arg2), \
+ "c"(arg3));
+
/// Magic value defined by SIMICS as the "leaf" value of a CPUID instruction
/// that is treated as a magic instruction.
#define MAGIC (0x4711U)
-/// Default magic instruction `n` value to signal the TSFFS fuzzer to start the
-/// fuzzing loop
-#define MAGIC_START (0x0001U)
-/// Default magic instruction `n` value to signal the TSFFS fuzzer to stop and
-/// reset the fuzzing loop
-#define MAGIC_STOP (0x0002U)
-/// Default magic instruction `n` value to signal the TSFFS fuzzer that an error
-/// has occurred and the testcase input should be saved as a solution
-#define MAGIC_ASSERT (0x0003U)
-
-/// Alternative magic numbers that can be used for start and stop events in
-/// conjunction with setting the magic number for each event via the SIMICS or
-/// SIMICS Python script interface
-#define MAGIC_ALT_0 (0x0004U)
-#define MAGIC_ALT_1 (0x0005U)
-#define MAGIC_ALT_2 (0x0006U)
-#define MAGIC_ALT_3 (0x0007U)
-#define MAGIC_ALT_4 (0x0008U)
-#define MAGIC_ALT_5 (0x0009U)
-#define MAGIC_ALT_6 (0x000aU)
-#define MAGIC_ALT_7 (0x000bU)
-
-/// Invoke the magic instruction defined by SIMICS for the x86-64 architecture
-/// (`cpuid`) with a specific value of `n`, after setting register `rdi` to the
-/// value of the pointer to the testcase and register `rsi` to the value of the
-/// pointer to the testcase size. These registers are accessed by the fuzzer and
-/// are defined per-architecture.
-#define __cpuid_extended2(value, inout_ptr_0, inout_ptr_1) \
- unsigned int _a __attribute__((unused)) = 0; \
- __asm__ __volatile__("cpuid" \
- : "=a"(_a) \
- : "a"(value), "D"(inout_ptr_0), "S"(inout_ptr_1) \
- : "rbx", "rcx", "rdx");
-
-/// Invoke the magic instruction defined by SIMICS for the x86-64 architecture
-/// (`cpuid`) with a specific value of `n`
-#define __cpuid(value) \
- unsigned int _a __attribute__((unused)) = 0; \
- __asm__ __volatile__("cpuid\n\t" \
- : "=a"(_a) \
- : "a"(value) \
- : "rbx", "rcx", "rdx")
-
-/// Signal the fuzzer using a specific magic value `start` to start the fuzzing
-/// loop at the point this macro is called. A snapshot will be taken when the
-/// macro is called, and the maximum testcase size `*size_ptr` will be saved as
-/// `max_testcase_size`. Each iteration of the fuzzing loop, the fuzzer input
-/// (the "testcase") will be written to `*testcase_ptr` as if running
-/// `memcpy(testcase_ptr, current_testcase, max_testcase_size)`, and the actual
-/// size of the current testcase will be written to
-/// `*size_ptr` as if running `*size_ptr = current_testcase_size`.
-#define __arch_harness_start(start, testcase_ptr, size_ptr) \
- do { \
- unsigned int magic = (start << 0x10U) | MAGIC; \
- __cpuid_extended2(magic, testcase_ptr, size_ptr); \
- } while (0)
-
-/// Signal the fuzzer using the a specific magic value (`stop`) to stop and
-/// reset to the beginning of the fuzzing loop with a "normal" stop status,
-/// indicating no solution has occurred.
-#define __arch_harness_stop(stop) \
- do { \
- unsigned int magic = (stop << 0x10U) | MAGIC; \
- __cpuid(magic); \
- } while (0)
-
-/// Signal the fuzzer using the default magic value to start the fuzzing loop at
-/// the point this macro is called. A snapshot will be taken when the macro is
-/// called, and the maximum testcase size `*size_ptr` will be saved as
-/// `max_testcase_size`. Each iteration of the fuzzing loop, the fuzzer input
-/// (the "testcase") will be written to
-/// `*testcase_ptr` as if running `memcpy(testcase_ptr, current_testcase,
-/// max_testcase_size)`, and the actual size of the current testcase will be
-/// written to
-/// `*size_ptr` as if running `*size_ptr = current_testcase_size`.
-#define HARNESS_START(testcase_ptr, size_ptr) \
- do { \
- __arch_harness_start(MAGIC_START, testcase_ptr, size_ptr); \
- } while (0)
-
-/// Signal the fuzzer using the default magic value to stop and reset to the
-/// beginning of the fuzzing loop with a "normal" stop status, indicating no
-/// solution has occurred.
-#define HARNESS_STOP() \
- do { \
- __arch_harness_stop(MAGIC_STOP); \
- } while (0)
-
-/// Signal the fuzzer using the default magic value to stop and reset to the
-/// beginning of the fuzzing loop with a "solution" stop status, indicating some
-/// custom error has occurred.
-#define HARNESS_ASSERT() \
- do { \
- __arch_harness_stop(MAGIC_ASSERT); \
- } while (0)
+
+/// The default index number used for magic instructions. All magic instructions
+/// support multiple start and stop indices, which defaults to 0 if not
+/// specified.
+#define DEFAULT_INDEX (0x0000U)
+
+/// Pseudo-hypercall number to signal the fuzzer to use the first argument to
+/// the magic instruction as the pointer to the testcase buffer and the second
+/// argument as a pointer to the size of the testcase buffer.
+#define N_START_BUFFER_PTR_SIZE_PTR (0x0001U)
+
+/// HARNESS_START
+///
+/// Signal the fuzzer to start the fuzzing loop at the point this macro is
+/// called. The default "index" of 0 will be used. If you need multiple start
+/// harnesses compiled into the same binary, you can use the
+/// `HARNESS_START_INDEX` macro to specify different indices, then enable them
+/// at runtime by configuring the fuzzer.
+///
+/// When this macro is called:
+///
+/// - A snapshot will be taken and saved
+/// - The buffer pointed to by `buffer` will be saved and used as the testcase
+/// buffer. Each
+/// fuzzing iteration, a new test case will be written to this buffer.
+/// - The size of the buffer pointed to by `size_ptr` will be saved as the
+/// maximum testcase size. Each fuzzing iteration, the actual size of the
+/// current testcase will be written to `*size_ptr`.
+///
+/// # Arguments
+///
+/// - `buffer`: The pointer to the testcase buffer
+/// - `size_ptr`: The pointer to the size of the testcase buffer
+///
+/// # Example
+///
+/// ```
+/// unsigned char buffer[1024];
+/// size_t size;
+/// HARNESS_START(buffer, &size);
+/// ```
+#define HARNESS_START(buffer, size_ptr) \
+ do { \
+ unsigned int value = (N_START_BUFFER_PTR_SIZE_PTR << 0x10U) | MAGIC; \
+ __cpuid_extended3(value, DEFAULT_INDEX, buffer, size_ptr); \
+ } while (0);
+
+/// HARNESS_START_INDEX
+///
+/// Signal the fuzzer to start the fuzzing loop at the point this macro is
+/// called. The index specified by `start_index` will be used. If you need
+/// multiple start harnesses compiled into the same binary, you can use this
+/// macro to specify different indices, then enable them at runtime by
+/// configuring the fuzzer.
+///
+/// When this macro is called:
+///
+/// - A snapshot will be taken and saved
+/// - The buffer pointed to by `buffer` will be saved and used as the testcase
+/// buffer. Each
+/// fuzzing iteration, a new test case will be written to this buffer.
+/// - The size of the buffer pointed to by `size_ptr` will be saved as the
+/// maximum testcase size. Each fuzzing iteration, the actual size of the
+/// current testcase will be written to `*size_ptr`.
+///
+/// # Arguments
+///
+/// - `start_index`: The index to use for this start harness
+/// - `buffer`: The pointer to the testcase buffer
+/// - `size_ptr`: The pointer to the size of the testcase buffer
+///
+/// # Example
+///
+/// ```
+/// unsigned char buffer[1024];
+/// size_t size;
+/// HARNESS_START_INDEX(0x0001U, buffer, &size);
+/// ```
+#define HARNESS_START_INDEX(start_index, buffer, size_ptr) \
+ do { \
+ unsigned int value = (N_START_BUFFER_PTR_SIZE_PTR << 0x10U) | MAGIC; \
+ __cpuid_extended3(value, start_index, buffer, size_ptr); \
+ } while (0);
+
+/// Pseudo-hypercall number to signal the fuzzer to use the first argument to
+/// the magic instruction as the pointer to the testcase buffer and the second
+/// argument as the maximum size of the testcase buffer.
+#define N_START_BUFFER_PTR_SIZE_VAL (0x0002U)
+
+/// HARNESS_START_WITH_MAXIMUM_SIZE
+///
+/// Signal the fuzzer to start the fuzzing loop at the point this macro is
+/// called. The default "index" of 0 will be used. If you need multiple start
+/// harnesses compiled into the same binary, you can use the
+/// `HARNESS_START_WITH_MAXIMUM_SIZE_INDEX` macro to specify different indices,
+/// then enable them at runtime by configuring the fuzzer.
+///
+/// When this macro is called:
+///
+/// - A snapshot will be taken and saved
+/// - The buffer pointed to by `buffer` will be saved and used as the testcase
+/// buffer. Each
+/// fuzzing iteration, a new test case will be written to this buffer.
+/// - The `max_size` value will be saved as the maximum testcase size. Fuzzing
+/// test cases will be truncated to this size before being written to the
+/// buffer.
+///
+/// # Arguments
+///
+/// - `buffer`: The pointer to the testcase buffer
+/// - `max_size`: The maximum size of the testcase buffer
+///
+/// # Example
+///
+/// ```
+/// unsigned char buffer[1024];
+/// HARNESS_START_WITH_MAXIMUM_SIZE(buffer, 1024);
+/// ```
+#define HARNESS_START_WITH_MAXIMUM_SIZE(buffer, max_size) \
+ do { \
+ unsigned int value = (N_START_BUFFER_PTR_SIZE_VAL << 0x10U) | MAGIC; \
+ __cpuid_extended3(value, DEFAULT_INDEX, buffer, max_size); \
+ } while (0);
+
+/// HARNESS_START_WITH_MAXIMUM_SIZE_INDEX
+///
+/// Signal the fuzzer to start the fuzzing loop at the point this macro is
+/// called. The index specified by `start_index` will be used. If you need
+/// multiple start harnesses compiled into the same binary, you can use this
+/// macro to specify different indices, then enable them at runtime by
+/// configuring the fuzzer.
+///
+/// When this macro is called:
+///
+/// - A snapshot will be taken and saved
+/// - The buffer pointed to by `buffer` will be saved and used as the testcase
+/// buffer. Each
+/// fuzzing iteration, a new test case will be written to this buffer.
+/// - The `max_size` value will be saved as the maximum testcase size. Fuzzing
+/// test cases will be truncated to this size before being written to the
+/// buffer.
+///
+/// # Arguments
+///
+/// - `start_index`: The index to use for this start harness
+/// - `buffer`: The pointer to the testcase buffer
+/// - `max_size`: The maximum size of the testcase buffer
+///
+/// # Example
+///
+/// ```
+/// unsigned char buffer[1024];
+/// HARNESS_START_WITH_MAXIMUM_SIZE_INDEX(0x0001U, buffer, 1024);
+/// ```
+#define HARNESS_START_WITH_MAXIMUM_SIZE_INDEX(start_index, buffer, max_size) \
+ do { \
+ unsigned int value = (N_START_BUFFER_PTR_SIZE_VAL << 0x10U) | MAGIC; \
+ __cpuid_extended3(value, start_index, buffer, max_size); \
+ } while (0);
+
+/// Pseudo-hypercall number to signal the fuzzer to use the first argument to
+/// the magic instruction as the pointer to the testcase buffer, the second
+/// argument as a pointer to the size of the testcase buffer, and the third
+/// argument as the maximum size of the testcase buffer.
+#define N_START_BUFFER_PTR_SIZE_PTR_VAL (0x0003U)
+
+/// HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR
+///
+/// Signal the fuzzer to start the fuzzing loop at the point this macro is
+/// called. The default "index" of 0 will be used. If you need multiple start
+/// harnesses compiled into the same binary, you can use the
+/// `HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR_INDEX` macro to specify different
+/// indices, then enable them at runtime by configuring the fuzzer.
+///
+/// When this macro is called:
+///
+/// - A snapshot will be taken and saved
+/// - The buffer pointed to by `buffer` will be saved and used as the testcase
+/// buffer. Each
+/// fuzzing iteration, a new test case will be written to this buffer.
+/// - The address `size_ptr` will be saved. Each fuzzing iteration, the actual
+/// size of the current testcase will be written to `*size_ptr`.
+/// - The `max_size` value will be saved as the maximum testcase size. Fuzzing
+/// test cases will be truncated to this size before being written to the
+/// buffer.
+///
+/// # Arguments
+///
+/// - `buffer`: The pointer to the testcase buffer
+/// - `size_ptr`: The pointer to the size of the testcase buffer
+/// - `max_size`: The maximum size of the testcase buffer
+///
+/// # Example
+///
+/// ```
+/// unsigned char buffer[1024];
+/// size_t size;
+/// HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR(buffer, &size, 1024);
+/// ```
+#define HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR(buffer, size_ptr, max_size) \
+ do { \
+ unsigned int value = (N_START_BUFFER_PTR_SIZE_PTR_VAL << 0x10U) | MAGIC; \
+ __cpuid_extended4(value, DEFAULT_INDEX, buffer, size_ptr, max_size); \
+ } while (0);
+
+/// HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR_INDEX
+///
+/// Signal the fuzzer to start the fuzzing loop at the point this macro is
+/// called. The index specified by `start_index` will be used. If you need
+/// multiple start harnesses compiled into the same binary, you can use this
+/// macro to specify different indices, then enable them at runtime by
+/// configuring the fuzzer.
+///
+/// When this macro is called:
+///
+/// - A snapshot will be taken and saved
+/// - The buffer pointed to by `buffer` will be saved and used as the testcase
+/// buffer. Each
+/// fuzzing iteration, a new test case will be written to this buffer.
+/// - The address `size_ptr` will be saved. Each fuzzing iteration, the actual
+/// size of the current testcase will be written to `*size_ptr`.
+/// - The `max_size` value will be saved as the maximum testcase size. Fuzzing
+/// test cases will be truncated to this size before being written to the
+/// buffer.
+///
+/// # Arguments
+///
+/// - `start_index`: The index to use for this start harness
+/// - `buffer`: The pointer to the testcase buffer
+/// - `size_ptr`: The pointer to the size of the testcase buffer
+/// - `max_size`: The maximum size of the testcase buffer
+///
+/// # Example
+///
+/// ```
+/// unsigned char buffer[1024];
+/// size_t size;
+/// HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR_INDEX(0x0001U, buffer, &size, 1024);
+/// ```
+#define HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR_INDEX(start_index, buffer, \
+ size_ptr, max_size) \
+ do { \
+ unsigned int value = (N_START_BUFFER_PTR_SIZE_PTR_VAL << 0x10U) | MAGIC; \
+ __cpuid_extended4(value, start_index, buffer, size_ptr, max_size); \
+ } while (0);
+
+/// Pseudo-hypercall number to signal the fuzzer to stop the current fuzzing
+/// iteration and reset to the beginning of the fuzzing loop with a "normal"
+/// stop status, indicating no solution has occurred.
+#define N_STOP_NORMAL (0x0004U)
+
+/// HARNESS_STOP
+///
+/// Signal the fuzzer to stop and reset to the beginning of the fuzzing loop
+/// with a "normal" stop status, indicating no solution has occurred. The
+/// default index of 0 will be used. If you need to differentiate between
+/// multiple stop harnesses compiled into the same binary, you can use the
+/// `HARNESS_STOP_INDEX` macro to specify different indices, then enable them at
+/// runtime by configuring the fuzzer.
+///
+/// # Example
+///
+/// ```
+/// HARNESS_STOP();
+/// ```
+#define HARNESS_STOP() \
+ do { \
+ unsigned int value = (N_STOP_NORMAL << 0x10U) | MAGIC; \
+ __cpuid_extended1(value, DEFAULT_INDEX); \
+ } while (0);
+
+/// HARNESS_STOP_INDEX
+///
+/// Signal the fuzzer to stop and reset to the beginning of the fuzzing loop
+/// with a "normal" stop status, indicating no solution has occurred. The index
+/// specified by `stop_index` will be used. If you need to differentiate between
+/// multiple stop harnesses compiled into the same binary, you can use this
+/// macro to specify different indices, then enable them at runtime by
+/// configuring the fuzzer.
+///
+/// # Arguments
+///
+/// - `stop_index`: The index to use for this stop harness
+///
+/// # Example
+///
+/// ```
+/// HARNESS_STOP_INDEX(0x0001U);
+/// ```
+#define HARNESS_STOP_INDEX(stop_index) \
+ do { \
+ unsigned int value = (N_STOP_NORMAL << 0x10U) | MAGIC; \
+ __cpuid_extended1(value, stop_index); \
+ } while (0);
+
+/// Pseudo-hypercall number to signal the fuzzer that a custom assertion has
+/// occurred, and the fuzzer should stop the current fuzzing iteration and reset
+/// to the beginning of the fuzzing loop with a "solution" stop status.
+#define N_STOP_ASSERT (0x0005U)
+
+/// HARNESS_ASSERT
+///
+/// Signal the fuzzer that a custom assertion has occurred, and the fuzzer
+/// should stop the current fuzzing iteration and reset to the beginning of the
+/// fuzzing loop with a "solution" stop status. The default index of 0 will be
+/// used. If you need to differentiate between multiple assertion harnesses
+/// compiled into the same binary, you can use the `HARNESS_ASSERT_INDEX` macro
+/// to specify different indices, then enable them at runtime by configuring the
+/// fuzzer.
+///
+/// # Example
+///
+/// ```
+/// HARNESS_ASSERT();
+/// ```
+#define HARNESS_ASSERT() \
+ do { \
+ unsigned int value = (N_STOP_ASSERT << 0x10U) | MAGIC; \
+ __cpuid_extended1(value, DEFAULT_INDEX); \
+ } while (0);
+
+/// HARNESS_ASSERT_INDEX
+///
+/// Signal the fuzzer that a custom assertion has occurred, and the fuzzer
+/// should stop the current fuzzing iteration and reset to the beginning of the
+/// fuzzing loop with a "solution" stop status. The index specified by
+/// `assert_index` will be used. If you need to differentiate between multiple
+/// assertion harnesses compiled into the same binary, you can use this macro to
+/// specify different indices, then enable them at runtime by configuring the
+/// fuzzer.
+///
+/// # Arguments
+///
+/// - `assert_index`: The index to use for this assertion harness
+///
+/// # Example
+///
+/// ```
+/// HARNESS_ASSERT_INDEX(0x0001U);
+/// ```
+#define HARNESS_ASSERT_INDEX(assert_index) \
+ do { \
+ unsigned int value = (N_STOP_ASSERT << 0x10U) | MAGIC; \
+ __cpuid_extended1(value, assert_index); \
+ } while (0);
struct tsffs_fme {
struct cpu_user_regs regs;
static uint8_t tsffs_vmread_counter;
static struct tsffs_fme tsffs_fme;
-
#endif // TSFFS_H