Welcome the RISC-V 64-bit kernel.

This is the final step required allowing to compile and to run RISC-V
kernel and userland from HEAD.

RISC-V is a completely open ISA that is freely available to academia
and industry.

Thanks to all the people involved! Special thanks to Andrew Turner,
David Chisnall, Ed Maste, Konstantin Belousov, John Baldwin and
Arun Thomas for their help.
Thanks to Robert Watson for organizing this project.

This project sponsored by UK Higher Education Innovation Fund (HEIF5) and
DARPA CTSRD project at the University of Cambridge Computer Laboratory.

FreeBSD/RISC-V project home: https://wiki.freebsd.org/riscv

Reviewed by:	andrew, emaste, kib
Relnotes:	Yes
Sponsored by:	DARPA, AFRL
Sponsored by:	HEIF5
Differential Revision:	https://reviews.freebsd.org/D4982
This commit is contained in:
br 2016-01-29 15:12:31 +00:00
parent 6c0e620fdb
commit 778a34fa2a
50 changed files with 10865 additions and 2 deletions

View File

@ -0,0 +1,92 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/dts-v1/;
/ {
model = "UC Berkeley Spike Simulator RV64I";
compatible = "riscv,rv64i";
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <1>;
aliases {
console0 = &console0;
};
memory {
device_type = "memory";
reg = <0x0 0x8000000>; /* 128MB at 0x0 */
};
soc {
#address-cells = <2>;
#size-cells = <2>;
#interrupt-cells = <1>;
compatible = "simple-bus";
ranges;
pic0: pic@0 {
compatible = "riscv,pic";
interrupt-controller;
};
timer0: timer@0 {
compatible = "riscv,timer";
interrupts = < 1 >;
interrupt-parent = < &pic0 >;
clock-frequency = < 1000000 >;
};
htif0: htif@0 {
compatible = "riscv,htif";
interrupts = < 0 >;
interrupt-parent = < &pic0 >;
console0: console@0 {
compatible = "htif,console";
status = "okay";
};
};
};
chosen {
bootargs = "-v";
stdin = "console0";
stdout = "console0";
};
};

View File

@ -0,0 +1,99 @@
/*******************************************************************
** s y s d e p . c
** Forth Inspired Command Language
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 16 Oct 1997
** Implementations of FICL external interface functions...
**
*******************************************************************/
/* $FreeBSD$ */
#ifdef TESTMAIN
#include <stdio.h>
#include <stdlib.h>
#else
#include <stand.h>
#endif
#include "ficl.h"
/*
******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith
*/
#if PORTABLE_LONGMULDIV == 0
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y)
{
DPUNS q;
u_int64_t qx;
qx = (u_int64_t)x * (u_int64_t) y;
q.hi = (u_int32_t)( qx >> 32 );
q.lo = (u_int32_t)( qx & 0xFFFFFFFFL);
return q;
}
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y)
{
UNSQR result;
u_int64_t qx, qh;
qh = q.hi;
qx = (qh << 32) | q.lo;
result.quot = qx / y;
result.rem = qx % y;
return result;
}
#endif
void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline)
{
IGNORE(pVM);
while(*msg != 0)
putchar(*(msg++));
if (fNewline)
putchar('\n');
return;
}
void *ficlMalloc (size_t size)
{
return malloc(size);
}
void *ficlRealloc (void *p, size_t size)
{
return realloc(p, size);
}
void ficlFree (void *p)
{
free(p);
}
/*
** Stub function for dictionary access control - does nothing
** by default, user can redefine to guarantee exclusive dict
** access to a single thread for updates. All dict update code
** is guaranteed to be bracketed as follows:
** ficlLockDictionary(TRUE);
** <code that updates dictionary>
** ficlLockDictionary(FALSE);
**
** Returns zero if successful, nonzero if unable to acquire lock
** befor timeout (optional - could also block forever)
*/
#if FICL_MULTITHREAD
int ficlLockDictionary(short fLock)
{
IGNORE(fLock);
return 0;
}
#endif /* FICL_MULTITHREAD */

View File

@ -0,0 +1,411 @@
/*******************************************************************
s y s d e p . h
** Forth Inspired Command Language
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 16 Oct 1997
** Ficl system dependent types and prototypes...
**
** Note: Ficl also depends on the use of "assert" when
** FICL_ROBUST is enabled. This may require some consideration
** in firmware systems since assert often
** assumes stderr/stdout.
** $Id: sysdep.h,v 1.6 2001-04-26 21:41:55-07 jsadler Exp jsadler $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
** All rights reserved.
**
** Get the latest Ficl release at http://ficl.sourceforge.net
**
** L I C E N S E and D I S C L A I M E R
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** I am interested in hearing from anyone who uses ficl. If you have
** a problem, a success story, a defect, an enhancement request, or
** if you would like to contribute to the ficl release, please send
** contact me by email at the address above.
**
** $Id: sysdep.h,v 1.6 2001-04-26 21:41:55-07 jsadler Exp jsadler $
** $FreeBSD$
*/
#if !defined (__SYSDEP_H__)
#define __SYSDEP_H__
#include <sys/types.h>
#include <stddef.h> /* size_t, NULL */
#include <setjmp.h>
#include <assert.h>
#if !defined IGNORE /* Macro to silence unused param warnings */
#define IGNORE(x) (void)(x)
#endif
/*
** TRUE and FALSE for C boolean operations, and
** portable 32 bit types for CELLs
**
*/
#if !defined TRUE
#define TRUE 1
#endif
#if !defined FALSE
#define FALSE 0
#endif
/*
** System dependent data type declarations...
*/
#if !defined INT32
#define INT32 int
#endif
#if !defined UNS32
#define UNS32 unsigned int
#endif
#if !defined UNS16
#define UNS16 unsigned short
#endif
#if !defined UNS8
#define UNS8 unsigned char
#endif
#if !defined NULL
#define NULL ((void *)0)
#endif
/*
** FICL_UNS and FICL_INT must have the same size as a void* on
** the target system. A CELL is a union of void*, FICL_UNS, and
** FICL_INT.
** (11/2000: same for FICL_FLOAT)
*/
#if !defined FICL_INT
#define FICL_INT long
#endif
#if !defined FICL_UNS
#define FICL_UNS unsigned long
#endif
#if !defined FICL_FLOAT
#define FICL_FLOAT float
#endif
/*
** Ficl presently supports values of 32 and 64 for BITS_PER_CELL
*/
#if !defined BITS_PER_CELL
#define BITS_PER_CELL 64
#endif
#if ((BITS_PER_CELL != 32) && (BITS_PER_CELL != 64))
Error!
#endif
typedef struct
{
FICL_UNS hi;
FICL_UNS lo;
} DPUNS;
typedef struct
{
FICL_UNS quot;
FICL_UNS rem;
} UNSQR;
typedef struct
{
FICL_INT hi;
FICL_INT lo;
} DPINT;
typedef struct
{
FICL_INT quot;
FICL_INT rem;
} INTQR;
/*
** B U I L D C O N T R O L S
*/
#if !defined (FICL_MINIMAL)
#define FICL_MINIMAL 0
#endif
#if (FICL_MINIMAL)
#define FICL_WANT_SOFTWORDS 0
#define FICL_WANT_FLOAT 0
#define FICL_WANT_USER 0
#define FICL_WANT_LOCALS 0
#define FICL_WANT_DEBUGGER 0
#define FICL_WANT_OOP 0
#define FICL_PLATFORM_EXTEND 0
#define FICL_MULTITHREAD 0
#define FICL_ROBUST 0
#define FICL_EXTENDED_PREFIX 0
#endif
/*
** FICL_PLATFORM_EXTEND
** Includes words defined in ficlCompilePlatform
*/
#if !defined (FICL_PLATFORM_EXTEND)
#define FICL_PLATFORM_EXTEND 1
#endif
/*
** FICL_WANT_FLOAT
** Includes a floating point stack for the VM, and words to do float operations.
** Contributed by Guy Carver
*/
#if !defined (FICL_WANT_FLOAT)
#define FICL_WANT_FLOAT 0
#endif
/*
** FICL_WANT_DEBUGGER
** Inludes a simple source level debugger
*/
#if !defined (FICL_WANT_DEBUGGER)
#define FICL_WANT_DEBUGGER 1
#endif
/*
** User variables: per-instance variables bound to the VM.
** Kinda like thread-local storage. Could be implemented in a
** VM private dictionary, but I've chosen the lower overhead
** approach of an array of CELLs instead.
*/
#if !defined FICL_WANT_USER
#define FICL_WANT_USER 1
#endif
#if !defined FICL_USER_CELLS
#define FICL_USER_CELLS 16
#endif
/*
** FICL_WANT_LOCALS controls the creation of the LOCALS wordset and
** a private dictionary for local variable compilation.
*/
#if !defined FICL_WANT_LOCALS
#define FICL_WANT_LOCALS 1
#endif
/* Max number of local variables per definition */
#if !defined FICL_MAX_LOCALS
#define FICL_MAX_LOCALS 16
#endif
/*
** FICL_WANT_OOP
** Inludes object oriented programming support (in softwords)
** OOP support requires locals and user variables!
*/
#if !(FICL_WANT_LOCALS) || !(FICL_WANT_USER)
#if !defined (FICL_WANT_OOP)
#define FICL_WANT_OOP 0
#endif
#endif
#if !defined (FICL_WANT_OOP)
#define FICL_WANT_OOP 1
#endif
/*
** FICL_WANT_SOFTWORDS
** Controls inclusion of all softwords in softcore.c
*/
#if !defined (FICL_WANT_SOFTWORDS)
#define FICL_WANT_SOFTWORDS 1
#endif
/*
** FICL_MULTITHREAD enables dictionary mutual exclusion
** wia the ficlLockDictionary system dependent function.
** Note: this implementation is experimental and poorly
** tested. Further, it's unnecessary unless you really
** intend to have multiple SESSIONS (poor choice of name
** on my part) - that is, threads that modify the dictionary
** at the same time.
*/
#if !defined FICL_MULTITHREAD
#define FICL_MULTITHREAD 0
#endif
/*
** PORTABLE_LONGMULDIV causes ficlLongMul and ficlLongDiv to be
** defined in C in sysdep.c. Use this if you cannot easily
** generate an inline asm definition
*/
#if !defined (PORTABLE_LONGMULDIV)
#define PORTABLE_LONGMULDIV 0
#endif
/*
** INLINE_INNER_LOOP causes the inner interpreter to be inline code
** instead of a function call. This is mainly because MS VC++ 5
** chokes with an internal compiler error on the function version.
** in release mode. Sheesh.
*/
#if !defined INLINE_INNER_LOOP
#if defined _DEBUG
#define INLINE_INNER_LOOP 0
#else
#define INLINE_INNER_LOOP 1
#endif
#endif
/*
** FICL_ROBUST enables bounds checking of stacks and the dictionary.
** This will detect stack over and underflows and dictionary overflows.
** Any exceptional condition will result in an assertion failure.
** (As generated by the ANSI assert macro)
** FICL_ROBUST == 1 --> stack checking in the outer interpreter
** FICL_ROBUST == 2 also enables checking in many primitives
*/
#if !defined FICL_ROBUST
#define FICL_ROBUST 2
#endif
/*
** FICL_DEFAULT_STACK Specifies the default size (in CELLs) of
** a new virtual machine's stacks, unless overridden at
** create time.
*/
#if !defined FICL_DEFAULT_STACK
#define FICL_DEFAULT_STACK 128
#endif
/*
** FICL_DEFAULT_DICT specifies the number of CELLs to allocate
** for the system dictionary by default. The value
** can be overridden at startup time as well.
** FICL_DEFAULT_ENV specifies the number of cells to allot
** for the environment-query dictionary.
*/
#if !defined FICL_DEFAULT_DICT
#define FICL_DEFAULT_DICT 12288
#endif
#if !defined FICL_DEFAULT_ENV
#define FICL_DEFAULT_ENV 260
#endif
/*
** FICL_DEFAULT_VOCS specifies the maximum number of wordlists in
** the dictionary search order. See Forth DPANS sec 16.3.3
** (file://dpans16.htm#16.3.3)
*/
#if !defined FICL_DEFAULT_VOCS
#define FICL_DEFAULT_VOCS 16
#endif
/*
** FICL_MAX_PARSE_STEPS controls the size of an array in the FICL_SYSTEM structure
** that stores pointers to parser extension functions. I would never expect to have
** more than 8 of these, so that's the default limit. Too many of these functions
** will probably exact a nasty performance penalty.
*/
#if !defined FICL_MAX_PARSE_STEPS
#define FICL_MAX_PARSE_STEPS 8
#endif
/*
** FICL_EXTENDED_PREFIX enables a bunch of extra prefixes in prefix.c and prefix.fr (if
** included as part of softcore.c)
*/
#if !defined FICL_EXTENDED_PREFIX
#define FICL_EXTENDED_PREFIX 0
#endif
/*
** FICL_ALIGN is the power of two to which the dictionary
** pointer address must be aligned. This value is usually
** either 1 or 2, depending on the memory architecture
** of the target system; 2 is safe on any 16 or 32 bit
** machine. 3 would be appropriate for a 64 bit machine.
*/
#if !defined FICL_ALIGN
#define FICL_ALIGN 3
#define FICL_ALIGN_ADD ((1 << FICL_ALIGN) - 1)
#endif
/*
** System dependent routines --
** edit the implementations in sysdep.c to be compatible
** with your runtime environment...
** ficlTextOut sends a NULL terminated string to the
** default output device - used for system error messages
** ficlMalloc and ficlFree have the same semantics as malloc and free
** in standard C
** ficlLongMul multiplies two UNS32s and returns a 64 bit unsigned
** product
** ficlLongDiv divides an UNS64 by an UNS32 and returns UNS32 quotient
** and remainder
*/
struct vm;
void ficlTextOut(struct vm *pVM, char *msg, int fNewline);
void *ficlMalloc (size_t size);
void ficlFree (void *p);
void *ficlRealloc(void *p, size_t size);
/*
** Stub function for dictionary access control - does nothing
** by default, user can redefine to guarantee exclusive dict
** access to a single thread for updates. All dict update code
** must be bracketed as follows:
** ficlLockDictionary(TRUE);
** <code that updates dictionary>
** ficlLockDictionary(FALSE);
**
** Returns zero if successful, nonzero if unable to acquire lock
** before timeout (optional - could also block forever)
**
** NOTE: this function must be implemented with lock counting
** semantics: nested calls must behave properly.
*/
#if FICL_MULTITHREAD
int ficlLockDictionary(short fLock);
#else
#define ficlLockDictionary(x) 0 /* ignore */
#endif
/*
** 64 bit integer math support routines: multiply two UNS32s
** to get a 64 bit product, & divide the product by an UNS32
** to get an UNS32 quotient and remainder. Much easier in asm
** on a 32 bit CPU than in C, which usually doesn't support
** the double length result (but it should).
*/
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y);
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y);
#endif /*__SYSDEP_H__*/

View File

@ -51,7 +51,7 @@ extern uint8_t atomic_or_8_nv(volatile uint8_t *target, uint8_t value);
extern void membar_producer(void);
#if defined(__sparc64__) || defined(__powerpc__) || defined(__arm__) || \
defined(__mips__) || defined(__aarch64__)
defined(__mips__) || defined(__aarch64__) || defined(__riscv__)
extern void atomic_or_8(volatile uint8_t *target, uint8_t value);
#else
static __inline void

View File

