Browse Source

WIP towards ECALL interface for SBI

fdt
Andrew Waterman 9 years ago
parent
commit
926b360655
  1. 56
      bbl/bbl.c
  2. 22
      dummy_payload/dummy_entry.S
  3. 21
      dummy_payload/dummy_payload.c
  4. 4
      dummy_payload/dummy_payload.lds
  5. 2
      dummy_payload/dummy_payload.mk.in
  6. 1
      dummy_payload/dummy_sbi.S
  7. 4
      machine/machine.mk.in
  8. 7
      machine/mcall.h
  9. 9
      machine/minit.c
  10. 8
      machine/mtrap.c
  11. 3
      machine/mtrap.h
  12. 15
      machine/sbi.S
  13. 30
      machine/sbi.h
  14. 111
      machine/sbi_entry.S
  15. 33
      machine/sbi_impl.c
  16. 1
      pk/frontend.c
  17. 2
      pk/pk.c

56
bbl/bbl.c

@ -9,68 +9,22 @@
static kernel_elf_info info;
static volatile int elf_loaded;
static void supervisor_vm_init()
void boot_other_hart()
{
uintptr_t highest_va = DRAM_BASE - first_free_paddr;
mem_size = MIN(mem_size, highest_va - info.first_user_vaddr) & -MEGAPAGE_SIZE;
pte_t* sbi_pt = (pte_t*)(info.first_vaddr_after_user + info.load_offset);
memset(sbi_pt, 0, RISCV_PGSIZE);
pte_t* middle_pt = (void*)sbi_pt + RISCV_PGSIZE;
#if __riscv_xlen == 32
size_t num_middle_pts = 1;
pte_t* root_pt = middle_pt;
memset(root_pt, 0, RISCV_PGSIZE);
#else
size_t num_middle_pts = (-info.first_user_vaddr - 1) / GIGAPAGE_SIZE + 1;
pte_t* root_pt = (void*)middle_pt + num_middle_pts * RISCV_PGSIZE;
memset(middle_pt, 0, (num_middle_pts + 1) * RISCV_PGSIZE);
for (size_t i = 0; i < num_middle_pts; i++)
root_pt[(1<<RISCV_PGLEVEL_BITS)-num_middle_pts+i] = ptd_create(((uintptr_t)middle_pt >> RISCV_PGSHIFT) + i);
#endif
for (uintptr_t vaddr = info.first_user_vaddr, paddr = vaddr + info.load_offset, end = info.first_vaddr_after_user;
paddr < DRAM_BASE + mem_size; vaddr += MEGAPAGE_SIZE, paddr += MEGAPAGE_SIZE) {
int l2_shift = RISCV_PGLEVEL_BITS + RISCV_PGSHIFT;
size_t l2_idx = (info.first_user_vaddr >> l2_shift) & ((1 << RISCV_PGLEVEL_BITS)-1);
l2_idx += ((vaddr - info.first_user_vaddr) >> l2_shift);
middle_pt[l2_idx] = pte_create(paddr >> RISCV_PGSHIFT, PTE_G | PTE_R | PTE_W | PTE_X);
}
// map SBI at top of vaddr space
extern char _sbi_end;
uintptr_t num_sbi_pages = ((uintptr_t)&_sbi_end - DRAM_BASE - 1) / RISCV_PGSIZE + 1;
assert(num_sbi_pages <= (1 << RISCV_PGLEVEL_BITS));
for (uintptr_t i = 0; i < num_sbi_pages; i++) {
uintptr_t idx = (1 << RISCV_PGLEVEL_BITS) - num_sbi_pages + i;
sbi_pt[idx] = pte_create((DRAM_BASE / RISCV_PGSIZE) + i, PTE_G | PTE_R | PTE_X);
}
pte_t* sbi_pte = middle_pt + ((num_middle_pts << RISCV_PGLEVEL_BITS)-1);
assert(!*sbi_pte);
*sbi_pte = ptd_create((uintptr_t)sbi_pt >> RISCV_PGSHIFT);
while (!elf_loaded)
;
mb();
root_page_table = root_pt;
write_csr(sptbr, ((uintptr_t)root_pt >> RISCV_PGSHIFT) | SPTBR_MODE);
enter_supervisor_mode((void *)info.entry + info.load_offset, read_csr(mhartid), 0);
}
void boot_loader()
{
extern char _payload_start, _payload_end;
load_kernel_elf(&_payload_start, &_payload_end - &_payload_start, &info);
supervisor_vm_init();
#ifdef PK_ENABLE_LOGO
print_logo();
#endif
mb();
elf_loaded = 1;
enter_supervisor_mode((void *)info.entry, 0);
}
void boot_other_hart()
{
while (!elf_loaded)
;
mb();
enter_supervisor_mode((void *)info.entry, 0);
boot_other_hart();
}

