47 lines · c
1#include <asm/hwcap.h>2#include <stdint.h>3#include <sys/auxv.h>4 5#ifndef HWCAP2_FPMR6#define HWCAP2_FPMR (1UL << 48)7#endif8 9uint64_t get_fpmr(void) {10 uint64_t fpmr = 0;11 __asm__ volatile("mrs %0, s3_3_c4_c4_2" : "=r"(fpmr));12 return fpmr;13}14 15void set_fpmr(uint64_t value) {16 __asm__ volatile("msr s3_3_c4_c4_2, %0" ::"r"(value));17}18 19// Set F8S1 (bits 0-2) and LSCALE2 (bits 37-32) (to prove we treat fpmr as 6420// bit).21const uint64_t original_fpmr = (uint64_t)0b101010 << 32 | (uint64_t)0b101;22 23void expr_func() { set_fpmr(original_fpmr); }24 25int main(int argc, char *argv[]) {26 if (!(getauxval(AT_HWCAP2) & HWCAP2_FPMR))27 return 1;28 29 // As FPMR controls a bunch of floating point options that are quite30 // extensive, we're not going to run any floating point ops here. Instead just31 // update the value from the debugger and check it from this program, and vice32 // versa.33 set_fpmr(original_fpmr);34 35 // Here the debugger checks it read back the value above, then writes in a new36 // value. Note that the bits are flipped in the new value.37 uint64_t new_fpmr = get_fpmr(); // Set break point at this line.38 uint64_t expected_fpmr = ((uint64_t)0b010101 << 32) | (uint64_t)0b010;39 40 // If the debugger failed to update the value, exit uncleanly.41 // This also allows you to run this program standalone to create a core file.42 if (new_fpmr != expected_fpmr)43 __builtin_trap();44 45 return 0;46}47