@ -388,6 +388,48 @@ extern "C" {
#define _DONT_USE_1275_GENERIC_NAMES
#define _HAVE_CPUID_INSN
#elif defined(__riscv__)
/*
* Define the appropriate "processor characteristics"
*/
#define _STACK_GROWS_DOWNWARD
#define _LONG_LONG_LTOH
#define _BIT_FIELDS_LTOH
#define _IEEE_754
#define _CHAR_IS_UNSIGNED
#define _BOOL_ALIGNMENT 1
#define _CHAR_ALIGNMENT 1
#define _SHORT_ALIGNMENT 2
#define _INT_ALIGNMENT 4
#define _FLOAT_ALIGNMENT 4
#define _FLOAT_COMPLEX_ALIGNMENT 4
#define _LONG_ALIGNMENT 8
#define _LONG_LONG_ALIGNMENT 8
#define _DOUBLE_ALIGNMENT 8
#define _DOUBLE_COMPLEX_ALIGNMENT 8
#define _LONG_DOUBLE_ALIGNMENT 16
#define _LONG_DOUBLE_COMPLEX_ALIGNMENT 16
#define _POINTER_ALIGNMENT 8
#define _MAX_ALIGNMENT 16
#define _ALIGNMENT_REQUIRED 1
#define _LONG_LONG_ALIGNMENT_32 _LONG_LONG_ALIGNMENT
/*
* Define the appropriate "implementation choices"
*/
#if !defined(_LP64)
#define _LP64
#endif
#define _SUNOS_VTOC_16
#define _DMA_USES_PHYSADDR
#define _FIRMWARE_NEEDS_FDISK
#define _PSM_MODULES
#define _RTC_CONFIG
#define _DONT_USE_1275_GENERIC_NAMES
#define _HAVE_CPUID_INSN
#elif defined(__arm__)
/*

49
sys/conf/Makefile.riscv Normal file
View File

@ -0,0 +1,49 @@
# Makefile.riscv -- with config changes.
# Copyright 1990 W. Jolitz
# from: @(#)Makefile.i386 7.1 5/10/91
# from FreeBSD: src/sys/conf/Makefile.i386,v 1.255 2002/02/20 23:35:49
# $FreeBSD$
#
# Makefile for FreeBSD
#
# RISCVTODO: copy pasted from aarch64, needs to be
# constructed from a machine description:
# config machineid
# Most changes should be made in the machine description
# /sys/riscv/conf/``machineid''
# after which you should do
# config machineid
# Generic makefile changes should be made in
# /sys/conf/Makefile.riscv
# after which config should be rerun for all machines.
#
# Which version of config(8) is required.
%VERSREQ= 600012
.if !defined(S)
S= ../../..
.endif
.include "$S/conf/kern.pre.mk"
INCLUDES+= -I$S/contrib/libfdt
.if !empty(DDB_ENABLED)
CFLAGS += -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
.endif
%BEFORE_DEPEND
%OBJS
%FILES.c
%FILES.s
%FILES.m
%CLEAN
%RULES
.include "$S/conf/kern.post.mk"

44
sys/conf/files.riscv Normal file
View File

@ -0,0 +1,44 @@
# $FreeBSD$
crypto/blowfish/bf_enc.c optional crypto | ipsec
crypto/des/des_enc.c optional crypto | ipsec | netsmb
kern/kern_clocksource.c standard
kern/subr_dummy_vdso_tc.c standard
libkern/bcmp.c standard
libkern/ffs.c standard
libkern/ffsl.c standard
libkern/fls.c standard
libkern/flsl.c standard
libkern/flsll.c standard
libkern/memmove.c standard
libkern/memset.c standard
riscv/htif/htif.c standard
riscv/htif/htif_block.c standard
riscv/htif/htif_console.c standard
riscv/riscv/autoconf.c standard
riscv/riscv/bcopy.c standard
riscv/riscv/bus_machdep.c standard
riscv/riscv/busdma_machdep.c standard
riscv/riscv/clock.c standard
riscv/riscv/copyinout.S standard
riscv/riscv/copystr.c standard
riscv/riscv/cpufunc_asm.S standard
riscv/riscv/devmap.c standard
riscv/riscv/dump_machdep.c standard
riscv/riscv/elf_machdep.c standard
riscv/riscv/intr_machdep.c standard
riscv/riscv/in_cksum.c optional inet | inet6
riscv/riscv/identcpu.c standard
riscv/riscv/locore.S standard no-obj
riscv/riscv/minidump_machdep.c standard
riscv/riscv/machdep.c standard
riscv/riscv/mem.c standard
riscv/riscv/nexus.c standard
riscv/riscv/pmap.c standard
riscv/riscv/sys_machdep.c standard
riscv/riscv/support.S standard
riscv/riscv/swtch.S standard
riscv/riscv/trap.c standard
riscv/riscv/timer.c standard
riscv/riscv/uio_machdep.c standard
riscv/riscv/uma_machdep.c standard
riscv/riscv/vm_machdep.c standard

View File

@ -104,6 +104,10 @@ CFLAGS += -mgeneral-regs-only
CFLAGS += -ffixed-x18
.endif
.if ${MACHINE_CPUARCH} == "riscv"
INLINE_LIMIT?= 8000
.endif
#
# For sparc64 we want the medany code model so modules may be located
# anywhere in the 64-bit address space. We also tell GCC to use floating

View File

@ -252,6 +252,7 @@ EMBEDFS_FORMAT.mips?= elf32-tradbigmips
EMBEDFS_FORMAT.mipsel?= elf32-tradlittlemips
EMBEDFS_FORMAT.mips64?= elf64-tradbigmips
EMBEDFS_FORMAT.mips64el?= elf64-tradlittlemips
EMBEDFS_FORMAT.riscv?= elf64-littleriscv
.endif
# Detect kernel config options that force stack frames to be turned on.

136
sys/conf/ldscript.riscv Normal file
View File

@ -0,0 +1,136 @@
/* $FreeBSD$ */
OUTPUT_ARCH(riscv)
ENTRY(_start)
SEARCH_DIR(/usr/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = kernbase + 0x100;
.text : AT(ADDR(.text) - kernbase)
{
*(.text)
*(.stub)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
} =0x9090
_etext = .;
PROVIDE (etext = .);
.fini : { *(.fini) } =0x9090
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.text :
{ *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text :
{ *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data :
{ *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data :
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata :
{ *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata :
{ *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x9090
.plt : { *(.plt) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(0x1000) + (. & (0x1000 - 1)) ;
.data :
{
*(.data)
*(.gnu.linkonce.d*)
CONSTRUCTORS
}
.data1 : { *(.data1) }
. = ALIGN(32 / 8);
_start_ctors = .;
PROVIDE (start_ctors = .);
.ctors :
{
*(.ctors)
}
_stop_ctors = .;
PROVIDE (stop_ctors = .);
.dtors :
{
*(.dtors)
}
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
. = ALIGN(8);
.sdata : { *(.sdata) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss : { *(.sbss) *(.scommon) }
.bss :
{
*(.dynbss)
*(.bss)
*(COMMON)
}
. = ALIGN(8);
_end = . ;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}

4
sys/conf/options.riscv Normal file
View File

@ -0,0 +1,4 @@
# $FreeBSD$
RISCV opt_global.h
VFP opt_global.h

View File

@ -0,0 +1,51 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by the University of Cambridge Computer
* Laboratory with support from ARM Ltd.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _DEV_HWPMC_RISCV_H_
#define _DEV_HWPMC_RISCV_H_
#define RISCV_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_USER | \
PMC_CAP_SYSTEM | PMC_CAP_EDGE | \
PMC_CAP_THRESHOLD | PMC_CAP_READ | \
PMC_CAP_WRITE | PMC_CAP_INVERT | \
PMC_CAP_QUALIFIER)
#define RISCV_RELOAD_COUNT_TO_PERFCTR_VALUE(R) (-(R))
#define RISCV_PERFCTR_VALUE_TO_RELOAD_COUNT(P) (-(P))
#define EVENT_ID_MASK 0xFF
#ifdef _KERNEL
/* MD extension for 'struct pmc' */
struct pmc_md_riscv_pmc {
uint32_t pm_riscv_evsel;
};
#endif /* _KERNEL */
#endif /* _DEV_HWPMC_RISCV_H_ */

13
sys/riscv/conf/DEFAULTS Normal file
View File

@ -0,0 +1,13 @@
#
# DEFAULTS -- Default kernel configuration file for FreeBSD/RISC-V
#
# $FreeBSD$
machine riscv riscv64
# Pseudo devices.
device mem # Memory and kernel memory devices
# Default partitioning schemes
options GEOM_PART_BSD
options GEOM_PART_MBR

104
sys/riscv/conf/GENERIC Normal file
View File

@ -0,0 +1,104 @@
#
# GENERIC -- Generic kernel configuration file for FreeBSD/RISC-V
#
# For more information on this file, please read the config(5) manual page,
# and/or the handbook section on Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
# device lines is also present in the ../../conf/NOTES and NOTES files.
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
cpu RISCV
ident GENERIC
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
# makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support
makeoptions NO_MODULES=1 # We don't yet support modules on RISC-V
options SCHED_ULE # ULE scheduler
options PREEMPTION # Enable kernel thread preemption
options INET # InterNETworking
options INET6 # IPv6 communications protocols
options IPSEC # IP (v4/v6) security
options TCP_OFFLOAD # TCP offload
options SCTP # Stream Control Transmission Protocol
options FFS # Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
options QUOTA # Enable disk quotas for UFS
options MD_ROOT # MD is a potential root device
options NFSCL # Network Filesystem Client
options NFSD # Network Filesystem Server
options NFSLOCKD # Network Lock Manager
options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
options PSEUDOFS # Pseudo-filesystem framework
options GEOM_PART_GPT # GUID Partition Tables.
# options GEOM_RAID # Soft RAID functionality.
options GEOM_LABEL # Provides labelization
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
# options STACK # stack(9) support
options SYSVSHM # SYSV-style shared memory
options SYSVMSG # SYSV-style message queues
options SYSVSEM # SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions
options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed.
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
# options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4)
options AUDIT # Security event auditing
options CAPABILITY_MODE # Capsicum capability mode
options CAPABILITIES # Capsicum capabilities
options MAC # TrustedBSD MAC Framework
# options KDTRACE_FRAME # Ensure frames are compiled in
# options KDTRACE_HOOKS # Kernel DTrace hooks
# options VFP # Floating-point support
options RACCT # Resource accounting framework
options RACCT_DEFAULT_TO_DISABLED # Set kern.racct.enable=0 by default
options RCTL # Resource limits
# options SMP
# Debugging support. Always need this:
# options KDB # Enable kernel debugger support.
# options KDB_TRACE # Print a stack trace for a panic.
# For full debugger support use (turn off in stable branch):
# options DDB # Support DDB.
# options GDB # Support remote GDB.
options DEADLKRES # Enable the deadlock resolver
options INVARIANTS # Enable calls of extra sanity checking
options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
# options WITNESS # Enable checks to detect deadlocks and cycles
# options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
options MALLOC_DEBUG_MAXZONES=8 # Separate malloc(9) zones
options ROOTDEVNAME=\"ufs:/dev/htif_blk0\"
# options EARLY_PRINTF
# Pseudo devices.
device loop # Network loopback
device random # Entropy device
device ether # Ethernet support
device vlan # 802.1Q VLAN support
device tun # Packet tunnel.
device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
device firmware # firmware assist module
# RISCVTODO: This needs to be done via loader (when it's available).
options FDT
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=spike.dts

284
sys/riscv/htif/htif.c Normal file
View File

@ -0,0 +1,284 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <machine/asm.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include "htif.h"
static struct resource_spec htif_spec[] = {
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ -1, 0 }
};
struct intr_entry {
void (*func) (void *, uint64_t);
void *arg;
};
struct intr_entry intrs[HTIF_NDEV];
uint64_t
htif_command(uint64_t arg)
{
return (machine_command(ECALL_HTIF_CMD, arg));
}
int
htif_setup_intr(int id, void *func, void *arg)
{
if (id >= HTIF_NDEV)
return (-1);
intrs[id].func = func;
intrs[id].arg = arg;
return (0);
}
static void
htif_handle_entry(struct htif_softc *sc)
{
uint64_t entry;
uint8_t devcmd;
uint8_t devid;
entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
while (entry) {
devid = HTIF_DEV_ID(entry);
devcmd = HTIF_DEV_CMD(entry);
if (devcmd == HTIF_CMD_IDENTIFY) {
/* Enumeration interrupt */
if (devid == sc->identify_id)
sc->identify_done = 1;
} else {
/* Device interrupt */
if (intrs[devid].func != NULL)
intrs[devid].func(intrs[devid].arg, entry);
}
entry = machine_command(ECALL_HTIF_GET_ENTRY, 0);
}
}
static int
htif_intr(void *arg)
{
struct htif_softc *sc;
sc = arg;
htif_handle_entry(sc);
csr_clear(sip, SIE_SSIE);
return (FILTER_HANDLED);
}
static int
htif_add_device(struct htif_softc *sc, int i, char *id, char *name)
{
struct htif_dev_ivars *di;
di = malloc(sizeof(struct htif_dev_ivars), M_DEVBUF, M_WAITOK | M_ZERO);
di->sc = sc;
di->index = i;
di->id = malloc(HTIF_ID_LEN, M_DEVBUF, M_WAITOK | M_ZERO);
memcpy(di->id, id, HTIF_ID_LEN);
di->dev = device_add_child(sc->dev, name, -1);
device_set_ivars(di->dev, di);
return (0);
}
static int
htif_enumerate(struct htif_softc *sc)
{
char id[HTIF_ID_LEN] __aligned(HTIF_ALIGN);
uint64_t paddr;
uint64_t data;
uint64_t cmd;
int len;
int i;
device_printf(sc->dev, "Enumerating devices\n");
for (i = 0; i < HTIF_NDEV; i++) {
paddr = pmap_kextract((vm_offset_t)&id);
data = (paddr << IDENTIFY_PADDR_SHIFT);
data |= IDENTIFY_IDENT;
sc->identify_id = i;
sc->identify_done = 0;
cmd = i;
cmd <<= HTIF_DEV_ID_SHIFT;
cmd |= (HTIF_CMD_IDENTIFY << HTIF_CMD_SHIFT);
cmd |= data;
htif_command(cmd);
/* Do poll as interrupts are disabled yet */
while (sc->identify_done == 0) {
htif_handle_entry(sc);
}
len = strnlen(id, sizeof(id));
if (len <= 0) {
continue;
}
if (bootverbose)
printf(" %d %s\n", i, id);
if (strncmp(id, "disk", 4) == 0)
htif_add_device(sc, i, id, "htif_blk");
else if (strncmp(id, "bcd", 3) == 0)
htif_add_device(sc, i, id, "htif_console");
else if (strncmp(id, "syscall_proxy", 13) == 0)
htif_add_device(sc, i, id, "htif_syscall_proxy");
}
return (bus_generic_attach(sc->dev));
}
int
htif_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct htif_dev_ivars *ivars;
ivars = device_get_ivars(child);
switch (which) {
case HTIF_IVAR_INDEX:
*result = ivars->index;
break;
case HTIF_IVAR_ID:
*result = (uintptr_t)ivars->id;
default:
return (EINVAL);
}
return (0);
}
static int
htif_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "riscv,htif"))
return (ENXIO);
device_set_desc(dev, "HTIF bus device");
return (BUS_PROBE_DEFAULT);
}
static int
htif_attach(device_t dev)
{
struct htif_softc *sc;
int error;
sc = device_get_softc(dev);
sc->dev = dev;
if (bus_alloc_resources(dev, htif_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
/* Setup IRQs handler */
error = bus_setup_intr(dev, sc->res[0], INTR_TYPE_CLK,
htif_intr, NULL, sc, &sc->ihl[0]);
if (error) {
device_printf(dev, "Unable to alloc int resource.\n");
return (ENXIO);
}
csr_set(sie, SIE_SSIE);
return (htif_enumerate(sc));
}
static device_method_t htif_methods[] = {
DEVMETHOD(device_probe, htif_probe),
DEVMETHOD(device_attach, htif_attach),
/* Bus interface */
DEVMETHOD(bus_read_ivar, htif_read_ivar),
DEVMETHOD_END
};
static driver_t htif_driver = {
"htif",
htif_methods,
sizeof(struct htif_softc)
};
static devclass_t htif_devclass;
DRIVER_MODULE(htif, simplebus, htif_driver,
htif_devclass, 0, 0);

93
sys/riscv/htif/htif.h Normal file
View File

@ -0,0 +1,93 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#define HTIF_DEV_ID_SHIFT (56)
#define HTIF_DEV_ID_MASK (0xfful << HTIF_DEV_ID_SHIFT)
#define HTIF_CMD_SHIFT (48)
#define HTIF_CMD_MASK (0xfful << HTIF_CMD_SHIFT)
#define HTIF_DATA_SHIFT (0)
#define HTIF_DATA_MASK (0xffffffff << HTIF_DATA_SHIFT)
#define HTIF_CMD_READ (0x00ul)
#define HTIF_CMD_WRITE (0x01ul)
#define HTIF_CMD_READ_CONTROL_REG (0x02ul)
#define HTIF_CMD_WRITE_CONTROL_REG (0x03ul)
#define HTIF_CMD_IDENTIFY (0xfful)
#define IDENTIFY_PADDR_SHIFT 8
#define IDENTIFY_IDENT 0xff
#define HTIF_NDEV (256)
#define HTIF_ID_LEN (64)
#define HTIF_ALIGN (64)
#define HTIF_DEV_CMD(entry) ((entry & HTIF_CMD_MASK) >> HTIF_CMD_SHIFT)
#define HTIF_DEV_ID(entry) ((entry & HTIF_DEV_ID_MASK) >> HTIF_DEV_ID_SHIFT)
#define HTIF_DEV_DATA(entry) ((entry & HTIF_DATA_MASK) >> HTIF_DATA_SHIFT)
/* bus softc */
struct htif_softc {
struct resource *res[1];
void *ihl[1];
device_t dev;
uint64_t identify_id;
uint64_t identify_done;
};
/* device private data */
struct htif_dev_ivars {
char *id;
int index;
device_t dev;
struct htif_softc *sc;
};
uint64_t htif_command(uint64_t);
int htif_setup_intr(int id, void *func, void *arg);
int htif_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
enum htif_device_ivars {
HTIF_IVAR_INDEX,
HTIF_IVAR_ID,
};
/*
* Simplified accessors for HTIF devices
*/
#define HTIF_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(htif, var, HTIF, ivar, type)
HTIF_ACCESSOR(index, INDEX, int);
HTIF_ACCESSOR(id, ID, char *);

289
sys/riscv/htif/htif_block.c Normal file
View File

@ -0,0 +1,289 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/selinfo.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
#include <sys/sysctl.h>
#include <sys/uio.h>
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/disk.h>
#include <geom/geom_disk.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/md_var.h>
#include <machine/bus.h>
#include <machine/trap.h>
#include <sys/rman.h>
#include "htif.h"
#define SECTOR_SIZE_SHIFT (9)
#define SECTOR_SIZE (1 << SECTOR_SIZE_SHIFT)
#define HTIF_BLK_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define HTIF_BLK_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define HTIF_BLK_LOCK_INIT(_sc) \
mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
"htif_blk", MTX_DEF)
#define HTIF_BLK_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
#define HTIF_BLK_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
#define HTIF_BLK_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
static void htif_blk_task(void *arg);
static disk_open_t htif_blk_open;
static disk_close_t htif_blk_close;
static disk_strategy_t htif_blk_strategy;
struct htif_blk_softc {
device_t dev;
struct disk *disk;
struct mtx htif_io_mtx;
struct mtx sc_mtx;
struct proc *p;
struct bio_queue_head bio_queue;
int running;
int intr_chan;
int cmd_done;
int index;
uint16_t curtag;
};
struct htif_blk_request {
uint64_t addr;
uint64_t offset; /* offset in bytes */
uint64_t size; /* length in bytes */
uint64_t tag;
};
static void
htif_blk_intr(void *arg, uint64_t entry)
{
struct htif_blk_softc *sc;
uint64_t devcmd;
uint64_t data;
sc = arg;
devcmd = HTIF_DEV_CMD(entry);
data = HTIF_DEV_DATA(entry);
if (sc->curtag == data) {
sc->cmd_done = 1;
wakeup(&sc->intr_chan);
}
}
static int
htif_blk_probe(device_t dev)
{
return (0);
}
static int
htif_blk_attach(device_t dev)
{
struct htif_blk_softc *sc;
char prefix[] = " size=";
char *str;
long size;
sc = device_get_softc(dev);
sc->dev = dev;
mtx_init(&sc->htif_io_mtx, device_get_nameunit(dev), "htif_blk", MTX_DEF);
HTIF_BLK_LOCK_INIT(sc);
str = strstr(htif_get_id(dev), prefix);
size = strtol((str + 6), NULL, 10);
if (size == 0) {
return (ENXIO);
}
sc->index = htif_get_index(dev);
if (sc->index < 0)
return (EINVAL);
htif_setup_intr(sc->index, htif_blk_intr, sc);
sc->disk = disk_alloc();
sc->disk->d_drv1 = sc;
sc->disk->d_maxsize = 4096; /* Max transfer */
sc->disk->d_name = "htif_blk";
sc->disk->d_open = htif_blk_open;
sc->disk->d_close = htif_blk_close;
sc->disk->d_strategy = htif_blk_strategy;
sc->disk->d_unit = 0;
sc->disk->d_sectorsize = SECTOR_SIZE;
sc->disk->d_mediasize = size;
disk_create(sc->disk, DISK_VERSION);
bioq_init(&sc->bio_queue);
sc->running = 1;
kproc_create(&htif_blk_task, sc, &sc->p, 0, 0, "%s: transfer",
device_get_nameunit(dev));
return (0);
}
static int
htif_blk_open(struct disk *dp)
{
return (0);
}
static int
htif_blk_close(struct disk *dp)
{
return (0);
}
static void
htif_blk_task(void *arg)
{
struct htif_blk_request req __aligned(HTIF_ALIGN);
struct htif_blk_softc *sc;
struct bio *bp;
uint64_t paddr;
uint64_t cmd;
int i;
sc = (struct htif_blk_softc *)arg;
while (1) {
HTIF_BLK_LOCK(sc);
do {
bp = bioq_takefirst(&sc->bio_queue);
if (bp == NULL)
msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
} while (bp == NULL);
HTIF_BLK_UNLOCK(sc);
if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
req.offset = (bp->bio_pblkno * sc->disk->d_sectorsize);
req.size = bp->bio_bcount;
paddr = vtophys(bp->bio_data);
KASSERT(paddr != 0, ("paddr is 0"));
req.addr = paddr;
req.tag = sc->curtag;
cmd = sc->index;
cmd <<= HTIF_DEV_ID_SHIFT;
if (bp->bio_cmd == BIO_READ)
cmd |= (HTIF_CMD_READ << HTIF_CMD_SHIFT);
else
cmd |= (HTIF_CMD_WRITE << HTIF_CMD_SHIFT);
paddr = vtophys(&req);
KASSERT(paddr != 0, ("paddr is 0"));
cmd |= paddr;
sc->cmd_done = 0;
htif_command(cmd);
/* Wait for interrupt */
HTIF_BLK_LOCK(sc);
i = 0;
while (sc->cmd_done == 0) {
msleep(&sc->intr_chan, &sc->sc_mtx, PRIBIO, "intr", hz/2);
if (i++ > 2) {
/* TODO: try to re-issue operation on timeout ? */
bp->bio_error = EIO;
bp->bio_flags |= BIO_ERROR;
disk_err(bp, "hard error", -1, 1);
break;
}
}
HTIF_BLK_UNLOCK(sc);
biodone(bp);
} else {
printf("unknown op %d\n", bp->bio_cmd);
}
}
}
static void
htif_blk_strategy(struct bio *bp)
{
struct htif_blk_softc *sc;
sc = bp->bio_disk->d_drv1;
HTIF_BLK_LOCK(sc);
if (sc->running > 0) {
bioq_disksort(&sc->bio_queue, bp);
HTIF_BLK_UNLOCK(sc);
wakeup(sc);
} else {
HTIF_BLK_UNLOCK(sc);
biofinish(bp, NULL, ENXIO);
}
}
static device_method_t htif_blk_methods[] = {
DEVMETHOD(device_probe, htif_blk_probe),
DEVMETHOD(device_attach, htif_blk_attach),
};
static driver_t htif_blk_driver = {
"htif_blk",
htif_blk_methods,
sizeof(struct htif_blk_softc)
};
static devclass_t htif_blk_devclass;
DRIVER_MODULE(htif_blk, htif, htif_blk_driver, htif_blk_devclass, 0, 0);

View File

@ -0,0 +1,361 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/priv.h>
#include <sys/systm.h>
#include <sys/types.h>
#include <sys/conf.h>
#include <sys/cons.h>
#include <sys/consio.h>
#include <sys/tty.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <machine/trap.h>
#include "htif.h"
#include <dev/ofw/openfirm.h>
#include <ddb/ddb.h>
extern uint64_t console_intr;
static tsw_outwakeup_t riscvtty_outwakeup;
static struct ttydevsw riscv_ttydevsw = {
.tsw_flags = TF_NOPREFIX,
.tsw_outwakeup = riscvtty_outwakeup,
};
static int polltime;
static struct callout riscv_callout;
static struct tty *tp = NULL;
#if defined(KDB)
static int alt_break_state;
#endif
static void riscv_timeout(void *);
static cn_probe_t riscv_cnprobe;
static cn_init_t riscv_cninit;
static cn_term_t riscv_cnterm;
static cn_getc_t riscv_cngetc;
static cn_putc_t riscv_cnputc;
static cn_grab_t riscv_cngrab;
static cn_ungrab_t riscv_cnungrab;
CONSOLE_DRIVER(riscv);
#define MAX_BURST_LEN 1
#define QUEUE_SIZE 256
#define CONSOLE_DEFAULT_ID 1ul
struct queue_entry {
uint64_t data;
uint64_t used;
struct queue_entry *next;
};
struct queue_entry cnqueue[QUEUE_SIZE];
struct queue_entry *entry_last;
struct queue_entry *entry_served;
static void
htif_putc(int c)
{
uint64_t cmd;
cmd = (HTIF_CMD_WRITE << HTIF_CMD_SHIFT);
cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
cmd |= c;
htif_command(cmd);
}
static uint8_t
htif_getc(void)
{
uint64_t cmd;
uint8_t res;
cmd = (HTIF_CMD_READ << HTIF_CMD_SHIFT);
cmd |= (CONSOLE_DEFAULT_ID << HTIF_DEV_ID_SHIFT);
res = htif_command(cmd);
return (res);
}
static void
riscv_putc(int c)
{
uint64_t counter;
uint64_t *cc;
uint64_t val;
val = 0;
counter = 0;
cc = (uint64_t*)&console_intr;
*cc = 0;
htif_putc(c);
/* Wait for an interrupt */
__asm __volatile(
"li %0, 1\n" /* counter = 1 */
"slli %0, %0, 12\n" /* counter <<= 12 */
"1:"
"addi %0, %0, -1\n" /* counter -= 1 */
"beqz %0, 2f\n" /* counter == 0 ? finish */
"ld %1, 0(%2)\n" /* val = *cc */
"beqz %1, 1b\n" /* val == 0 ? repeat */
"2:"
: "=&r"(counter), "=&r"(val) : "r"(cc)
);
}
#ifdef EARLY_PRINTF
early_putc_t *early_putc = riscv_putc;
#endif
static void
cn_drvinit(void *unused)
{
if (riscv_consdev.cn_pri != CN_DEAD &&
riscv_consdev.cn_name[0] != '\0') {
tp = tty_alloc(&riscv_ttydevsw, NULL);
tty_init_console(tp, 0);
tty_makedev(tp, NULL, "%s", "rcons");
polltime = 1;
callout_init(&riscv_callout, 1);
callout_reset(&riscv_callout, polltime, riscv_timeout, NULL);
}
}
SYSINIT(cndev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, cn_drvinit, NULL);
static void
riscvtty_outwakeup(struct tty *tp)
{
u_char buf[MAX_BURST_LEN];
int len;
int i;
for (;;) {
len = ttydisc_getc(tp, buf, sizeof(buf));
if (len == 0)
break;
KASSERT(len == 1, ("tty error"));
for (i = 0; i < len; i++)
riscv_putc(buf[i]);
}
}
static void
riscv_timeout(void *v)
{
int c;
tty_lock(tp);
while ((c = riscv_cngetc(NULL)) != -1)
ttydisc_rint(tp, c, 0);
ttydisc_rint_done(tp);
tty_unlock(tp);
callout_reset(&riscv_callout, polltime, riscv_timeout, NULL);
}
static void
riscv_cnprobe(struct consdev *cp)
{
cp->cn_pri = CN_NORMAL;
}
static void
riscv_cninit(struct consdev *cp)
{
int i;
strcpy(cp->cn_name, "rcons");
for (i = 0; i < QUEUE_SIZE; i++) {
if (i == (QUEUE_SIZE - 1))
cnqueue[i].next = &cnqueue[0];
else
cnqueue[i].next = &cnqueue[i+1];
cnqueue[i].data = 0;
cnqueue[i].used = 0;
}
entry_last = &cnqueue[0];
entry_served = &cnqueue[0];
}
static void
riscv_cnterm(struct consdev *cp)
{
}
static void
riscv_cngrab(struct consdev *cp)
{
}
static void
riscv_cnungrab(struct consdev *cp)
{
}
static int
riscv_cngetc(struct consdev *cp)
{
uint8_t data;
int ch;
ch = htif_getc();
if (entry_served->used == 1) {
data = entry_served->data;
entry_served->used = 0;
entry_served = entry_served->next;
ch = (data & 0xff);
if (ch > 0 && ch < 0xff) {
#if defined(KDB)
kdb_alt_break(ch, &alt_break_state);
#endif
return (ch);
}
}
return (-1);
}
static void
riscv_cnputc(struct consdev *cp, int c)
{
riscv_putc(c);
}
/*
* Bus interface.
*/
struct htif_console_softc {
device_t dev;
int running;
int intr_chan;
int cmd_done;
int curtag;
int index;
};
static void
htif_console_intr(void *arg, uint64_t entry)
{
struct htif_console_softc *sc;
uint8_t devcmd;
uint64_t data;
sc = arg;
devcmd = HTIF_DEV_CMD(entry);
data = HTIF_DEV_DATA(entry);
if (devcmd == 0) {
entry_last->data = data;
entry_last->used = 1;
entry_last = entry_last->next;
}
}
static int
htif_console_probe(device_t dev)
{
return (0);
}
static int
htif_console_attach(device_t dev)
{
struct htif_console_softc *sc;
sc = device_get_softc(dev);
sc->dev = dev;
sc->index = htif_get_index(dev);
if (sc->index < 0)
return (EINVAL);
htif_setup_intr(sc->index, htif_console_intr, sc);
return (0);
}
static device_method_t htif_console_methods[] = {
DEVMETHOD(device_probe, htif_console_probe),
DEVMETHOD(device_attach, htif_console_attach),
DEVMETHOD_END
};
static driver_t htif_console_driver = {
"htif_console",
htif_console_methods,
sizeof(struct htif_console_softc)
};
static devclass_t htif_console_devclass;
DRIVER_MODULE(htif_console, htif, htif_console_driver,
htif_console_devclass, 0, 0);

View File

@ -0,0 +1,94 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Setup the system to run on the current machine.
*
* Configure() is called at boot time and initializes the vba
* device tables and the memory controller monitoring. Available
* devices are determined (from possibilities mentioned in ioconf.c),
* and the drivers are initialized.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/cons.h>
static void configure_first(void *);
static void configure(void *);
static void configure_final(void *);
SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL);
/* SI_ORDER_SECOND is hookable */
SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL);
/* SI_ORDER_MIDDLE is hookable */
SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL);
/*
* Determine i/o configuration for a machine.
*/
static void
configure_first(void *dummy)
{
/* nexus0 is the top of the riscv device tree */
device_add_child(root_bus, "nexus", 0);
}
static void
configure(void *dummy)
{
/* initialize new bus architecture */
root_bus_configure();
}
static void
configure_final(void *dummy)
{
intr_enable();
cninit_finish();
if (bootverbose)
printf("Device configuration finished.\n");
cold = 0;
}