22
dummy_payload/dummy_entry.S

@ -0,0 +1,22 @@
#include "mcall.h"
.section ".text.init"
.globl _start
_start:
la s0, str
1:
lbu a0, (s0)
beqz a0, 1f
li a7, MCALL_CONSOLE_PUTCHAR
ecall
add s0, s0, 1
j 1b
1:
li a7, MCALL_SHUTDOWN
ecall
.data
str:
.asciz "This is bbl's dummy_payload. To boot a real kernel, reconfigure\n\
bbl with the flag --with-payload=PATH, then rebuild bbl.\n"

21
dummy_payload/dummy_payload.c

@ -1,21 +0,0 @@
#include <stdint.h>
#include "sbi.h"
asm (".globl _start\n\
_start: la sp, stack\n\
j entry\n\
.pushsection .rodata\n\
.align 4\n\
.skip 4096\n\
stack:\n\
.popsection");
void entry()
{
const char* message =
"This is bbl's dummy_payload. To boot a real kernel, reconfigure\n\
bbl with the flag --with-payload=PATH, then rebuild bbl.\n";
while (*message)
sbi_console_putchar(*message++);
sbi_shutdown();
}

4
dummy_payload/dummy_payload.lds

@ -1,3 +1,7 @@
ENTRY(_start)
SECTIONS {
. = -0x80000000;
.text.init : { *(.text.init) }
}

2
dummy_payload/dummy_payload.mk.in

@ -5,7 +5,7 @@ dummy_payload_hdrs = \
dummy_payload_c_srcs = \
dummy_payload_asm_srcs = \
dummy_sbi.S \
dummy_entry.S \
dummy_payload_test_srcs =

1
dummy_payload/dummy_sbi.S

@ -1 +0,0 @@
../machine/sbi.S

4
machine/machine.mk.in

@ -11,7 +11,6 @@ machine_hdrs = \
htif.h \
mcall.h \
mtrap.h \
sbi.h \
unprivileged_memory.h \
vm.h \
@ -24,11 +23,8 @@ machine_c_srcs = \
fp_emulation.c \
fp_ldst.c \
misaligned_ldst.c \
sbi_impl.c \
configstring.c \
machine_asm_srcs = \
mentry.S \
fp_asm.S \
sbi_entry.S \
sbi.S \

7
machine/mcall.h

@ -1,7 +1,6 @@
#ifndef _RISCV_MCALL_H
#define _RISCV_MCALL_H
#define MCALL_HART_ID 0
#define MCALL_CONSOLE_PUTCHAR 1
#define MCALL_CONSOLE_GETCHAR 2
#define MCALL_SEND_IPI 4
@ -11,10 +10,4 @@
#define MCALL_REMOTE_SFENCE_VM 8
#define MCALL_REMOTE_FENCE_I 9
#ifndef __ASSEMBLER__
extern uintptr_t do_mcall(uintptr_t which, ...);
#endif
#endif

9
machine/minit.c

