summaryrefslogtreecommitdiff
path: root/lib/sbi_ecall.c
blob: 731a6652a7b46593b500809a58da2bc16cc4e3d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*
 * Copyright (c) 2018 Western Digital Corporation or its affiliates.
 *
 * Authors:
 *   Anup Patel <anup.patel@wdc.com>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <sbi/sbi_console.h>
#include <sbi/sbi_ecall.h>
#include <sbi/sbi_ecall_interface.h>
#include <sbi/sbi_error.h>
#include <sbi/sbi_ipi.h>
#include <sbi/sbi_system.h>
#include <sbi/sbi_timer.h>
#include <sbi/sbi_trap.h>

#define SBI_ECALL_VERSION_MAJOR			0
#define SBI_ECALL_VERSION_MINOR			1

u16 sbi_ecall_version_major(void)
{
	return SBI_ECALL_VERSION_MAJOR;
}

u16 sbi_ecall_version_minor(void)
{
	return SBI_ECALL_VERSION_MINOR;
}

int sbi_ecall_handler(u32 hartid, ulong mcause,
		      struct sbi_trap_regs *regs,
		      struct sbi_scratch *scratch)
{
	int ret = SBI_ENOTSUPP;

	switch (regs->a7) {
	case SBI_ECALL_SET_TIMER:
#if __riscv_xlen == 32
		sbi_timer_event_start(scratch, hartid,
			(((u64)regs->a1 << 32) || (u64)regs->a0));
#else
		sbi_timer_event_start(scratch, hartid, (u64)regs->a0);
#endif
		ret = 0;
		break;
	case SBI_ECALL_CONSOLE_PUTCHAR:
		sbi_putc(regs->a0);
		ret = 0;
		break;
	case SBI_ECALL_CONSOLE_GETCHAR:
		regs->a0 = sbi_getc();
		ret = 0;
		break;
	case SBI_ECALL_CLEAR_IPI:
		sbi_ipi_clear_smode(scratch, hartid);
		ret = 0;
		break;
	case SBI_ECALL_SEND_IPI:
		ret = sbi_ipi_send_many(scratch, hartid,
					(ulong *)regs->a0,
					SBI_IPI_EVENT_SOFT);
		break;
	case SBI_ECALL_REMOTE_FENCE_I:
		ret = sbi_ipi_send_many(scratch, hartid,
					(ulong *)regs->a0,
					SBI_IPI_EVENT_FENCE_I);
		break;
	case SBI_ECALL_REMOTE_SFENCE_VMA:
	case SBI_ECALL_REMOTE_SFENCE_VMA_ASID:
		ret = sbi_ipi_send_many(scratch, hartid,
					(ulong *)regs->a0,
					SBI_IPI_EVENT_SFENCE_VMA);
		break;
	case SBI_ECALL_SHUTDOWN:
		sbi_system_shutdown(scratch, 0);
		ret = 0;
		break;
	default:
		break;
	};

	if (!ret) {
		regs->mepc += 4;
	}

	return ret;
}