139
sys/riscv/riscv/bcopy.c Normal file
View File

@ -0,0 +1,139 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* From: sys/powerpc/powerpc/bcopy.c
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
/*
* sizeof(word) MUST BE A POWER OF TWO
* SO THAT wmask BELOW IS ALL ONES
*/
typedef long word; /* "word" used for optimal copy speed */
#define wsize sizeof(word)
#define wmask (wsize - 1)
/*
* Copy a block of memory, handling overlap.
* This is the routine that actually implements
* (the portable versions of) bcopy, memcpy, and memmove.
*/
void *
memcpy(void *dst0, const void *src0, size_t length)
{
char *dst;
const char *src;
size_t t;
dst = dst0;
src = src0;
if (length == 0 || dst == src) { /* nothing to do */
goto done;
}
/*
* Macros: loop-t-times; and loop-t-times, t>0
*/
#define TLOOP(s) if (t) TLOOP1(s)
#define TLOOP1(s) do { s; } while (--t)
if ((unsigned long)dst < (unsigned long)src) {
/*
* Copy forward.
*/
t = (size_t)src; /* only need low bits */
if ((t | (uintptr_t)dst) & wmask) {
/*
* Try to align operands. This cannot be done
* unless the low bits match.
*/
if ((t ^ (uintptr_t)dst) & wmask || length < wsize) {
t = length;
} else {
t = wsize - (t & wmask);
}
length -= t;
TLOOP1(*dst++ = *src++);
}
/*
* Copy whole words, then mop up any trailing bytes.
*/
t = length / wsize;
TLOOP(*(word *)dst = *(const word *)src; src += wsize;
dst += wsize);
t = length & wmask;
TLOOP(*dst++ = *src++);
} else {
/*
* Copy backwards. Otherwise essentially the same.
* Alignment works as before, except that it takes
* (t&wmask) bytes to align, not wsize-(t&wmask).
*/
src += length;
dst += length;
t = (uintptr_t)src;
if ((t | (uintptr_t)dst) & wmask) {
if ((t ^ (uintptr_t)dst) & wmask || length <= wsize) {
t = length;
} else {
t &= wmask;
}
length -= t;
TLOOP1(*--dst = *--src);
}
t = length / wsize;
TLOOP(src -= wsize; dst -= wsize;
*(word *)dst = *(const word *)src);
t = length & wmask;
TLOOP(*--dst = *--src);
}
done:
return (dst0);
}
void
bcopy(const void *src0, void *dst0, size_t length)
{
memcpy(dst0, src0, length);
}

View File

@ -0,0 +1,144 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "opt_platform.h"
#include <sys/param.h>
__FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/bus.h>
struct bus_space memmap_bus = {
/* cookie */
.bs_cookie = NULL,
/* mapping/unmapping */
.bs_map = NULL,
.bs_unmap = NULL,
.bs_subregion = NULL,
/* allocation/deallocation */
.bs_alloc = NULL,
.bs_free = NULL,
/* barrier */
.bs_barrier = NULL,
/* read single */
.bs_r_1 = NULL,
.bs_r_2 = NULL,
.bs_r_4 = NULL,
.bs_r_8 = NULL,
/* read multiple */
.bs_rm_1 = NULL,
.bs_rm_2 = NULL,
.bs_rm_4 = NULL,
.bs_rm_8 = NULL,
/* write single */
.bs_w_1 = NULL,
.bs_w_2 = NULL,
.bs_w_4 = NULL,
.bs_w_8 = NULL,
/* write multiple */
.bs_wm_1 = NULL,
.bs_wm_2 = NULL,
.bs_wm_4 = NULL,
.bs_wm_8 = NULL,
/* write region */
.bs_wr_1 = NULL,
.bs_wr_2 = NULL,
.bs_wr_4 = NULL,
.bs_wr_8 = NULL,
/* set multiple */
.bs_sm_1 = NULL,
.bs_sm_2 = NULL,
.bs_sm_4 = NULL,
.bs_sm_8 = NULL,
/* set region */
.bs_sr_1 = NULL,
.bs_sr_2 = NULL,
.bs_sr_4 = NULL,
.bs_sr_8 = NULL,
/* copy */
.bs_c_1 = NULL,
.bs_c_2 = NULL,
.bs_c_4 = NULL,
.bs_c_8 = NULL,
/* read single stream */
.bs_r_1_s = NULL,
.bs_r_2_s = NULL,
.bs_r_4_s = NULL,
.bs_r_8_s = NULL,
/* read multiple stream */
.bs_rm_1_s = NULL,
.bs_rm_2_s = NULL,
.bs_rm_4_s = NULL,
.bs_rm_8_s = NULL,
/* read region stream */
.bs_rr_1_s = NULL,
.bs_rr_2_s = NULL,
.bs_rr_4_s = NULL,
.bs_rr_8_s = NULL,
/* write single stream */
.bs_w_1_s = NULL,
.bs_w_2_s = NULL,
.bs_w_4_s = NULL,
.bs_w_8_s = NULL,
/* write multiple stream */
.bs_wm_1_s = NULL,
.bs_wm_2_s = NULL,
.bs_wm_4_s = NULL,
.bs_wm_8_s = NULL,
/* write region stream */
.bs_wr_1_s = NULL,
.bs_wr_2_s = NULL,
.bs_wr_4_s = NULL,
.bs_wr_8_s = NULL,
};

View File

@ -0,0 +1,102 @@
/*-
* Copyright (c) 1997, 1998 Justin T. Gibbs.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/lock.h>
#include <sys/memdesc.h>
#include <sys/mutex.h>
#include <sys/uio.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/pmap.h>
#include <machine/bus.h>
int
_bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
bus_size_t buflen, int flags, bus_dma_segment_t *segs, int *segp)
{
panic("busdma");
}
int
_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map, struct vm_page **ma,
bus_size_t tlen, int ma_offs, int flags, bus_dma_segment_t *segs,
int *segp)
{
panic("busdma");
}
int
_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
bus_size_t buflen, pmap_t pmap, int flags, bus_dma_segment_t *segs,
int *segp)
{
panic("busdma");
}
void
__bus_dmamap_waitok(bus_dma_tag_t dmat, bus_dmamap_t map,
struct memdesc *mem, bus_dmamap_callback_t *callback, void *callback_arg)
{
panic("busdma");
}
bus_dma_segment_t *
_bus_dmamap_complete(bus_dma_tag_t dmat, bus_dmamap_t map,
bus_dma_segment_t *segs, int nsegs, int error)
{
panic("busdma");
}
/*
* Release the mapping held by map.
*/
void
_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
{
panic("busdma");
}
void
_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
{
panic("busdma");
}

46
sys/riscv/riscv/clock.c Normal file
View File

@ -0,0 +1,46 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/systm.h>
void
cpu_initclocks(void)
{
cpu_initclocks_bsp();
}

137
sys/riscv/riscv/copyinout.S Normal file
View File

@ -0,0 +1,137 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include <sys/errno.h>
#include "assym.s"
/*
* Fault handler for the copy{in,out} functions below.
*/
ENTRY(copyio_fault)
SET_FAULT_HANDLER(x0, a1) /* Clear the handler */
copyio_fault_nopcb:
li a0, EFAULT
ret
END(copyio_fault)
/*
* Copies from a kernel to user address
*
* int copyout(const void *kaddr, void *udaddr, size_t len)
*/
ENTRY(copyout)
beqz a2, 2f /* If len == 0 then skip loop */
add a3, a1, a2
li a4, VM_MAXUSER_ADDRESS
bgt a3, a4, copyio_fault_nopcb
la a6, copyio_fault /* Get the handler address */
SET_FAULT_HANDLER(a6, a7) /* Set the handler */
1: lb a4, 0(a0) /* Load from kaddr */
addi a0, a0, 1
sb a4, 0(a1) /* Store in uaddr */
addi a1, a1, 1
addi a2, a2, -1 /* len-- */
bnez a2, 1b
SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
2: li a0, 0 /* return 0 */
ret
END(copyout)
/*
* Copies from a user to kernel address
*
* int copyin(const void *uaddr, void *kdaddr, size_t len)
*/
ENTRY(copyin)
beqz a2, 2f /* If len == 0 then skip loop */
add a3, a0, a2
li a4, VM_MAXUSER_ADDRESS
bgt a3, a4, copyio_fault_nopcb
la a6, copyio_fault /* Get the handler address */
SET_FAULT_HANDLER(a6, a7) /* Set the handler */
1: lb a4, 0(a0) /* Load from uaddr */
addi a0, a0, 1
sb a4, 0(a1) /* Store in kaddr */
addi a1, a1, 1
addi a2, a2, -1 /* len-- */
bnez a2, 1b
SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
2: li a0, 0 /* return 0 */
ret
END(copyin)
/*
* Copies a string from a user to kernel address
*
* int copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
*/
ENTRY(copyinstr)
mv a5, x0 /* count = 0 */
beqz a2, 3f /* If len == 0 then skip loop */
li a7, VM_MAXUSER_ADDRESS
la a6, copyio_fault /* Get the handler address */
SET_FAULT_HANDLER(a6, a7) /* Set the handler */
1: bgt a7, a0, copyio_fault
lb a4, 0(a0) /* Load from uaddr */
addi a0, a0, 1
sb a4, 0(a1) /* Store in kaddr */
addi a1, a1, 1
beqz a4, 2f
addi a2, a2, -1 /* len-- */
addi a5, a5, 1 /* count++ */
bnez a2, 1b
2: SET_FAULT_HANDLER(x0, a7) /* Clear the handler */
3: beqz a3, 4f /* Check if done != NULL */
addi a5, a5, 1 /* count++ */
sd a5, 0(a3) /* done = count */
4: mv a0, x0 /* return 0 */
ret
END(copyinstr)

59
sys/riscv/riscv/copystr.c Normal file
View File

@ -0,0 +1,59 @@
/*-
* Copyright (c) 2014 Andrew Turner
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
int
copystr(const void * __restrict kfaddr, void * __restrict kdaddr, size_t len,
size_t * __restrict lencopied)
{
const char *src;
size_t pos;
char *dst;
int error;
error = ENAMETOOLONG;
src = kfaddr;
dst = kdaddr;
for (pos = 0; pos < len; pos++) {
dst[pos] = src[pos];
if (src[pos] == '\0') {
/* Increment pos to hold the number of bytes copied */
pos++;
error = 0;
break;
}
}
if (lencopied != NULL)
*lencopied = pos;
return (error);
}

View File

@ -0,0 +1,101 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <machine/asm.h>
#include <machine/param.h>
__FBSDID("$FreeBSD$");
.text
.align 2
.Lpage_mask:
.word PAGE_MASK
ENTRY(riscv_nullop)
ret
END(riscv_nullop)
/*
* Generic functions to read/modify/write the internal coprocessor registers
*/
ENTRY(riscv_tlb_flushID)
sfence.vm
ret
END(riscv_tlb_flushID)
ENTRY(riscv_tlb_flushID_SE)
sfence.vm
ret
END(riscv_tlb_flushID_SE)
/*
* void riscv_dcache_wb_range(vm_offset_t, vm_size_t)
*/
ENTRY(riscv_dcache_wb_range)
/* RISCVTODO */
ret
END(riscv_dcache_wb_range)
/*
* void riscv_dcache_wbinv_range(vm_offset_t, vm_size_t)
*/
ENTRY(riscv_dcache_wbinv_range)
/* RISCVTODO */
ret
END(riscv_dcache_wbinv_range)
/*
* void riscv_dcache_inv_range(vm_offset_t, vm_size_t)
*/
ENTRY(riscv_dcache_inv_range)
/* RISCVTODO */
ret
END(riscv_dcache_inv_range)
/*
* void riscv_idcache_wbinv_range(vm_offset_t, vm_size_t)
*/
ENTRY(riscv_idcache_wbinv_range)
/* RISCVTODO */
ret
END(riscv_idcache_wbinv_range)
/*
* void riscv_icache_sync_range(vm_offset_t, vm_size_t)
*/
ENTRY(riscv_icache_sync_range)
/* RISCVTODO */
ret
END(riscv_icache_sync_range)

61
sys/riscv/riscv/devmap.c Normal file
View File

@ -0,0 +1,61 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* RISC-V doesn't provide memory-mapped devices yet */
#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/pmap.h>
#include <machine/riscvreg.h>
#include <machine/vmparam.h>
void *
pmap_mapdev(vm_offset_t pa, vm_size_t size)
{
return (NULL);
}
void
pmap_unmapdev(vm_offset_t va, vm_size_t size)
{
}

View File

@ -0,0 +1,57 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_watchdog.h"
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/kerneldump.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <vm/vm.h>
#include <vm/pmap.h>
int do_minidump = 1;
SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RWTUN, &do_minidump, 0,
"Enable mini crash dumps");
void
dumpsys_map_chunk(vm_paddr_t pa, size_t chunk, void **va)
{
printf("dumpsys_map_chunk\n");
}

View File