@ -141,7 +141,7 @@ void init_other_hart()
boot_other_hart();
}
void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t stack)
void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1)
{
uintptr_t mstatus = read_csr(mstatus);
mstatus = INSERT_FIELD(mstatus, MSTATUS_MPP, PRV_S);
@ -149,7 +149,10 @@ void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t stack)
write_csr(mstatus, mstatus);
write_csr(mscratch, MACHINE_STACK_TOP() - MENTRY_FRAME_SIZE);
write_csr(mepc, fn);
write_csr(sptbr, ((uintptr_t)root_page_table >> RISCV_PGSHIFT) | SPTBR_MODE);
asm volatile ("mv a0, %0; mv sp, %0; mret" : : "r" (stack));
write_csr(sptbr, 0);
register uintptr_t a0 asm ("a0") = arg0;
register uintptr_t a1 asm ("a1") = arg1;
asm volatile ("mret" : : "r" (a0), "r" (a1));
__builtin_unreachable();
}

8
machine/mtrap.c

@ -13,11 +13,6 @@ void __attribute__((noreturn)) bad_trap()
die("machine mode: unhandlable trap %d @ %p", read_csr(mcause), read_csr(mepc));
}
static uintptr_t mcall_hart_id()
{
return read_const_csr(mhartid);
}
uintptr_t timer_interrupt()
{
// just send the timer interrupt to the supervisor
@ -156,9 +151,6 @@ void mcall_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc)
uintptr_t n = regs[17], arg0 = regs[10], arg1 = regs[11], retval;
switch (n)
{
case MCALL_HART_ID:
retval = mcall_hart_id();
break;
case MCALL_CONSOLE_PUTCHAR:
retval = mcall_console_putchar(arg0);
break;

3
machine/mtrap.h

@ -11,7 +11,6 @@
#ifndef __ASSEMBLER__
#include "sbi.h"
#include <stdint.h>
#include <stddef.h>
@ -68,7 +67,7 @@ void putstring(const char* s);
#define assert(x) ({ if (!(x)) die("assertion failed: %s", #x); })
#define die(str, ...) ({ printm("%s:%d: " str "\n", __FILE__, __LINE__, ##__VA_ARGS__); poweroff(); })
void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t stack)
void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1)
__attribute__((noreturn));
void boot_loader();
void boot_other_hart();

15
machine/sbi.S

@ -1,15 +0,0 @@
.globl sbi_hart_id; sbi_hart_id = -2048
.globl sbi_num_harts; sbi_num_harts = -2032
.globl sbi_query_memory; sbi_query_memory = -2016
.globl sbi_console_putchar; sbi_console_putchar = -2000
.globl sbi_console_getchar; sbi_console_getchar = -1984
.globl sbi_send_ipi; sbi_send_ipi = -1952
.globl sbi_clear_ipi; sbi_clear_ipi = -1936
.globl sbi_timebase; sbi_timebase = -1920
.globl sbi_shutdown; sbi_shutdown = -1904
.globl sbi_set_timer; sbi_set_timer = -1888
.globl sbi_mask_interrupt; sbi_mask_interrupt = -1872
.globl sbi_unmask_interrupt; sbi_unmask_interrupt = -1856
.globl sbi_remote_sfence_vm; sbi_remote_sfence_vm = -1840
.globl sbi_remote_sfence_vm_range; sbi_remote_sfence_vm_range = -1824
.globl sbi_remote_fence_i; sbi_remote_fence_i = -1808

30
machine/sbi.h

@ -1,30 +0,0 @@
#ifndef _ASM_RISCV_SBI_H
#define _ASM_RISCV_SBI_H
typedef struct {
unsigned long base;
unsigned long size;
unsigned long node_id;
} memory_block_info;
unsigned long sbi_query_memory(unsigned long id, memory_block_info *p);
unsigned long sbi_hart_id(void);
unsigned long sbi_num_harts(void);
unsigned long sbi_timebase(void);
void sbi_set_timer(unsigned long long stime_value);
void sbi_send_ipi(unsigned long hart_id);
unsigned long sbi_clear_ipi(void);
void sbi_shutdown(void);
void sbi_console_putchar(unsigned char ch);
int sbi_console_getchar(void);
void sbi_remote_sfence_vm(unsigned long hart_mask_ptr, unsigned long asid);
void sbi_remote_sfence_vm_range(unsigned long hart_mask_ptr, unsigned long asid, unsigned long start, unsigned long size);
void sbi_remote_fence_i(unsigned long hart_mask_ptr);
unsigned long sbi_mask_interrupt(unsigned long which);
unsigned long sbi_unmask_interrupt(unsigned long which);
#endif

