Index: stable/12/sys/conf/ldscript.riscv
===================================================================
--- stable/12/sys/conf/ldscript.riscv (revision 349484)
+++ stable/12/sys/conf/ldscript.riscv (revision 349485)
@@ -1,139 +1,143 @@
/* $FreeBSD$ */
OUTPUT_ARCH(riscv)
ENTRY(_start)
SEARCH_DIR(/usr/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = kernbase;
.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*)
}
.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) }
+ .sdata :
+ {
+ __global_pointer$ = . + 0x800;
+ *(.sdata)
+ }
_edata = .;
PROVIDE (edata = .);
/* Ensure __bss_start is associated with the next section in case orphan
sections are placed directly after .sdata, as has been seen to happen with
LLD. */
. = .;
__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 . */
}
Index: stable/12/sys/riscv/include/asm.h
===================================================================
--- stable/12/sys/riscv/include/asm.h (revision 349484)
+++ stable/12/sys/riscv/include/asm.h (revision 349485)
@@ -1,74 +1,74 @@
/*-
* Copyright (c) 2015-2018 Ruslan Bukin
* 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$
*/
#ifndef _MACHINE_ASM_H_
#define _MACHINE_ASM_H_
#undef __FBSDID
#if !defined(lint) && !defined(STRIP_FBSDID)
#define __FBSDID(s) .ident s
#else
#define __FBSDID(s) /* nothing */
#endif /* not lint and not STRIP_FBSDID */
#define _C_LABEL(x) x
#define ENTRY(sym) \
.text; .globl sym; .type sym,@function; .align 4; sym:
#define END(sym) .size sym, . - sym
#define EENTRY(sym) \
.globl sym; sym:
#define EEND(sym)
#define WEAK_REFERENCE(sym, alias) \
.weak alias; \
.set alias,sym
#define SET_FAULT_HANDLER(handler, tmp) \
- ld tmp, PC_CURTHREAD(gp); \
+ ld tmp, PC_CURTHREAD(tp); \
ld tmp, TD_PCB(tmp); /* Load the pcb */ \
sd handler, PCB_ONFAULT(tmp) /* Set the handler */
#define ENTER_USER_ACCESS(tmp) \
li tmp, SSTATUS_SUM; \
csrs sstatus, tmp
#define EXIT_USER_ACCESS(tmp) \
li tmp, SSTATUS_SUM; \
csrc sstatus, tmp
#endif /* _MACHINE_ASM_H_ */
Index: stable/12/sys/riscv/include/pcpu.h
===================================================================
--- stable/12/sys/riscv/include/pcpu.h (revision 349484)
+++ stable/12/sys/riscv/include/pcpu.h (revision 349485)
@@ -1,88 +1,88 @@
/*-
* Copyright (c) 1999 Luoqi Chen
* Copyright (c) 2015-2016 Ruslan Bukin
* 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.
*
* from: FreeBSD: src/sys/i386/include/globaldata.h,v 1.27 2001/04/27
* $FreeBSD$
*/
#ifndef _MACHINE_PCPU_H_
#define _MACHINE_PCPU_H_
#include
#include
#define ALT_STACK_SIZE 128
#define PCPU_MD_FIELDS \
struct pmap *pc_curpmap; /* Currently active pmap */ \
uint32_t pc_pending_ipis; /* IPIs pending to this CPU */ \
uint32_t pc_hart; /* Hart ID */ \
char __pad[57]
#ifdef _KERNEL
struct pcb;
struct pcpu;
static inline struct pcpu *
get_pcpu(void)
{
struct pcpu *pcpu;
- __asm __volatile("mv %0, gp" : "=&r"(pcpu));
+ __asm __volatile("mv %0, tp" : "=&r"(pcpu));
return (pcpu);
}
static inline struct thread *
get_curthread(void)
{
struct thread *td;
- __asm __volatile("ld %0, 0(gp)" : "=&r"(td));
+ __asm __volatile("ld %0, 0(tp)" : "=&r"(td));
return (td);
}
#define curthread get_curthread()
#define PCPU_GET(member) (get_pcpu()->pc_ ## member)
#define PCPU_ADD(member, value) (get_pcpu()->pc_ ## member += (value))
#define PCPU_INC(member) PCPU_ADD(member, 1)
#define PCPU_PTR(member) (&get_pcpu()->pc_ ## member)
#define PCPU_SET(member,value) (get_pcpu()->pc_ ## member = (value))
#endif /* _KERNEL */
#endif /* !_MACHINE_PCPU_H_ */
Index: stable/12/sys/riscv/riscv/exception.S
===================================================================
--- stable/12/sys/riscv/riscv/exception.S (revision 349484)
+++ stable/12/sys/riscv/riscv/exception.S (revision 349485)
@@ -1,237 +1,236 @@
/*-
* Copyright (c) 2015-2018 Ruslan Bukin
* 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
__FBSDID("$FreeBSD$");
#include "assym.inc"
#include
#include
.macro save_registers el
addi sp, sp, -(TF_SIZE)
sd ra, (TF_RA)(sp)
- sd tp, (TF_TP)(sp)
-.if \el == 0 /* We came from userspace. Load our pcpu */
+.if \el == 0 /* We came from userspace. */
sd gp, (TF_GP)(sp)
- ld gp, (TF_SIZE)(sp)
+.option push
+.option norelax
+ /* Load the kernel's global pointer */
+ la gp, __global_pointer$
+.option pop
+
+ /* Load our pcpu */
+ sd tp, (TF_TP)(sp)
+ ld tp, (TF_SIZE)(sp)
.endif
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 */
li t1, TF_SIZE
add t0, sp, t1
sd t0, (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, stval
sd t0, (TF_STVAL)(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 */
li t1, SSTATUS_SPIE
or t0, t0, t1
.else
/*
* Disable interrupts for supervisor mode exceptions.
* For user mode exceptions we have already done this
* in do_ast.
*/
li t1, ~SSTATUS_SIE
and t0, t0, t1
.endif
csrw sstatus, t0
ld t0, (TF_SEPC)(sp)
csrw sepc, t0
.if \el == 0
/* We go to userspace. Load user sp */
ld t0, (TF_SP)(sp)
csrw sscratch, t0
- /* And store our pcpu */
- sd gp, (TF_SIZE)(sp)
+ /* Store our pcpu */
+ sd tp, (TF_SIZE)(sp)
+ ld tp, (TF_TP)(sp)
+
+ /* And restore the user's global pointer */
ld gp, (TF_GP)(sp)
.endif
ld ra, (TF_RA)(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, (TF_SIZE)
.endm
.macro do_ast
/* Disable interrupts */
csrr a4, sstatus
1:
csrci sstatus, (SSTATUS_SIE)
- ld a1, PC_CURTHREAD(gp)
+ ld a1, PC_CURTHREAD(tp)
lw a2, TD_FLAGS(a1)
li a3, (TDF_ASTPENDING|TDF_NEEDRESCHED)
and a2, a2, a3
beqz a2, 2f
/* Restore interrupts */
andi a4, a4, (SSTATUS_SIE)
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)
csrrw sp, sscratch, sp
beqz sp, 1f
/* User mode detected */
csrrw sp, sscratch, sp
j cpu_exception_handler_user
1:
/* Supervisor mode detected */
csrrw sp, sscratch, sp
j cpu_exception_handler_supervisor
END(cpu_exception_handler)
ENTRY(cpu_exception_handler_supervisor)
save_registers 1
mv a0, sp
call _C_LABEL(do_trap_supervisor)
load_registers 1
sret
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
sret
END(cpu_exception_handler_user)
Index: stable/12/sys/riscv/riscv/locore.S
===================================================================
--- stable/12/sys/riscv/riscv/locore.S (revision 349484)
+++ stable/12/sys/riscv/riscv/locore.S (revision 349485)
@@ -1,329 +1,335 @@
/*-
* Copyright (c) 2015-2018 Ruslan Bukin
* 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.inc"
#include
#include
#include
#include
#include
#include
.globl kernbase
.set kernbase, KERNBASE
/* Trap entries */
.text
/* Reset vector */
.text
.globl _start
_start:
/* Get the physical address kernel loaded to */
la t0, virt_map
ld t1, 0(t0)
sub t1, t1, t0
li t2, KERNBASE
sub s9, t2, t1 /* s9 = physmem base */
/*
* a0 = hart id
* a1 = dtbp
*/
/* Pick a hart to run the boot process. */
la t0, hart_lottery
li t1, 1
amoadd.w t0, t1, 0(t0)
bnez t0, mpentry
/*
* Page tables
*/
/* Add L1 entry for kernel */
la s1, pagetable_l1
la s2, pagetable_l2 /* Link to next level PN */
srli s2, s2, PAGE_SHIFT
li a5, KERNBASE
srli a5, a5, L1_SHIFT /* >> L1_SHIFT */
andi a5, a5, 0x1ff /* & 0x1ff */
li t4, PTE_V
slli t5, s2, PTE_PPN0_S /* (s2 << PTE_PPN0_S) */
or t6, t4, t5
/* Store L1 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
srli t4, s9, 21 /* Div physmem base by 2 MiB */
li t2, 512 /* Build 512 entries */
add t3, t4, t2
li t5, 0
2:
li t0, (PTE_KERN | PTE_X)
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
/* Create an L1 page for early devmap */
la s1, pagetable_l1
la s2, pagetable_l2_devmap /* Link to next level PN */
srli s2, s2, PAGE_SHIFT
li a5, (VM_MAX_KERNEL_ADDRESS - L2_SIZE)
srli a5, a5, L1_SHIFT /* >> L1_SHIFT */
andi a5, a5, 0x1ff /* & 0x1ff */
li t4, PTE_V
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)
/* Create an L2 page superpage for DTB */
la s1, pagetable_l2_devmap
mv s2, a1
srli s2, s2, PAGE_SHIFT
li t0, (PTE_KERN)
slli t2, s2, PTE_PPN0_S /* << PTE_PPN0_S */
or t0, t0, t2
/* Store PTE entry to position */
li a6, PTE_SIZE
li a5, 510
mulw a5, a5, a6
add t1, s1, a5
sd t0, (t1)
/* Page tables END */
/* Setup supervisor trap vector */
la t0, va
sub t0, t0, s9
li t1, KERNBASE
add t0, t0, t1
csrw stvec, t0
/* Set page tables base register */
la s2, pagetable_l1
srli s2, s2, PAGE_SHIFT
li t0, SATP_MODE_SV39
or s2, s2, t0
sfence.vma
csrw satp, s2
.align 2
va:
/* Setup supervisor trap vector */
la t0, cpu_exception_handler
csrw stvec, t0
/* Ensure sscratch is zero */
li t0, 0
csrw sscratch, t0
+ /* Set the global pointer */
+.option push
+.option norelax
+ la gp, __global_pointer$
+.option pop
+
/* Initialize stack pointer */
la s3, initstack_end
mv sp, s3
addi sp, sp, -PCB_SIZE
- /* Clear BSS */
+ /* Clear BSS */
la s0, _C_LABEL(__bss_start)
la s1, _C_LABEL(_end)
1:
sd zero, 0(s0)
addi s0, s0, 8
bltu s0, s1, 1b
#ifdef SMP
/* Store boot hart id. */
la t0, boot_hart
sw a0, 0(t0)
#endif
/* Fill riscv_bootparams */
addi sp, sp, -40
la t0, pagetable_l1
sd t0, 0(sp) /* kern_l1pt */
sd s9, 8(sp) /* kern_phys */
la t0, initstack_end
sd t0, 16(sp) /* kern_stack */
li t0, (VM_MAX_KERNEL_ADDRESS - 2 * L2_SIZE)
sd t0, 24(sp) /* dtbp_virt */
sd a1, 32(sp) /* dtbp_phys */
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:
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
pagetable_l1:
.space PAGE_SIZE
pagetable_l2:
.space PAGE_SIZE
pagetable_l2_devmap:
.space PAGE_SIZE
.align 3
virt_map:
.quad virt_map
hart_lottery:
.space 4
- /* Not in use, but required for linking. */
- .align 3
- .globl __global_pointer$
-__global_pointer$:
- .space 8
-
.globl init_pt_va
init_pt_va:
.quad pagetable_l2 /* XXX: Keep page tables VA */
#ifndef SMP
ENTRY(mpentry)
1:
wfi
j 1b
END(mpentry)
#else
/*
* mpentry(unsigned long)
*
* Called by a core when it is being brought online.
*/
ENTRY(mpentry)
/*
* Calculate the offset to __riscv_boot_ap
* for the current core, cpuid is in a0.
*/
li t1, 4
mulw t1, t1, a0
/* Get the pointer */
la t0, __riscv_boot_ap
add t0, t0, t1
1:
/* Wait the kernel to be ready */
lw t1, 0(t0)
beqz t1, 1b
/* Setup stack pointer */
la t0, secondary_stacks
li t1, (PAGE_SIZE * KSTACK_PAGES)
mulw t2, t1, a0
add t0, t0, t2
add t0, t0, t1
sub t0, t0, s9
li t1, KERNBASE
add sp, t0, t1
/* Setup supervisor trap vector */
la t0, mpva
sub t0, t0, s9
li t1, KERNBASE
add t0, t0, t1
csrw stvec, t0
/* Set page tables base register */
la s2, pagetable_l1
srli s2, s2, PAGE_SHIFT
li t0, SATP_MODE_SV39
or s2, s2, t0
sfence.vma
csrw satp, s2
.align 2
mpva:
/* Setup supervisor trap vector */
la t0, cpu_exception_handler
csrw stvec, t0
/* Ensure sscratch is zero */
li t0, 0
csrw sscratch, t0
+
+ /* Set the global pointer */
+.option push
+.option norelax
+ la gp, __global_pointer$
+.option pop
call init_secondary
END(mpentry)
#endif
Index: stable/12/sys/riscv/riscv/machdep.c
===================================================================
--- stable/12/sys/riscv/riscv/machdep.c (revision 349484)
+++ stable/12/sys/riscv/riscv/machdep.c (revision 349485)
@@ -1,901 +1,901 @@
/*-
* Copyright (c) 2014 Andrew Turner
* Copyright (c) 2015-2017 Ruslan Bukin
* 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
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef FPE
#include
#endif
#ifdef FDT
#include
#include
#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 DTB_SIZE_MAX (1024 * 1024)
#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 */
uint32_t boot_hart; /* The hart we booted on. */
cpuset_t all_harts;
extern int *end;
extern int *initstack_end;
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);
}
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_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)
{
#ifdef FPE
struct pcb *pcb;
pcb = td->td_pcb;
if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
/*
* If we have just been running FPE instructions we will
* need to save the state to memcpy it below.
*/
if (td == curthread)
fpe_state_save(td);
memcpy(regs->fp_x, pcb->pcb_x, sizeof(regs->fp_x));
regs->fp_fcsr = pcb->pcb_fcsr;
} else
#endif
memset(regs, 0, sizeof(*regs));
return (0);
}
int
set_fpregs(struct thread *td, struct fpreg *regs)
{
#ifdef FPE
struct trapframe *frame;
struct pcb *pcb;
frame = td->td_frame;
pcb = td->td_pcb;
memcpy(pcb->pcb_x, regs->fp_x, sizeof(regs->fp_x));
pcb->pcb_fcsr = regs->fp_fcsr;
pcb->pcb_fpflags |= PCB_FP_STARTED;
frame->tf_sstatus &= ~SSTATUS_FS_MASK;
frame->tf_sstatus |= SSTATUS_FS_CLEAN;
#endif
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;
struct pcb *pcb;
tf = td->td_frame;
pcb = td->td_pcb;
memset(tf, 0, sizeof(struct trapframe));
tf->tf_a[0] = stack;
tf->tf_sp = STACKALIGN(stack);
tf->tf_ra = imgp->entry_addr;
tf->tf_sepc = imgp->entry_addr;
pcb->pcb_fpflags &= ~PCB_FP_STARTED;
}
/* 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);
/* Support for FDT configurations only. */
CTASSERT(FDT);
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_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)
{
#ifdef FPE
struct pcb *curpcb;
critical_enter();
curpcb = curthread->td_pcb;
KASSERT(td->td_pcb == curpcb, ("Invalid fpe pcb"));
if ((curpcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
/*
* If we have just been running FPE instructions we will
* need to save the state to memcpy it below.
*/
fpe_state_save(td);
KASSERT((curpcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
("Non-userspace FPE flags set in get_fpcontext"));
memcpy(mcp->mc_fpregs.fp_x, curpcb->pcb_x,
sizeof(mcp->mc_fpregs));
mcp->mc_fpregs.fp_fcsr = curpcb->pcb_fcsr;
mcp->mc_fpregs.fp_flags = curpcb->pcb_fpflags;
mcp->mc_flags |= _MC_FP_VALID;
}
critical_exit();
#endif
}
static void
set_fpcontext(struct thread *td, mcontext_t *mcp)
{
#ifdef FPE
struct pcb *curpcb;
critical_enter();
if ((mcp->mc_flags & _MC_FP_VALID) != 0) {
curpcb = curthread->td_pcb;
/* FPE usage is enabled, override registers. */
memcpy(curpcb->pcb_x, mcp->mc_fpregs.fp_x,
sizeof(mcp->mc_fpregs));
curpcb->pcb_fcsr = mcp->mc_fpregs.fp_fcsr;
curpcb->pcb_fpflags = mcp->mc_fpregs.fp_flags & PCB_FP_USERMASK;
}
critical_exit();
#endif
}
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)
{
intr_disable();
for (;;)
__asm __volatile("wfi");
}
/*
* 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;
register_t reg;
td = curthread;
if (td->td_md.md_spinlock_count == 0) {
reg = intr_disable();
td->td_md.md_spinlock_count = 1;
td->td_md.md_saved_sstatus_ie = reg;
} 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.
* Supervisor interrupts in user mode are always enabled.
*/
sstatus = uc.uc_mcontext.mc_gpregs.gp_sstatus;
if ((sstatus & SSTATUS_SPP) != 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 sig;
td = curthread;
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
sig = ksi->ksi_signo;
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 */
bzero(&frame, sizeof(frame));
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_sepc,
tf->tf_sp);
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
static void
init_proc0(vm_offset_t kstack)
{
struct pcpu *pcpup;
pcpup = &__pcpu[0];
proc_linkup0(&proc0, &thread0);
thread0.td_kstack = kstack;
thread0.td_pcb = (struct pcb *)(thread0.td_kstack) - 1;
thread0.td_pcb->pcb_fpflags = 0;
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)
{
#if defined(FDT_DTB_STATIC)
dtbp = (vm_offset_t)&fdt_static_dtb;
#endif
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 */
dcache_line_size = 0;
icache_line_size = 0;
idcache_line_size = 0;
}
/*
* 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)
{
static uint32_t fake_preload[35];
#ifdef DDB
vm_offset_t zstart = 0, zend = 0;
#endif
vm_offset_t lastaddr;
int i;
i = 0;
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);
*(vm_offset_t *)&fake_preload[i++] =
(vm_offset_t)(KERNBASE + KERNENTRY);
i += 1;
fake_preload[i++] = MODINFO_SIZE;
fake_preload[i++] = sizeof(vm_offset_t);
fake_preload[i++] = (vm_offset_t)&end -
(vm_offset_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)
{
struct mem_region mem_regions[FDT_MEM_REGIONS];
struct pcpu *pcpup;
vm_offset_t rstart, rend;
vm_offset_t s, e;
int mem_regions_sz;
vm_offset_t lastaddr;
vm_size_t kernlen;
caddr_t kmdp;
int i;
/* Set the pcpu data, this is needed by pmap_bootstrap */
pcpup = &__pcpu[0];
pcpu_init(pcpup, 0, sizeof(struct pcpu));
pcpup->pc_hart = boot_hart;
/* Set the pcpu pointer */
- __asm __volatile("mv gp, %0" :: "r"(pcpup));
+ __asm __volatile("mv tp, %0" :: "r"(pcpup));
PCPU_SET(curthread, &thread0);
/* 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 = RB_VERBOSE | RB_SINGLE;
boothowto = RB_VERBOSE;
kern_envp = NULL;
#ifdef FDT
try_load_dtb(kmdp, rvbp->dtbp_virt);
#endif
/* Load the physical memory ranges */
physmap_idx = 0;
#ifdef FDT
/* Grab physical memory regions information from device tree. */
if (fdt_get_mem_regions(mem_regions, &mem_regions_sz, NULL) != 0)
panic("Cannot get physical memory regions");
s = rvbp->dtbp_phys;
e = s + DTB_SIZE_MAX;
for (i = 0; i < mem_regions_sz; i++) {
rstart = mem_regions[i].mr_start;
rend = (mem_regions[i].mr_start + mem_regions[i].mr_size);
if ((rstart < s) && (rend > e)) {
/* Exclude DTB region. */
add_physmap_entry(rstart, (s - rstart), physmap, &physmap_idx);
add_physmap_entry(e, (rend - e), physmap, &physmap_idx);
} else {
add_physmap_entry(mem_regions[i].mr_start,
mem_regions[i].mr_size, physmap, &physmap_idx);
}
}
#endif
/* 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, mem_regions[0].mr_start, kernlen);
cninit();
init_proc0(rvbp->kern_stack);
msgbufinit(msgbufp, msgbufsize);
mutex_init();
init_param2(physmem);
kdb_init();
early_boot = 0;
}
#undef bzero
void
bzero(void *buf, size_t len)
{
uint8_t *p;
p = buf;
while(len-- > 0)
*p++ = 0;
}
Index: stable/12/sys/riscv/riscv/mp_machdep.c
===================================================================
--- stable/12/sys/riscv/riscv/mp_machdep.c (revision 349484)
+++ stable/12/sys/riscv/riscv/mp_machdep.c (revision 349485)
@@ -1,496 +1,496 @@
/*-
* Copyright (c) 2015 The FreeBSD Foundation
* Copyright (c) 2016 Ruslan Bukin
* All rights reserved.
*
* Portions of this software were developed by Andrew Turner under
* sponsorship from the FreeBSD Foundation.
*
* 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_kstack_pages.h"
#include "opt_platform.h"
#include
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef FDT
#include
#include
#endif
boolean_t ofw_cpu_reg(phandle_t node, u_int, cell_t *);
extern struct pcpu __pcpu[];
uint32_t __riscv_boot_ap[MAXCPU];
static enum {
CPUS_UNKNOWN,
#ifdef FDT
CPUS_FDT,
#endif
} cpu_enum_method;
static device_identify_t riscv64_cpu_identify;
static device_probe_t riscv64_cpu_probe;
static device_attach_t riscv64_cpu_attach;
static int ipi_handler(void *);
struct mtx ap_boot_mtx;
struct pcb stoppcbs[MAXCPU];
extern uint32_t boot_hart;
extern cpuset_t all_harts;
#ifdef INVARIANTS
static uint32_t cpu_reg[MAXCPU][2];
#endif
static device_t cpu_list[MAXCPU];
void mpentry(unsigned long cpuid);
void init_secondary(uint64_t);
uint8_t secondary_stacks[MAXCPU][PAGE_SIZE * KSTACK_PAGES] __aligned(16);
/* Set to 1 once we're ready to let the APs out of the pen. */
volatile int aps_ready = 0;
/* Temporary variables for init_secondary() */
void *dpcpu[MAXCPU - 1];
static device_method_t riscv64_cpu_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, riscv64_cpu_identify),
DEVMETHOD(device_probe, riscv64_cpu_probe),
DEVMETHOD(device_attach, riscv64_cpu_attach),
DEVMETHOD_END
};
static devclass_t riscv64_cpu_devclass;
static driver_t riscv64_cpu_driver = {
"riscv64_cpu",
riscv64_cpu_methods,
0
};
DRIVER_MODULE(riscv64_cpu, cpu, riscv64_cpu_driver, riscv64_cpu_devclass, 0, 0);
static void
riscv64_cpu_identify(driver_t *driver, device_t parent)
{
if (device_find_child(parent, "riscv64_cpu", -1) != NULL)
return;
if (BUS_ADD_CHILD(parent, 0, "riscv64_cpu", -1) == NULL)
device_printf(parent, "add child failed\n");
}
static int
riscv64_cpu_probe(device_t dev)
{
u_int cpuid;
cpuid = device_get_unit(dev);
if (cpuid >= MAXCPU || cpuid > mp_maxid)
return (EINVAL);
device_quiet(dev);
return (0);
}
static int
riscv64_cpu_attach(device_t dev)
{
const uint32_t *reg;
size_t reg_size;
u_int cpuid;
int i;
cpuid = device_get_unit(dev);
if (cpuid >= MAXCPU || cpuid > mp_maxid)
return (EINVAL);
KASSERT(cpu_list[cpuid] == NULL, ("Already have cpu %u", cpuid));
reg = cpu_get_cpuid(dev, ®_size);
if (reg == NULL)
return (EINVAL);
if (bootverbose) {
device_printf(dev, "register <");
for (i = 0; i < reg_size; i++)
printf("%s%x", (i == 0) ? "" : " ", reg[i]);
printf(">\n");
}
/* Set the device to start it later */
cpu_list[cpuid] = dev;
return (0);
}
static void
release_aps(void *dummy __unused)
{
cpuset_t mask;
int cpu, i;
if (mp_ncpus == 1)
return;
/* Setup the IPI handler */
riscv_setup_ipihandler(ipi_handler);
atomic_store_rel_int(&aps_ready, 1);
/* Wake up the other CPUs */
mask = all_harts;
CPU_CLR(boot_hart, &mask);
printf("Release APs\n");
sbi_send_ipi(mask.__bits);
for (i = 0; i < 2000; i++) {
if (smp_started) {
for (cpu = 0; cpu <= mp_maxid; cpu++) {
if (CPU_ABSENT(cpu))
continue;
}
return;
}
DELAY(1000);
}
printf("APs not started\n");
}
SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL);
void
init_secondary(uint64_t hart)
{
struct pcpu *pcpup;
u_int cpuid;
/* Renumber this cpu */
cpuid = hart;
if (cpuid < boot_hart)
cpuid += mp_maxid + 1;
cpuid -= boot_hart;
/* Setup the pcpu pointer */
pcpup = &__pcpu[cpuid];
- __asm __volatile("mv gp, %0" :: "r"(pcpup));
+ __asm __volatile("mv tp, %0" :: "r"(pcpup));
/* Workaround: make sure wfi doesn't halt the hart */
csr_set(sie, SIE_SSIE);
csr_set(sip, SIE_SSIE);
/* Spin until the BSP releases the APs */
while (!aps_ready)
__asm __volatile("wfi");
/* Initialize curthread */
KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
pcpup->pc_curthread = pcpup->pc_idlethread;
pcpup->pc_curpcb = pcpup->pc_idlethread->td_pcb;
/*
* Identify current CPU. This is necessary to setup
* affinity registers and to provide support for
* runtime chip identification.
*/
identify_cpu();
/* Enable software interrupts */
riscv_unmask_ipi();
/* Start per-CPU event timers. */
cpu_initclocks_ap();
/* Enable external (PLIC) interrupts */
csr_set(sie, SIE_SEIE);
/* Activate process 0's pmap. */
pmap_activate_boot(vmspace_pmap(proc0.p_vmspace));
mtx_lock_spin(&ap_boot_mtx);
atomic_add_rel_32(&smp_cpus, 1);
if (smp_cpus == mp_ncpus) {
/* enable IPI's, tlb shootdown, freezes etc */
atomic_store_rel_int(&smp_started, 1);
}
mtx_unlock_spin(&ap_boot_mtx);
/* Enter the scheduler */
sched_throw(NULL);
panic("scheduler returned us to init_secondary");
/* NOTREACHED */
}
static int
ipi_handler(void *arg)
{
u_int ipi_bitmap;
u_int cpu, ipi;
int bit;
sbi_clear_ipi();
cpu = PCPU_GET(cpuid);
mb();
ipi_bitmap = atomic_readandclear_int(PCPU_PTR(pending_ipis));
if (ipi_bitmap == 0)
return (FILTER_HANDLED);
while ((bit = ffs(ipi_bitmap))) {
bit = (bit - 1);
ipi = (1 << bit);
ipi_bitmap &= ~ipi;
mb();
switch (ipi) {
case IPI_AST:
CTR0(KTR_SMP, "IPI_AST");
break;
case IPI_PREEMPT:
CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
sched_preempt(curthread);
break;
case IPI_RENDEZVOUS:
CTR0(KTR_SMP, "IPI_RENDEZVOUS");
smp_rendezvous_action();
break;
case IPI_STOP:
case IPI_STOP_HARD:
CTR0(KTR_SMP, (ipi == IPI_STOP) ? "IPI_STOP" : "IPI_STOP_HARD");
savectx(&stoppcbs[cpu]);
/* Indicate we are stopped */
CPU_SET_ATOMIC(cpu, &stopped_cpus);
/* Wait for restart */
while (!CPU_ISSET(cpu, &started_cpus))
cpu_spinwait();
CPU_CLR_ATOMIC(cpu, &started_cpus);
CPU_CLR_ATOMIC(cpu, &stopped_cpus);
CTR0(KTR_SMP, "IPI_STOP (restart)");
/*
* The kernel debugger might have set a breakpoint,
* so flush the instruction cache.
*/
fence_i();
break;
case IPI_HARDCLOCK:
CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
hardclockintr();
break;
default:
panic("Unknown IPI %#0x on cpu %d", ipi, curcpu);
}
}
return (FILTER_HANDLED);
}
struct cpu_group *
cpu_topo(void)
{
return (smp_topo_none());
}
/* Determine if we running MP machine */
int
cpu_mp_probe(void)
{
return (mp_ncpus > 1);
}
#ifdef FDT
static boolean_t
cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
{
struct pcpu *pcpup;
uint64_t hart;
u_int cpuid;
/* Check if this hart supports MMU. */
if (OF_getproplen(node, "mmu-type") < 0)
return (0);
KASSERT(id < MAXCPU, ("Too many CPUs"));
KASSERT(addr_size == 1 || addr_size == 2, ("Invalid register size"));
#ifdef INVARIANTS
cpu_reg[id][0] = reg[0];
if (addr_size == 2)
cpu_reg[id][1] = reg[1];
#endif
hart = reg[0];
if (addr_size == 2) {
hart <<= 32;
hart |= reg[1];
}
KASSERT(hart < MAXCPU, ("Too many harts."));
/* We are already running on this cpu */
if (hart == boot_hart)
return (1);
/*
* Rotate the CPU IDs to put the boot CPU as CPU 0.
* We keep the other CPUs ordered.
*/
cpuid = hart;
if (cpuid < boot_hart)
cpuid += mp_maxid + 1;
cpuid -= boot_hart;
/* Check if we are able to start this cpu */
if (cpuid > mp_maxid)
return (0);
pcpup = &__pcpu[cpuid];
pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
pcpup->pc_hart = hart;
dpcpu[cpuid - 1] = (void *)kmem_malloc(DPCPU_SIZE, M_WAITOK | M_ZERO);
dpcpu_init(dpcpu[cpuid - 1], cpuid);
printf("Starting CPU %u (hart %lx)\n", cpuid, hart);
__riscv_boot_ap[hart] = 1;
CPU_SET(cpuid, &all_cpus);
CPU_SET(hart, &all_harts);
return (1);
}
#endif
/* Initialize and fire up non-boot processors */
void
cpu_mp_start(void)
{
mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
CPU_SET(0, &all_cpus);
CPU_SET(boot_hart, &all_harts);
switch(cpu_enum_method) {
#ifdef FDT
case CPUS_FDT:
ofw_cpu_early_foreach(cpu_init_fdt, true);
break;
#endif
case CPUS_UNKNOWN:
break;
}
}
/* Introduce rest of cores to the world */
void
cpu_mp_announce(void)
{
}
static boolean_t
cpu_check_mmu(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
{
/* Check if this hart supports MMU. */
if (OF_getproplen(node, "mmu-type") < 0)
return (0);
return (1);
}
void
cpu_mp_setmaxid(void)
{
#ifdef FDT
int cores;
cores = ofw_cpu_early_foreach(cpu_check_mmu, true);
if (cores > 0) {
cores = MIN(cores, MAXCPU);
if (bootverbose)
printf("Found %d CPUs in the device tree\n", cores);
mp_ncpus = cores;
mp_maxid = cores - 1;
cpu_enum_method = CPUS_FDT;
return;
}
#endif
if (bootverbose)
printf("No CPU data, limiting to 1 core\n");
mp_ncpus = 1;
mp_maxid = 0;
}
Index: stable/12/sys/riscv/riscv/swtch.S
===================================================================
--- stable/12/sys/riscv/riscv/swtch.S (revision 349484)
+++ stable/12/sys/riscv/riscv/swtch.S (revision 349485)
@@ -1,476 +1,475 @@
/*-
* Copyright (c) 2015-2017 Ruslan Bukin
* 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.inc"
#include "opt_sched.h"
#include
#include
#include
#include
__FBSDID("$FreeBSD$");
#ifdef FPE
.macro __fpe_state_save p
/*
* Enable FPE usage in supervisor mode,
* so we can access registers.
*/
li t0, SSTATUS_FS_INITIAL
csrs sstatus, t0
/* Store registers */
frcsr t0
sd t0, (PCB_FCSR)(\p)
fsd f0, (PCB_X + 0 * 16)(\p)
fsd f1, (PCB_X + 1 * 16)(\p)
fsd f2, (PCB_X + 2 * 16)(\p)
fsd f3, (PCB_X + 3 * 16)(\p)
fsd f4, (PCB_X + 4 * 16)(\p)
fsd f5, (PCB_X + 5 * 16)(\p)
fsd f6, (PCB_X + 6 * 16)(\p)
fsd f7, (PCB_X + 7 * 16)(\p)
fsd f8, (PCB_X + 8 * 16)(\p)
fsd f9, (PCB_X + 9 * 16)(\p)
fsd f10, (PCB_X + 10 * 16)(\p)
fsd f11, (PCB_X + 11 * 16)(\p)
fsd f12, (PCB_X + 12 * 16)(\p)
fsd f13, (PCB_X + 13 * 16)(\p)
fsd f14, (PCB_X + 14 * 16)(\p)
fsd f15, (PCB_X + 15 * 16)(\p)
fsd f16, (PCB_X + 16 * 16)(\p)
fsd f17, (PCB_X + 17 * 16)(\p)
fsd f18, (PCB_X + 18 * 16)(\p)
fsd f19, (PCB_X + 19 * 16)(\p)
fsd f20, (PCB_X + 20 * 16)(\p)
fsd f21, (PCB_X + 21 * 16)(\p)
fsd f22, (PCB_X + 22 * 16)(\p)
fsd f23, (PCB_X + 23 * 16)(\p)
fsd f24, (PCB_X + 24 * 16)(\p)
fsd f25, (PCB_X + 25 * 16)(\p)
fsd f26, (PCB_X + 26 * 16)(\p)
fsd f27, (PCB_X + 27 * 16)(\p)
fsd f28, (PCB_X + 28 * 16)(\p)
fsd f29, (PCB_X + 29 * 16)(\p)
fsd f30, (PCB_X + 30 * 16)(\p)
fsd f31, (PCB_X + 31 * 16)(\p)
/* Disable FPE usage in supervisor mode. */
li t0, SSTATUS_FS_MASK
csrc sstatus, t0
.endm
.macro __fpe_state_load p
/*
* Enable FPE usage in supervisor mode,
* so we can access registers.
*/
li t0, SSTATUS_FS_INITIAL
csrs sstatus, t0
/* Restore registers */
ld t0, (PCB_FCSR)(\p)
fscsr t0
fld f0, (PCB_X + 0 * 16)(\p)
fld f1, (PCB_X + 1 * 16)(\p)
fld f2, (PCB_X + 2 * 16)(\p)
fld f3, (PCB_X + 3 * 16)(\p)
fld f4, (PCB_X + 4 * 16)(\p)
fld f5, (PCB_X + 5 * 16)(\p)
fld f6, (PCB_X + 6 * 16)(\p)
fld f7, (PCB_X + 7 * 16)(\p)
fld f8, (PCB_X + 8 * 16)(\p)
fld f9, (PCB_X + 9 * 16)(\p)
fld f10, (PCB_X + 10 * 16)(\p)
fld f11, (PCB_X + 11 * 16)(\p)
fld f12, (PCB_X + 12 * 16)(\p)
fld f13, (PCB_X + 13 * 16)(\p)
fld f14, (PCB_X + 14 * 16)(\p)
fld f15, (PCB_X + 15 * 16)(\p)
fld f16, (PCB_X + 16 * 16)(\p)
fld f17, (PCB_X + 17 * 16)(\p)
fld f18, (PCB_X + 18 * 16)(\p)
fld f19, (PCB_X + 19 * 16)(\p)
fld f20, (PCB_X + 20 * 16)(\p)
fld f21, (PCB_X + 21 * 16)(\p)
fld f22, (PCB_X + 22 * 16)(\p)
fld f23, (PCB_X + 23 * 16)(\p)
fld f24, (PCB_X + 24 * 16)(\p)
fld f25, (PCB_X + 25 * 16)(\p)
fld f26, (PCB_X + 26 * 16)(\p)
fld f27, (PCB_X + 27 * 16)(\p)
fld f28, (PCB_X + 28 * 16)(\p)
fld f29, (PCB_X + 29 * 16)(\p)
fld f30, (PCB_X + 30 * 16)(\p)
fld f31, (PCB_X + 31 * 16)(\p)
/* Disable FPE usage in supervisor mode. */
li t0, SSTATUS_FS_MASK
csrc sstatus, t0
.endm
/*
* void
* fpe_state_save(struct thread *td)
*/
ENTRY(fpe_state_save)
/* Get pointer to PCB */
ld a0, TD_PCB(a0)
__fpe_state_save a0
ret
END(fpe_state_save)
#endif /* FPE */
/*
* void
* fpe_state_clear(void)
*/
ENTRY(fpe_state_clear)
/*
* Enable FPE usage in supervisor mode,
* so we can access registers.
*/
li t0, SSTATUS_FS_INITIAL
csrs sstatus, t0
fscsr zero
fcvt.d.l f0, zero
fcvt.d.l f1, zero
fcvt.d.l f2, zero
fcvt.d.l f3, zero
fcvt.d.l f4, zero
fcvt.d.l f5, zero
fcvt.d.l f6, zero
fcvt.d.l f7, zero
fcvt.d.l f8, zero
fcvt.d.l f9, zero
fcvt.d.l f10, zero
fcvt.d.l f11, zero
fcvt.d.l f12, zero
fcvt.d.l f13, zero
fcvt.d.l f14, zero
fcvt.d.l f15, zero
fcvt.d.l f16, zero
fcvt.d.l f17, zero
fcvt.d.l f18, zero
fcvt.d.l f19, zero
fcvt.d.l f20, zero
fcvt.d.l f21, zero
fcvt.d.l f22, zero
fcvt.d.l f23, zero
fcvt.d.l f24, zero
fcvt.d.l f25, zero
fcvt.d.l f26, zero
fcvt.d.l f27, zero
fcvt.d.l f28, zero
fcvt.d.l f29, zero
fcvt.d.l f30, zero
fcvt.d.l f31, zero
/* Disable FPE usage in supervisor mode. */
li t0, SSTATUS_FS_MASK
csrc sstatus, t0
ret
END(fpe_state_clear)
/*
* void cpu_throw(struct thread *old __unused, struct thread *new)
*/
ENTRY(cpu_throw)
/* Activate the new thread's pmap. */
mv s0, a1
mv a0, a1
call _C_LABEL(pmap_activate_sw)
mv a0, s0
/* Store the new curthread */
- sd a0, PC_CURTHREAD(gp)
+ sd a0, PC_CURTHREAD(tp)
/* And the new pcb */
ld x13, TD_PCB(a0)
- sd x13, PC_CURPCB(gp)
+ sd x13, PC_CURPCB(tp)
/* Load registers */
ld ra, (PCB_RA)(x13)
ld sp, (PCB_SP)(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)
#ifdef FPE
/* Is FPE enabled for new thread? */
ld t0, TD_FRAME(a0)
ld t1, (TF_SSTATUS)(t0)
li t2, SSTATUS_FS_MASK
and t3, t1, t2
beqz t3, 1f /* No, skip. */
/* Restore registers. */
__fpe_state_load x13
1:
#endif
ret
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)
/* Store the new curthread */
- sd a1, PC_CURTHREAD(gp)
+ sd a1, PC_CURTHREAD(tp)
/* And the new pcb */
ld x13, TD_PCB(a1)
- sd x13, PC_CURPCB(gp)
+ sd x13, PC_CURPCB(tp)
/* Save the old context. */
ld x13, TD_PCB(a0)
/* Store ra, sp and the callee-saved registers */
sd ra, (PCB_RA)(x13)
sd sp, (PCB_SP)(x13)
- sd tp, (PCB_TP)(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)
#ifdef FPE
/*
* Is FPE enabled and is it in dirty state
* for the old thread?
*/
ld t0, TD_FRAME(a0)
ld t1, (TF_SSTATUS)(t0)
li t2, SSTATUS_FS_MASK
and t3, t1, t2
li t2, SSTATUS_FS_DIRTY
bne t3, t2, 1f /* No, skip. */
/* Yes, mark FPE state clean and save registers. */
li t2, ~SSTATUS_FS_MASK
and t3, t1, t2
li t2, SSTATUS_FS_CLEAN
or t3, t3, t2
sd t3, (TF_SSTATUS)(t0)
__fpe_state_save x13
1:
#endif
/* Activate the new thread's pmap */
mv s0, a0
mv s1, a1
mv s2, a2
mv a0, a1
call _C_LABEL(pmap_activate_sw)
mv a1, s1
/* Release the old thread */
sd s2, TD_LOCK(s0)
#if defined(SCHED_ULE) && defined(SMP)
/* Spin if TD_LOCK points to a blocked_lock */
la s2, _C_LABEL(blocked_lock)
1:
ld t0, TD_LOCK(a1)
beq t0, s2, 1b
#endif
/*
* Restore the saved context.
*/
ld x13, TD_PCB(a1)
/* Restore the registers */
- ld tp, (PCB_TP)(x13)
ld ra, (PCB_RA)(x13)
ld sp, (PCB_SP)(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)
#ifdef FPE
/* Is FPE enabled for new thread? */
ld t0, TD_FRAME(a1)
ld t1, (TF_SSTATUS)(t0)
li t2, SSTATUS_FS_MASK
and t3, t1, t2
beqz t3, 1f /* No, skip. */
/* Restore registers. */
__fpe_state_load x13
1:
#endif
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, s0
mv a1, s1
mv a2, sp
call _C_LABEL(fork_exit)
/* Restore sstatus */
ld t0, (TF_SSTATUS)(sp)
/* Ensure interrupts disabled */
li t1, ~SSTATUS_SIE
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)
- /* Load user ra and sp */
+ /* Load user ra and gp */
ld ra, (TF_RA)(sp)
+ ld gp, (TF_GP)(sp)
/*
* Store our pcpup on stack, we will load it back
* on kernel mode trap.
*/
- sd gp, (TF_SIZE)(sp)
- ld gp, (TF_GP)(sp)
+ sd tp, (TF_SIZE)(sp)
+ ld tp, (TF_TP)(sp)
/* Save kernel stack so we can use it doing a user trap */
addi sp, sp, TF_SIZE
csrw sscratch, sp
/* Load user stack */
ld sp, (TF_SP - TF_SIZE)(sp)
sret
END(fork_trampoline)
ENTRY(savectx)
/* Store ra, sp and the callee-saved registers */
sd ra, (PCB_RA)(a0)
sd sp, (PCB_SP)(a0)
sd tp, (PCB_TP)(a0)
+ sd gp, (PCB_GP)(a0)
/* s[0-11] */
sd s0, (PCB_S + 0 * 8)(a0)
sd s1, (PCB_S + 1 * 8)(a0)
sd s2, (PCB_S + 2 * 8)(a0)
sd s3, (PCB_S + 3 * 8)(a0)
sd s4, (PCB_S + 4 * 8)(a0)
sd s5, (PCB_S + 5 * 8)(a0)
sd s6, (PCB_S + 6 * 8)(a0)
sd s7, (PCB_S + 7 * 8)(a0)
sd s8, (PCB_S + 8 * 8)(a0)
sd s9, (PCB_S + 9 * 8)(a0)
sd s10, (PCB_S + 10 * 8)(a0)
sd s11, (PCB_S + 11 * 8)(a0)
#ifdef FPE
__fpe_state_save a0
#endif
ret
END(savectx)
Index: stable/12/sys/riscv/riscv/vm_machdep.c
===================================================================
--- stable/12/sys/riscv/riscv/vm_machdep.c (revision 349484)
+++ stable/12/sys/riscv/riscv/vm_machdep.c (revision 349485)
@@ -1,287 +1,276 @@
/*-
* Copyright (c) 2015-2018 Ruslan Bukin
* 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
__FBSDID("$FreeBSD$");
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if __riscv_xlen == 64
#define TP_OFFSET 16 /* sizeof(struct tcb) */
#endif
/*
* 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;
- register_t val;
if ((flags & RFPROC) == 0)
return;
- if (td1 == curthread) {
- /*
- * Save the tp. These normally happen in cpu_switch,
- * but if userland changes this then forks this may
- * not have happened.
- */
- __asm __volatile("mv %0, tp" : "=&r"(val));
- td1->td_pcb->pcb_tp = val;
+ /* RISCVTODO: save the FPU state here */
- /* RISCVTODO: save the FPU state here */
- }
-
pcb2 = (struct pcb *)(td2->td_kstack +
td2->td_kstack_pages * PAGE_SIZE) - 1;
td2->td_pcb = pcb2;
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
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_SPIE); /* Enable interrupts. */
tf->tf_sstatus &= ~(SSTATUS_SPP); /* User mode. */
td2->td_frame = tf;
/* Set the return value registers for fork() */
td2->td_pcb->pcb_s[0] = (uintptr_t)fork_return;
td2->td_pcb->pcb_s[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 = (SSTATUS_SIE);
}
void
cpu_reset(void)
{
sbi_shutdown();
while(1);
}
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, mostly pcb and trap frame for a new
* thread, about to return to userspace. Put enough state in the new
* thread's PCB to get it to go back to the fork_return(), which
* finalizes the thread state and handles peculiarities of the first
* return to userspace for the new thread.
*/
void
cpu_copy_thread(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_s[0] = (uintptr_t)fork_return;
td->td_pcb->pcb_s[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 = (SSTATUS_SIE);
}
/*
* Set that machine state for performing an upcall that starts
* the entry function with the given argument.
*/
void
cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
stack_t *stack)
{
struct trapframe *tf;
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 + TP_OFFSET;
- if (td == curthread)
- __asm __volatile("mv tp, %0" :: "r"(pcb->pcb_tp));
+ /*
+ * The user TLS is set by modifying the trapframe's tp value, which
+ * will be restored when returning to userspace.
+ */
+ td->td_frame->tf_tp = (register_t)tls_base + TP_OFFSET;
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(
(caddr_t)td->td_pcb - 8 - sizeof(struct trapframe));
}
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_fork_kthread_handler(struct thread *td, void (*func)(void *), void *arg)
{
td->td_pcb->pcb_s[0] = (uintptr_t)func;
td->td_pcb->pcb_s[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)
{
}
bool
cpu_exec_vmspace_reuse(struct proc *p __unused, vm_map_t map __unused)
{
return (true);
}
int
cpu_procctl(struct thread *td __unused, int idtype __unused, id_t id __unused,
int com __unused, void *data __unused)
{
return (EINVAL);
}
void
swi_vm(void *v)
{
/* Nothing to do here - busdma bounce buffers are not implemented. */
}
Index: stable/12
===================================================================
--- stable/12 (revision 349484)
+++ stable/12 (revision 349485)
Property changes on: stable/12
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head:r348835-348836