@ -0,0 +1,169 @@
/*-
* Copyright 1996-1998 John D. Polstra.
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/linker.h>
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
#include <sys/signalvar.h>
#include <sys/vnode.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_param.h>
#include <machine/elf.h>
#include <machine/md_var.h>
struct sysentvec elf64_freebsd_sysvec = {
.sv_size = SYS_MAXSYSCALL,
.sv_table = sysent,
.sv_mask = 0,
.sv_errsize = 0,
.sv_errtbl = NULL,
.sv_transtrap = NULL,
.sv_fixup = __elfN(freebsd_fixup),
.sv_sendsig = sendsig,
.sv_sigcode = sigcode,
.sv_szsigcode = &szsigcode,
.sv_name = "FreeBSD ELF64",
.sv_coredump = __elfN(coredump),
.sv_imgact_try = NULL,
.sv_minsigstksz = MINSIGSTKSZ,
.sv_pagesize = PAGE_SIZE,
.sv_minuser = VM_MIN_ADDRESS,
.sv_maxuser = VM_MAXUSER_ADDRESS,
.sv_usrstack = USRSTACK,
.sv_psstrings = PS_STRINGS,
.sv_stackprot = VM_PROT_ALL,
.sv_copyout_strings = exec_copyout_strings,
.sv_setregs = exec_setregs,
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_LP64,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
static Elf64_Brandinfo freebsd_brand_info = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_RISCV,
.compat_3_brand = "FreeBSD",
.emul_path = NULL,
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_newpath = NULL,
.brand_note = &elf64_freebsd_brandnote,
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_FIRST,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_info);
static Elf64_Brandinfo freebsd_brand_oinfo = {
.brand = ELFOSABI_FREEBSD,
.machine = EM_RISCV,
.compat_3_brand = "FreeBSD",
.emul_path = NULL,
.interp_path = "/usr/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_newpath = NULL,
.brand_note = &elf64_freebsd_brandnote,
.flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf64_insert_brand_entry,
&freebsd_brand_oinfo);
void
elf64_dump_thread(struct thread *td, void *dst, size_t *off)
{
}
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
int type, int local, elf_lookup_fn lookup)
{
panic("elf_reloc_internal");
}
int
elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
elf_lookup_fn lookup)
{
return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup));
}
int
elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
int type, elf_lookup_fn lookup)
{
return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup));
}
int
elf_cpu_load_file(linker_file_t lf __unused)
{
return (0);
}
int
elf_cpu_unload_file(linker_file_t lf __unused)
{
return (0);
}

456
sys/riscv/riscv/exception.S Normal file
View File

@ -0,0 +1,456 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include "assym.s"
#include <machine/trap.h>
#include <machine/riscvreg.h>
.macro save_registers el
addi sp, sp, -280
sd ra, (TF_RA)(sp)
sd gp, (TF_GP)(sp)
sd tp, (TF_TP)(sp)
sd t0, (TF_T + 0 * 8)(sp)
sd t1, (TF_T + 1 * 8)(sp)
sd t2, (TF_T + 2 * 8)(sp)
sd t3, (TF_T + 3 * 8)(sp)
sd t4, (TF_T + 4 * 8)(sp)
sd t5, (TF_T + 5 * 8)(sp)
sd t6, (TF_T + 6 * 8)(sp)
sd s0, (TF_S + 0 * 8)(sp)
sd s1, (TF_S + 1 * 8)(sp)
sd s2, (TF_S + 2 * 8)(sp)
sd s3, (TF_S + 3 * 8)(sp)
sd s4, (TF_S + 4 * 8)(sp)
sd s5, (TF_S + 5 * 8)(sp)
sd s6, (TF_S + 6 * 8)(sp)
sd s7, (TF_S + 7 * 8)(sp)
sd s8, (TF_S + 8 * 8)(sp)
sd s9, (TF_S + 9 * 8)(sp)
sd s10, (TF_S + 10 * 8)(sp)
sd s11, (TF_S + 11 * 8)(sp)
sd a0, (TF_A + 0 * 8)(sp)
sd a1, (TF_A + 1 * 8)(sp)
sd a2, (TF_A + 2 * 8)(sp)
sd a3, (TF_A + 3 * 8)(sp)
sd a4, (TF_A + 4 * 8)(sp)
sd a5, (TF_A + 5 * 8)(sp)
sd a6, (TF_A + 6 * 8)(sp)
sd a7, (TF_A + 7 * 8)(sp)
#if 0
/* XXX: temporary test: spin if stack is not kernel one */
.if \el == 1 /* kernel */
mv t0, sp
srli t0, t0, 63
1:
beqz t0, 1b
.endif
#endif
.if \el == 1
/* Store kernel sp */
sd sp, (TF_SP)(sp)
.else
/* Store user sp */
csrr t0, sscratch
sd t0, (TF_SP)(sp)
.endif
li t0, 0
csrw sscratch, t0
csrr t0, sepc
sd t0, (TF_SEPC)(sp)
csrr t0, sstatus
sd t0, (TF_SSTATUS)(sp)
csrr t0, sbadaddr
sd t0, (TF_SBADADDR)(sp)
csrr t0, scause
sd t0, (TF_SCAUSE)(sp)
.endm
.macro load_registers el
ld t0, (TF_SSTATUS)(sp)
.if \el == 0
/* Ensure user interrupts will be enabled on eret. */
ori t0, t0, SSTATUS_PIE
.else
/*
* Disable interrupts for supervisor mode exceptions.
* For user mode exceptions we have already done this
* in do_ast.
*/
li t1, ~SSTATUS_IE
and t0, t0, t1
.endif
csrw sstatus, t0
ld t0, (TF_SEPC)(sp)
csrw sepc, t0
.if \el == 0
/* Load user sp */
ld t0, (TF_SP)(sp)
csrw sscratch, t0
.endif
ld ra, (TF_RA)(sp)
ld gp, (TF_GP)(sp)
ld tp, (TF_TP)(sp)
ld t0, (TF_T + 0 * 8)(sp)
ld t1, (TF_T + 1 * 8)(sp)
ld t2, (TF_T + 2 * 8)(sp)
ld t3, (TF_T + 3 * 8)(sp)
ld t4, (TF_T + 4 * 8)(sp)
ld t5, (TF_T + 5 * 8)(sp)
ld t6, (TF_T + 6 * 8)(sp)
ld s0, (TF_S + 0 * 8)(sp)
ld s1, (TF_S + 1 * 8)(sp)
ld s2, (TF_S + 2 * 8)(sp)
ld s3, (TF_S + 3 * 8)(sp)
ld s4, (TF_S + 4 * 8)(sp)
ld s5, (TF_S + 5 * 8)(sp)
ld s6, (TF_S + 6 * 8)(sp)
ld s7, (TF_S + 7 * 8)(sp)
ld s8, (TF_S + 8 * 8)(sp)
ld s9, (TF_S + 9 * 8)(sp)
ld s10, (TF_S + 10 * 8)(sp)
ld s11, (TF_S + 11 * 8)(sp)
ld a0, (TF_A + 0 * 8)(sp)
ld a1, (TF_A + 1 * 8)(sp)
ld a2, (TF_A + 2 * 8)(sp)
ld a3, (TF_A + 3 * 8)(sp)
ld a4, (TF_A + 4 * 8)(sp)
ld a5, (TF_A + 5 * 8)(sp)
ld a6, (TF_A + 6 * 8)(sp)
ld a7, (TF_A + 7 * 8)(sp)
addi sp, sp, 280
.endm
.macro do_ast
/* Disable interrupts */
csrr a4, sstatus
1:
csrci sstatus, SSTATUS_IE
la a1, pcpup
ld a1, 0(a1)
ld a1, PC_CURTHREAD(a1)
lw a2, TD_FLAGS(a1)
li a3, (TDF_ASTPENDING|TDF_NEEDRESCHED)
and a2, a2, a3
beqz a2, 2f
/* Restore interrupts */
andi a4, a4, SSTATUS_IE
csrs sstatus, a4
/* Handle the ast */
mv a0, sp
call _C_LABEL(ast)
/* Re-check for new ast scheduled */
j 1b
2:
.endm
ENTRY(cpu_exception_handler_supervisor)
save_registers 1
mv a0, sp
call _C_LABEL(do_trap_supervisor)
load_registers 1
eret
END(cpu_exception_handler_supervisor)
ENTRY(cpu_exception_handler_user)
csrrw sp, sscratch, sp
save_registers 0
mv a0, sp
call _C_LABEL(do_trap_user)
do_ast
load_registers 0
csrrw sp, sscratch, sp
eret
END(cpu_exception_handler_user)
/*
* Trap handlers
*/
.text
bad_trap:
j bad_trap
user_trap:
csrrw sp, mscratch, sp
addi sp, sp, -64
sd t0, (8 * 0)(sp)
sd t1, (8 * 1)(sp)
sd t2, (8 * 2)(sp)
sd t3, (8 * 3)(sp)
sd t4, (8 * 4)(sp)
sd t5, (8 * 5)(sp)
sd a0, (8 * 7)(sp)
la t2, _C_LABEL(cpu_exception_handler_user)
csrr t0, mcause
bltz t0, machine_interrupt
j exit_mrts
supervisor_trap:
/* Save state */
csrrw sp, mscratch, sp
addi sp, sp, -64
sd t0, (8 * 0)(sp)
sd t1, (8 * 1)(sp)
sd t2, (8 * 2)(sp)
sd t3, (8 * 3)(sp)
sd t4, (8 * 4)(sp)
sd t5, (8 * 5)(sp)
sd a0, (8 * 7)(sp)
la t2, _C_LABEL(cpu_exception_handler_supervisor)
csrr t0, mcause
bltz t0, machine_interrupt
li t1, EXCP_SMODE_ENV_CALL
beq t0, t1, supervisor_call
j exit_mrts
machine_interrupt:
/* Type of interrupt ? */
csrr t0, mcause
andi t0, t0, 3
li t1, 0
beq t1, t0, software_interrupt
li t1, 1
beq t1, t0, timer_interrupt
li t1, 2
beq t1, t0, htif_interrupt
/* not reached */
1:
j 1b
software_interrupt:
/* Redirect to supervisor */
j exit_mrts
timer_interrupt:
/* Disable machine timer interrupts */
li t0, MIE_MTIE
csrc mie, t0
/* Clear machine pending */
li t0, MIP_MTIP
csrc mip, t0
/* Post supervisor software interrupt */
li t0, MIP_STIP
csrs mip, t0
/* If PRV1 is PRV_U (user) then serve a trap */
csrr t0, mstatus
li t1, (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT)
and t0, t0, t1
beqz t0, 1f
/* If PRV1 is supervisor and interrupts were enabled, then serve a trap */
csrr t0, mstatus
li t1, (SR_IE1 | (MSTATUS_PRV_M << MSTATUS_PRV1_SHIFT))
and t0, t0, t1
li t1, (SR_IE1 | (MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT))
beq t0, t1, 1f
j exit
1:
/* Serve a trap in supervisor mode */
j exit_mrts
htif_interrupt:
1:
li t5, 0
csrrw t5, mfromhost, t5
beqz t5, 3f
/* Console PUT intr ? */
mv t1, t5
li t0, 0x101
srli t1, t1, 48
bne t1, t0, 2f
/* Yes */
la t0, console_intr
li t1, 1
sd t1, 0(t0)
j 3f
2:
/* Save entry */
la t0, htif_ring_cursor
beqz t0, 3f /* not initialized */
ld t0, 0(t0) /* load struct */
sd t5, 0(t0) /* put entry */
li t4, 1
sd t4, 8(t0) /* mark used */
ld t4, 16(t0) /* take next */
/* Update cursor */
la t0, htif_ring_cursor
sd t4, 0(t0)
/* Post supervisor software interrupt */
li t0, MIP_SSIP
csrs mip, t0
3:
j exit
supervisor_call:
csrr t1, mepc
addi t1, t1, 4 /* Next instruction in t1 */
li t4, ECALL_HTIF_CMD
beq t5, t4, htif_cmd
li t4, ECALL_HTIF_GET_ENTRY
beq t5, t4, htif_get_entry
li t4, ECALL_MTIMECMP
beq t5, t4, set_mtimecmp
li t4, ECALL_CLEAR_PENDING
beq t5, t4, clear_pending
li t4, ECALL_MCPUID_GET
beq t5, t4, mcpuid_get
li t4, ECALL_MIMPID_GET
beq t5, t4, mimpid_get
j exit_next_instr
mcpuid_get:
csrr t6, mcpuid
j exit_next_instr
mimpid_get:
csrr t6, mimpid
j exit_next_instr
htif_get_entry:
li t6, 0 /* preset return value */
la t0, htif_ring_last
ld t0, 0(t0) /* load struct */
ld t4, 8(t0) /* get used */
beqz t4, 1f
ld t6, 0(t0) /* get entry */
li t4, 0
sd t4, 8(t0) /* mark free */
sd t4, 0(t0) /* free entry, just in case */
ld t4, 16(t0) /* take next */
la t0, htif_ring_last
sd t4, 0(t0)
1:
/* Exit. Result is stored in t6 */
j exit_next_instr
htif_cmd:
mv t0, t6
1:
csrrw t0, mtohost, t0
bnez t0, 1b
j exit_next_instr
set_mtimecmp:
csrr t2, stime
add t6, t6, t2
csrw mtimecmp, t6
/* Enable interrupts */
li t0, (MIE_MTIE | MIE_STIE)
csrs mie, t0
j exit_next_instr
clear_pending:
li t0, MIP_STIP
csrc mip, t0
j exit_next_instr
/*
* Trap exit functions
*/
exit_next_instr:
/* Next instruction is in t1 */
csrw mepc, t1
exit:
/* Restore state */
ld t0, (8 * 0)(sp)
ld t1, (8 * 1)(sp)
ld t2, (8 * 2)(sp)
ld t3, (8 * 3)(sp)
ld t4, (8 * 4)(sp)
ld t5, (8 * 5)(sp)
ld a0, (8 * 7)(sp)
addi sp, sp, 64
csrrw sp, mscratch, sp
eret
/*
* Redirect to supervisor
*/
exit_mrts:
/* Setup exception handler */
li t1, KERNBASE
add t2, t2, t1
csrw stvec, t2
/* Restore state */
ld t0, (8 * 0)(sp)
ld t1, (8 * 1)(sp)
ld t2, (8 * 2)(sp)
ld t3, (8 * 3)(sp)
ld t4, (8 * 4)(sp)
ld t5, (8 * 5)(sp)
ld a0, (8 * 7)(sp)
addi sp, sp, 64
csrrw sp, mscratch, sp
/* Redirect to supervisor */
mrts

View File

@ -0,0 +1,98 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/assym.h>
#include <sys/proc.h>
#include <sys/mbuf.h>
#include <sys/vmmeter.h>
#include <sys/bus.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <machine/vmparam.h>
#include <machine/riscvreg.h>
#include <machine/frame.h>
#include <machine/pcb.h>
#include <machine/cpu.h>
#include <machine/proc.h>
#include <machine/cpufunc.h>
#include <machine/pte.h>
#include <machine/intr.h>
ASSYM(KERNBASE, KERNBASE);
ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS);
ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
ASSYM(PCB_L1ADDR, offsetof(struct pcb, pcb_l1addr));
ASSYM(PCB_SIZE, sizeof(struct pcb));
ASSYM(PCB_RA, offsetof(struct pcb, pcb_ra));
ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
ASSYM(PCB_GP, offsetof(struct pcb, pcb_gp));
ASSYM(PCB_TP, offsetof(struct pcb, pcb_tp));
ASSYM(PCB_T, offsetof(struct pcb, pcb_t));
ASSYM(PCB_S, offsetof(struct pcb, pcb_s));
ASSYM(PCB_A, offsetof(struct pcb, pcb_a));
ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread));
ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
ASSYM(TD_PROC, offsetof(struct thread, td_proc));
ASSYM(TD_FRAME, offsetof(struct thread, td_frame));
ASSYM(TD_MD, offsetof(struct thread, td_md));
ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
ASSYM(TF_RA, offsetof(struct trapframe, tf_ra));
ASSYM(TF_SP, offsetof(struct trapframe, tf_sp));
ASSYM(TF_GP, offsetof(struct trapframe, tf_gp));
ASSYM(TF_TP, offsetof(struct trapframe, tf_tp));
ASSYM(TF_T, offsetof(struct trapframe, tf_t));
ASSYM(TF_S, offsetof(struct trapframe, tf_s));
ASSYM(TF_A, offsetof(struct trapframe, tf_a));
ASSYM(TF_SEPC, offsetof(struct trapframe, tf_sepc));
ASSYM(TF_SBADADDR, offsetof(struct trapframe, tf_sbadaddr));
ASSYM(TF_SCAUSE, offsetof(struct trapframe, tf_scause));
ASSYM(TF_SSTATUS, offsetof(struct trapframe, tf_sstatus));

149
sys/riscv/riscv/identcpu.c Normal file
View File

@ -0,0 +1,149 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/pcpu.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/trap.h>
char machine[] = "riscv";
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
"Machine class");
struct cpu_desc {
u_int cpu_impl;
u_int cpu_part_num;
const char *cpu_impl_name;
const char *cpu_part_name;
};
struct cpu_desc cpu_desc[MAXCPU];
struct cpu_parts {
u_int part_id;
const char *part_name;
};
#define CPU_PART_NONE { -1, "Unknown Processor" }
struct cpu_implementers {
u_int impl_id;
const char *impl_name;
/*
* Part number is implementation defined
* so each vendor will have its own set of values and names.
*/
const struct cpu_parts *cpu_parts;
};
#define CPU_IMPLEMENTER_NONE { 0, "Unknown Implementer", cpu_parts_none }
/*
* Per-implementer table of (PartNum, CPU Name) pairs.
*/
/* UC Berkeley */
static const struct cpu_parts cpu_parts_ucb[] = {
{ CPU_PART_RV32I, "RV32I" },
{ CPU_PART_RV32E, "RV32E" },
{ CPU_PART_RV64I, "RV64I" },
{ CPU_PART_RV128I, "RV128I" },
CPU_PART_NONE,
};
/* Unknown */
static const struct cpu_parts cpu_parts_none[] = {
CPU_PART_NONE,
};
/*
* Implementers table.
*/
const struct cpu_implementers cpu_implementers[] = {
{ CPU_IMPL_UCB_ROCKET, "UC Berkeley Rocket", cpu_parts_ucb },
CPU_IMPLEMENTER_NONE,
};
void
identify_cpu(void)
{
const struct cpu_parts *cpu_partsp;
uint32_t part_id;
uint32_t impl_id;
uint64_t mimpid;
uint64_t mcpuid;
u_int cpu;
size_t i;
cpu_partsp = NULL;
mimpid = machine_command(ECALL_MIMPID_GET, 0);
mcpuid = machine_command(ECALL_MCPUID_GET, 0);
/* SMPTODO: use mhartid ? */
cpu = PCPU_GET(cpuid);
impl_id = CPU_IMPL(mimpid);
for (i = 0; i < nitems(cpu_implementers); i++) {
if (impl_id == cpu_implementers[i].impl_id ||
cpu_implementers[i].impl_id == 0) {
cpu_desc[cpu].cpu_impl = impl_id;
cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
cpu_partsp = cpu_implementers[i].cpu_parts;
break;
}
}
part_id = CPU_PART(mcpuid);
for (i = 0; &cpu_partsp[i] != NULL; i++) {
if (part_id == cpu_partsp[i].part_id ||
cpu_partsp[i].part_id == -1) {
cpu_desc[cpu].cpu_part_num = part_id;
cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name;
break;
}
}
/* Print details for boot CPU or if we want verbose output */
if (cpu == 0 || bootverbose) {
printf("CPU(%d): %s %s\n", cpu,
cpu_desc[cpu].cpu_impl_name,
cpu_desc[cpu].cpu_part_name);
}
}

241
sys/riscv/riscv/in_cksum.c Normal file
View File

