Skip to content
Closed
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
15 changes: 11 additions & 4 deletions events-arch-x86/ras-mce-handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,16 +783,23 @@ static const struct db_fields mce_record_fields[] = {
{ .name = "id", .type = DB_TYPE_SERIAL, .is_pk = true },
{ .name = "timestamp", .type = DB_TYPE_TIMESTAMP, .create_index = true },

/* MCE registers */
{ .name = "mcgcap", .type = DB_TYPE_INT32 },
{ .name = "mcgstatus", .type = DB_TYPE_INT32 },
/*
* MCE registers.
*
* The MSR-backed fields are uint64_t at struct mce_event. Binding
* them as DB_TYPE_INT32 truncates the value to 32 bits, which is
* unrecoverable once stored. DB_TYPE_INT64 keeps all 64 bits and
* maps to the same SQL column type on sqlite3 (INTEGER).
*/
{ .name = "mcgcap", .type = DB_TYPE_INT64 },
{ .name = "mcgstatus", .type = DB_TYPE_INT64 },
{ .name = "status", .type = DB_TYPE_INT64 },
{ .name = "addr", .type = DB_TYPE_INT64 }, // 5
{ .name = "misc", .type = DB_TYPE_INT64 },
{ .name = "ip", .type = DB_TYPE_INT64 },
{ .name = "tsc", .type = DB_TYPE_INT64 },
{ .name = "walltime", .type = DB_TYPE_INT64 },
{ .name = "ppin", .type = DB_TYPE_INT32 }, // 10
{ .name = "ppin", .type = DB_TYPE_INT64 }, // 10
{ .name = "cpu", .type = DB_TYPE_INT32 },
{ .name = "cpuid", .type = DB_TYPE_INT32 },
{ .name = "apicid", .type = DB_TYPE_INT32 },
Expand Down
29 changes: 28 additions & 1 deletion tests/test-sqlite3.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,22 @@ static void sqlite3_assert_row_count(sqlite3 *db, const char *table,
assert_int_equal(sqlite3_finalize(stmt), SQLITE_OK);
}

#ifdef HAVE_MCE
static void sqlite3_assert_u64_column(sqlite3 *db, const char *table,
const char *column, uint64_t expected)
{
sqlite3_stmt *stmt = NULL;
char sql[256];

snprintf(sql, sizeof(sql), "SELECT %s FROM %s", column, table);
assert_int_equal(sqlite3_prepare_v2(db, sql, -1, &stmt, NULL),
SQLITE_OK);
assert_int_equal(sqlite3_step(stmt), SQLITE_ROW);
assert_int_equal((uint64_t)sqlite3_column_int64(stmt, 0), expected);
assert_int_equal(sqlite3_finalize(stmt), SQLITE_OK);
}
#endif

static int sqlite3_get_busy_timeout(sqlite3 *db)
{
sqlite3_stmt *stmt = NULL;
Expand Down Expand Up @@ -690,7 +706,10 @@ static void test_mc_event_recording(void **state)
.dev_name = "0000:01:00.0", .msg = "Receiver Error" };
#endif
#ifdef HAVE_MCE
struct mce_event mce = { .status = MCI_STATUS_VAL, .cpu = 1 };
struct mce_event mce = { .status = MCI_STATUS_VAL, .cpu = 1,
.mcgcap = 0x0000000000000c0aULL,
.mcgstatus = 0x0000000000000005ULL,
.ppin = 0x123456789abcdef0ULL };
#endif
#ifdef HAVE_EXTLOG
static const unsigned char fru_id[16] = { 1 };
Expand Down Expand Up @@ -800,6 +819,14 @@ static void test_mc_event_recording(void **state)
#ifdef HAVE_MCE
strscpy(mce.timestamp, mc.timestamp, sizeof(mce.timestamp));
RECORD_AND_CHECK(ras_event_publish(&ras, MCE_EVENT, &mce), "mce_record");
/*
* MSR-backed registers are uint64_t and must survive a round trip.
* A 32-bit column type would truncate ppin and sign-extend it back.
*/
sqlite3_assert_u64_column(db, "mce_record", "mcgcap", mce.mcgcap);
sqlite3_assert_u64_column(db, "mce_record", "mcgstatus", mce.mcgstatus);
sqlite3_assert_u64_column(db, "mce_record", "status", mce.status);
sqlite3_assert_u64_column(db, "mce_record", "ppin", mce.ppin);
#endif
#ifdef HAVE_EXTLOG
strscpy(extlog.timestamp, mc.timestamp, sizeof(extlog.timestamp));
Expand Down
Loading