111
machine/sbi_entry.S

@ -1,111 +0,0 @@
#include "encoding.h"
#include "mcall.h"
.section .sbi,"ax",@progbits
.option norvc
.align RISCV_PGSHIFT
.globl sbi_base
sbi_base:
# TODO: figure out something better to do with this space. It's not
# protected from the OS, so beware.
.skip RISCV_PGSIZE - 2048
# hart_id
.align 4
li a7, MCALL_HART_ID
ecall
ret
# num_harts
.align 4
lw a0, num_harts
ret
# query_memory
.align 4
tail __sbi_query_memory
# console_putchar
.align 4
li a7, MCALL_CONSOLE_PUTCHAR
ecall
ret
# console_getchar
.align 4
li a7, MCALL_CONSOLE_GETCHAR
ecall
ret
# empty
.align 4
unimp
# send ipi
.align 4
li a7, MCALL_SEND_IPI
ecall
ret
# clear ipi
.align 4
li a7, MCALL_CLEAR_IPI
ecall
ret
# timebase
.align 4
li a0, 10000000 # or, you know, we could provide the correct answer
ret
# shutdown
.align 4
li a7, MCALL_SHUTDOWN
ecall
# set_timer
.align 4
li a7, MCALL_SET_TIMER
ecall
ret
# mask_interrupt
.align 4
tail __sbi_mask_interrupt
# unmask_interrupt
.align 4
tail __sbi_unmask_interrupt
# remote_sfence_vm
.align 4
li a7, MCALL_REMOTE_SFENCE_VM
ecall
ret
# remote_sfence_vm_range
.align 4
li a7, MCALL_REMOTE_SFENCE_VM
ecall
ret
# remote_fence_i
.align 4
li a7, MCALL_REMOTE_FENCE_I
ecall
ret
# end of SBI trampolines
.globl do_mcall
do_mcall:
mv a7, a0
mv a0, a1
mv a1, a2
ecall
ret
.align RISCV_PGSHIFT
.globl _sbi_end
_sbi_end:

33
machine/sbi_impl.c

@ -1,33 +0,0 @@
#include "mtrap.h"
#include "sbi.h"
uintptr_t __sbi_query_memory(uintptr_t id, memory_block_info *p)
{
if (id == 0) {
p->base = first_free_paddr;
p->size = mem_size + DRAM_BASE - p->base;
return 0;
}
return -1;
}
#define LOW_IRQ_OK(n) ((n) == IRQ_S_SOFT || (n) == IRQ_S_TIMER)
uintptr_t __sbi_mask_interrupt(uintptr_t which)
{
if (!LOW_IRQ_OK(which))
return -1;
clear_csr(sie, 1UL << which);
return 0;
}
uintptr_t __sbi_unmask_interrupt(uintptr_t which)
{
if (!LOW_IRQ_OK(which))
return -1;
set_csr(sie, 1UL << which);
return 0;
}

1
pk/frontend.c

@ -3,7 +3,6 @@
#include "pk.h"
#include "atomic.h"
#include "frontend.h"
#include "sbi.h"
#include "syscall.h"
#include "htif.h"
#include <stdint.h>

2
pk/pk.c

@ -162,7 +162,7 @@ void boot_loader()
write_csr(sie, 0);
file_init();
enter_supervisor_mode(rest_of_boot_loader, pk_vm_init());
enter_supervisor_mode(rest_of_boot_loader, pk_vm_init(), 0);
}
void boot_other_hart()

Loading…
Cancel
Save