@ -0,0 +1,241 @@
/* $NetBSD: in_cksum.c,v 1.7 1997/09/02 13:18:15 thorpej Exp $ */
/*-
* Copyright (c) 1988, 1992, 1993
* The Regents of the University of California. All rights reserved.
* Copyright (c) 1996
* Matt Thomas <matt@3am-software.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
*/
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/systm.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <machine/in_cksum.h>
/*
* Checksum routine for Internet Protocol family headers
* (Portable Alpha version).
*
* This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible.
*/
#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
#define REDUCE32 \
{ \
q_util.q = sum; \
sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
}
#define REDUCE16 \
{ \
q_util.q = sum; \
l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \
sum = l_util.s[0] + l_util.s[1]; \
ADDCARRY(sum); \
}
static const u_int32_t in_masks[] = {
/*0 bytes*/ /*1 byte*/ /*2 bytes*/ /*3 bytes*/
0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */
0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */
0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000, /* offset 2 */
0x00000000, 0xFF000000, 0xFF000000, 0xFF000000, /* offset 3 */
};
union l_util {
u_int16_t s[2];
u_int32_t l;
};
union q_util {
u_int16_t s[4];
u_int32_t l[2];
u_int64_t q;
};
static u_int64_t
in_cksumdata(const void *buf, int len)
{
const u_int32_t *lw = (const u_int32_t *) buf;
u_int64_t sum = 0;
u_int64_t prefilled;
int offset;
union q_util q_util;
if ((3 & (long) lw) == 0 && len == 20) {
sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4];
REDUCE32;
return sum;
}
if ((offset = 3 & (long) lw) != 0) {
const u_int32_t *masks = in_masks + (offset << 2);
lw = (u_int32_t *) (((long) lw) - offset);
sum = *lw++ & masks[len >= 3 ? 3 : len];
len -= 4 - offset;
if (len <= 0) {
REDUCE32;
return sum;
}
}
#if 0
/*
* Force to cache line boundary.
*/
offset = 32 - (0x1f & (long) lw);
if (offset < 32 && len > offset) {
len -= offset;
if (4 & offset) {
sum += (u_int64_t) lw[0];
lw += 1;
}
if (8 & offset) {
sum += (u_int64_t) lw[0] + lw[1];
lw += 2;
}
if (16 & offset) {
sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3];
lw += 4;
}
}
#endif
/*
* access prefilling to start load of next cache line.
* then add current cache line
* save result of prefilling for loop iteration.
*/
prefilled = lw[0];
while ((len -= 32) >= 4) {
u_int64_t prefilling = lw[8];
sum += prefilled + lw[1] + lw[2] + lw[3]
+ lw[4] + lw[5] + lw[6] + lw[7];
lw += 8;
prefilled = prefilling;
}
if (len >= 0) {
sum += prefilled + lw[1] + lw[2] + lw[3]
+ lw[4] + lw[5] + lw[6] + lw[7];
lw += 8;
} else {
len += 32;
}
while ((len -= 16) >= 0) {
sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3];
lw += 4;
}
len += 16;
while ((len -= 4) >= 0) {
sum += (u_int64_t) *lw++;
}
len += 4;
if (len > 0)
sum += (u_int64_t) (in_masks[len] & *lw);
REDUCE32;
return sum;
}
u_short
in_addword(u_short a, u_short b)
{
u_int64_t sum = a + b;
ADDCARRY(sum);
return (sum);
}
u_short
in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c)
{
u_int64_t sum;
union q_util q_util;
union l_util l_util;
sum = (u_int64_t) a + b + c;
REDUCE16;
return (sum);
}
u_short
in_cksum_skip(struct mbuf *m, int len, int skip)
{
u_int64_t sum = 0;
int mlen = 0;
int clen = 0;
caddr_t addr;
union q_util q_util;
union l_util l_util;
len -= skip;
for (; skip && m; m = m->m_next) {
if (m->m_len > skip) {
mlen = m->m_len - skip;
addr = mtod(m, caddr_t) + skip;
goto skip_start;
} else {
skip -= m->m_len;
}
}
for (; m && len; m = m->m_next) {
if (m->m_len == 0)
continue;
mlen = m->m_len;
addr = mtod(m, caddr_t);
skip_start:
if (len < mlen)
mlen = len;
if ((clen ^ (long) addr) & 1)
sum += in_cksumdata(addr, mlen) << 8;
else
sum += in_cksumdata(addr, mlen);
clen += mlen;
len -= mlen;
}
REDUCE16;
return (~sum & 0xffff);
}
u_int in_cksum_hdr(const struct ip *ip)
{
u_int64_t sum = in_cksumdata(ip, sizeof(struct ip));
union q_util q_util;
union l_util l_util;
REDUCE16;
return (~sum & 0xffff);
}

View File

@ -0,0 +1,223 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/frame.h>
#include <machine/intr.h>
enum {
IRQ_SOFTWARE,
IRQ_TIMER,
IRQ_HTIF,
NIRQS
};
u_long intrcnt[NIRQS];
size_t sintrcnt = sizeof(intrcnt);
char intrnames[NIRQS * (MAXCOMLEN + 1) * 2];
size_t sintrnames = sizeof(intrnames);
static struct intr_event *intr_events[NIRQS];
static riscv_intrcnt_t riscv_intr_counters[NIRQS];
static int intrcnt_index;
riscv_intrcnt_t
riscv_intrcnt_create(const char* name)
{
riscv_intrcnt_t counter;
counter = &intrcnt[intrcnt_index++];
riscv_intrcnt_setname(counter, name);
return (counter);
}
void
riscv_intrcnt_setname(riscv_intrcnt_t counter, const char *name)
{
int i;
i = (counter - intrcnt);
KASSERT(counter != NULL, ("riscv_intrcnt_setname: NULL counter"));
snprintf(intrnames + (MAXCOMLEN + 1) * i,
MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
}
static void
riscv_mask_irq(void *source)
{
uintptr_t irq;
irq = (uintptr_t)source;
switch (irq) {
case IRQ_TIMER:
csr_clear(sie, SIE_STIE);
break;
case IRQ_SOFTWARE:
csr_clear(sie, SIE_SSIE);
break;
default:
panic("Unknown irq %d\n", irq);
}
}
static void
riscv_unmask_irq(void *source)
{
uintptr_t irq;
irq = (uintptr_t)source;
switch (irq) {
case IRQ_TIMER:
csr_set(sie, SIE_STIE);
break;
case IRQ_SOFTWARE:
csr_set(sie, SIE_SSIE);
break;
default:
panic("Unknown irq %d\n", irq);
}
}
void
riscv_init_interrupts(void)
{
char name[MAXCOMLEN + 1];
int i;
for (i = 0; i < NIRQS; i++) {
snprintf(name, MAXCOMLEN + 1, "int%d:", i);
riscv_intr_counters[i] = riscv_intrcnt_create(name);
}
}
int
riscv_setup_intr(const char *name, driver_filter_t *filt,
void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
{
struct intr_event *event;
int error;
if (irq < 0 || irq >= NIRQS)
panic("%s: unknown intr %d", __func__, irq);
event = intr_events[irq];
if (event == NULL) {
error = intr_event_create(&event, (void *)(uintptr_t)irq, 0,
irq, riscv_mask_irq, riscv_unmask_irq,
NULL, NULL, "int%d", irq);
if (error)
return (error);
intr_events[irq] = event;
riscv_unmask_irq((void*)(uintptr_t)irq);
}
intr_event_add_handler(event, name, filt, handler, arg,
intr_priority(flags), flags, cookiep);
riscv_intrcnt_setname(riscv_intr_counters[irq],
event->ie_fullname);
return (0);
}
int
riscv_teardown_intr(void *ih)
{
/* TODO */
return (0);
}
int
riscv_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
{
/* There is no configuration for interrupts */
return (0);
}
void
riscv_cpu_intr(struct trapframe *frame)
{
struct intr_event *event;
int active_irq;
critical_enter();
KASSERT(frame->tf_scause & EXCP_INTR,
("riscv_cpu_intr: wrong frame passed"));
active_irq = (frame->tf_scause & EXCP_MASK);
switch (active_irq) {
case IRQ_SOFTWARE:
case IRQ_TIMER:
event = intr_events[active_irq];
/* Update counters */
atomic_add_long(riscv_intr_counters[active_irq], 1);
PCPU_INC(cnt.v_intr);
break;
case IRQ_HTIF:
/* HTIF interrupts are only handled in machine mode */
panic("%s: HTIF interrupt", __func__);
break;
default:
event = NULL;
}
if (!event || TAILQ_EMPTY(&event->ie_handlers) ||
(intr_event_handle(event, frame) != 0))
printf("stray interrupt %d\n", active_irq);
critical_exit();
}

274
sys/riscv/riscv/locore.S Normal file
View File

@ -0,0 +1,274 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "assym.s"
#include <sys/syscall.h>
#include <machine/asm.h>
#include <machine/param.h>
#include <machine/trap.h>
#include <machine/riscvreg.h>
#include <machine/pte.h>
#define HTIF_RING_SIZE (64)
#define HTIF_RING_LAST (24 * (HTIF_RING_SIZE - 1))
.globl kernbase
.set kernbase, KERNBASE
/* Trap entries */
.text
mentry:
/* User mode entry point (mtvec + 0x000) */
.align 6
j user_trap
/* Supervisor mode entry point (mtvec + 0x040) */
.align 6
j supervisor_trap
/* Hypervisor mode entry point (mtvec + 0x080) */
.align 6
j bad_trap
/* Machine mode entry point (mtvec + 0x0C0) */
.align 6
j bad_trap
/* Reset vector */
.text
.align 8
.globl _start
_start:
li s11, KERNBASE
/* Build ring */
la t0, htif_ring
li t1, 0
sd t1, 0(t0) /* zero data */
sd t1, 8(t0) /* zero used */
mv t2, t0
mv t3, t0
li t5, HTIF_RING_LAST
li t6, 0
add t4, t0, t5
1:
addi t3, t3, 24 /* pointer to next */
beq t3, t4, 2f /* finish */
sd t3, 16(t2) /* store pointer */
addi t2, t2, 24 /* next entry */
addi t6, t6, 1 /* counter */
j 1b
2:
sd t0, 16(t3) /* last -> first */
la t1, htif_ring_cursor
sd t0, 0(t1)
la t1, htif_ring_last
sd t0, 0(t1)
/* finish building ring */
la t0, hardstack_end
sub t0, t0, s11
csrw mscratch, t0
la t0, mentry
csrw mtvec, t0
li t0, 0
csrw sscratch, t0
li s10, PAGE_SIZE
li s9, (PAGE_SIZE * KSTACK_PAGES)
/* Page tables */
/* Level 0 */
la s1, pagetable_l0
la s2, pagetable_l1 /* Link to next level PN */
srli s2, s2, PAGE_SHIFT
li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
or t6, t4, t5
/* Store single level0 PTE entry to position */
li a5, 0x1ff
li a6, PTE_SIZE
mulw a5, a5, a6
add t0, s1, a5
sd t6, 0(t0)
/* Level 1 */
la s1, pagetable_l1
la s2, pagetable_l2 /* Link to next level PN */
srli s2, s2, PAGE_SHIFT
li a5, KERNBASE
srli a5, a5, 0x1e /* >> 30 */
andi a5, a5, 0x1ff /* & 0x1ff */
li t4, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
or t6, t4, t5
/* Store single level1 PTE entry to position */
li a6, PTE_SIZE
mulw a5, a5, a6
add t0, s1, a5
sd t6, (t0)
/* Level 2 superpages (512 x 2MiB) */
la s1, pagetable_l2
li t3, 512 /* Build 512 entries */
li t4, 0 /* Counter */
li t5, 0
2:
li t0, (PTE_VALID | (PTE_TYPE_SRWX << PTE_TYPE_S))
slli t2, t4, PTE_PPN1_S /* << PTE_PPN1_S */
or t5, t0, t2
sd t5, (s1) /* Store PTE entry to position */
addi s1, s1, PTE_SIZE
addi t4, t4, 1
bltu t4, t3, 2b
/* Set page tables base register */
la s1, pagetable_l0
csrw sptbr, s1
/* Page tables END */
/* Enter supervisor mode */
li s0, ((MSTATUS_VM_SV48 << MSTATUS_VM_SHIFT) | \
(MSTATUS_PRV_M << MSTATUS_PRV_SHIFT) | \
(MSTATUS_PRV_S << MSTATUS_PRV1_SHIFT) | \
(MSTATUS_PRV_U << MSTATUS_PRV2_SHIFT));
csrw mstatus, s0
/* Exit from machine mode */
la t0, .Lmmu_on
add t0, t0, s11
csrw mepc, t0
eret
.Lmmu_on:
/* Initialize stack pointer */
la s3, initstack_end
mv sp, s3
addi sp, sp, -PCB_SIZE
/* Clear BSS */
la a0, _C_LABEL(__bss_start)
la s1, _C_LABEL(_end)
1:
sd zero, 0(a0)
addi a0, a0, 8
bltu a0, s1, 1b
/* Fill riscv_bootparams */
addi sp, sp, -16
la t0, pagetable_l1
sd t0, 0(sp) /* kern_l1pt */
la t0, initstack_end
sd t0, 8(sp) /* kern_stack */
mv a0, sp
call _C_LABEL(initriscv) /* Off we go */
call _C_LABEL(mi_startup)
.align 4
initstack:
.space (PAGE_SIZE * KSTACK_PAGES)
initstack_end:
hardstack:
.space (PAGE_SIZE)
hardstack_end:
.globl htif_ring
htif_ring:
.space (24 * 1024)
.globl htif_ring_cursor
htif_ring_cursor:
.space (8)
.globl htif_ring_last
htif_ring_last:
.space (8)
.globl console_intr
console_intr:
.space (8)
ENTRY(sigcode)
mv a0, sp
addi a0, a0, SF_UC
1:
li t0, SYS_sigreturn
ecall
/* sigreturn failed, exit */
li t0, SYS_exit
ecall
j 1b
END(sigcode)
/* This may be copied to the stack, keep it 16-byte aligned */
.align 3
esigcode:
.data
.align 3
.global szsigcode
szsigcode:
.quad esigcode - sigcode
.align 12
.globl pagetable_l0
pagetable_l0:
.space PAGE_SIZE
pagetable_l1:
.space PAGE_SIZE
pagetable_l2:
.space PAGE_SIZE
pagetable_end:
.globl init_pt_va
init_pt_va:
.quad pagetable_l2 /* XXX: Keep page tables VA */
#include "exception.S"

795
sys/riscv/riscv/machdep.c Normal file
View File

@ -0,0 +1,795 @@
/*-
* Copyright (c) 2014 Andrew Turner
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "opt_platform.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/cpu.h>
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/limits.h>
#include <sys/linker.h>
#include <sys/msgbuf.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/reboot.h>
#include <sys/rwlock.h>
#include <sys/sched.h>
#include <sys/signalvar.h>
#include <sys/syscallsubr.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/ucontext.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_pager.h>
#include <machine/riscvreg.h>
#include <machine/cpu.h>
#include <machine/kdb.h>
#include <machine/machdep.h>
#include <machine/pcb.h>
#include <machine/reg.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
#include <machine/intr.h>
#include <machine/asm.h>
#ifdef VFP
#include <machine/vfp.h>
#endif
#ifdef FDT
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#endif
struct pcpu __pcpu[MAXCPU];
static struct trapframe proc0_tf;
vm_paddr_t phys_avail[PHYS_AVAIL_SIZE + 2];
vm_paddr_t dump_avail[PHYS_AVAIL_SIZE + 2];
int early_boot = 1;
int cold = 1;
long realmem = 0;
long Maxmem = 0;
#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1))
vm_paddr_t physmap[PHYSMAP_SIZE];
u_int physmap_idx;
struct kva_md_info kmi;
int64_t dcache_line_size; /* The minimum D cache line size */
int64_t icache_line_size; /* The minimum I cache line size */
int64_t idcache_line_size; /* The minimum cache line size */
extern int *end;
extern int *initstack_end;
struct pcpu *pcpup;
uintptr_t mcall_trap(uintptr_t mcause, uintptr_t* regs);
uintptr_t
mcall_trap(uintptr_t mcause, uintptr_t* regs)
{
return (0);
}
static void
cpu_startup(void *dummy)
{
identify_cpu();
vm_ksubmap_init(&kmi);
bufinit();
vm_pager_bufferinit();
}
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
int
cpu_idle_wakeup(int cpu)
{
return (0);
}
void
bzero(void *buf, size_t len)
{
uint8_t *p;
p = buf;
while(len-- > 0)
*p++ = 0;
}
int
fill_regs(struct thread *td, struct reg *regs)
{
struct trapframe *frame;
frame = td->td_frame;
regs->sepc = frame->tf_sepc;
regs->sstatus = frame->tf_sstatus;
regs->ra = frame->tf_ra;
regs->sp = frame->tf_sp;
regs->gp = frame->tf_gp;
regs->tp = frame->tf_tp;
memcpy(regs->t, frame->tf_t, sizeof(regs->t));
memcpy(regs->s, frame->tf_s, sizeof(regs->s));
memcpy(regs->a, frame->tf_a, sizeof(regs->a));
return (0);
}
int
set_regs(struct thread *td, struct reg *regs)
{
struct trapframe *frame;
frame = td->td_frame;
frame->tf_sepc = regs->sepc;
frame->tf_sstatus = regs->sstatus;
frame->tf_ra = regs->ra;
frame->tf_sp = regs->sp;
frame->tf_gp = regs->gp;
frame->tf_tp = regs->tp;
memcpy(frame->tf_t, regs->t, sizeof(frame->tf_t));
memcpy(frame->tf_s, regs->s, sizeof(frame->tf_s));
memcpy(frame->tf_a, regs->a, sizeof(frame->tf_a));
return (0);
}
int
fill_fpregs(struct thread *td, struct fpreg *regs)
{
/* TODO */
bzero(regs, sizeof(*regs));
return (0);
}
int
set_fpregs(struct thread *td, struct fpreg *regs)
{
/* TODO */
return (0);
}
int
fill_dbregs(struct thread *td, struct dbreg *regs)
{
panic("fill_dbregs");
}
int
set_dbregs(struct thread *td, struct dbreg *regs)
{
panic("set_dbregs");
}
int
ptrace_set_pc(struct thread *td, u_long addr)
{
panic("ptrace_set_pc");
return (0);
}
int
ptrace_single_step(struct thread *td)
{
/* TODO; */
return (0);
}
int
ptrace_clear_single_step(struct thread *td)
{
/* TODO; */
return (0);
}
void
exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
{
struct trapframe *tf = td->td_frame;
memset(tf, 0, sizeof(struct trapframe));
/*
* We need to set a0 for init as it doesn't call
* cpu_set_syscall_retval to copy the value. We also
* need to set td_retval for the cases where we do.
*/
tf->tf_a[0] = td->td_retval[0] = stack;
tf->tf_sp = STACKALIGN(stack);
tf->tf_ra = imgp->entry_addr;
tf->tf_sepc = imgp->entry_addr;
}
/* Sanity check these are the same size, they will be memcpy'd to and fro */
CTASSERT(sizeof(((struct trapframe *)0)->tf_a) ==
sizeof((struct gpregs *)0)->gp_a);
CTASSERT(sizeof(((struct trapframe *)0)->tf_s) ==
sizeof((struct gpregs *)0)->gp_s);
CTASSERT(sizeof(((struct trapframe *)0)->tf_t) ==
sizeof((struct gpregs *)0)->gp_t);
CTASSERT(sizeof(((struct trapframe *)0)->tf_a) ==
sizeof((struct reg *)0)->a);
CTASSERT(sizeof(((struct trapframe *)0)->tf_s) ==
sizeof((struct reg *)0)->s);
CTASSERT(sizeof(((struct trapframe *)0)->tf_t) ==
sizeof((struct reg *)0)->t);
int
get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
{
struct trapframe *tf = td->td_frame;
memcpy(mcp->mc_gpregs.gp_t, tf->tf_t, sizeof(mcp->mc_gpregs.gp_t));
memcpy(mcp->mc_gpregs.gp_s, tf->tf_s, sizeof(mcp->mc_gpregs.gp_s));
memcpy(mcp->mc_gpregs.gp_a, tf->tf_a, sizeof(mcp->mc_gpregs.gp_a));
if (clear_ret & GET_MC_CLEAR_RET) {
mcp->mc_gpregs.gp_a[0] = 0;
mcp->mc_gpregs.gp_t[0] = 0; /* clear syscall error */
}
mcp->mc_gpregs.gp_ra = tf->tf_ra;
mcp->mc_gpregs.gp_sp = tf->tf_sp;
mcp->mc_gpregs.gp_gp = tf->tf_gp;
mcp->mc_gpregs.gp_tp = tf->tf_tp;
mcp->mc_gpregs.gp_sepc = tf->tf_sepc;
mcp->mc_gpregs.gp_sstatus = tf->tf_sstatus;
return (0);
}
int
set_mcontext(struct thread *td, mcontext_t *mcp)
{
struct trapframe *tf;
tf = td->td_frame;
memcpy(tf->tf_t, mcp->mc_gpregs.gp_t, sizeof(tf->tf_t));
memcpy(tf->tf_s, mcp->mc_gpregs.gp_s, sizeof(tf->tf_s));
memcpy(tf->tf_a, mcp->mc_gpregs.gp_a, sizeof(tf->tf_a));
tf->tf_ra = mcp->mc_gpregs.gp_ra;
tf->tf_sp = mcp->mc_gpregs.gp_sp;
tf->tf_gp = mcp->mc_gpregs.gp_gp;
tf->tf_tp = mcp->mc_gpregs.gp_tp;
tf->tf_sepc = mcp->mc_gpregs.gp_sepc;
tf->tf_sstatus = mcp->mc_gpregs.gp_sstatus;
return (0);
}
static void
get_fpcontext(struct thread *td, mcontext_t *mcp)
{
/* TODO */
}
static void
set_fpcontext(struct thread *td, mcontext_t *mcp)
{
/* TODO */
}
void
cpu_idle(int busy)
{
spinlock_enter();
if (!busy)
cpu_idleclock();
if (!sched_runnable())
__asm __volatile(
"fence \n"
"wfi \n");
if (!busy)
cpu_activeclock();
spinlock_exit();
}
void
cpu_halt(void)
{
panic("cpu_halt");
}
/*
* Flush the D-cache for non-DMA I/O so that the I-cache can
* be made coherent later.
*/
void
cpu_flush_dcache(void *ptr, size_t len)
{
/* TBD */
}
/* Get current clock frequency for the given CPU ID. */
int
cpu_est_clockrate(int cpu_id, uint64_t *rate)
{
panic("cpu_est_clockrate");
}
void
cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
{
}
void
spinlock_enter(void)
{
struct thread *td;
td = curthread;
if (td->td_md.md_spinlock_count == 0) {
td->td_md.md_spinlock_count = 1;
td->td_md.md_saved_sstatus_ie = intr_disable();
} else
td->td_md.md_spinlock_count++;
critical_enter();
}
void
spinlock_exit(void)
{
struct thread *td;
register_t sstatus_ie;
td = curthread;
critical_exit();
sstatus_ie = td->td_md.md_saved_sstatus_ie;
td->td_md.md_spinlock_count--;
if (td->td_md.md_spinlock_count == 0)
intr_restore(sstatus_ie);
}
#ifndef _SYS_SYSPROTO_H_
struct sigreturn_args {
ucontext_t *ucp;
};
#endif
int
sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
{
uint64_t sstatus;
ucontext_t uc;
int error;
if (uap == NULL)
return (EFAULT);
if (copyin(uap->sigcntxp, &uc, sizeof(uc)))
return (EFAULT);
/*
* Make sure the processor mode has not been tampered with and
* interrupts have not been disabled.
*/
sstatus = uc.uc_mcontext.mc_gpregs.gp_sstatus;
if ((sstatus & SSTATUS_PS) != 0 ||
(sstatus & SSTATUS_PIE) == 0)
return (EINVAL);
error = set_mcontext(td, &uc.uc_mcontext);
if (error != 0)
return (error);
set_fpcontext(td, &uc.uc_mcontext);
/* Restore signal mask. */
kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
return (EJUSTRETURN);
}
/*
* Construct a PCB from a trapframe. This is called from kdb_trap() where
* we want to start a backtrace from the function that caused us to enter
* the debugger. We have the context in the trapframe, but base the trace
* on the PCB. The PCB doesn't have to be perfect, as long as it contains
* enough for a backtrace.
*/
void
makectx(struct trapframe *tf, struct pcb *pcb)
{
memcpy(pcb->pcb_t, tf->tf_t, sizeof(tf->tf_t));
memcpy(pcb->pcb_s, tf->tf_s, sizeof(tf->tf_s));
memcpy(pcb->pcb_a, tf->tf_a, sizeof(tf->tf_a));
pcb->pcb_ra = tf->tf_ra;
pcb->pcb_sp = tf->tf_sp;
pcb->pcb_gp = tf->tf_gp;
pcb->pcb_tp = tf->tf_tp;
pcb->pcb_sepc = tf->tf_sepc;
}
void
sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct sigframe *fp, frame;
struct sysentvec *sysent;
struct trapframe *tf;
struct sigacts *psp;
struct thread *td;
struct proc *p;
int onstack;
int code;
int sig;
td = curthread;
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
sig = ksi->ksi_signo;
code = ksi->ksi_code;
psp = p->p_sigacts;
mtx_assert(&psp->ps_mtx, MA_OWNED);
tf = td->td_frame;
onstack = sigonstack(tf->tf_sp);
CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
catcher, sig);
/* Allocate and validate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !onstack &&
SIGISMEMBER(psp->ps_sigonstack, sig)) {
fp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
td->td_sigstk.ss_size);
} else {
fp = (struct sigframe *)td->td_frame->tf_sp;
}
/* Make room, keeping the stack aligned */
fp--;
fp = (struct sigframe *)STACKALIGN(fp);
/* Fill in the frame to copy out */
get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
get_fpcontext(td, &frame.sf_uc.uc_mcontext);
frame.sf_si = ksi->ksi_info;
frame.sf_uc.uc_sigmask = *mask;
frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) ?
((onstack) ? SS_ONSTACK : 0) : SS_DISABLE;
frame.sf_uc.uc_stack = td->td_sigstk;
mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(td->td_proc);
/* Copy the sigframe out to the user's stack. */
if (copyout(&frame, fp, sizeof(*fp)) != 0) {
/* Process has trashed its stack. Kill it. */
CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp);
PROC_LOCK(p);
sigexit(td, SIGILL);
}
tf->tf_a[0] = sig;
tf->tf_a[1] = (register_t)&fp->sf_si;
tf->tf_a[2] = (register_t)&fp->sf_uc;
tf->tf_sepc = (register_t)catcher;
tf->tf_sp = (register_t)fp;
sysent = p->p_sysent;
if (sysent->sv_sigcode_base != 0)
tf->tf_ra = (register_t)sysent->sv_sigcode_base;
else
tf->tf_ra = (register_t)(sysent->sv_psstrings -
*(sysent->sv_szsigcode));
CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_elr,
tf->tf_sp);
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
static void
init_proc0(vm_offset_t kstack)
{
pcpup = &__pcpu[0];
proc_linkup0(&proc0, &thread0);
thread0.td_kstack = kstack;
thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1;
thread0.td_frame = &proc0_tf;
pcpup->pc_curpcb = thread0.td_pcb;
}
static int
add_physmap_entry(uint64_t base, uint64_t length, vm_paddr_t *physmap,
u_int *physmap_idxp)
{
u_int i, insert_idx, _physmap_idx;
_physmap_idx = *physmap_idxp;
if (length == 0)
return (1);
/*
* Find insertion point while checking for overlap. Start off by
* assuming the new entry will be added to the end.
*/
insert_idx = _physmap_idx;
for (i = 0; i <= _physmap_idx; i += 2) {
if (base < physmap[i + 1]) {
if (base + length <= physmap[i]) {
insert_idx = i;
break;
}
if (boothowto & RB_VERBOSE)
printf(
"Overlapping memory regions, ignoring second region\n");
return (1);
}
}
/* See if we can prepend to the next entry. */
if (insert_idx <= _physmap_idx &&
base + length == physmap[insert_idx]) {
physmap[insert_idx] = base;
return (1);
}
/* See if we can append to the previous entry. */
if (insert_idx > 0 && base == physmap[insert_idx - 1]) {
physmap[insert_idx - 1] += length;
return (1);
}
_physmap_idx += 2;
*physmap_idxp = _physmap_idx;
if (_physmap_idx == PHYSMAP_SIZE) {
printf(
"Too many segments in the physical address map, giving up\n");
return (0);
}
/*
* Move the last 'N' entries down to make room for the new
* entry if needed.
*/
for (i = _physmap_idx; i > insert_idx; i -= 2) {
physmap[i] = physmap[i - 2];
physmap[i + 1] = physmap[i - 1];
}
/* Insert the new entry. */
physmap[insert_idx] = base;
physmap[insert_idx + 1] = base + length;
printf("physmap[%d] = 0x%016lx\n", insert_idx, base);
printf("physmap[%d] = 0x%016lx\n", insert_idx + 1, base + length);
return (1);
}
#ifdef FDT
static void
try_load_dtb(caddr_t kmdp)
{
vm_offset_t dtbp;
dtbp = (vm_offset_t)&fdt_static_dtb;
if (dtbp == (vm_offset_t)NULL) {
printf("ERROR loading DTB\n");
return;
}
if (OF_install(OFW_FDT, 0) == FALSE)
panic("Cannot install FDT");
if (OF_init((void *)dtbp) != 0)
panic("OF_init failed with the found device tree");
}
#endif
static void
cache_setup(void)
{
/* TODO */
}
/*
* Fake up a boot descriptor table.
* RISCVTODO: This needs to be done via loader (when it's available).
*/
vm_offset_t
fake_preload_metadata(struct riscv_bootparams *rvbp __unused)
{
#ifdef DDB
vm_offset_t zstart = 0, zend = 0;
#endif
vm_offset_t lastaddr;
int i = 0;
static uint32_t fake_preload[35];
fake_preload[i++] = MODINFO_NAME;
fake_preload[i++] = strlen("kernel") + 1;
strcpy((char*)&fake_preload[i++], "kernel");
i += 1;
fake_preload[i++] = MODINFO_TYPE;
fake_preload[i++] = strlen("elf64 kernel") + 1;
strcpy((char*)&fake_preload[i++], "elf64 kernel");
i += 3;
fake_preload[i++] = MODINFO_ADDR;
fake_preload[i++] = sizeof(vm_offset_t);
fake_preload[i++] = (uint64_t)(KERNBASE + KERNENTRY);
i += 1;
fake_preload[i++] = MODINFO_SIZE;
fake_preload[i++] = sizeof(uint64_t);
printf("end is 0x%016lx\n", (uint64_t)&end);
fake_preload[i++] = (uint64_t)&end - (uint64_t)(KERNBASE + KERNENTRY);
i += 1;
#ifdef DDB
#if 0
/* RISCVTODO */
if (*(uint32_t *)KERNVIRTADDR == MAGIC_TRAMP_NUMBER) {
fake_preload[i++] = MODINFO_METADATA|MODINFOMD_SSYM;
fake_preload[i++] = sizeof(vm_offset_t);
fake_preload[i++] = *(uint32_t *)(KERNVIRTADDR + 4);
fake_preload[i++] = MODINFO_METADATA|MODINFOMD_ESYM;
fake_preload[i++] = sizeof(vm_offset_t);
fake_preload[i++] = *(uint32_t *)(KERNVIRTADDR + 8);
lastaddr = *(uint32_t *)(KERNVIRTADDR + 8);
zend = lastaddr;
zstart = *(uint32_t *)(KERNVIRTADDR + 4);
db_fetch_ksymtab(zstart, zend);
} else
#endif
#endif
lastaddr = (vm_offset_t)&end;
fake_preload[i++] = 0;
fake_preload[i] = 0;
preload_metadata = (void *)fake_preload;
return (lastaddr);
}
void
initriscv(struct riscv_bootparams *rvbp)
{
vm_offset_t lastaddr;
vm_size_t kernlen;
caddr_t kmdp;
/* Set the module data location */
lastaddr = fake_preload_metadata(rvbp);
/* Find the kernel address */
kmdp = preload_search_by_type("elf kernel");
if (kmdp == NULL)
kmdp = preload_search_by_type("elf64 kernel");
boothowto = 0;
kern_envp = NULL;
#ifdef FDT
try_load_dtb(kmdp);
#endif
/* Load the physical memory ranges */
physmap_idx = 0;
/*
* RISCVTODO: figure out whether platform provides ranges,
* or grab from FDT.
*/
add_physmap_entry(0, 0x8000000, physmap, &physmap_idx);
/* Set the pcpu data, this is needed by pmap_bootstrap */
pcpup = &__pcpu[0];
pcpu_init(pcpup, 0, sizeof(struct pcpu));
/* Set the pcpu pointer */
#if 0
/* SMP TODO: try re-use gp for pcpu pointer */
__asm __volatile(
"mv gp, %0" :: "r"(pcpup));
#endif
PCPU_SET(curthread, &thread0);
/* Do basic tuning, hz etc */
init_param1();
cache_setup();
/* Bootstrap enough of pmap to enter the kernel proper */
kernlen = (lastaddr - KERNBASE);
pmap_bootstrap(rvbp->kern_l1pt, KERNENTRY, kernlen);
cninit();
init_proc0(rvbp->kern_stack);
/* set page table base register for thread0 */
thread0.td_pcb->pcb_l1addr = (rvbp->kern_l1pt - KERNBASE);
msgbufinit(msgbufp, msgbufsize);
mutex_init();
init_param2(physmem);
kdb_init();
riscv_init_interrupts();
early_boot = 0;
}

