171 lines
3.9 KiB
C
171 lines
3.9 KiB
C
#include "kernel.h"
|
|
|
|
extern char __bss[], __bss_end[], __stack_top[];
|
|
|
|
static inline struct sbiret sbi_call(long a0, long a1, long a2, long a3,
|
|
long a4, long a5, long fid, long eid) {
|
|
register long x0 __asm__("a0") = a0;
|
|
register long x1 __asm__("a1") = a1;
|
|
register long x2 __asm__("a2") = a2;
|
|
register long x3 __asm__("a3") = a3;
|
|
register long x4 __asm__("a4") = a4;
|
|
register long x5 __asm__("a5") = a5;
|
|
register long x6 __asm__("a6") = fid;
|
|
register long x7 __asm__("a7") = eid;
|
|
|
|
__asm__ __volatile__("ecall"
|
|
: "+r"(x0), "+r"(x1)
|
|
: "r"(x2), "r"(x3), "r"(x4), "r"(x5), "r"(x6), "r"(x7)
|
|
: "memory");
|
|
return (struct sbiret){ .error = x0, .value = x1 };
|
|
}
|
|
|
|
void putchar(char ch) {
|
|
sbi_call((long)ch, 0, 0, 0, 0, 0, 0, 1);
|
|
}
|
|
|
|
int getchar(void) {
|
|
int ch;
|
|
do {
|
|
struct sbiret ret = sbi_call(0, 0, 0, 0, 0, 0, 0, 2);
|
|
ch = (int)ret.error;
|
|
} while (ch == -1);
|
|
return ch;
|
|
}
|
|
|
|
static void get_sbi_spec_version(void) {
|
|
struct sbiret ret = sbi_call(0, 0, 0, 0, 0, 0, 0, SBI_EXT_BASE);
|
|
|
|
if (ret.error != SBI_SUCCESS) {
|
|
printf("Error: %d\n", (int)ret.error);
|
|
return;
|
|
}
|
|
|
|
long version = ret.value;
|
|
int major = (version >> 24) & 0x7F;
|
|
int minor = version & 0xFFFFFF;
|
|
|
|
printf("SBI Specification Version: %d.%d\n", major, minor);
|
|
}
|
|
|
|
static void get_num_counters(void) {
|
|
struct sbiret ret = sbi_call(0, 0, 0, 0, 0, 0, 0, SBI_EXT_PMU);
|
|
|
|
if (ret.error != SBI_SUCCESS) {
|
|
printf("Error: %d\n", (int)ret.error);
|
|
return;
|
|
}
|
|
|
|
printf("Number of counters: %d\n", (int)ret.value);
|
|
}
|
|
|
|
static int read_number(void) {
|
|
int num = 0;
|
|
int ch;
|
|
|
|
while (1) {
|
|
ch = getchar();
|
|
|
|
if (ch == '\r' || ch == '\n') {
|
|
putchar('\n');
|
|
break;
|
|
}
|
|
|
|
if (ch >= '0' && ch <= '9') {
|
|
putchar(ch);
|
|
num = num * 10 + (ch - '0');
|
|
}
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
static void get_counter_info(void) {
|
|
printf("Enter counter index: ");
|
|
int idx = read_number();
|
|
|
|
struct sbiret ret = sbi_call(idx, 0, 0, 0, 0, 0, 1, SBI_EXT_PMU);
|
|
|
|
if (ret.error == SBI_ERR_NOT_SUPPORTED) {
|
|
printf("PMU extension not supported\n");
|
|
return;
|
|
}
|
|
|
|
if (ret.error != SBI_SUCCESS) {
|
|
printf("Error: %d (invalid counter index?)\n", (int)ret.error);
|
|
return;
|
|
}
|
|
|
|
uint32_t info = (uint32_t)ret.value;
|
|
|
|
uint32_t csr = info & 0xFFF;
|
|
uint32_t width_minus_one = (info >> 12) & 0x3F;
|
|
uint32_t type = (info >> 31) & 0x1;
|
|
|
|
printf("Counter %d details:\n", idx);
|
|
printf(" Type: %s\n", type ? "Firmware" : "Hardware");
|
|
|
|
if (type == 0) {
|
|
printf(" CSR: 0x%x\n", csr);
|
|
printf(" Width: %d bits\n", width_minus_one + 1);
|
|
} else {
|
|
printf(" (CSR and Width fields ignored for firmware counters)\n");
|
|
}
|
|
|
|
printf(" Raw info: 0x%x\n", info);
|
|
}
|
|
|
|
static void system_shutdown(void) {
|
|
printf("Goodbye!\n");
|
|
sbi_call(0, 0, 0, 0, 0, 0, 0, SBI_EXT_SRST);
|
|
}
|
|
|
|
static void print_menu(void) {
|
|
printf("1. Get SBI specification version\n");
|
|
printf("2. Get number of counters\n");
|
|
printf("3. Get details of a counter\n");
|
|
printf("4. System Shutdown\n");
|
|
}
|
|
|
|
static void kernel_main(void) {
|
|
memset(__bss, 0, (size_t)(__bss_end - __bss));
|
|
|
|
print_menu();
|
|
|
|
while (1) {
|
|
printf("Choose option (1-4): ");
|
|
int ch = getchar();
|
|
putchar(ch);
|
|
putchar('\n');
|
|
|
|
switch (ch) {
|
|
case '1':
|
|
get_sbi_spec_version();
|
|
break;
|
|
case '2':
|
|
get_num_counters();
|
|
break;
|
|
case '3':
|
|
get_counter_info();
|
|
break;
|
|
case '4':
|
|
system_shutdown();
|
|
return;
|
|
default:
|
|
printf("Invalid option\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
__attribute__((section(".text.boot")))
|
|
__attribute__((naked))
|
|
void boot(void) {
|
|
__asm__ __volatile__(
|
|
"mv sp, %[stack_top]\n"
|
|
"j %[kmain]\n"
|
|
:
|
|
: [stack_top] "r" (__stack_top),
|
|
[kmain] "i" (kernel_main)
|
|
);
|
|
} |