Skip to content

Commit a008f77

Browse files
add ability to register debug key combinations so we dont have to put code into the keyboard driver for it
1 parent f5cfde1 commit a008f77

7 files changed

Lines changed: 128 additions & 26 deletions

File tree

include/kernel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,5 @@ struct reqset request_addresses(void);
201201
#endif
202202

203203
void entropy_irq_event(void);
204+
205+
void init_profiler(void);

include/keyboard.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,37 @@ struct key_state {
7474
uint16_t ticks_held; ///< Number of ticks the key has been held
7575
};
7676

77+
#define DEBUGKEY_COUNT 256
78+
#define DEBUGKEY_INVALID 256
79+
80+
/**
81+
* @brief Debug key handler
82+
*/
83+
typedef void (*debugkey_handler_t)(void);
84+
85+
/**
86+
* @brief Register a debug key combination
87+
*
88+
* @param key Key ('A'-'Z')
89+
* @param ctrl Ctrl modifier
90+
* @param alt Alt modifier
91+
* @param shift Shift modifier
92+
* @param handler Handler to invoke
93+
*
94+
* @return true on success, false on invalid key or NULL handler
95+
*/
96+
bool debugkey_register(char key, bool ctrl, bool alt, bool shift, debugkey_handler_t handler);
97+
98+
/**
99+
* @brief Unregister a debug key combination
100+
*
101+
* @param key Key ('A'-'Z')
102+
* @param ctrl Ctrl modifier
103+
* @param alt Alt modifier
104+
* @param shift Shift modifier
105+
*/
106+
void debugkey_unregister(char key, bool ctrl, bool alt, bool shift);
107+
77108
/**
78109
* @brief Initialises the keyboard driver.
79110
*
@@ -145,4 +176,4 @@ _Noreturn void reboot(void);
145176
*/
146177
void keyboard_process_scancode_input(uint8_t sc);
147178

148-
bool key_held(unsigned char ch);
179+
bool key_held(unsigned char ch);

include/memory_trace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,5 @@ void memory_trace_dump_leaks(memory_trace_owner_type_t owner_type, void *owner);
8383

8484
#endif
8585

86+
void init_memtrace(void);
87+

src/init.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ spinlock_t console_spinlock = 0;
66
spinlock_t debug_console_spinlock = 0;
77

88
init_func_t init_funcs[] = {
9+
init_memtrace, init_profiler,
910
validate_limine_page_tables_and_gdt, init_heap, init_console,
1011
init_acpi, init_interrupts, boot_aps, init_pci, init_realtime_clock,
1112
init_devicenames, init_keyboard, init_ide, init_ahci, init_nvme,
@@ -15,6 +16,7 @@ init_func_t init_funcs[] = {
1516
};
1617

1718
char* init_funcs_names[] = {
19+
"memtrace", "profiler",
1820
"gdt", "heap", "console", "acpi",
1921
"interrupts", "cpus", "pci", "clock",
2022
"devicenames", "keyboard", "ide", "ahci",

src/keyboard.c

Lines changed: 62 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ static bool alt_state = false;
1616
static struct key_state key_states[256] = {0};
1717
static uint8_t key_was_extended[256] = {0};
1818

19+
static debugkey_handler_t debugkeys[256];
20+
1921
/* UK mappings of scan codes to characters, based in part off http://www.ee.bgu.ac.il/~microlab/MicroLab/Labs/ScanCodes.htm
2022
* These are DEFAULTS. They can be replaced by the KEYMAP BASIC keyword.
2123
*/
@@ -106,7 +108,7 @@ static char parse_token(const char **p)
106108
}
107109
buf[len] = 0;
108110
c = (char)atoll(buf, 16);
109-
} else { /* bare character literal */
111+
} else { /* bare character literal */
110112
c = *s++;
111113
}
112114

@@ -309,13 +311,21 @@ void keyboard_repeat_tick() {
309311
}
310312
}
311313

314+
static void debugkey_dprintf_dump(void) {
315+
const char *log = dprintf_buffer_snapshot();
316+
kprintf("\n%s\n", log);
317+
kfree_null(&log);
318+
return;
319+
}
320+
312321
void init_keyboard() {
313322
char devname[16];
314323
buffer_write_ptr = 0;
315324
buffer_read_ptr = 0;
316325
make_unique_device_name("kb", devname, sizeof(devname));
317326
register_interrupt_handler(IRQ1, keyboard_handler, dev_zero, NULL);
318327
proc_register_idle(keyboard_repeat_tick, IDLE_BACKGROUND, 1);
328+
debugkey_register('D', true, false, true, debugkey_dprintf_dump);
319329
}
320330

321331
// Map a keyboard scan code to a keymap value
@@ -389,27 +399,57 @@ bool caps_lock_on() {
389399
return caps_lock;
390400
}
391401