124
sys/riscv/riscv/mem.c Normal file
View File

@ -0,0 +1,124 @@
/*-
* Copyright (c) 2014 Andrew Turner
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/malloc.h>
#include <sys/memrange.h>
#include <sys/uio.h>
#include <machine/memdev.h>
#include <machine/vmparam.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <vm/vm_page.h>
struct mem_range_softc mem_range_softc;
int
memrw(struct cdev *dev, struct uio *uio, int flags)
{
ssize_t orig_resid;
vm_offset_t off, v;
struct iovec *iov;
struct vm_page m;
vm_page_t marr;
u_int cnt;
int error;
error = 0;
orig_resid = uio->uio_resid;
while (uio->uio_resid > 0 && error == 0) {
iov = uio->uio_iov;
if (iov->iov_len == 0) {
uio->uio_iov++;
uio->uio_iovcnt--;
if (uio->uio_iovcnt < 0)
panic("memrw");
continue;
}
v = uio->uio_offset;
off = v & PAGE_MASK;
cnt = ulmin(iov->iov_len, PAGE_SIZE - (u_int)off);
if (cnt == 0)
continue;
switch(dev2unit(dev)) {
case CDEV_MINOR_KMEM:
/* If the address is in the DMAP just copy it */
if (VIRT_IN_DMAP(v)) {
error = uiomove((void *)v, cnt, uio);
break;
}
if (!kernacc((void *)v, cnt, uio->uio_rw == UIO_READ ?
VM_PROT_READ : VM_PROT_WRITE)) {
error = EFAULT;
break;
}
/* Get the physical address to read */
v = pmap_extract(kernel_pmap, v);
if (v == 0) {
error = EFAULT;
break;
}
/* FALLTHROUGH */
case CDEV_MINOR_MEM:
/* If within the DMAP use this to copy from */
if (PHYS_IN_DMAP(v)) {
v = PHYS_TO_DMAP(v);
error = uiomove((void *)v, cnt, uio);
break;
}
/* Have uiomove_fromphys handle the data */
m.phys_addr = trunc_page(v);
marr = &m;
uiomove_fromphys(&marr, off, cnt, uio);
break;
}
}
/*
* Don't return error if any byte was written. Read and write
* can return error only if no i/o was performed.
*/
if (uio->uio_resid != orig_resid)
error = 0;
return (error);
}

View File

@ -0,0 +1,59 @@
/*-
* Copyright (c) 2006 Peter Wemm
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_watchdog.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/cons.h>
#include <sys/kernel.h>
#include <sys/kerneldump.h>
#include <sys/msgbuf.h>
#include <sys/watchdog.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
#include <vm/vm_phys.h>
#include <vm/pmap.h>
#include <machine/atomic.h>
#include <machine/elf.h>
#include <machine/md_var.h>
#include <machine/vmparam.h>
#include <machine/minidump.h>
CTASSERT(sizeof(struct kerneldumpheader) == 512);
CTASSERT(sizeof(*vm_page_dump) == 8);
int
minidumpsys(struct dumperinfo *di)
{
panic("minidumpsys");
}

387
sys/riscv/riscv/nexus.c Normal file
View File

@ -0,0 +1,387 @@
/*-
* Copyright 1998 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
* granted, provided that both the above copyright notice and this
* permission notice appear in all copies, that both the above
* copyright notice and this permission notice appear in all
* supporting documentation, and that the name of M.I.T. not be used
* in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission. M.I.T. makes
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* This code implements a `root nexus' for RISC-V Architecture
* machines. The function of the root nexus is to serve as an
* attachment point for both processors and buses, and to manage
* resources which are common to all of them. In particular,
* this code implements the core resource managers for interrupt
* requests, DMA requests (which rightfully should be a part of the
* ISA code but it's easier to do it here for now), I/O port addresses,
* and I/O memory address space.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <sys/interrupt.h>
#include <machine/vmparam.h>
#include <machine/pcb.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/resource.h>
#include <machine/intr.h>
#include "opt_platform.h"
#include <dev/fdt/fdt_common.h>
#include "ofw_bus_if.h"
extern struct bus_space memmap_bus;
static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
struct nexus_device {
struct resource_list nx_resources;
};
#define DEVTONX(dev) ((struct nexus_device *)device_get_ivars(dev))
static struct rman mem_rman;
static struct rman irq_rman;
static device_probe_t nexus_fdt_probe;
static int nexus_attach(device_t);
static int nexus_print_child(device_t, device_t);
static device_t nexus_add_child(device_t, u_int, const char *, int);
static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
u_long, u_long, u_long, u_int);
static int nexus_activate_resource(device_t, device_t, int, int,
struct resource *);
static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
enum intr_polarity pol);
static struct resource_list *nexus_get_reslist(device_t, device_t);
static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long);
static int nexus_deactivate_resource(device_t, device_t, int, int,
struct resource *);
static int nexus_setup_intr(device_t dev, device_t child, struct resource *res,
int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep);
static int nexus_teardown_intr(device_t, device_t, struct resource *, void *);
static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent,
int icells, pcell_t *intr);
static device_method_t nexus_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, nexus_fdt_probe),
DEVMETHOD(device_attach, nexus_attach),
/* OFW interface */
DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr),
/* Bus interface */
DEVMETHOD(bus_print_child, nexus_print_child),
DEVMETHOD(bus_add_child, nexus_add_child),
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
DEVMETHOD(bus_activate_resource, nexus_activate_resource),
DEVMETHOD(bus_config_intr, nexus_config_intr),
DEVMETHOD(bus_get_resource_list, nexus_get_reslist),
DEVMETHOD(bus_set_resource, nexus_set_resource),
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
{ 0, 0 }
};
static driver_t nexus_fdt_driver = {
"nexus",
nexus_methods,
1 /* no softc */
};
static int
nexus_fdt_probe(device_t dev)
{
device_quiet(dev);
return (BUS_PROBE_DEFAULT);
}
static int
nexus_attach(device_t dev)
{
mem_rman.rm_start = 0;
mem_rman.rm_end = ~0ul;
mem_rman.rm_type = RMAN_ARRAY;
mem_rman.rm_descr = "I/O memory addresses";
if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0, ~0))
panic("nexus_attach mem_rman");
irq_rman.rm_start = 0;
irq_rman.rm_end = ~0ul;
irq_rman.rm_type = RMAN_ARRAY;
irq_rman.rm_descr = "Interrupts";
if (rman_init(&irq_rman) || rman_manage_region(&irq_rman, 0, ~0))
panic("nexus_attach irq_rman");
nexus_add_child(dev, 10, "ofwbus", 0);
bus_generic_probe(dev);
bus_generic_attach(dev);
return (0);
}
static int
nexus_print_child(device_t bus, device_t child)
{
int retval = 0;
retval += bus_print_child_header(bus, child);
retval += printf("\n");
return (retval);
}
static device_t
nexus_add_child(device_t bus, u_int order, const char *name, int unit)
{
device_t child;
struct nexus_device *ndev;
ndev = malloc(sizeof(struct nexus_device), M_NEXUSDEV, M_NOWAIT|M_ZERO);
if (!ndev)
return (0);
resource_list_init(&ndev->nx_resources);
child = device_add_child_ordered(bus, order, name, unit);
/* should we free this in nexus_child_detached? */
device_set_ivars(child, ndev);
return (child);
}
/*
* Allocate a resource on behalf of child. NB: child is usually going to be a
* child of one of our descendants, not a direct child of nexus0.
* (Exceptions include footbridge.)
*/
static struct resource *
nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct nexus_device *ndev = DEVTONX(child);
struct resource *rv;
struct resource_list_entry *rle;
struct rman *rm;
int needactivate = flags & RF_ACTIVE;
/*
* If this is an allocation of the "default" range for a given
* RID, and we know what the resources for this device are
* (ie. they aren't maintained by a child bus), then work out
* the start/end values.
*/
if ((start == 0UL) && (end == ~0UL) && (count == 1)) {
if (device_get_parent(child) != bus || ndev == NULL)
return(NULL);
rle = resource_list_find(&ndev->nx_resources, type, *rid);
if (rle == NULL)
return(NULL);
start = rle->start;
end = rle->end;
count = rle->count;
}
switch (type) {
case SYS_RES_IRQ:
rm = &irq_rman;
break;
case SYS_RES_MEMORY:
case SYS_RES_IOPORT:
rm = &mem_rman;
break;
default:
return (NULL);
}
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0)
return (NULL);
rman_set_rid(rv, *rid);
rman_set_bushandle(rv, rman_get_start(rv));
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
rman_release_resource(rv);
return (NULL);
}
}
return (rv);
}
static int
nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
enum intr_polarity pol)
{
return (riscv_config_intr(irq, trig, pol));
}
static int
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
{
int error;
if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
flags |= INTR_EXCL;
/* We depend here on rman_activate_resource() being idempotent. */
error = rman_activate_resource(res);
if (error)
return (error);
error = riscv_setup_intr(device_get_nameunit(child), filt, intr,
arg, rman_get_start(res), flags, cookiep);
return (error);
}
static int
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
return (riscv_teardown_intr(ih));
}
static int
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
int err;
bus_addr_t paddr;
bus_size_t psize;
bus_space_handle_t vaddr;
if ((err = rman_activate_resource(r)) != 0)
return (err);
/*
* If this is a memory resource, map it into the kernel.
*/
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
paddr = (bus_addr_t)rman_get_start(r);
psize = (bus_size_t)rman_get_size(r);
err = bus_space_map(&memmap_bus, paddr, psize, 0, &vaddr);
if (err != 0) {
rman_deactivate_resource(r);
return (err);
}
rman_set_bustag(r, &memmap_bus);
rman_set_virtual(r, (void *)vaddr);
rman_set_bushandle(r, vaddr);
}
return (0);
}
static struct resource_list *
nexus_get_reslist(device_t dev, device_t child)
{
struct nexus_device *ndev = DEVTONX(child);
return (&ndev->nx_resources);
}
static int
nexus_set_resource(device_t dev, device_t child, int type, int rid,
u_long start, u_long count)
{
struct nexus_device *ndev = DEVTONX(child);
struct resource_list *rl = &ndev->nx_resources;
/* XXX this should return a success/failure indicator */
resource_list_add(rl, type, rid, start, start + count - 1, count);
return(0);
}
static int
nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
bus_size_t psize;
bus_space_handle_t vaddr;
psize = (bus_size_t)rman_get_size(r);
vaddr = rman_get_bushandle(r);
if (vaddr != 0) {
bus_space_unmap(&memmap_bus, vaddr, psize);
rman_set_virtual(r, NULL);
rman_set_bushandle(r, 0);
}
return (rman_deactivate_resource(r));
}
static devclass_t nexus_fdt_devclass;
EARLY_DRIVER_MODULE(nexus_fdt, root, nexus_fdt_driver, nexus_fdt_devclass,
0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST);
static int
nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
pcell_t *intr)
{
int irq;
if (icells == 3) {
irq = intr[1];
if (intr[0] == 0)
irq += 32; /* SPI */
else
irq += 16; /* PPI */
} else
irq = intr[0];
return (irq);
}

