2021-01-13 03:22:11 +09:00
|
|
|
/* SPDX-License-Identifier: MIT */
|
|
|
|
|
2021-09-15 23:17:32 +09:00
|
|
|
#include <assert.h>
|
2021-02-06 14:46:16 +09:00
|
|
|
#include <stdarg.h>
|
|
|
|
|
2021-02-12 20:09:49 +01:00
|
|
|
#include "utils.h"
|
2021-04-15 22:47:33 +09:00
|
|
|
#include "iodev.h"
|
2021-09-15 23:17:32 +09:00
|
|
|
#include "smp.h"
|
2021-04-15 22:47:33 +09:00
|
|
|
#include "types.h"
|
2021-01-13 03:22:11 +09:00
|
|
|
#include "vsprintf.h"
|
2022-01-17 04:09:46 +09:00
|
|
|
#include "xnuboot.h"
|
2021-01-13 03:22:11 +09:00
|
|
|
|
|
|
|
static char ascii(char s)
|
|
|
|
{
|
|
|
|
if (s < 0x20)
|
|
|
|
return '.';
|
|
|
|
if (s > 0x7E)
|
|
|
|
return '.';
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2021-01-14 18:18:07 +09:00
|
|
|
void hexdump(const void *d, size_t len)
|
2021-01-13 03:22:11 +09:00
|
|
|
{
|
|
|
|
u8 *data;
|
2021-01-14 18:18:07 +09:00
|
|
|
size_t i, off;
|
2021-01-13 03:22:11 +09:00
|
|
|
data = (u8 *)d;
|
|
|
|
for (off = 0; off < len; off += 16) {
|
2021-05-01 18:23:44 +09:00
|
|
|
printf("%08lx ", off);
|
2021-01-13 03:22:11 +09:00
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
if ((i + off) >= len)
|
|
|
|
printf(" ");
|
|
|
|
else
|
|
|
|
printf("%02x ", data[off + i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
printf(" ");
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
if ((i + off) >= len)
|
|
|
|
printf(" ");
|
|
|
|
else
|
|
|
|
printf("%c", ascii(data[off + i]));
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-16 20:57:43 +00:00
|
|
|
void regdump(u64 addr, size_t len)
|
2021-01-13 03:22:11 +09:00
|
|
|
{
|
|
|
|
u64 i, off;
|
|
|
|
for (off = 0; off < len; off += 32) {
|
2021-05-01 18:23:44 +09:00
|
|
|
printf("%016lx ", addr + off);
|
2021-01-13 03:22:11 +09:00
|
|
|
for (i = 0; i < 32; i += 4) {
|
|
|
|
printf("%08x ", read32(addr + off + i));
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-12 13:47:03 +01:00
|
|
|
int snprintf(char *buffer, size_t size, const char *fmt, ...)
|
2021-01-13 03:22:11 +09:00
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
2021-11-12 13:47:03 +01:00
|
|
|
i = vsnprintf(buffer, size, fmt, args);
|
2021-01-13 03:22:11 +09:00
|
|
|
va_end(args);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
int debug_printf(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
char buffer[512];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
2021-05-27 21:09:15 +09:00
|
|
|
i = vsnprintf(buffer, sizeof(buffer), fmt, args);
|
2021-01-13 03:22:11 +09:00
|
|
|
va_end(args);
|
|
|
|
|
2021-05-27 21:09:15 +09:00
|
|
|
iodev_console_write(buffer, min(i, (int)(sizeof(buffer) - 1)));
|
2021-01-13 03:22:11 +09:00
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
2021-01-23 22:30:42 +09:00
|
|
|
|
2021-01-28 15:27:35 +09:00
|
|
|
void __assert_fail(const char *assertion, const char *file, unsigned int line, const char *function)
|
2021-01-23 22:30:42 +09:00
|
|
|
{
|
2021-01-28 15:27:35 +09:00
|
|
|
printf("Assertion failed: '%s' on %s:%d:%s\n", assertion, file, line, function);
|
2021-05-15 20:42:50 +09:00
|
|
|
flush_and_reboot();
|
2021-01-23 22:30:42 +09:00
|
|
|
}
|
2021-01-23 22:31:15 +09:00
|
|
|
|
|
|
|
void udelay(u32 d)
|
|
|
|
{
|
2021-11-02 12:36:07 +09:00
|
|
|
u64 delay = ((u64)d) * mrs(CNTFRQ_EL0) / 1000000;
|
|
|
|
u64 val = mrs(CNTPCT_EL0);
|
2021-11-01 18:57:51 +09:00
|
|
|
while ((mrs(CNTPCT_EL0) - val) < delay)
|
2021-01-25 14:04:30 +09:00
|
|
|
;
|
2021-11-02 12:36:07 +09:00
|
|
|
sysop("isb");
|
2021-01-23 22:31:15 +09:00
|
|
|
}
|
2021-05-05 03:21:48 +09:00
|
|
|
|
2022-06-01 02:03:32 +09:00
|
|
|
u64 ticks_to_msecs(u64 ticks)
|
|
|
|
{
|
|
|
|
// NOTE: only accurate if freq is even kHz
|
|
|
|
return ticks / (mrs(CNTFRQ_EL0) / 1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 ticks_to_usecs(u64 ticks)
|
|
|
|
{
|
|
|
|
// NOTE: only accurate if freq is even MHz
|
|
|
|
return ticks / (mrs(CNTFRQ_EL0) / 1000000);
|
|
|
|
}
|
|
|
|
|
2022-01-21 17:24:23 +01:00
|
|
|
u64 timeout_calculate(u32 usec)
|
|
|
|
{
|
|
|
|
u64 delay = ((u64)usec) * mrs(CNTFRQ_EL0) / 1000000;
|
|
|
|
return mrs(CNTPCT_EL0) + delay;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool timeout_expired(u64 timeout)
|
|
|
|
{
|
|
|
|
bool expired = mrs(CNTPCT_EL0) > timeout;
|
|
|
|
sysop("isb");
|
|
|
|
return expired;
|
|
|
|
}
|
|
|
|
|
2021-05-05 03:21:48 +09:00
|
|
|
void flush_and_reboot(void)
|
|
|
|
{
|
2021-05-15 21:01:25 +09:00
|
|
|
iodev_console_flush();
|
2021-05-05 03:21:48 +09:00
|
|
|
reboot();
|
|
|
|
}
|
2021-09-15 22:02:05 +09:00
|
|
|
|
2021-11-04 03:53:39 +09:00
|
|
|
void spin_init(spinlock_t *lock)
|
|
|
|
{
|
|
|
|
lock->lock = -1;
|
|
|
|
lock->count = 0;
|
|
|
|
}
|
|
|
|
|
2021-09-15 22:02:05 +09:00
|
|
|
void spin_lock(spinlock_t *lock)
|
|
|
|
{
|
2022-05-31 21:33:23 +09:00
|
|
|
s64 tmp;
|
2021-09-15 23:17:32 +09:00
|
|
|
s64 me = smp_id();
|
|
|
|
if (__atomic_load_n(&lock->lock, __ATOMIC_ACQUIRE) == me) {
|
|
|
|
lock->count++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-05-31 21:33:23 +09:00
|
|
|
__asm__ volatile("1:\n"
|
|
|
|
"mov\t%0, -1\n"
|
|
|
|
"2:\n"
|
|
|
|
"\tcasa\t%0, %2, %1\n"
|
|
|
|
"\tcmn\t%0, 1\n"
|
|
|
|
"\tbeq\t3f\n"
|
|
|
|
"\tldxr\t%0, %1\n"
|
|
|
|
"\tcmn\t%0, 1\n"
|
|
|
|
"\tbeq\t2b\n"
|
|
|
|
"\twfe\n"
|
|
|
|
"\tb\t1b\n"
|
|
|
|
"3:"
|
|
|
|
: "=&r"(tmp), "+m"(lock->lock)
|
|
|
|
: "r"(me)
|
|
|
|
: "cc", "memory");
|
2021-09-15 23:17:32 +09:00
|
|
|
|
|
|
|
assert(__atomic_load_n(&lock->lock, __ATOMIC_RELAXED) == me);
|
|
|
|
lock->count++;
|
2021-09-15 22:02:05 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
void spin_unlock(spinlock_t *lock)
|
|
|
|
{
|
2021-09-15 23:17:32 +09:00
|
|
|
s64 me = smp_id();
|
|
|
|
assert(__atomic_load_n(&lock->lock, __ATOMIC_RELAXED) == me);
|
|
|
|
assert(lock->count > 0);
|
|
|
|
if (!--lock->count)
|
|
|
|
__atomic_store_n(&lock->lock, -1L, __ATOMIC_RELEASE);
|
2021-09-15 22:02:05 +09:00
|
|
|
}
|
2022-01-17 04:09:46 +09:00
|
|
|
|
|
|
|
bool is_heap(void *addr)
|
|
|
|
{
|
|
|
|
u64 p = (u64)addr;
|
|
|
|
u64 top_of_kernel_data = (u64)cur_boot_args.top_of_kernel_data;
|
|
|
|
u64 top_of_ram = cur_boot_args.mem_size + cur_boot_args.phys_base;
|
|
|
|
|
|
|
|
return p > top_of_kernel_data && p < top_of_ram;
|
|
|
|
}
|