402+
static size_t debugkey_index(char key, bool ctrl, bool alt, bool shift) {
403+
if (key < 'A' || key > 'Z') {
404+
return DEBUGKEY_INVALID;
405+
}
406+
407+
size_t mods =
408+
(ctrl ? 0x20 : 0) |
409+
(alt ? 0x40 : 0) |
410+
(shift ? 0x80 : 0);
411+
412+
return mods | (key - 'A');
413+
}
414+
415+
bool debugkey_register(char key, bool ctrl, bool alt, bool shift, debugkey_handler_t handler) {
416+
size_t idx = debugkey_index(key, ctrl, alt, shift);
417+
418+
if (idx == DEBUGKEY_INVALID || !handler) {
419+
return false;
420+
}
421+
422+
debugkeys[idx] = handler;
423+
return true;
424+
}
425+
426+
void debugkey_unregister(char key, bool ctrl, bool alt, bool shift) {
427+
size_t idx = debugkey_index(key, ctrl, alt, shift);
428+
429+
if (idx != DEBUGKEY_INVALID) {
430+
debugkeys[idx] = NULL;
431+
}
432+
}
433+
434+
static bool debugkey_dispatch(char key) {
435+
size_t idx = debugkey_index(key, ctrl_held(), alt_held(), shift_held());
436+
437+
if (idx == DEBUGKEY_INVALID) {
438+
return false;
439+
}
440+
441+
debugkey_handler_t handler = debugkeys[idx];
442+
443+
if (!handler) {
444+
return false;
445+
}
446+
447+
handler();
448+
return true;
449+
}
450+
392451
static void push_to_buffer(char x) {
393-
#ifdef PROFILE_KERNEL
394-
if (ctrl_held() && alt_held() && shift_held() && x == 'P') {
395-
kprintf("\nDumping callgrind.out to serial port...\n");
396-
rr_flip();
397-
profile_dump();
398-
kprintf("Profile written.\n");
399-
rr_flip();
400-
return;
401-
}
402-
#endif
403-
#ifdef MEMORY_TRACE
404-
if (ctrl_held() && alt_held() && shift_held() && x == 'M') {
405-
memory_trace_dump_leaks(memory_trace_owner_buddy, NULL);
406-
memory_trace_dump_leaks(memory_trace_owner_kmalloc, NULL);
407-
}
408-
#endif
409-
if (ctrl_held() && shift_held() && x == 'D') {
410-
const char *log = dprintf_buffer_snapshot();
411-
kprintf("\n%s\n", log);
412-
kfree_null(&log);
452+
if (debugkey_dispatch(x)) {
413453
return;
414454
}
415455

@@ -439,7 +479,7 @@ void keyboard_process_scancode_input(uint8_t sc) {
439479
}
440480

441481
uint8_t was_escaped = escaped; /* one-shot */
442-
escaped = false; /* consume E0 regardless of outcome */
482+
escaped = false; /* consume E0 regardless of outcome */
443483

444484
switch (sc) {
445485
case 0x2A:

src/memory_trace.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,5 +227,15 @@ void memory_trace_dump_leaks(memory_trace_owner_type_t owner_type, void *owner)
227227
}
228228
}
229229

230+
static void debugkey_memory_trace_dump(void) {
231+
memory_trace_dump_leaks(memory_trace_owner_kmalloc, NULL);
232+
}
233+
234+
#endif
235+
236+
void init_memtrace(void) {
237+
#ifdef MEMORY_TRACE
238+
debugkey_register('M', true, true, true, debugkey_memory_trace_dump);
230239
#endif
240+
}
231241

src/profiler.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ static profile_edge* edge_hash[PROFILE_EDGE_HASH_SIZE];
7979
* @brief Call stack frame used to measure function entry/exit.
8080
*/
8181
struct call_frame {
82-
void *fn; /**< Function pointer. */
83-
uint64_t enter_time; /**< Timestamp (TSC) at function entry. */
82+
void *fn; /**< Function pointer. */
83+
uint64_t enter_time; /**< Timestamp (TSC) at function entry. */
8484
profile_edge *parent_edge; /**< Edge from the parent to this frame. */
8585
};
8686
static struct call_frame call_stack[PROFILE_STACK_DEPTH];
@@ -393,4 +393,19 @@ __attribute__((no_instrument_function)) void profile_dump(void) {
393393
}
394394
}
395395

396-
#endif /* PROFILE_KERNEL */
396+
void debugkey_profile_dump(void) {
397+
kprintf("\nDumping callgrind.out to serial port...\n");
398+
rr_flip();
399+
profile_dump();
400+
kprintf("Profile written.\n");
401+
rr_flip();
402+
return;
403+
}
404+
405+
#endif /* PROFILE_KERNEL */
406+
407+
void init_profiler(void) {
408+
#ifdef PROFILE_KERNEL
409+
debugkey_register('P', true, true, true, debugkey_profile_dump);
410+
#endif
411+
}

0 commit comments

Comments
 (0)