3197
sys/riscv/riscv/pmap.c Normal file

File diff suppressed because it is too large Load Diff

295
sys/riscv/riscv/support.S Normal file
View File

@ -0,0 +1,295 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
#include <machine/setjmp.h>
#include "assym.s"
/*
* One of the fu* or su* functions failed, return -1.
*/
ENTRY(fsu_fault)
SET_FAULT_HANDLER(x0, a1) /* Reset the handler function */
fsu_fault_nopcb:
li a0, -1
ret
END(fsu_fault)
/*
* int casueword32(volatile uint32_t *, uint32_t, uint32_t *, uint32_t)
*/
ENTRY(casueword32)
li a4, (VM_MAXUSER_ADDRESS-3)
bgt a0, a4, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a4) /* And set it */
1: lr.w a4, 0(a0) /* Load-exclusive the data */
bne a4, a1, 2f /* If not equal then exit */
sc.w a5, a3, 0(a0) /* Store the new data */
bnez a5, 1b /* Retry on failure */
2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
sw a4, 0(a2) /* Store the read data */
li a0, 0 /* Success */
ret /* Return */
END(casueword32)
/*
* int casueword(volatile u_long *, u_long, u_long *, u_long)
*/
ENTRY(casueword)
li a4, (VM_MAXUSER_ADDRESS-7)
bgt a0, a4, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a4) /* And set it */
1: lr.d a4, 0(a0) /* Load-exclusive the data */
bne a4, a1, 2f /* If not equal then exit */
sc.d a5, a3, 0(a0) /* Store the new data */
bnez a5, 1b /* Retry on failure */
2: SET_FAULT_HANDLER(x0, a5) /* Reset the fault handler */
sd a4, 0(a2) /* Store the read data */
li a0, 0 /* Success */
ret /* Return */
END(casueword)
/*
* int fubyte(volatile const void *)
*/
ENTRY(fubyte)
li a1, VM_MAXUSER_ADDRESS
bgt a0, a1, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a1) /* And set it */
lb a0, 0(a0) /* Try loading the data */
SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */
ret /* Return */
END(fubyte)
/*
* int fuword(volatile const void *)
*/
ENTRY(fuword16)
li a1, (VM_MAXUSER_ADDRESS-1)
bgt a0, a1, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a1) /* And set it */
lh a0, 0(a0) /* Try loading the data */
SET_FAULT_HANDLER(x0, a1) /* Reset the fault handler */
ret /* Return */
END(fuword16)
/*
* int32_t fueword32(volatile const void *, int32_t *)
*/
ENTRY(fueword32)
li a2, (VM_MAXUSER_ADDRESS-3)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
lw a0, 0(a0) /* Try loading the data */
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
sw a0, 0(a1) /* Save the data in kernel space */
li a0, 0 /* Success */
ret /* Return */
END(fueword32)
/*
* long fueword(volatile const void *, int64_t *)
* int64_t fueword64(volatile const void *, int64_t *)
*/
ENTRY(fueword)
EENTRY(fueword64)
li a2, (VM_MAXUSER_ADDRESS-7)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
ld a0, 0(a0) /* Try loading the data */
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
sd a0, 0(a1) /* Save the data in kernel space */
li a0, 0 /* Success */
ret /* Return */
EEND(fueword64)
END(fueword)
/*
* int subyte(volatile void *, int)
*/
ENTRY(subyte)
li a2, VM_MAXUSER_ADDRESS
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
sb a1, 0(a0) /* Try storing the data */
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
li a0, 0 /* Success */
ret /* Return */
END(subyte)
/*
* int suword16(volatile void *, int)
*/
ENTRY(suword16)
li a2, (VM_MAXUSER_ADDRESS-1)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
sh a1, 0(a0) /* Try storing the data */
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
li a0, 0 /* Success */
ret /* Return */
END(suword16)
/*
* int suword32(volatile void *, int)
*/
ENTRY(suword32)
li a2, (VM_MAXUSER_ADDRESS-3)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
sw a1, 0(a0) /* Try storing the data */
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
li a0, 0 /* Success */
ret /* Return */
END(suword32)
/*
* int suword(volatile void *, long)
*/
ENTRY(suword)
EENTRY(suword64)
li a2, (VM_MAXUSER_ADDRESS-7)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
sd a1, 0(a0) /* Try storing the data */
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
li a0, 0 /* Success */
ret /* Return */
EEND(suword64)
END(suword)
/*
* fuswintr and suswintr are just like fusword and susword except that if
* the page is not in memory or would cause a trap, then we return an error.
* The important thing is to prevent sleep() and switch().
*/
/*
* Special handler so the trap code knows not to sleep.
*/
ENTRY(fsu_intr_fault)
SET_FAULT_HANDLER(x0, a1) /* Reset the handler function */
li a0, -1
ret
END(fsu_fault)
/*
* int fuswintr(void *)
*/
ENTRY(fuswintr)
li a1, (VM_MAXUSER_ADDRESS-3)
bgt a0, a1, fsu_fault_nopcb
la a6, fsu_intr_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a1) /* And set it */
lw a0, 0(a0) /* Try loading the data */
SET_FAULT_HANDLER(x0, x1) /* Reset the fault handler */
ret /* Return */
END(fuswintr)
/*
* int suswintr(void *base, int word)
*/
ENTRY(suswintr)
li a2, (VM_MAXUSER_ADDRESS-3)
bgt a0, a2, fsu_fault_nopcb
la a6, fsu_intr_fault /* Load the fault handler */
SET_FAULT_HANDLER(a6, a2) /* And set it */
sw a1, 0(a0) /* Try storing the data */
SET_FAULT_HANDLER(x0, a2) /* Reset the fault handler */
li a0, 0 /* Success */
ret /* Return */
END(suswintr)
ENTRY(setjmp)
/* Store the stack pointer */
sd sp, 0(a0)
addi a0, a0, 8
/* Store the general purpose registers and ra */
sd s0, (0 * 8)(a0)
sd s1, (1 * 8)(a0)
sd s2, (2 * 8)(a0)
sd s3, (3 * 8)(a0)
sd s4, (4 * 8)(a0)
sd s5, (5 * 8)(a0)
sd s6, (6 * 8)(a0)
sd s7, (7 * 8)(a0)
sd s8, (8 * 8)(a0)
sd s9, (9 * 8)(a0)
sd s10, (10 * 8)(a0)
sd s11, (11 * 8)(a0)
sd ra, (12 * 8)(a0)
/* Return value */
li a0, 0
ret
END(setjmp)
ENTRY(longjmp)
/* Restore the stack pointer */
ld sp, 0(a0)
addi a0, a0, 8
/* Restore the general purpose registers and ra */
ld s0, (0 * 8)(a0)
ld s1, (1 * 8)(a0)
ld s2, (2 * 8)(a0)
ld s3, (3 * 8)(a0)
ld s4, (4 * 8)(a0)
ld s5, (5 * 8)(a0)
ld s6, (6 * 8)(a0)
ld s7, (7 * 8)(a0)
ld s8, (8 * 8)(a0)
ld s9, (9 * 8)(a0)
ld s10, (10 * 8)(a0)
ld s11, (11 * 8)(a0)
ld ra, (12 * 8)(a0)
/* Load the return value */
mv a0, a1
ret
END(longjmp)

272
sys/riscv/riscv/swtch.S Normal file
View File

@ -0,0 +1,272 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "assym.s"
#include "opt_sched.h"
#include <machine/param.h>
#include <machine/asm.h>
#include <machine/riscvreg.h>
#include <machine/pte.h>
__FBSDID("$FreeBSD$");
/*
* void cpu_throw(struct thread *old, struct thread *new)
*/
ENTRY(cpu_throw)
/* Load pcpu */
la x14, pcpup
ld x14, 0(x14)
/* Store the new curthread */
sd a1, PC_CURTHREAD(x14)
/* And the new pcb */
ld x13, TD_PCB(a1)
sd x13, PC_CURPCB(x14)
sfence.vm
/* Switch to the new pmap */
la t0, pagetable_l0
ld t1, PCB_L1ADDR(x13) /* Link to next level PN */
srli t1, t1, PAGE_SHIFT /* PN no */
li t2, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
slli t3, t1, PTE_PPN0_S /* (t1 << PTE_PPN0_S) */
or t4, t2, t3
/* Store single level0 PTE entry to position */
sd t4, 0(t0)
/* TODO: Invalidate the TLB */
sfence.vm
/* Load registers */
ld ra, (PCB_RA)(x13)
ld sp, (PCB_SP)(x13)
ld gp, (PCB_GP)(x13)
ld tp, (PCB_TP)(x13)
/* s[0-11] */
ld s0, (PCB_S + 0 * 8)(x13)
ld s1, (PCB_S + 1 * 8)(x13)
ld s2, (PCB_S + 2 * 8)(x13)
ld s3, (PCB_S + 3 * 8)(x13)
ld s4, (PCB_S + 4 * 8)(x13)
ld s5, (PCB_S + 5 * 8)(x13)
ld s6, (PCB_S + 6 * 8)(x13)
ld s7, (PCB_S + 7 * 8)(x13)
ld s8, (PCB_S + 8 * 8)(x13)
ld s9, (PCB_S + 9 * 8)(x13)
ld s10, (PCB_S + 10 * 8)(x13)
ld s11, (PCB_S + 11 * 8)(x13)
ret
.Lcpu_throw_panic_str:
.asciz "cpu_throw: %p\0"
END(cpu_throw)
/*
* void cpu_switch(struct thread *old, struct thread *new, struct mtx *mtx)
*
* a0 = old
* a1 = new
* a2 = mtx
* x3 to x7, x16 and x17 are caller saved
*/
ENTRY(cpu_switch)
/* Load pcpu */
la x14, pcpup
ld x14, 0(x14)
/* Store the new curthread */
sd a1, PC_CURTHREAD(x14)
/* And the new pcb */
ld x13, TD_PCB(a1)
sd x13, PC_CURPCB(x14)
/* Save the old context. */
ld x13, TD_PCB(a0)
/* Store the callee-saved registers */
sd ra, (PCB_RA)(x13)
sd sp, (PCB_SP)(x13)
sd gp, (PCB_GP)(x13)
sd tp, (PCB_TP)(x13)
/* We use these in fork_trampoline */
sd t0, (PCB_T + 0 * 8)(x13)
sd t1, (PCB_T + 1 * 8)(x13)
/* s[0-11] */
sd s0, (PCB_S + 0 * 8)(x13)
sd s1, (PCB_S + 1 * 8)(x13)
sd s2, (PCB_S + 2 * 8)(x13)
sd s3, (PCB_S + 3 * 8)(x13)
sd s4, (PCB_S + 4 * 8)(x13)
sd s5, (PCB_S + 5 * 8)(x13)
sd s6, (PCB_S + 6 * 8)(x13)
sd s7, (PCB_S + 7 * 8)(x13)
sd s8, (PCB_S + 8 * 8)(x13)
sd s9, (PCB_S + 9 * 8)(x13)
sd s10, (PCB_S + 10 * 8)(x13)
sd s11, (PCB_S + 11 * 8)(x13)
/*
* Restore the saved context.
*/
ld x13, TD_PCB(a1)
/*
* TODO: We may need to flush the cache here if switching
* to a user process.
*/
sfence.vm
/* Switch to the new pmap */
la t0, pagetable_l0
ld t1, PCB_L1ADDR(x13) /* Link to next level PN */
srli t1, t1, PAGE_SHIFT /* PN no */
li t2, (PTE_VALID | (PTE_TYPE_PTR << PTE_TYPE_S))
slli t3, t1, PTE_PPN0_S /* (t1 << PTE_PPN0_S) */
or t4, t2, t3
/* Store single level0 PTE entry to position */
sd t4, 0(t0)
/* TODO: Invalidate the TLB */
sfence.vm
/* Release the old thread */
sd a2, TD_LOCK(a0)
#if defined(SCHED_ULE) && defined(SMP)
/* TODO */
#endif
/* Restore the registers */
ld ra, (PCB_RA)(x13)
ld sp, (PCB_SP)(x13)
ld gp, (PCB_GP)(x13)
ld tp, (PCB_TP)(x13)
/* We use these in fork_trampoline */
ld t0, (PCB_T + 0 * 8)(x13)
ld t1, (PCB_T + 1 * 8)(x13)
/* s[0-11] */
ld s0, (PCB_S + 0 * 8)(x13)
ld s1, (PCB_S + 1 * 8)(x13)
ld s2, (PCB_S + 2 * 8)(x13)
ld s3, (PCB_S + 3 * 8)(x13)
ld s4, (PCB_S + 4 * 8)(x13)
ld s5, (PCB_S + 5 * 8)(x13)
ld s6, (PCB_S + 6 * 8)(x13)
ld s7, (PCB_S + 7 * 8)(x13)
ld s8, (PCB_S + 8 * 8)(x13)
ld s9, (PCB_S + 9 * 8)(x13)
ld s10, (PCB_S + 10 * 8)(x13)
ld s11, (PCB_S + 11 * 8)(x13)
ret
.Lcpu_switch_panic_str:
.asciz "cpu_switch: %p\0"
END(cpu_switch)
/*
* fork_exit(void (*callout)(void *, struct trapframe *), void *arg,
* struct trapframe *frame)
*/
ENTRY(fork_trampoline)
mv a0, x5
mv a1, x6
mv a2, sp
call _C_LABEL(fork_exit)
/* Restore sstatus */
ld t0, (TF_SSTATUS)(sp)
/* Ensure interrupts disabled */
li t1, ~SSTATUS_IE
and t0, t0, t1
csrw sstatus, t0
/* Restore exception program counter */
ld t0, (TF_SEPC)(sp)
csrw sepc, t0
/* Restore the registers */
ld t0, (TF_T + 0 * 8)(sp)
ld t1, (TF_T + 1 * 8)(sp)
ld t2, (TF_T + 2 * 8)(sp)
ld t3, (TF_T + 3 * 8)(sp)
ld t4, (TF_T + 4 * 8)(sp)
ld t5, (TF_T + 5 * 8)(sp)
ld t6, (TF_T + 6 * 8)(sp)
ld s0, (TF_S + 0 * 8)(sp)
ld s1, (TF_S + 1 * 8)(sp)
ld s2, (TF_S + 2 * 8)(sp)
ld s3, (TF_S + 3 * 8)(sp)
ld s4, (TF_S + 4 * 8)(sp)
ld s5, (TF_S + 5 * 8)(sp)
ld s6, (TF_S + 6 * 8)(sp)
ld s7, (TF_S + 7 * 8)(sp)
ld s8, (TF_S + 8 * 8)(sp)
ld s9, (TF_S + 9 * 8)(sp)
ld s10, (TF_S + 10 * 8)(sp)
ld s11, (TF_S + 11 * 8)(sp)
ld a0, (TF_A + 0 * 8)(sp)
ld a1, (TF_A + 1 * 8)(sp)
ld a2, (TF_A + 2 * 8)(sp)
ld a3, (TF_A + 3 * 8)(sp)
ld a4, (TF_A + 4 * 8)(sp)
ld a5, (TF_A + 5 * 8)(sp)
ld a6, (TF_A + 6 * 8)(sp)
ld a7, (TF_A + 7 * 8)(sp)
/* Save kernel stack so we can use it doing a user trap */
csrw sscratch, sp
/* Load user ra and sp */
ld ra, (TF_RA)(sp)
ld sp, (TF_SP)(sp)
eret
END(fork_trampoline)
ENTRY(savectx)
la a0, .Lsavectx_panic_str
call panic
.Lsavectx_panic_str:
.asciz "savectx_panic: %p\0"
END(savectx)

View File

@ -0,0 +1,49 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <machine/sysarch.h>
int
sysarch(struct thread *td, struct sysarch_args *uap)
{
return (ENOTSUP);
}

298
sys/riscv/riscv/timer.c Normal file
View File

@ -0,0 +1,298 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* RISC-V Timer
*/
#include "opt_platform.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/timeet.h>
#include <sys/timetc.h>
#include <sys/watchdog.h>
#include <sys/proc.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <machine/asm.h>
#include <machine/trap.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#define DEFAULT_FREQ 1000000
struct riscv_tmr_softc {
struct resource *res[1];
void *ihl[1];
uint32_t clkfreq;
struct eventtimer et;
};
static struct riscv_tmr_softc *riscv_tmr_sc = NULL;
static struct resource_spec timer_spec[] = {
{ SYS_RES_IRQ, 0, RF_ACTIVE },
{ -1, 0 }
};
static timecounter_get_t riscv_tmr_get_timecount;
static struct timecounter riscv_tmr_timecount = {
.tc_name = "RISC-V Timecounter",
.tc_get_timecount = riscv_tmr_get_timecount,
.tc_poll_pps = NULL,
.tc_counter_mask = ~0u,
.tc_frequency = 0,
.tc_quality = 1000,
};
static long
get_counts(void)
{
return (csr_read(stime));
}
static unsigned
riscv_tmr_get_timecount(struct timecounter *tc)
{
return (get_counts());
}
static int
riscv_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct riscv_tmr_softc *sc;
int counts;
sc = (struct riscv_tmr_softc *)et->et_priv;
if (first != 0) {
counts = ((uint32_t)et->et_frequency * first) >> 32;
machine_command(ECALL_MTIMECMP, counts);
return (0);
}
return (EINVAL);
}
static int
riscv_tmr_stop(struct eventtimer *et)
{
struct riscv_tmr_softc *sc;
sc = (struct riscv_tmr_softc *)et->et_priv;
/* TODO */
return (0);
}
static int
riscv_tmr_intr(void *arg)
{
struct riscv_tmr_softc *sc;
sc = (struct riscv_tmr_softc *)arg;
/*
* Clear interrupt pending bit.
* Note sip register is unimplemented in Spike simulator,
* so use machine command to clear in mip.
*/
machine_command(ECALL_CLEAR_PENDING, 0);
if (sc->et.et_active)
sc->et.et_event_cb(&sc->et, sc->et.et_arg);
return (FILTER_HANDLED);
}
static int
riscv_tmr_fdt_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (ofw_bus_is_compatible(dev, "riscv,timer")) {
device_set_desc(dev, "RISC-V Timer");
return (BUS_PROBE_DEFAULT);
}
return (ENXIO);
}
static int
riscv_tmr_attach(device_t dev)
{
struct riscv_tmr_softc *sc;
phandle_t node;
pcell_t clock;
int error;
sc = device_get_softc(dev);
if (riscv_tmr_sc)
return (ENXIO);
/* Get the base clock frequency */
node = ofw_bus_get_node(dev);
if (node > 0) {
error = OF_getprop(node, "clock-frequency", &clock,
sizeof(clock));
if (error > 0) {
sc->clkfreq = fdt32_to_cpu(clock);
}
}
if (sc->clkfreq == 0)
sc->clkfreq = DEFAULT_FREQ;
if (sc->clkfreq == 0) {
device_printf(dev, "No clock frequency specified\n");
return (ENXIO);
}
if (bus_alloc_resources(dev, timer_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
riscv_tmr_sc = sc;
/* Setup IRQs handler */
error = bus_setup_intr(dev, sc->res[0], INTR_TYPE_CLK,
riscv_tmr_intr, NULL, sc, &sc->ihl[0]);
if (error) {
device_printf(dev, "Unable to alloc int resource.\n");
return (ENXIO);
}
riscv_tmr_timecount.tc_frequency = sc->clkfreq;
tc_init(&riscv_tmr_timecount);
sc->et.et_name = "RISC-V Eventtimer";
sc->et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
sc->et.et_quality = 1000;
sc->et.et_frequency = sc->clkfreq;
sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
sc->et.et_start = riscv_tmr_start;
sc->et.et_stop = riscv_tmr_stop;
sc->et.et_priv = sc;
et_register(&sc->et);
return (0);
}
static device_method_t riscv_tmr_fdt_methods[] = {
DEVMETHOD(device_probe, riscv_tmr_fdt_probe),
DEVMETHOD(device_attach, riscv_tmr_attach),
{ 0, 0 }
};
static driver_t riscv_tmr_fdt_driver = {
"timer",
riscv_tmr_fdt_methods,
sizeof(struct riscv_tmr_softc),
};
static devclass_t riscv_tmr_fdt_devclass;
EARLY_DRIVER_MODULE(timer, simplebus, riscv_tmr_fdt_driver, riscv_tmr_fdt_devclass,
0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
EARLY_DRIVER_MODULE(timer, ofwbus, riscv_tmr_fdt_driver, riscv_tmr_fdt_devclass,
0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
void
DELAY(int usec)
{
int32_t counts, counts_per_usec;
uint32_t first, last;
/*
* Check the timers are setup, if not just
* use a for loop for the meantime
*/
if (riscv_tmr_sc == NULL) {
for (; usec > 0; usec--)
for (counts = 200; counts > 0; counts--)
/*
* Prevent the compiler from optimizing
* out the loop
*/
cpufunc_nullop();
return;
}
/* Get the number of times to count */
counts_per_usec = ((riscv_tmr_timecount.tc_frequency / 1000000) + 1);
/*
* Clamp the timeout at a maximum value (about 32 seconds with
* a 66MHz clock). *Nobody* should be delay()ing for anywhere
* near that length of time and if they are, they should be hung
* out to dry.
*/
if (usec >= (0x80000000U / counts_per_usec))
counts = (0x80000000U / counts_per_usec) - 1;
else
counts = usec * counts_per_usec;
first = get_counts();
while (counts > 0) {
last = get_counts();
counts -= (int32_t)(last - first);
first = last;
}
}

311
sys/riscv/riscv/trap.c Normal file
View File

@ -0,0 +1,311 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/pioctl.h>
#include <sys/bus.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/sysent.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_kern.h>
#include <vm/vm_map.h>
#include <vm/vm_param.h>
#include <vm/vm_extern.h>
#include <machine/frame.h>
#include <machine/pcb.h>
#include <machine/pcpu.h>
#include <machine/vmparam.h>
#include <machine/resource.h>
#include <machine/intr.h>
extern register_t fsu_intr_fault;
/* Called from exception.S */
void do_trap_supervisor(struct trapframe *);
void do_trap_user(struct trapframe *);
static __inline void
call_trapsignal(struct thread *td, int sig, int code, void *addr)
{
ksiginfo_t ksi;
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = sig;
ksi.ksi_code = code;
ksi.ksi_addr = addr;
trapsignal(td, &ksi);
}
int
cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
struct proc *p;
register_t *ap;
int nap;
nap = 8;
p = td->td_proc;
ap = &td->td_frame->tf_a[0];
sa->code = td->td_frame->tf_t[0];
if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
sa->code = *ap++;
nap--;
}
if (p->p_sysent->sv_mask)
sa->code &= p->p_sysent->sv_mask;
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
else
sa->callp = &p->p_sysent->sv_table[sa->code];
sa->narg = sa->callp->sy_narg;
memcpy(sa->args, ap, nap * sizeof(register_t));
if (sa->narg > nap)
panic("TODO: Could we have more then 8 args?");
td->td_retval[0] = 0;
td->td_retval[1] = 0;
return (0);
}
#include "../../kern/subr_syscall.c"
static void
dump_regs(struct trapframe *frame)
{
int n;
int i;
n = (sizeof(frame->tf_t) / sizeof(frame->tf_t[0]));
for (i = 0; i < n; i++)
printf("t[%d] == 0x%016lx\n", i, frame->tf_t[i]);
n = (sizeof(frame->tf_s) / sizeof(frame->tf_s[0]));
for (i = 0; i < n; i++)
printf("s[%d] == 0x%016lx\n", i, frame->tf_s[i]);
n = (sizeof(frame->tf_a) / sizeof(frame->tf_a[0]));
for (i = 0; i < n; i++)
printf("a[%d] == 0x%016lx\n", i, frame->tf_a[i]);
printf("sepc == 0x%016lx\n", frame->tf_sepc);
printf("sstatus == 0x%016lx\n", frame->tf_sstatus);
}
static void
svc_handler(struct trapframe *frame)
{
struct syscall_args sa;
struct thread *td;
int error;
td = curthread;
td->td_frame = frame;
error = syscallenter(td, &sa);
syscallret(td, error, &sa);
}
static void
data_abort(struct trapframe *frame, int lower)
{
struct vm_map *map;
uint64_t sbadaddr;
struct thread *td;
struct pcb *pcb;
vm_prot_t ftype;
vm_offset_t va;
struct proc *p;
int ucode;
int error;
int sig;
td = curthread;
pcb = td->td_pcb;
/*
* Special case for fuswintr and suswintr. These can't sleep so
* handle them early on in the trap handler.
*/
if (__predict_false(pcb->pcb_onfault == (vm_offset_t)&fsu_intr_fault)) {
frame->tf_sepc = pcb->pcb_onfault;
return;
}
sbadaddr = frame->tf_sbadaddr;
p = td->td_proc;
if (lower)
map = &td->td_proc->p_vmspace->vm_map;
else {
/* The top bit tells us which range to use */
if ((sbadaddr >> 63) == 1)
map = kernel_map;
else
map = &td->td_proc->p_vmspace->vm_map;
}
va = trunc_page(sbadaddr);
if (frame->tf_scause == EXCP_STORE_ACCESS_FAULT) {
ftype = (VM_PROT_READ | VM_PROT_WRITE);
} else {
ftype = (VM_PROT_READ);
}
if (map != kernel_map) {
/*
* Keep swapout from messing with us during this
* critical time.
*/
PROC_LOCK(p);
++p->p_lock;
PROC_UNLOCK(p);
/* Fault in the user page: */
error = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
PROC_LOCK(p);
--p->p_lock;
PROC_UNLOCK(p);
} else {
/*
* Don't have to worry about process locking or stacks in the
* kernel.
*/
error = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
}
if (error != KERN_SUCCESS) {
if (lower) {
sig = SIGSEGV;
if (error == KERN_PROTECTION_FAILURE)
ucode = SEGV_ACCERR;
else
ucode = SEGV_MAPERR;
call_trapsignal(td, sig, ucode, (void *)sbadaddr);
} else {
if (td->td_intr_nesting_level == 0 &&
pcb->pcb_onfault != 0) {
frame->tf_a[0] = error;
frame->tf_sepc = pcb->pcb_onfault;
return;
}
dump_regs(frame);
panic("vm_fault failed: %lx, va 0x%016lx",
frame->tf_sepc, sbadaddr);
}
}
if (lower)
userret(td, frame);
}
void
do_trap_supervisor(struct trapframe *frame)
{
uint64_t exception;
exception = (frame->tf_scause & EXCP_MASK);
if (frame->tf_scause & EXCP_INTR) {
/* Interrupt */
riscv_cpu_intr(frame);
return;
}
CTR3(KTR_TRAP, "do_trap_supervisor: curthread: %p, sepc: %lx, frame: %p",
curthread, frame->tf_sepc, frame);
switch(exception) {
case EXCP_LOAD_ACCESS_FAULT:
case EXCP_STORE_ACCESS_FAULT:
case EXCP_INSTR_ACCESS_FAULT:
data_abort(frame, 0);
break;
default:
dump_regs(frame);
panic("Unknown kernel exception %x badaddr %lx\n",
exception, frame->tf_sbadaddr);
}
}
void
do_trap_user(struct trapframe *frame)
{
uint64_t exception;
exception = (frame->tf_scause & EXCP_MASK);
if (frame->tf_scause & EXCP_INTR) {
/* Interrupt */
riscv_cpu_intr(frame);
return;
}
CTR3(KTR_TRAP, "do_trap_user: curthread: %p, sepc: %lx, frame: %p",
curthread, frame->tf_sepc, frame);
switch(exception) {
case EXCP_LOAD_ACCESS_FAULT:
case EXCP_STORE_ACCESS_FAULT:
case EXCP_INSTR_ACCESS_FAULT:
data_abort(frame, 1);
break;
case EXCP_UMODE_ENV_CALL:
frame->tf_sepc += 4; /* Next instruction */
svc_handler(frame);
break;
default:
dump_regs(frame);
panic("Unknown userland exception %x badaddr %lx\n",
exception, frame->tf_sbadaddr);
}
}

View File

@ -0,0 +1,134 @@
/*-
* Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu>
* Copyright (c) 1982, 1986, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/uio.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <machine/vmparam.h>
/*
* Implement uiomove(9) from physical memory using the direct map to
* avoid the creation and destruction of ephemeral mappings.
*/
int
uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
{
struct thread *td = curthread;
struct iovec *iov;
void *cp;
vm_offset_t page_offset, vaddr;
size_t cnt;
int error = 0;
int save = 0;
boolean_t mapped;
KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
("uiomove_fromphys: mode"));
KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
("uiomove_fromphys proc"));
save = td->td_pflags & TDP_DEADLKTREAT;
td->td_pflags |= TDP_DEADLKTREAT;
mapped = FALSE;
while (n > 0 && uio->uio_resid) {
iov = uio->uio_iov;
cnt = iov->iov_len;
if (cnt == 0) {
uio->uio_iov++;
uio->uio_iovcnt--;
continue;
}
if (cnt > n)
cnt = n;
page_offset = offset & PAGE_MASK;
cnt = min(cnt, PAGE_SIZE - page_offset);
if (uio->uio_segflg != UIO_NOCOPY) {
mapped = pmap_map_io_transient(
&ma[offset >> PAGE_SHIFT], &vaddr, 1, TRUE);
cp = (char *)vaddr + page_offset;
}
switch (uio->uio_segflg) {
case UIO_USERSPACE:
maybe_yield();
if (uio->uio_rw == UIO_READ)
error = copyout(cp, iov->iov_base, cnt);
else
error = copyin(iov->iov_base, cp, cnt);
if (error)
goto out;
break;
case UIO_SYSSPACE:
if (uio->uio_rw == UIO_READ)
bcopy(cp, iov->iov_base, cnt);
else
bcopy(iov->iov_base, cp, cnt);
break;
case UIO_NOCOPY:
break;
}
if (__predict_false(mapped)) {
pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT],
&vaddr, 1, TRUE);
mapped = FALSE;
}
iov->iov_base = (char *)iov->iov_base + cnt;
iov->iov_len -= cnt;
uio->uio_resid -= cnt;
uio->uio_offset += cnt;
offset += cnt;
n -= cnt;
}
out:
if (__predict_false(mapped)) {
panic("TODO 3");
pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT], &vaddr, 1,
TRUE);
}
if (save == 0)
td->td_pflags &= ~TDP_DEADLKTREAT;
return (error);
}

View File

@ -0,0 +1,55 @@
/*-
* Copyright (c) 2003 Alan L. Cox <alc@cs.rice.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <vm/vm_pageout.h>
#include <vm/uma.h>
#include <vm/uma_int.h>
#include <machine/md_var.h>
#include <machine/vmparam.h>
void *
uma_small_alloc(uma_zone_t zone, vm_size_t bytes, u_int8_t *flags, int wait)
{
panic("uma_small_alloc");
}
void
uma_small_free(void *mem, vm_size_t size, u_int8_t flags)
{
panic("uma_small_free");
}

View File

@ -0,0 +1,259 @@
/*-
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/limits.h>
#include <sys/proc.h>
#include <sys/sf_buf.h>
#include <sys/signal.h>
#include <sys/unistd.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
#include <vm/uma.h>
#include <vm/uma_int.h>
#include <machine/riscvreg.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
#include <machine/frame.h>
/*
* Finish a fork operation, with process p2 nearly set up.
* Copy and update the pcb, set up the stack so that the child
* ready to run and return to user mode.
*/
void
cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
{
struct pcb *pcb2;
struct trapframe *tf;
uint64_t val;
if ((flags & RFPROC) == 0)
return;
if (td1 == curthread) {
__asm __volatile("mv %0, tp" : "=&r"(val));
td1->td_pcb->pcb_tp = val;
}
pcb2 = (struct pcb *)(td2->td_kstack +
td2->td_kstack_pages * PAGE_SIZE) - 1;
td2->td_pcb = pcb2;
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
td2->td_pcb->pcb_l1addr =
vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l1);
tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1);
bcopy(td1->td_frame, tf, sizeof(*tf));
/* Clear syscall error flag */
tf->tf_t[0] = 0;
/* Arguments for child */
tf->tf_a[0] = 0;
tf->tf_a[1] = 0;
tf->tf_sstatus = SSTATUS_PIE;
td2->td_frame = tf;
/* Set the return value registers for fork() */
td2->td_pcb->pcb_t[0] = (uintptr_t)fork_return;
td2->td_pcb->pcb_t[1] = (uintptr_t)td2;
td2->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame;
/* Setup to release spin count in fork_exit(). */
td2->td_md.md_spinlock_count = 1;
td2->td_md.md_saved_sstatus_ie = 1;
}
void
cpu_reset(void)
{
printf("cpu_reset");
while(1)
__asm volatile("wfi" ::: "memory");
}
void
cpu_thread_swapin(struct thread *td)
{
}
void
cpu_thread_swapout(struct thread *td)
{
}
void
cpu_set_syscall_retval(struct thread *td, int error)
{
struct trapframe *frame;
frame = td->td_frame;
switch (error) {
case 0:
frame->tf_a[0] = td->td_retval[0];
frame->tf_a[1] = td->td_retval[1];
frame->tf_t[0] = 0; /* syscall succeeded */
break;
case ERESTART:
frame->tf_sepc -= 4; /* prev instruction */
break;
case EJUSTRETURN:
break;
default:
frame->tf_a[0] = error;
frame->tf_t[0] = 1; /* syscall error */
break;
}
}
/*
* Initialize machine state (pcb and trap frame) for a new thread about to
* upcall. Put enough state in the new thread's PCB to get it to go back
* userret(), where we can intercept it again to set the return (upcall)
* Address and stack, along with those from upcals that are from other sources
* such as those generated in thread_userret() itself.
*/
void
cpu_set_upcall(struct thread *td, struct thread *td0)
{
bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe));
bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb));
td->td_pcb->pcb_t[0] = (uintptr_t)fork_return;
td->td_pcb->pcb_t[1] = (uintptr_t)td;
td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
/* Setup to release spin count in fork_exit(). */
td->td_md.md_spinlock_count = 1;
td->td_md.md_saved_sstatus_ie = 1;
}
/*
* Set that machine state for performing an upcall that has to
* be done in thread_userret() so that those upcalls generated
* in thread_userret() itself can be done as well.
*/
void
cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
stack_t *stack)
{
struct trapframe *tf = td->td_frame;
tf->tf_sp = STACKALIGN((uintptr_t)stack->ss_sp + stack->ss_size);
tf->tf_sepc = (register_t)entry;
tf->tf_a[0] = (register_t)arg;
}
int
cpu_set_user_tls(struct thread *td, void *tls_base)
{
struct pcb *pcb;
if ((uintptr_t)tls_base >= VM_MAXUSER_ADDRESS)
return (EINVAL);
pcb = td->td_pcb;
pcb->pcb_tp = (register_t)tls_base;
return (0);
}
void
cpu_thread_exit(struct thread *td)
{
}
void
cpu_thread_alloc(struct thread *td)
{
td->td_pcb = (struct pcb *)(td->td_kstack +
td->td_kstack_pages * PAGE_SIZE) - 1;
td->td_frame = (struct trapframe *)STACKALIGN(
td->td_pcb - 1);
}
void
cpu_thread_free(struct thread *td)
{
}
void
cpu_thread_clean(struct thread *td)
{
}
/*
* Intercept the return address from a freshly forked process that has NOT
* been scheduled yet.
*
* This is needed to make kernel threads stay in kernel mode.
*/
void
cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg)
{
td->td_pcb->pcb_t[0] = (uintptr_t)func;
td->td_pcb->pcb_t[1] = (uintptr_t)arg;
td->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
td->td_pcb->pcb_sp = (uintptr_t)td->td_frame;
}
void
cpu_exit(struct thread *td)
{
}
void
swi_vm(void *v)
{
/* Nothing to do here - busdma bounce buffers are not implemented. */
}

View File

@ -776,7 +776,7 @@
#endif
#endif
#if defined(__mips) || defined(__powerpc64__)
#if defined(__mips) || defined(__powerpc64__) || defined(__riscv__)
#define __NO_TLS 1
#endif

View File

@ -72,6 +72,7 @@ struct kerneldumpheader {
#define KERNELDUMP_I386_VERSION 2
#define KERNELDUMP_MIPS_VERSION 1
#define KERNELDUMP_POWERPC_VERSION 1
#define KERNELDUMP_RISCV_VERSION 1
#define KERNELDUMP_SPARC64_VERSION 1
#define KERNELDUMP_TEXT_VERSION 1
uint64_t dumplength; /* excl headers */