mirror of https://github.com/xemu-project/xemu.git
target/nios2: Remove the deprecated Nios II target
The Nios II target is deprecated since v8.2 in commit 9997771bc1
("target/nios2: Deprecate the Nios II architecture").
Remove:
- Buildsys / CI infra
- User emulation
- System emulation (10m50-ghrd & nios2-generic-nommu machines)
- Tests
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Acked-by: Marek Vasut <marex@denx.de>
Message-Id: <20240327144806.11319-3-philmd@linaro.org>
This commit is contained in:
parent
92360d6e62
commit
6c3014858c
.gitlab-ci.d
MAINTAINERSconfigs
configuredisas
docs
fpu
hw
include
linux-user
elfload.c
meson.buildnios2
cpu_loop.csignal.csockbits.hsyscall_nr.htarget_cpu.htarget_elf.htarget_errno_defs.htarget_fcntl.htarget_mman.htarget_prctl.htarget_proc.htarget_resource.htarget_signal.htarget_structs.htarget_syscall.htermbits.h
syscall_defs.hqapi
qemu-options.hxscripts
target
tests
avocado
docker
qtest
tcg/nios2
|
@ -164,7 +164,7 @@ build-system-centos:
|
|||
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
|
||||
--enable-modules --enable-trace-backends=dtrace --enable-docs
|
||||
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
|
||||
x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu
|
||||
x86_64-softmmu rx-softmmu sh4-softmmu
|
||||
MAKE_CHECK_ARGS: check-build
|
||||
|
||||
# Previous QEMU release. Used for cross-version migration tests.
|
||||
|
@ -254,7 +254,7 @@ avocado-system-centos:
|
|||
IMAGE: centos8
|
||||
MAKE_CHECK_ARGS: check-avocado
|
||||
AVOCADO_TAGS: arch:ppc64 arch:or1k arch:s390x arch:x86_64 arch:rx
|
||||
arch:sh4 arch:nios2
|
||||
arch:sh4
|
||||
|
||||
build-system-opensuse:
|
||||
extends:
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
- ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
|
||||
--disable-system --target-list-exclude="aarch64_be-linux-user
|
||||
alpha-linux-user cris-linux-user m68k-linux-user microblazeel-linux-user
|
||||
nios2-linux-user or1k-linux-user ppc-linux-user sparc-linux-user
|
||||
or1k-linux-user ppc-linux-user sparc-linux-user
|
||||
xtensa-linux-user $CROSS_SKIP_TARGETS"
|
||||
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ cross-win64-system:
|
|||
IMAGE: fedora-win64-cross
|
||||
EXTRA_CONFIGURE_OPTS: --enable-fdt=internal --disable-plugins
|
||||
CROSS_SKIP_TARGETS: alpha-softmmu avr-softmmu hppa-softmmu
|
||||
m68k-softmmu microblazeel-softmmu nios2-softmmu
|
||||
m68k-softmmu microblazeel-softmmu
|
||||
or1k-softmmu rx-softmmu sh4eb-softmmu sparc64-softmmu
|
||||
tricore-softmmu xtensaeb-softmmu
|
||||
artifacts:
|
||||
|
|
13
MAINTAINERS
13
MAINTAINERS
|
@ -291,19 +291,6 @@ F: disas/*mips.c
|
|||
F: docs/system/cpu-models-mips.rst.inc
|
||||
F: tests/tcg/mips/
|
||||
|
||||
NiosII TCG CPUs
|
||||
R: Chris Wulff <crwulff@gmail.com>
|
||||
R: Marek Vasut <marex@denx.de>
|
||||
S: Orphan
|
||||
F: target/nios2/
|
||||
F: hw/nios2/
|
||||
F: hw/intc/nios2_vic.c
|
||||
F: disas/nios2.c
|
||||
F: include/hw/intc/nios2_vic.h
|
||||
F: configs/devices/nios2-softmmu/default.mak
|
||||
F: tests/docker/dockerfiles/debian-nios2-cross.d/build-toolchain.sh
|
||||
F: tests/tcg/nios2/
|
||||
|
||||
OpenRISC TCG CPUs
|
||||
M: Stafford Horne <shorne@gmail.com>
|
||||
S: Odd Fixes
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
# Default configuration for nios2-softmmu
|
||||
|
||||
# Boards:
|
||||
#
|
||||
CONFIG_NIOS2_10M50=y
|
||||
CONFIG_NIOS2_GENERIC_NOMMU=y
|
|
@ -1 +0,0 @@
|
|||
TARGET_ARCH=nios2
|
|
@ -1,2 +0,0 @@
|
|||
TARGET_ARCH=nios2
|
||||
TARGET_NEED_FDT=y
|
|
@ -1169,7 +1169,6 @@ fi
|
|||
: ${cross_prefix_mips64="mips64-linux-gnuabi64-"}
|
||||
: ${cross_prefix_mipsel="mipsel-linux-gnu-"}
|
||||
: ${cross_prefix_mips="mips-linux-gnu-"}
|
||||
: ${cross_prefix_nios2="nios2-linux-gnu-"}
|
||||
: ${cross_prefix_ppc="powerpc-linux-gnu-"}
|
||||
: ${cross_prefix_ppc64="powerpc64-linux-gnu-"}
|
||||
: ${cross_prefix_ppc64le="$cross_prefix_ppc64"}
|
||||
|
@ -1258,7 +1257,6 @@ probe_target_compiler() {
|
|||
mips64) container_hosts=x86_64 ;;
|
||||
mipsel) container_hosts=x86_64 ;;
|
||||
mips) container_hosts=x86_64 ;;
|
||||
nios2) container_hosts=x86_64 ;;
|
||||
ppc) container_hosts=x86_64 ;;
|
||||
ppc64|ppc64le) container_hosts=x86_64 ;;
|
||||
riscv64) container_hosts=x86_64 ;;
|
||||
|
|
|
@ -5,7 +5,6 @@ common_ss.add(when: 'CONFIG_HPPA_DIS', if_true: files('hppa.c'))
|
|||
common_ss.add(when: 'CONFIG_M68K_DIS', if_true: files('m68k.c'))
|
||||
common_ss.add(when: 'CONFIG_MICROBLAZE_DIS', if_true: files('microblaze.c'))
|
||||
common_ss.add(when: 'CONFIG_MIPS_DIS', if_true: files('mips.c', 'nanomips.c'))
|
||||
common_ss.add(when: 'CONFIG_NIOS2_DIS', if_true: files('nios2.c'))
|
||||
common_ss.add(when: 'CONFIG_RISCV_DIS', if_true: files(
|
||||
'riscv.c',
|
||||
'riscv-xthead.c',
|
||||
|
|
3514
disas/nios2.c
3514
disas/nios2.c
File diff suppressed because it is too large
Load Diff
|
@ -185,12 +185,6 @@ it. Since all recent x86 hardware from the past >10 years is capable of the
|
|||
System emulator CPUs
|
||||
--------------------
|
||||
|
||||
Nios II CPU (since 8.2)
|
||||
'''''''''''''''''''''''
|
||||
|
||||
The Nios II architecture is orphan. The ``nios2`` guest CPU support is
|
||||
deprecated and will be removed in a future version of QEMU.
|
||||
|
||||
``power5+`` and ``power7+`` CPU names (since 9.0)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
|
@ -226,11 +220,6 @@ These old machine types are quite neglected nowadays and thus might have
|
|||
various pitfalls with regards to live migration. Use a newer machine type
|
||||
instead.
|
||||
|
||||
Nios II ``10m50-ghrd`` and ``nios2-generic-nommu`` machines (since 8.2)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The Nios II architecture is orphan.
|
||||
|
||||
``shix`` (since 9.0)
|
||||
''''''''''''''''''''
|
||||
|
||||
|
|
|
@ -58,10 +58,6 @@ depending on the guest architecture.
|
|||
- :ref:`Yes<MIPS-System-emulator>`
|
||||
- Yes
|
||||
- Venerable RISC architecture originally out of Stanford University
|
||||
* - Nios2
|
||||
- Yes
|
||||
- Yes
|
||||
- 32 bit embedded soft-core by Altera
|
||||
* - OpenRISC
|
||||
- :ref:`Yes<OpenRISC-System-emulator>`
|
||||
- Yes
|
||||
|
@ -180,9 +176,6 @@ for that architecture.
|
|||
* - MIPS
|
||||
- System
|
||||
- Unified Hosting Interface (MD01069)
|
||||
* - Nios II
|
||||
- System
|
||||
- https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=libgloss/nios2/nios2-semi.txt;hb=HEAD
|
||||
* - RISC-V
|
||||
- System and User-mode
|
||||
- https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
|
||||
|
|
|
@ -757,6 +757,12 @@ x86 ``Icelake-Client`` CPU (removed in 7.1)
|
|||
There isn't ever Icelake Client CPU, it is some wrong and imaginary one.
|
||||
Use ``Icelake-Server`` instead.
|
||||
|
||||
Nios II CPU (removed in 9.1)
|
||||
''''''''''''''''''''''''''''
|
||||
|
||||
QEMU Nios II architecture was orphan; Intel has EOL'ed the Nios II
|
||||
processor IP (see `Intel discontinuance notification`_).
|
||||
|
||||
System accelerators
|
||||
-------------------
|
||||
|
||||
|
@ -841,6 +847,11 @@ ppc ``taihu`` machine (removed in 7.2)
|
|||
This machine was removed because it was partially emulated and 405
|
||||
machines are very similar. Use the ``ref405ep`` machine instead.
|
||||
|
||||
Nios II ``10m50-ghrd`` and ``nios2-generic-nommu`` machines (removed in 9.1)
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
The Nios II architecture was orphan.
|
||||
|
||||
linux-user mode CPUs
|
||||
--------------------
|
||||
|
||||
|
@ -860,6 +871,11 @@ The ``ppc64abi32`` architecture has a number of issues which regularly
|
|||
tripped up the CI testing and was suspected to be quite broken. For that
|
||||
reason the maintainers strongly suspected no one actually used it.
|
||||
|
||||
``nios2`` CPU (removed in 9.1)
|
||||
''''''''''''''''''''''''''''''
|
||||
|
||||
QEMU Nios II architecture was orphan; Intel has EOL'ed the Nios II
|
||||
processor IP (see `Intel discontinuance notification`_).
|
||||
|
||||
TCG introspection features
|
||||
--------------------------
|
||||
|
@ -1006,3 +1022,4 @@ stable for some time and is now widely used.
|
|||
The command line and feature set is very close to the removed
|
||||
C implementation.
|
||||
|
||||
.. _Intel discontinuance notification: https://www.intel.com/content/www/us/en/content-details/781327/intel-is-discontinuing-ip-ordering-codes-listed-in-pdn2312-for-nios-ii-ip.html
|
||||
|
|
|
@ -24,7 +24,7 @@ Deterministic replay has the following features:
|
|||
* Writes execution log into the file for later replaying for multiple times
|
||||
on different machines.
|
||||
* Supports i386, x86_64, ARM, AArch64, Risc-V, MIPS, MIPS64, S390X, Alpha,
|
||||
PowerPC, PowerPC64, M68000, Microblaze, OpenRISC, Nios II, SPARC,
|
||||
PowerPC, PowerPC64, M68000, Microblaze, OpenRISC, SPARC,
|
||||
and Xtensa hardware platforms.
|
||||
* Performs deterministic replay of all operations with keyboard and mouse
|
||||
input devices, serial ports, and network.
|
||||
|
|
|
@ -159,10 +159,6 @@ Other binaries
|
|||
* ``qemu-mipsn32el`` executes 32-bit little endian MIPS binaries (MIPS N32
|
||||
ABI).
|
||||
|
||||
- user mode (NiosII)
|
||||
|
||||
* ``qemu-nios2`` TODO.
|
||||
|
||||
- user mode (PowerPC)
|
||||
|
||||
* ``qemu-ppc64`` TODO.
|
||||
|
|
|
@ -152,7 +152,7 @@ static void parts64_default_nan(FloatParts64 *p, float_status *status)
|
|||
/*
|
||||
* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
|
||||
* S390, SH4, TriCore, and Xtensa. Our other supported targets,
|
||||
* CRIS and Nios2, do not have floating-point.
|
||||
* such CRIS, do not have floating-point.
|
||||
*/
|
||||
if (snan_bit_is_one(status)) {
|
||||
/* set all bits other than msb */
|
||||
|
|
|
@ -57,7 +57,6 @@ source loongarch/Kconfig
|
|||
source m68k/Kconfig
|
||||
source microblaze/Kconfig
|
||||
source mips/Kconfig
|
||||
source nios2/Kconfig
|
||||
source openrisc/Kconfig
|
||||
source ppc/Kconfig
|
||||
source riscv/Kconfig
|
||||
|
|
|
@ -87,9 +87,6 @@ config GOLDFISH_PIC
|
|||
config M68K_IRQC
|
||||
bool
|
||||
|
||||
config NIOS2_VIC
|
||||
bool
|
||||
|
||||
config LOONGARCH_IPI
|
||||
bool
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ specific_ss.add(when: 'CONFIG_XIVE', if_true: files('xive.c'))
|
|||
specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'],
|
||||
if_true: files('spapr_xive_kvm.c'))
|
||||
specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
|
||||
specific_ss.add(when: 'CONFIG_NIOS2_VIC', if_true: files('nios2_vic.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
|
||||
|
|
|
@ -1,313 +0,0 @@
|
|||
/*
|
||||
* Vectored Interrupt Controller for nios2 processor
|
||||
*
|
||||
* Copyright (c) 2022 Neuroblade
|
||||
*
|
||||
* Interface:
|
||||
* QOM property "cpu": link to the Nios2 CPU (must be set)
|
||||
* Unnamed GPIO inputs 0..NIOS2_VIC_MAX_IRQ-1: input IRQ lines
|
||||
* IRQ should be connected to nios2 IRQ0.
|
||||
*
|
||||
* Reference: "Embedded Peripherals IP User Guide
|
||||
* for Intel® Quartus® Prime Design Suite: 21.4"
|
||||
* Chapter 38 "Vectored Interrupt Controller Core"
|
||||
* See: https://www.intel.com/content/www/us/en/docs/programmable/683130/21-4/vectored-interrupt-controller-core.html
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qom/object.h"
|
||||
#include "hw/intc/nios2_vic.h"
|
||||
#include "cpu.h"
|
||||
|
||||
|
||||
enum {
|
||||
INT_CONFIG0 = 0,
|
||||
INT_CONFIG31 = 31,
|
||||
INT_ENABLE = 32,
|
||||
INT_ENABLE_SET = 33,
|
||||
INT_ENABLE_CLR = 34,
|
||||
INT_PENDING = 35,
|
||||
INT_RAW_STATUS = 36,
|
||||
SW_INTERRUPT = 37,
|
||||
SW_INTERRUPT_SET = 38,
|
||||
SW_INTERRUPT_CLR = 39,
|
||||
VIC_CONFIG = 40,
|
||||
VIC_STATUS = 41,
|
||||
VEC_TBL_BASE = 42,
|
||||
VEC_TBL_ADDR = 43,
|
||||
CSR_COUNT /* Last! */
|
||||
};
|
||||
|
||||
/* Requested interrupt level (INT_CONFIG[0:5]) */
|
||||
static inline uint32_t vic_int_config_ril(const Nios2VIC *vic, int irq_num)
|
||||
{
|
||||
return extract32(vic->int_config[irq_num], 0, 6);
|
||||
}
|
||||
|
||||
/* Requested NMI (INT_CONFIG[6]) */
|
||||
static inline uint32_t vic_int_config_rnmi(const Nios2VIC *vic, int irq_num)
|
||||
{
|
||||
return extract32(vic->int_config[irq_num], 6, 1);
|
||||
}
|
||||
|
||||
/* Requested register set (INT_CONFIG[7:12]) */
|
||||
static inline uint32_t vic_int_config_rrs(const Nios2VIC *vic, int irq_num)
|
||||
{
|
||||
return extract32(vic->int_config[irq_num], 7, 6);
|
||||
}
|
||||
|
||||
static inline uint32_t vic_config_vec_size(const Nios2VIC *vic)
|
||||
{
|
||||
return 1 << (2 + extract32(vic->vic_config, 0, 3));
|
||||
}
|
||||
|
||||
static inline uint32_t vic_int_pending(const Nios2VIC *vic)
|
||||
{
|
||||
return (vic->int_raw_status | vic->sw_int) & vic->int_enable;
|
||||
}
|
||||
|
||||
static void vic_update_irq(Nios2VIC *vic)
|
||||
{
|
||||
Nios2CPU *cpu = NIOS2_CPU(vic->cpu);
|
||||
uint32_t pending = vic_int_pending(vic);
|
||||
int irq = -1;
|
||||
int max_ril = 0;
|
||||
/* Note that if RIL is 0 for an interrupt it is effectively disabled */
|
||||
|
||||
vic->vec_tbl_addr = 0;
|
||||
vic->vic_status = 0;
|
||||
|
||||
if (pending == 0) {
|
||||
qemu_irq_lower(vic->output_int);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NIOS2_VIC_MAX_IRQ; i++) {
|
||||
if (pending & BIT(i)) {
|
||||
int ril = vic_int_config_ril(vic, i);
|
||||
if (ril > max_ril) {
|
||||
irq = i;
|
||||
max_ril = ril;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (irq < 0) {
|
||||
qemu_irq_lower(vic->output_int);
|
||||
return;
|
||||
}
|
||||
|
||||
vic->vec_tbl_addr = irq * vic_config_vec_size(vic) + vic->vec_tbl_base;
|
||||
vic->vic_status = irq | BIT(31);
|
||||
|
||||
/*
|
||||
* In hardware, the interface between the VIC and the CPU is via the
|
||||
* External Interrupt Controller interface, where the interrupt controller
|
||||
* presents the CPU with a packet of data containing:
|
||||
* - Requested Handler Address (RHA): 32 bits
|
||||
* - Requested Register Set (RRS) : 6 bits
|
||||
* - Requested Interrupt Level (RIL) : 6 bits
|
||||
* - Requested NMI flag (RNMI) : 1 bit
|
||||
* In our emulation, we implement this by writing the data directly to
|
||||
* fields in the CPU object and then raising the IRQ line to tell
|
||||
* the CPU that we've done so.
|
||||
*/
|
||||
|
||||
cpu->rha = vic->vec_tbl_addr;
|
||||
cpu->ril = max_ril;
|
||||
cpu->rrs = vic_int_config_rrs(vic, irq);
|
||||
cpu->rnmi = vic_int_config_rnmi(vic, irq);
|
||||
|
||||
qemu_irq_raise(vic->output_int);
|
||||
}
|
||||
|
||||
static void vic_set_irq(void *opaque, int irq_num, int level)
|
||||
{
|
||||
Nios2VIC *vic = opaque;
|
||||
|
||||
vic->int_raw_status = deposit32(vic->int_raw_status, irq_num, 1, !!level);
|
||||
vic_update_irq(vic);
|
||||
}
|
||||
|
||||
static void nios2_vic_reset(DeviceState *dev)
|
||||
{
|
||||
Nios2VIC *vic = NIOS2_VIC(dev);
|
||||
|
||||
memset(&vic->int_config, 0, sizeof(vic->int_config));
|
||||
vic->vic_config = 0;
|
||||
vic->int_raw_status = 0;
|
||||
vic->int_enable = 0;
|
||||
vic->sw_int = 0;
|
||||
vic->vic_status = 0;
|
||||
vic->vec_tbl_base = 0;
|
||||
vic->vec_tbl_addr = 0;
|
||||
}
|
||||
|
||||
static uint64_t nios2_vic_csr_read(void *opaque, hwaddr offset, unsigned size)
|
||||
{
|
||||
Nios2VIC *vic = opaque;
|
||||
int index = offset / 4;
|
||||
|
||||
switch (index) {
|
||||
case INT_CONFIG0 ... INT_CONFIG31:
|
||||
return vic->int_config[index - INT_CONFIG0];
|
||||
case INT_ENABLE:
|
||||
return vic->int_enable;
|
||||
case INT_PENDING:
|
||||
return vic_int_pending(vic);
|
||||
case INT_RAW_STATUS:
|
||||
return vic->int_raw_status;
|
||||
case SW_INTERRUPT:
|
||||
return vic->sw_int;
|
||||
case VIC_CONFIG:
|
||||
return vic->vic_config;
|
||||
case VIC_STATUS:
|
||||
return vic->vic_status;
|
||||
case VEC_TBL_BASE:
|
||||
return vic->vec_tbl_base;
|
||||
case VEC_TBL_ADDR:
|
||||
return vic->vec_tbl_addr;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void nios2_vic_csr_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
unsigned size)
|
||||
{
|
||||
Nios2VIC *vic = opaque;
|
||||
int index = offset / 4;
|
||||
|
||||
switch (index) {
|
||||
case INT_CONFIG0 ... INT_CONFIG31:
|
||||
vic->int_config[index - INT_CONFIG0] = value;
|
||||
break;
|
||||
case INT_ENABLE:
|
||||
vic->int_enable = value;
|
||||
break;
|
||||
case INT_ENABLE_SET:
|
||||
vic->int_enable |= value;
|
||||
break;
|
||||
case INT_ENABLE_CLR:
|
||||
vic->int_enable &= ~value;
|
||||
break;
|
||||
case SW_INTERRUPT:
|
||||
vic->sw_int = value;
|
||||
break;
|
||||
case SW_INTERRUPT_SET:
|
||||
vic->sw_int |= value;
|
||||
break;
|
||||
case SW_INTERRUPT_CLR:
|
||||
vic->sw_int &= ~value;
|
||||
break;
|
||||
case VIC_CONFIG:
|
||||
vic->vic_config = value;
|
||||
break;
|
||||
case VEC_TBL_BASE:
|
||||
vic->vec_tbl_base = value;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"nios2-vic: write to invalid CSR address %#"
|
||||
HWADDR_PRIx "\n", offset);
|
||||
}
|
||||
|
||||
vic_update_irq(vic);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps nios2_vic_csr_ops = {
|
||||
.read = nios2_vic_csr_read,
|
||||
.write = nios2_vic_csr_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = { .min_access_size = 4, .max_access_size = 4 }
|
||||
};
|
||||
|
||||
static void nios2_vic_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
Nios2VIC *vic = NIOS2_VIC(dev);
|
||||
|
||||
if (!vic->cpu) {
|
||||
/* This is a programming error in the code using this device */
|
||||
error_setg(errp, "nios2-vic 'cpu' link property was not set");
|
||||
return;
|
||||
}
|
||||
|
||||
sysbus_init_irq(SYS_BUS_DEVICE(dev), &vic->output_int);
|
||||
qdev_init_gpio_in(dev, vic_set_irq, NIOS2_VIC_MAX_IRQ);
|
||||
|
||||
memory_region_init_io(&vic->csr, OBJECT(dev), &nios2_vic_csr_ops, vic,
|
||||
"nios2.vic.csr", CSR_COUNT * sizeof(uint32_t));
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &vic->csr);
|
||||
}
|
||||
|
||||
static Property nios2_vic_properties[] = {
|
||||
DEFINE_PROP_LINK("cpu", Nios2VIC, cpu, TYPE_CPU, CPUState *),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static const VMStateDescription nios2_vic_vmstate = {
|
||||
.name = "nios2-vic",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (const VMStateField[]){
|
||||
VMSTATE_UINT32_ARRAY(int_config, Nios2VIC, 32),
|
||||
VMSTATE_UINT32(vic_config, Nios2VIC),
|
||||
VMSTATE_UINT32(int_raw_status, Nios2VIC),
|
||||
VMSTATE_UINT32(int_enable, Nios2VIC),
|
||||
VMSTATE_UINT32(sw_int, Nios2VIC),
|
||||
VMSTATE_UINT32(vic_status, Nios2VIC),
|
||||
VMSTATE_UINT32(vec_tbl_base, Nios2VIC),
|
||||
VMSTATE_UINT32(vec_tbl_addr, Nios2VIC),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
||||
static void nios2_vic_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->reset = nios2_vic_reset;
|
||||
dc->realize = nios2_vic_realize;
|
||||
dc->vmsd = &nios2_vic_vmstate;
|
||||
device_class_set_props(dc, nios2_vic_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo nios2_vic_info = {
|
||||
.name = TYPE_NIOS2_VIC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(Nios2VIC),
|
||||
.class_init = nios2_vic_class_init,
|
||||
};
|
||||
|
||||
static void nios2_vic_register_types(void)
|
||||
{
|
||||
type_register_static(&nios2_vic_info);
|
||||
}
|
||||
|
||||
type_init(nios2_vic_register_types);
|
|
@ -56,7 +56,6 @@ subdir('loongarch')
|
|||
subdir('m68k')
|
||||
subdir('microblaze')
|
||||
subdir('mips')
|
||||
subdir('nios2')
|
||||
subdir('openrisc')
|
||||
subdir('ppc')
|
||||
subdir('remote')
|
||||
|
|
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
* Altera 10M50 Nios2 GHRD
|
||||
*
|
||||
* Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
|
||||
*
|
||||
* Based on LabX device code
|
||||
*
|
||||
* Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/char/serial.h"
|
||||
#include "hw/intc/nios2_vic.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qemu/config-file.h"
|
||||
|
||||
#include "boot.h"
|
||||
|
||||
struct Nios2MachineState {
|
||||
MachineState parent_obj;
|
||||
|
||||
MemoryRegion phys_tcm;
|
||||
MemoryRegion phys_tcm_alias;
|
||||
MemoryRegion phys_ram;
|
||||
MemoryRegion phys_ram_alias;
|
||||
|
||||
bool vic;
|
||||
};
|
||||
|
||||
#define TYPE_NIOS2_MACHINE MACHINE_TYPE_NAME("10m50-ghrd")
|
||||
OBJECT_DECLARE_TYPE(Nios2MachineState, MachineClass, NIOS2_MACHINE)
|
||||
|
||||
#define BINARY_DEVICE_TREE_FILE "10m50-devboard.dtb"
|
||||
|
||||
static void nios2_10m50_ghrd_init(MachineState *machine)
|
||||
{
|
||||
Nios2MachineState *nms = NIOS2_MACHINE(machine);
|
||||
Nios2CPU *cpu;
|
||||
DeviceState *dev;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
ram_addr_t tcm_base = 0x0;
|
||||
ram_addr_t tcm_size = 0x1000; /* 1 kiB, but QEMU limit is 4 kiB */
|
||||
ram_addr_t ram_base = 0x08000000;
|
||||
ram_addr_t ram_size = 0x08000000;
|
||||
qemu_irq irq[32];
|
||||
int i;
|
||||
|
||||
/* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */
|
||||
memory_region_init_ram(&nms->phys_tcm, NULL, "nios2.tcm", tcm_size,
|
||||
&error_abort);
|
||||
memory_region_init_alias(&nms->phys_tcm_alias, NULL, "nios2.tcm.alias",
|
||||
&nms->phys_tcm, 0, tcm_size);
|
||||
memory_region_add_subregion(address_space_mem, tcm_base, &nms->phys_tcm);
|
||||
memory_region_add_subregion(address_space_mem, 0xc0000000 + tcm_base,
|
||||
&nms->phys_tcm_alias);
|
||||
|
||||
/* Physical DRAM with alias at 0xc0000000 */
|
||||
memory_region_init_ram(&nms->phys_ram, NULL, "nios2.ram", ram_size,
|
||||
&error_abort);
|
||||
memory_region_init_alias(&nms->phys_ram_alias, NULL, "nios2.ram.alias",
|
||||
&nms->phys_ram, 0, ram_size);
|
||||
memory_region_add_subregion(address_space_mem, ram_base, &nms->phys_ram);
|
||||
memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base,
|
||||
&nms->phys_ram_alias);
|
||||
|
||||
/* Create CPU. We need to set eic_present between init and realize. */
|
||||
cpu = NIOS2_CPU(object_new(TYPE_NIOS2_CPU));
|
||||
|
||||
/* Enable the External Interrupt Controller within the CPU. */
|
||||
cpu->eic_present = nms->vic;
|
||||
|
||||
/* Configure new exception vectors. */
|
||||
cpu->reset_addr = 0xd4000000;
|
||||
cpu->exception_addr = 0xc8000120;
|
||||
cpu->fast_tlb_miss_addr = 0xc0000100;
|
||||
|
||||
qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal);
|
||||
|
||||
if (nms->vic) {
|
||||
dev = qdev_new(TYPE_NIOS2_VIC);
|
||||
MemoryRegion *dev_mr;
|
||||
qemu_irq cpu_irq;
|
||||
|
||||
object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_fatal);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
|
||||
cpu_irq = qdev_get_gpio_in_named(DEVICE(cpu), "EIC", 0);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq);
|
||||
for (i = 0; i < 32; i++) {
|
||||
irq[i] = qdev_get_gpio_in(dev, i);
|
||||
}
|
||||
|
||||
dev_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
|
||||
memory_region_add_subregion(address_space_mem, 0x18002000, dev_mr);
|
||||
} else {
|
||||
for (i = 0; i < 32; i++) {
|
||||
irq[i] = qdev_get_gpio_in_named(DEVICE(cpu), "IRQ", i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register: Altera 16550 UART */
|
||||
serial_mm_init(address_space_mem, 0xf8001600, 2, irq[1], 115200,
|
||||
serial_hd(0), DEVICE_NATIVE_ENDIAN);
|
||||
|
||||
/* Register: Timer sys_clk_timer */
|
||||
dev = qdev_new("ALTR.timer");
|
||||
qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xf8001440);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[0]);
|
||||
|
||||
/* Register: Timer sys_clk_timer_1 */
|
||||
dev = qdev_new("ALTR.timer");
|
||||
qdev_prop_set_uint32(dev, "clock-frequency", 75 * 1000000);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xe0000880);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[5]);
|
||||
|
||||
nios2_load_kernel(cpu, ram_base, ram_size, machine->initrd_filename,
|
||||
BINARY_DEVICE_TREE_FILE, NULL);
|
||||
}
|
||||
|
||||
static bool get_vic(Object *obj, Error **errp)
|
||||
{
|
||||
Nios2MachineState *nms = NIOS2_MACHINE(obj);
|
||||
return nms->vic;
|
||||
}
|
||||
|
||||
static void set_vic(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
Nios2MachineState *nms = NIOS2_MACHINE(obj);
|
||||
nms->vic = value;
|
||||
}
|
||||
|
||||
static void nios2_10m50_ghrd_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
|
||||
mc->desc = "Altera 10M50 GHRD Nios II design";
|
||||
mc->init = nios2_10m50_ghrd_init;
|
||||
mc->is_default = true;
|
||||
mc->deprecation_reason = "Nios II architecture is deprecated";
|
||||
|
||||
object_class_property_add_bool(oc, "vic", get_vic, set_vic);
|
||||
object_class_property_set_description(oc, "vic",
|
||||
"Set on/off to enable/disable the Vectored Interrupt Controller");
|
||||
}
|
||||
|
||||
static const TypeInfo nios2_10m50_ghrd_type_info = {
|
||||
.name = TYPE_NIOS2_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.instance_size = sizeof(Nios2MachineState),
|
||||
.class_init = nios2_10m50_ghrd_class_init,
|
||||
};
|
||||
|
||||
static void nios2_10m50_ghrd_type_init(void)
|
||||
{
|
||||
type_register_static(&nios2_10m50_ghrd_type_info);
|
||||
}
|
||||
type_init(nios2_10m50_ghrd_type_init);
|
|
@ -1,13 +0,0 @@
|
|||
config NIOS2_10M50
|
||||
bool
|
||||
select NIOS2
|
||||
select SERIAL
|
||||
select ALTERA_TIMER
|
||||
select NIOS2_VIC
|
||||
|
||||
config NIOS2_GENERIC_NOMMU
|
||||
bool
|
||||
select NIOS2
|
||||
|
||||
config NIOS2
|
||||
bool
|
234
hw/nios2/boot.c
234
hw/nios2/boot.c
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* Nios2 kernel loader
|
||||
*
|
||||
* Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
|
||||
*
|
||||
* Based on microblaze kernel loader
|
||||
*
|
||||
* Copyright (c) 2012 Peter Crosthwaite <peter.crosthwaite@petalogix.com>
|
||||
* Copyright (c) 2012 PetaLogix
|
||||
* Copyright (c) 2009 Edgar E. Iglesias.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/datadir.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
|
||||
#include "boot.h"
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#define NIOS2_MAGIC 0x534f494e
|
||||
|
||||
static struct nios2_boot_info {
|
||||
void (*machine_cpu_reset)(Nios2CPU *);
|
||||
uint32_t bootstrap_pc;
|
||||
uint32_t cmdline;
|
||||
uint32_t initrd_start;
|
||||
uint32_t initrd_end;
|
||||
uint32_t fdt;
|
||||
} boot_info;
|
||||
|
||||
static void main_cpu_reset(void *opaque)
|
||||
{
|
||||
Nios2CPU *cpu = opaque;
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUNios2State *env = &cpu->env;
|
||||
|
||||
cpu_reset(CPU(cpu));
|
||||
|
||||
env->regs[R_ARG0] = NIOS2_MAGIC;
|
||||
env->regs[R_ARG1] = boot_info.initrd_start;
|
||||
env->regs[R_ARG2] = boot_info.fdt;
|
||||
env->regs[R_ARG3] = boot_info.cmdline;
|
||||
|
||||
cpu_set_pc(cs, boot_info.bootstrap_pc);
|
||||
if (boot_info.machine_cpu_reset) {
|
||||
boot_info.machine_cpu_reset(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
|
||||
{
|
||||
return addr - 0xc0000000LL;
|
||||
}
|
||||
|
||||
static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t ramsize,
|
||||
const char *kernel_cmdline, const char *dtb_filename)
|
||||
{
|
||||
MachineState *machine = MACHINE(qdev_get_machine());
|
||||
int fdt_size;
|
||||
void *fdt = NULL;
|
||||
int r;
|
||||
uint8_t rng_seed[32];
|
||||
|
||||
if (dtb_filename) {
|
||||
fdt = load_device_tree(dtb_filename, &fdt_size);
|
||||
}
|
||||
if (!fdt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
|
||||
qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
|
||||
|
||||
if (kernel_cmdline) {
|
||||
r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs",
|
||||
kernel_cmdline);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "couldn't set /chosen/bootargs\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (bi.initrd_start) {
|
||||
qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
|
||||
translate_kernel_address(NULL, bi.initrd_start));
|
||||
|
||||
qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
|
||||
translate_kernel_address(NULL, bi.initrd_end));
|
||||
}
|
||||
|
||||
cpu_physical_memory_write(bi.fdt, fdt, fdt_size);
|
||||
|
||||
/* Set machine->fdt for 'dumpdtb' QMP/HMP command */
|
||||
machine->fdt = fdt;
|
||||
|
||||
return fdt_size;
|
||||
}
|
||||
|
||||
void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
|
||||
uint32_t ramsize,
|
||||
const char *initrd_filename,
|
||||
const char *dtb_filename,
|
||||
void (*machine_cpu_reset)(Nios2CPU *))
|
||||
{
|
||||
const char *kernel_filename;
|
||||
const char *kernel_cmdline;
|
||||
const char *dtb_arg;
|
||||
char *filename = NULL;
|
||||
|
||||
kernel_filename = current_machine->kernel_filename;
|
||||
kernel_cmdline = current_machine->kernel_cmdline;
|
||||
dtb_arg = current_machine->dtb;
|
||||
/* default to pcbios dtb as passed by machine_init */
|
||||
if (!dtb_arg) {
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
|
||||
}
|
||||
|
||||
boot_info.machine_cpu_reset = machine_cpu_reset;
|
||||
qemu_register_reset(main_cpu_reset, cpu);
|
||||
|
||||
if (kernel_filename) {
|
||||
int kernel_size, fdt_size;
|
||||
uint64_t entry, high;
|
||||
|
||||
/* Boots a kernel elf binary. */
|
||||
kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
|
||||
&entry, NULL, &high, NULL,
|
||||
TARGET_BIG_ENDIAN, EM_ALTERA_NIOS2, 0, 0);
|
||||
if ((uint32_t)entry == 0xc0000000) {
|
||||
/*
|
||||
* The Nios II processor reference guide documents that the
|
||||
* kernel is placed at virtual memory address 0xc0000000,
|
||||
* and we've got something that points there. Reload it
|
||||
* and adjust the entry to get the address in physical RAM.
|
||||
*/
|
||||
kernel_size = load_elf(kernel_filename, NULL,
|
||||
translate_kernel_address, NULL,
|
||||
&entry, NULL, NULL, NULL,
|
||||
TARGET_BIG_ENDIAN, EM_ALTERA_NIOS2, 0, 0);
|
||||
boot_info.bootstrap_pc = ddr_base + 0xc0000000 +
|
||||
(entry & 0x07ffffff);
|
||||
} else {
|
||||
/* Use the entry point in the ELF image. */
|
||||
boot_info.bootstrap_pc = (uint32_t)entry;
|
||||
}
|
||||
|
||||
/* If it wasn't an ELF image, try an u-boot image. */
|
||||
if (kernel_size < 0) {
|
||||
hwaddr uentry, loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
|
||||
|
||||
kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0,
|
||||
NULL, NULL);
|
||||
boot_info.bootstrap_pc = uentry;
|
||||
high = loadaddr + kernel_size;
|
||||
}
|
||||
|
||||
/* Not an ELF image nor an u-boot image, try a RAW image. */
|
||||
if (kernel_size < 0) {
|
||||
kernel_size = load_image_targphys(kernel_filename, ddr_base,
|
||||
ramsize);
|
||||
boot_info.bootstrap_pc = ddr_base;
|
||||
high = ddr_base + kernel_size;
|
||||
}
|
||||
|
||||
high = ROUND_UP(high, 1 * MiB);
|
||||
|
||||
/* If initrd is available, it goes after the kernel, aligned to 1M. */
|
||||
if (initrd_filename) {
|
||||
int initrd_size;
|
||||
uint32_t initrd_offset;
|
||||
|
||||
boot_info.initrd_start = high;
|
||||
initrd_offset = boot_info.initrd_start - ddr_base;
|
||||
|
||||
initrd_size = load_ramdisk(initrd_filename,
|
||||
boot_info.initrd_start,
|
||||
ramsize - initrd_offset);
|
||||
if (initrd_size < 0) {
|
||||
initrd_size = load_image_targphys(initrd_filename,
|
||||
boot_info.initrd_start,
|
||||
ramsize - initrd_offset);
|
||||
}
|
||||
if (initrd_size < 0) {
|
||||
error_report("could not load initrd '%s'",
|
||||
initrd_filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
high += initrd_size;
|
||||
}
|
||||
high = ROUND_UP(high, 4);
|
||||
boot_info.initrd_end = high;
|
||||
|
||||
/* Device tree must be placed right after initrd (if available) */
|
||||
boot_info.fdt = high;
|
||||
fdt_size = nios2_load_dtb(boot_info, ramsize, kernel_cmdline,
|
||||
/* Preference a -dtb argument */
|
||||
dtb_arg ? dtb_arg : filename);
|
||||
high += fdt_size;
|
||||
|
||||
/* Kernel command is at the end, 4k aligned. */
|
||||
boot_info.cmdline = ROUND_UP(high, 4 * KiB);
|
||||
if (kernel_cmdline && strlen(kernel_cmdline)) {
|
||||
pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
|
||||
}
|
||||
}
|
||||
g_free(filename);
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef NIOS2_BOOT_H
|
||||
#define NIOS2_BOOT_H
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base, uint32_t ramsize,
|
||||
const char *initrd_filename, const char *dtb_filename,
|
||||
void (*machine_cpu_reset)(Nios2CPU *));
|
||||
|
||||
#endif /* NIOS2_BOOT_H */
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Generic simulator target with no MMU or devices. This emulation is
|
||||
* compatible with the libgloss qemu-hosted.ld linker script for using
|
||||
* QEMU as an instruction set simulator.
|
||||
*
|
||||
* Copyright (c) 2018-2019 Mentor Graphics
|
||||
*
|
||||
* Copyright (c) 2016 Marek Vasut <marek.vasut@gmail.com>
|
||||
*
|
||||
* Based on LabX device code
|
||||
*
|
||||
* Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
#include "hw/char/serial.h"
|
||||
#include "hw/boards.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qemu/config-file.h"
|
||||
|
||||
#include "boot.h"
|
||||
|
||||
#define BINARY_DEVICE_TREE_FILE "generic-nommu.dtb"
|
||||
|
||||
static void nios2_generic_nommu_init(MachineState *machine)
|
||||
{
|
||||
Nios2CPU *cpu;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
MemoryRegion *phys_tcm = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *phys_tcm_alias = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *phys_ram = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *phys_ram_alias = g_new(MemoryRegion, 1);
|
||||
ram_addr_t tcm_base = 0x0;
|
||||
ram_addr_t tcm_size = 0x1000; /* 1 kiB, but QEMU limit is 4 kiB */
|
||||
ram_addr_t ram_base = 0x10000000;
|
||||
ram_addr_t ram_size = 0x08000000;
|
||||
|
||||
/* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */
|
||||
memory_region_init_ram(phys_tcm, NULL, "nios2.tcm", tcm_size,
|
||||
&error_abort);
|
||||
memory_region_init_alias(phys_tcm_alias, NULL, "nios2.tcm.alias",
|
||||
phys_tcm, 0, tcm_size);
|
||||
memory_region_add_subregion(address_space_mem, tcm_base, phys_tcm);
|
||||
memory_region_add_subregion(address_space_mem, 0xc0000000 + tcm_base,
|
||||
phys_tcm_alias);
|
||||
|
||||
/* Physical DRAM with alias at 0xc0000000 */
|
||||
memory_region_init_ram(phys_ram, NULL, "nios2.ram", ram_size,
|
||||
&error_abort);
|
||||
memory_region_init_alias(phys_ram_alias, NULL, "nios2.ram.alias",
|
||||
phys_ram, 0, ram_size);
|
||||
memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
|
||||
memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base,
|
||||
phys_ram_alias);
|
||||
|
||||
cpu = NIOS2_CPU(cpu_create(TYPE_NIOS2_CPU));
|
||||
|
||||
/* Remove MMU */
|
||||
cpu->mmu_present = false;
|
||||
|
||||
/* Reset vector is the first 32 bytes of RAM. */
|
||||
cpu->reset_addr = ram_base;
|
||||
|
||||
/* The interrupt vector comes right after reset. */
|
||||
cpu->exception_addr = ram_base + 0x20;
|
||||
|
||||
/*
|
||||
* The linker script does have a TLB miss memory region declared,
|
||||
* but this should never be used with no MMU.
|
||||
*/
|
||||
cpu->fast_tlb_miss_addr = 0x7fff400;
|
||||
|
||||
nios2_load_kernel(cpu, ram_base, ram_size, machine->initrd_filename,
|
||||
BINARY_DEVICE_TREE_FILE, NULL);
|
||||
}
|
||||
|
||||
static void nios2_generic_nommu_machine_init(struct MachineClass *mc)
|
||||
{
|
||||
mc->desc = "Generic NOMMU Nios II design";
|
||||
mc->init = nios2_generic_nommu_init;
|
||||
mc->deprecation_reason = "Nios II architecture is deprecated";
|
||||
}
|
||||
|
||||
DEFINE_MACHINE("nios2-generic-nommu", nios2_generic_nommu_machine_init);
|
|
@ -1,6 +0,0 @@
|
|||
nios2_ss = ss.source_set()
|
||||
nios2_ss.add(files('boot.c'), fdt)
|
||||
nios2_ss.add(when: 'CONFIG_NIOS2_10M50', if_true: files('10m50_devboard.c'))
|
||||
nios2_ss.add(when: 'CONFIG_NIOS2_GENERIC_NOMMU', if_true: files('generic_nommu.c'))
|
||||
|
||||
hw_arch += {'nios2': nios2_ss}
|
|
@ -241,10 +241,6 @@ enum bfd_architecture
|
|||
bfd_arch_ia64, /* HP/Intel ia64 */
|
||||
#define bfd_mach_ia64_elf64 64
|
||||
#define bfd_mach_ia64_elf32 32
|
||||
bfd_arch_nios2, /* Nios II */
|
||||
#define bfd_mach_nios2 0
|
||||
#define bfd_mach_nios2r1 1
|
||||
#define bfd_mach_nios2r2 2
|
||||
bfd_arch_rx, /* Renesas RX */
|
||||
#define bfd_mach_rx 0x75
|
||||
#define bfd_mach_rx_v2 0x76
|
||||
|
@ -456,7 +452,6 @@ int print_insn_crisv32 (bfd_vma, disassemble_info*);
|
|||
int print_insn_crisv10 (bfd_vma, disassemble_info*);
|
||||
int print_insn_microblaze (bfd_vma, disassemble_info*);
|
||||
int print_insn_ia64 (bfd_vma, disassemble_info*);
|
||||
int print_insn_nios2(bfd_vma, disassemble_info*);
|
||||
int print_insn_xtensa (bfd_vma, disassemble_info*);
|
||||
int print_insn_riscv32 (bfd_vma, disassemble_info*);
|
||||
int print_insn_riscv64 (bfd_vma, disassemble_info*);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#pragma GCC poison TARGET_ABI_MIPSO32
|
||||
#pragma GCC poison TARGET_MIPS64
|
||||
#pragma GCC poison TARGET_ABI_MIPSN64
|
||||
#pragma GCC poison TARGET_NIOS2
|
||||
#pragma GCC poison TARGET_OPENRISC
|
||||
#pragma GCC poison TARGET_PPC
|
||||
#pragma GCC poison TARGET_PPC64
|
||||
|
@ -73,7 +72,6 @@
|
|||
#pragma GCC poison CONFIG_M68K_DIS
|
||||
#pragma GCC poison CONFIG_MICROBLAZE_DIS
|
||||
#pragma GCC poison CONFIG_MIPS_DIS
|
||||
#pragma GCC poison CONFIG_NIOS2_DIS
|
||||
#pragma GCC poison CONFIG_PPC_DIS
|
||||
#pragma GCC poison CONFIG_RISCV_DIS
|
||||
#pragma GCC poison CONFIG_S390_DIS
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
#if (defined(TARGET_I386) && !defined(TARGET_X86_64)) \
|
||||
|| defined(TARGET_SH4) \
|
||||
|| defined(TARGET_OPENRISC) \
|
||||
|| defined(TARGET_MICROBLAZE) \
|
||||
|| defined(TARGET_NIOS2)
|
||||
|| defined(TARGET_MICROBLAZE)
|
||||
#define ABI_LLONG_ALIGNMENT 4
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Vectored Interrupt Controller for nios2 processor
|
||||
*
|
||||
* Copyright (c) 2022 Neuroblade
|
||||
*
|
||||
* Interface:
|
||||
* QOM property "cpu": link to the Nios2 CPU (must be set)
|
||||
* Unnamed GPIO inputs 0..NIOS2_VIC_MAX_IRQ-1: input IRQ lines
|
||||
* IRQ should be connected to nios2 IRQ0.
|
||||
*
|
||||
* Reference: "Embedded Peripherals IP User Guide
|
||||
* for Intel® Quartus® Prime Design Suite: 21.4"
|
||||
* Chapter 38 "Vectored Interrupt Controller Core"
|
||||
* See: https://www.intel.com/content/www/us/en/docs/programmable/683130/21-4/vectored-interrupt-controller-core.html
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef HW_INTC_NIOS2_VIC_H
|
||||
#define HW_INTC_NIOS2_VIC_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_NIOS2_VIC "nios2-vic"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(Nios2VIC, NIOS2_VIC)
|
||||
|
||||
#define NIOS2_VIC_MAX_IRQ 32
|
||||
|
||||
struct Nios2VIC {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
qemu_irq output_int;
|
||||
|
||||
/* properties */
|
||||
CPUState *cpu;
|
||||
MemoryRegion csr;
|
||||
|
||||
uint32_t int_config[NIOS2_VIC_MAX_IRQ];
|
||||
uint32_t vic_config;
|
||||
uint32_t int_raw_status;
|
||||
uint32_t int_enable;
|
||||
uint32_t sw_int;
|
||||
uint32_t vic_status;
|
||||
uint32_t vec_tbl_base;
|
||||
uint32_t vec_tbl_addr;
|
||||
};
|
||||
|
||||
#endif /* HW_INTC_NIOS2_VIC_H */
|
|
@ -18,7 +18,6 @@ enum {
|
|||
QEMU_ARCH_XTENSA = (1 << 12),
|
||||
QEMU_ARCH_OPENRISC = (1 << 13),
|
||||
QEMU_ARCH_TRICORE = (1 << 16),
|
||||
QEMU_ARCH_NIOS2 = (1 << 17),
|
||||
QEMU_ARCH_HPPA = (1 << 18),
|
||||
QEMU_ARCH_RISCV = (1 << 19),
|
||||
QEMU_ARCH_RX = (1 << 20),
|
||||
|
|
|
@ -1505,105 +1505,6 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env
|
|||
|
||||
#endif /* TARGET_MICROBLAZE */
|
||||
|
||||
#ifdef TARGET_NIOS2
|
||||
|
||||
#define elf_check_arch(x) ((x) == EM_ALTERA_NIOS2)
|
||||
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ELF_ARCH EM_ALTERA_NIOS2
|
||||
|
||||
static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
|
||||
{
|
||||
regs->ea = infop->entry;
|
||||
regs->sp = infop->start_stack;
|
||||
}
|
||||
|
||||
#define LO_COMMPAGE TARGET_PAGE_SIZE
|
||||
|
||||
static bool init_guest_commpage(void)
|
||||
{
|
||||
static const uint8_t kuser_page[4 + 2 * 64] = {
|
||||
/* __kuser_helper_version */
|
||||
[0x00] = 0x02, 0x00, 0x00, 0x00,
|
||||
|
||||
/* __kuser_cmpxchg */
|
||||
[0x04] = 0x3a, 0x6c, 0x3b, 0x00, /* trap 16 */
|
||||
0x3a, 0x28, 0x00, 0xf8, /* ret */
|
||||
|
||||
/* __kuser_sigtramp */
|
||||
[0x44] = 0xc4, 0x22, 0x80, 0x00, /* movi r2, __NR_rt_sigreturn */
|
||||
0x3a, 0x68, 0x3b, 0x00, /* trap 0 */
|
||||
};
|
||||
|
||||
int host_page_size = qemu_real_host_page_size();
|
||||
void *want, *addr;
|
||||
|
||||
want = g2h_untagged(LO_COMMPAGE & -host_page_size);
|
||||
addr = mmap(want, host_page_size, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE |
|
||||
(reserved_va ? MAP_FIXED : MAP_FIXED_NOREPLACE),
|
||||
-1, 0);
|
||||
if (addr == MAP_FAILED) {
|
||||
perror("Allocating guest commpage");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (addr != want) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(g2h_untagged(LO_COMMPAGE), kuser_page, sizeof(kuser_page));
|
||||
|
||||
if (mprotect(addr, host_page_size, PROT_READ)) {
|
||||
perror("Protecting guest commpage");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK,
|
||||
PAGE_READ | PAGE_EXEC | PAGE_VALID);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ELF_EXEC_PAGESIZE 4096
|
||||
|
||||
#define USE_ELF_CORE_DUMP
|
||||
#define ELF_NREG 49
|
||||
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
|
||||
|
||||
/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
|
||||
static void elf_core_copy_regs(target_elf_gregset_t *regs,
|
||||
const CPUNios2State *env)
|
||||
{
|
||||
int i;
|
||||
|
||||
(*regs)[0] = -1;
|
||||
for (i = 1; i < 8; i++) /* r0-r7 */
|
||||
(*regs)[i] = tswapreg(env->regs[i + 7]);
|
||||
|
||||
for (i = 8; i < 16; i++) /* r8-r15 */
|
||||
(*regs)[i] = tswapreg(env->regs[i - 8]);
|
||||
|
||||
for (i = 16; i < 24; i++) /* r16-r23 */
|
||||
(*regs)[i] = tswapreg(env->regs[i + 7]);
|
||||
(*regs)[24] = -1; /* R_ET */
|
||||
(*regs)[25] = -1; /* R_BT */
|
||||
(*regs)[26] = tswapreg(env->regs[R_GP]);
|
||||
(*regs)[27] = tswapreg(env->regs[R_SP]);
|
||||
(*regs)[28] = tswapreg(env->regs[R_FP]);
|
||||
(*regs)[29] = tswapreg(env->regs[R_EA]);
|
||||
(*regs)[30] = -1; /* R_SSTATUS */
|
||||
(*regs)[31] = tswapreg(env->regs[R_RA]);
|
||||
|
||||
(*regs)[32] = tswapreg(env->pc);
|
||||
|
||||
(*regs)[33] = -1; /* R_STATUS */
|
||||
(*regs)[34] = tswapreg(env->regs[CR_ESTATUS]);
|
||||
|
||||
for (i = 35; i < 49; i++) /* ... */
|
||||
(*regs)[i] = -1;
|
||||
}
|
||||
|
||||
#endif /* TARGET_NIOS2 */
|
||||
|
||||
#ifdef TARGET_OPENRISC
|
||||
|
||||
#define ELF_ARCH EM_OPENRISC
|
||||
|
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
* qemu user cpu loop
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "user-internals.h"
|
||||
#include "cpu_loop-common.h"
|
||||
#include "signal-common.h"
|
||||
|
||||
void cpu_loop(CPUNios2State *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr, ret;
|
||||
|
||||
for (;;) {
|
||||
cpu_exec_start(cs);
|
||||
trapnr = cpu_exec(cs);
|
||||
cpu_exec_end(cs);
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
switch (trapnr) {
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
break;
|
||||
|
||||
case EXCP_DIV:
|
||||
/* Match kernel's handle_diverror_c(). */
|
||||
env->pc -= 4;
|
||||
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc);
|
||||
break;
|
||||
|
||||
case EXCP_UNALIGN:
|
||||
case EXCP_UNALIGND:
|
||||
force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN,
|
||||
env->ctrl[CR_BADADDR]);
|
||||
break;
|
||||
|
||||
case EXCP_ILLEGAL:
|
||||
case EXCP_UNIMPL:
|
||||
/* Match kernel's handle_illegal_c(). */
|
||||
env->pc -= 4;
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
|
||||
break;
|
||||
case EXCP_SUPERI:
|
||||
/* Match kernel's handle_supervisor_instr(). */
|
||||
env->pc -= 4;
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc);
|
||||
break;
|
||||
|
||||
case EXCP_TRAP:
|
||||
switch (env->error_code) {
|
||||
case 0:
|
||||
qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
|
||||
|
||||
ret = do_syscall(env, env->regs[2],
|
||||
env->regs[4], env->regs[5], env->regs[6],
|
||||
env->regs[7], env->regs[8], env->regs[9],
|
||||
0, 0);
|
||||
|
||||
if (ret == -QEMU_ESIGRETURN) {
|
||||
/* rt_sigreturn has set all state. */
|
||||
break;
|
||||
}
|
||||
if (ret == -QEMU_ERESTARTSYS) {
|
||||
env->pc -= 4;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* See the code after translate_rc_and_ret: all negative
|
||||
* values are errors (aided by userspace restricted to 2G),
|
||||
* errno is returned positive in r2, and error indication
|
||||
* is a boolean in r7.
|
||||
*/
|
||||
env->regs[2] = abs(ret);
|
||||
env->regs[7] = ret < 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n");
|
||||
force_sig_fault(TARGET_SIGUSR1, 0, env->pc);
|
||||
break;
|
||||
case 2:
|
||||
qemu_log_mask(CPU_LOG_INT, "\nTrap 2\n");
|
||||
force_sig_fault(TARGET_SIGUSR2, 0, env->pc);
|
||||
break;
|
||||
case 31:
|
||||
qemu_log_mask(CPU_LOG_INT, "\nTrap 31\n");
|
||||
/* Match kernel's breakpoint_c(). */
|
||||
env->pc -= 4;
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(CPU_LOG_INT, "\nTrap %d\n", env->error_code);
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP, env->pc);
|
||||
break;
|
||||
|
||||
case 16: /* QEMU specific, for __kuser_cmpxchg */
|
||||
{
|
||||
abi_ptr g = env->regs[4];
|
||||
uint32_t *h, n, o;
|
||||
|
||||
if (g & 0x3) {
|
||||
force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, g);
|
||||
break;
|
||||
}
|
||||
ret = page_get_flags(g);
|
||||
if (!(ret & PAGE_VALID)) {
|
||||
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, g);
|
||||
break;
|
||||
}
|
||||
if (!(ret & PAGE_READ) || !(ret & PAGE_WRITE)) {
|
||||
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_ACCERR, g);
|
||||
break;
|
||||
}
|
||||
h = g2h(cs, g);
|
||||
o = env->regs[5];
|
||||
n = env->regs[6];
|
||||
env->regs[2] = qatomic_cmpxchg(h, o, n) - o;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCP_DEBUG:
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
|
||||
break;
|
||||
default:
|
||||
EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
|
||||
trapnr);
|
||||
abort();
|
||||
}
|
||||
|
||||
process_pending_signals(env);
|
||||
}
|
||||
}
|
||||
|
||||
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
||||
{
|
||||
env->regs[R_SP] = regs->sp;
|
||||
env->pc = regs->ea;
|
||||
}
|
|
@ -1,210 +0,0 @@
|
|||
/*
|
||||
* Emulation of Linux signals
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "user-internals.h"
|
||||
#include "signal-common.h"
|
||||
#include "linux-user/trace.h"
|
||||
|
||||
#define MCONTEXT_VERSION 2
|
||||
|
||||
struct target_sigcontext {
|
||||
int version;
|
||||
unsigned long gregs[32];
|
||||
};
|
||||
|
||||
struct target_ucontext {
|
||||
abi_ulong tuc_flags;
|
||||
abi_ulong tuc_link;
|
||||
target_stack_t tuc_stack;
|
||||
struct target_sigcontext tuc_mcontext;
|
||||
target_sigset_t tuc_sigmask; /* mask last for extensibility */
|
||||
};
|
||||
|
||||
struct target_rt_sigframe {
|
||||
struct target_siginfo info;
|
||||
struct target_ucontext uc;
|
||||
};
|
||||
|
||||
static void rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
|
||||
{
|
||||
unsigned long *gregs = uc->tuc_mcontext.gregs;
|
||||
|
||||
__put_user(MCONTEXT_VERSION, &uc->tuc_mcontext.version);
|
||||
__put_user(env->regs[1], &gregs[0]);
|
||||
__put_user(env->regs[2], &gregs[1]);
|
||||
__put_user(env->regs[3], &gregs[2]);
|
||||
__put_user(env->regs[4], &gregs[3]);
|
||||
__put_user(env->regs[5], &gregs[4]);
|
||||
__put_user(env->regs[6], &gregs[5]);
|
||||
__put_user(env->regs[7], &gregs[6]);
|
||||
__put_user(env->regs[8], &gregs[7]);
|
||||
__put_user(env->regs[9], &gregs[8]);
|
||||
__put_user(env->regs[10], &gregs[9]);
|
||||
__put_user(env->regs[11], &gregs[10]);
|
||||
__put_user(env->regs[12], &gregs[11]);
|
||||
__put_user(env->regs[13], &gregs[12]);
|
||||
__put_user(env->regs[14], &gregs[13]);
|
||||
__put_user(env->regs[15], &gregs[14]);
|
||||
__put_user(env->regs[16], &gregs[15]);
|
||||
__put_user(env->regs[17], &gregs[16]);
|
||||
__put_user(env->regs[18], &gregs[17]);
|
||||
__put_user(env->regs[19], &gregs[18]);
|
||||
__put_user(env->regs[20], &gregs[19]);
|
||||
__put_user(env->regs[21], &gregs[20]);
|
||||
__put_user(env->regs[22], &gregs[21]);
|
||||
__put_user(env->regs[23], &gregs[22]);
|
||||
__put_user(env->regs[R_RA], &gregs[23]);
|
||||
__put_user(env->regs[R_FP], &gregs[24]);
|
||||
__put_user(env->regs[R_GP], &gregs[25]);
|
||||
__put_user(env->pc, &gregs[27]);
|
||||
__put_user(env->regs[R_SP], &gregs[28]);
|
||||
}
|
||||
|
||||
static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc)
|
||||
{
|
||||
int temp;
|
||||
unsigned long *gregs = uc->tuc_mcontext.gregs;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
/* current->restart_block.fn = do_no_restart_syscall; */
|
||||
|
||||
__get_user(temp, &uc->tuc_mcontext.version);
|
||||
if (temp != MCONTEXT_VERSION) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* restore passed registers */
|
||||
__get_user(env->regs[1], &gregs[0]);
|
||||
__get_user(env->regs[2], &gregs[1]);
|
||||
__get_user(env->regs[3], &gregs[2]);
|
||||
__get_user(env->regs[4], &gregs[3]);
|
||||
__get_user(env->regs[5], &gregs[4]);
|
||||
__get_user(env->regs[6], &gregs[5]);
|
||||
__get_user(env->regs[7], &gregs[6]);
|
||||
__get_user(env->regs[8], &gregs[7]);
|
||||
__get_user(env->regs[9], &gregs[8]);
|
||||
__get_user(env->regs[10], &gregs[9]);
|
||||
__get_user(env->regs[11], &gregs[10]);
|
||||
__get_user(env->regs[12], &gregs[11]);
|
||||
__get_user(env->regs[13], &gregs[12]);
|
||||
__get_user(env->regs[14], &gregs[13]);
|
||||
__get_user(env->regs[15], &gregs[14]);
|
||||
__get_user(env->regs[16], &gregs[15]);
|
||||
__get_user(env->regs[17], &gregs[16]);
|
||||
__get_user(env->regs[18], &gregs[17]);
|
||||
__get_user(env->regs[19], &gregs[18]);
|
||||
__get_user(env->regs[20], &gregs[19]);
|
||||
__get_user(env->regs[21], &gregs[20]);
|
||||
__get_user(env->regs[22], &gregs[21]);
|
||||
__get_user(env->regs[23], &gregs[22]);
|
||||
/* gregs[23] is handled below */
|
||||
/* Verify, should this be settable */
|
||||
__get_user(env->regs[R_FP], &gregs[24]);
|
||||
/* Verify, should this be settable */
|
||||
__get_user(env->regs[R_GP], &gregs[25]);
|
||||
/* Not really necessary no user settable bits */
|
||||
__get_user(temp, &gregs[26]);
|
||||
__get_user(env->pc, &gregs[27]);
|
||||
|
||||
__get_user(env->regs[R_RA], &gregs[23]);
|
||||
__get_user(env->regs[R_SP], &gregs[28]);
|
||||
|
||||
target_restore_altstack(&uc->tuc_stack, env);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static abi_ptr get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long usp;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
usp = target_sigsp(get_sp_from_cpustate(env), ka);
|
||||
|
||||
/* Verify, is it 32 or 64 bit aligned */
|
||||
return (usp - frame_size) & -8;
|
||||
}
|
||||
|
||||
void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
target_siginfo_t *info,
|
||||
target_sigset_t *set,
|
||||
CPUNios2State *env)
|
||||
{
|
||||
struct target_rt_sigframe *frame;
|
||||
abi_ptr frame_addr;
|
||||
int i;
|
||||
|
||||
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
|
||||
force_sigsegv(sig);
|
||||
return;
|
||||
}
|
||||
|
||||
frame->info = *info;
|
||||
|
||||
/* Create the ucontext. */
|
||||
__put_user(0, &frame->uc.tuc_flags);
|
||||
__put_user(0, &frame->uc.tuc_link);
|
||||
target_save_altstack(&frame->uc.tuc_stack, env);
|
||||
rt_setup_ucontext(&frame->uc, env);
|
||||
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
|
||||
}
|
||||
|
||||
/* Set up to return from userspace; jump to fixed address sigreturn
|
||||
trampoline on kuser page. */
|
||||
env->regs[R_RA] = (unsigned long) (0x1044);
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
env->regs[R_SP] = frame_addr;
|
||||
env->regs[4] = sig;
|
||||
env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info);
|
||||
env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc);
|
||||
env->pc = ka->_sa_handler;
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUNios2State *env)
|
||||
{
|
||||
/* Verify, can we follow the stack back */
|
||||
abi_ulong frame_addr = env->regs[R_SP];
|
||||
struct target_rt_sigframe *frame;
|
||||
sigset_t set;
|
||||
|
||||
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
|
||||
goto badframe;
|
||||
}
|
||||
|
||||
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
|
||||
set_sigmask(&set);
|
||||
|
||||
if (rt_restore_ucontext(env, &frame->uc)) {
|
||||
goto badframe;
|
||||
}
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return -QEMU_ESIGRETURN;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
#include "../generic/sockbits.h"
|
|
@ -1,333 +0,0 @@
|
|||
/*
|
||||
* This file contains the system call numbers.
|
||||
* Do not modify.
|
||||
* This file is generated by scripts/gensyscalls.sh
|
||||
*/
|
||||
#ifndef LINUX_USER_NIOS2_SYSCALL_NR_H
|
||||
#define LINUX_USER_NIOS2_SYSCALL_NR_H
|
||||
|
||||
#define TARGET_NR_cacheflush (TARGET_NR_arch_specific_syscall)
|
||||
#define TARGET_NR_io_setup 0
|
||||
#define TARGET_NR_io_destroy 1
|
||||
#define TARGET_NR_io_submit 2
|
||||
#define TARGET_NR_io_cancel 3
|
||||
#define TARGET_NR_io_getevents 4
|
||||
#define TARGET_NR_setxattr 5
|
||||
#define TARGET_NR_lsetxattr 6
|
||||
#define TARGET_NR_fsetxattr 7
|
||||
#define TARGET_NR_getxattr 8
|
||||
#define TARGET_NR_lgetxattr 9
|
||||
#define TARGET_NR_fgetxattr 10
|
||||
#define TARGET_NR_listxattr 11
|
||||
#define TARGET_NR_llistxattr 12
|
||||
#define TARGET_NR_flistxattr 13
|
||||
#define TARGET_NR_removexattr 14
|
||||
#define TARGET_NR_lremovexattr 15
|
||||
#define TARGET_NR_fremovexattr 16
|
||||
#define TARGET_NR_getcwd 17
|
||||
#define TARGET_NR_lookup_dcookie 18
|
||||
#define TARGET_NR_eventfd2 19
|
||||
#define TARGET_NR_epoll_create1 20
|
||||
#define TARGET_NR_epoll_ctl 21
|
||||
#define TARGET_NR_epoll_pwait 22
|
||||
#define TARGET_NR_dup 23
|
||||
#define TARGET_NR_dup3 24
|
||||
#define TARGET_NR_fcntl64 25
|
||||
#define TARGET_NR_inotify_init1 26
|
||||
#define TARGET_NR_inotify_add_watch 27
|
||||
#define TARGET_NR_inotify_rm_watch 28
|
||||
#define TARGET_NR_ioctl 29
|
||||
#define TARGET_NR_ioprio_set 30
|
||||
#define TARGET_NR_ioprio_get 31
|
||||
#define TARGET_NR_flock 32
|
||||
#define TARGET_NR_mknodat 33
|
||||
#define TARGET_NR_mkdirat 34
|
||||
#define TARGET_NR_unlinkat 35
|
||||
#define TARGET_NR_symlinkat 36
|
||||
#define TARGET_NR_linkat 37
|
||||
#define TARGET_NR_renameat 38
|
||||
#define TARGET_NR_umount2 39
|
||||
#define TARGET_NR_mount 40
|
||||
#define TARGET_NR_pivot_root 41
|
||||
#define TARGET_NR_nfsservctl 42
|
||||
#define TARGET_NR_statfs64 43
|
||||
#define TARGET_NR_fstatfs64 44
|
||||
#define TARGET_NR_truncate64 45
|
||||
#define TARGET_NR_ftruncate64 46
|
||||
#define TARGET_NR_fallocate 47
|
||||
#define TARGET_NR_faccessat 48
|
||||
#define TARGET_NR_chdir 49
|
||||
#define TARGET_NR_fchdir 50
|
||||
#define TARGET_NR_chroot 51
|
||||
#define TARGET_NR_fchmod 52
|
||||
#define TARGET_NR_fchmodat 53
|
||||
#define TARGET_NR_fchownat 54
|
||||
#define TARGET_NR_fchown 55
|
||||
#define TARGET_NR_openat 56
|
||||
#define TARGET_NR_close 57
|
||||
#define TARGET_NR_vhangup 58
|
||||
#define TARGET_NR_pipe2 59
|
||||
#define TARGET_NR_quotactl 60
|
||||
#define TARGET_NR_getdents64 61
|
||||
#define TARGET_NR_llseek 62
|
||||
#define TARGET_NR_read 63
|
||||
#define TARGET_NR_write 64
|
||||
#define TARGET_NR_readv 65
|
||||
#define TARGET_NR_writev 66
|
||||
#define TARGET_NR_pread64 67
|
||||
#define TARGET_NR_pwrite64 68
|
||||
#define TARGET_NR_preadv 69
|
||||
#define TARGET_NR_pwritev 70
|
||||
#define TARGET_NR_sendfile64 71
|
||||
#define TARGET_NR_pselect6 72
|
||||
#define TARGET_NR_ppoll 73
|
||||
#define TARGET_NR_signalfd4 74
|
||||
#define TARGET_NR_vmsplice 75
|
||||
#define TARGET_NR_splice 76
|
||||
#define TARGET_NR_tee 77
|
||||
#define TARGET_NR_readlinkat 78
|
||||
#define TARGET_NR_fstatat64 79
|
||||
#define TARGET_NR_fstat64 80
|
||||
#define TARGET_NR_sync 81
|
||||
#define TARGET_NR_fsync 82
|
||||
#define TARGET_NR_fdatasync 83
|
||||
#define TARGET_NR_sync_file_range 84
|
||||
#define TARGET_NR_timerfd_create 85
|
||||
#define TARGET_NR_timerfd_settime 86
|
||||
#define TARGET_NR_timerfd_gettime 87
|
||||
#define TARGET_NR_utimensat 88
|
||||
#define TARGET_NR_acct 89
|
||||
#define TARGET_NR_capget 90
|
||||
#define TARGET_NR_capset 91
|
||||
#define TARGET_NR_personality 92
|
||||
#define TARGET_NR_exit 93
|
||||
#define TARGET_NR_exit_group 94
|
||||
#define TARGET_NR_waitid 95
|
||||
#define TARGET_NR_set_tid_address 96
|
||||
#define TARGET_NR_unshare 97
|
||||
#define TARGET_NR_futex 98
|
||||
#define TARGET_NR_set_robust_list 99
|
||||
#define TARGET_NR_get_robust_list 100
|
||||
#define TARGET_NR_nanosleep 101
|
||||
#define TARGET_NR_getitimer 102
|
||||
#define TARGET_NR_setitimer 103
|
||||
#define TARGET_NR_kexec_load 104
|
||||
#define TARGET_NR_init_module 105
|
||||
#define TARGET_NR_delete_module 106
|
||||
#define TARGET_NR_timer_create 107
|
||||
#define TARGET_NR_timer_gettime 108
|
||||
#define TARGET_NR_timer_getoverrun 109
|
||||
#define TARGET_NR_timer_settime 110
|
||||
#define TARGET_NR_timer_delete 111
|
||||
#define TARGET_NR_clock_settime 112
|
||||
#define TARGET_NR_clock_gettime 113
|
||||
#define TARGET_NR_clock_getres 114
|
||||
#define TARGET_NR_clock_nanosleep 115
|
||||
#define TARGET_NR_syslog 116
|
||||
#define TARGET_NR_ptrace 117
|
||||
#define TARGET_NR_sched_setparam 118
|
||||
#define TARGET_NR_sched_setscheduler 119
|
||||
#define TARGET_NR_sched_getscheduler 120
|
||||
#define TARGET_NR_sched_getparam 121
|
||||
#define TARGET_NR_sched_setaffinity 122
|
||||
#define TARGET_NR_sched_getaffinity 123
|
||||
#define TARGET_NR_sched_yield 124
|
||||
#define TARGET_NR_sched_get_priority_max 125
|
||||
#define TARGET_NR_sched_get_priority_min 126
|
||||
#define TARGET_NR_sched_rr_get_interval 127
|
||||
#define TARGET_NR_restart_syscall 128
|
||||
#define TARGET_NR_kill 129
|
||||
#define TARGET_NR_tkill 130
|
||||
#define TARGET_NR_tgkill 131
|
||||
#define TARGET_NR_sigaltstack 132
|
||||
#define TARGET_NR_rt_sigsuspend 133
|
||||
#define TARGET_NR_rt_sigaction 134
|
||||
#define TARGET_NR_rt_sigprocmask 135
|
||||
#define TARGET_NR_rt_sigpending 136
|
||||
#define TARGET_NR_rt_sigtimedwait 137
|
||||
#define TARGET_NR_rt_sigqueueinfo 138
|
||||
#define TARGET_NR_rt_sigreturn 139
|
||||
#define TARGET_NR_setpriority 140
|
||||
#define TARGET_NR_getpriority 141
|
||||
#define TARGET_NR_reboot 142
|
||||
#define TARGET_NR_setregid 143
|
||||
#define TARGET_NR_setgid 144
|
||||
#define TARGET_NR_setreuid 145
|
||||
#define TARGET_NR_setuid 146
|
||||
#define TARGET_NR_setresuid 147
|
||||
#define TARGET_NR_getresuid 148
|
||||
#define TARGET_NR_setresgid 149
|
||||
#define TARGET_NR_getresgid 150
|
||||
#define TARGET_NR_setfsuid 151
|
||||
#define TARGET_NR_setfsgid 152
|
||||
#define TARGET_NR_times 153
|
||||
#define TARGET_NR_setpgid 154
|
||||
#define TARGET_NR_getpgid 155
|
||||
#define TARGET_NR_getsid 156
|
||||
#define TARGET_NR_setsid 157
|
||||
#define TARGET_NR_getgroups 158
|
||||
#define TARGET_NR_setgroups 159
|
||||
#define TARGET_NR_uname 160
|
||||
#define TARGET_NR_sethostname 161
|
||||
#define TARGET_NR_setdomainname 162
|
||||
#define TARGET_NR_getrlimit 163
|
||||
#define TARGET_NR_setrlimit 164
|
||||
#define TARGET_NR_getrusage 165
|
||||
#define TARGET_NR_umask 166
|
||||
#define TARGET_NR_prctl 167
|
||||
#define TARGET_NR_getcpu 168
|
||||
#define TARGET_NR_gettimeofday 169
|
||||
#define TARGET_NR_settimeofday 170
|
||||
#define TARGET_NR_adjtimex 171
|
||||
#define TARGET_NR_getpid 172
|
||||
#define TARGET_NR_getppid 173
|
||||
#define TARGET_NR_getuid 174
|
||||
#define TARGET_NR_geteuid 175
|
||||
#define TARGET_NR_getgid 176
|
||||
#define TARGET_NR_getegid 177
|
||||
#define TARGET_NR_gettid 178
|
||||
#define TARGET_NR_sysinfo 179
|
||||
#define TARGET_NR_mq_open 180
|
||||
#define TARGET_NR_mq_unlink 181
|
||||
#define TARGET_NR_mq_timedsend 182
|
||||
#define TARGET_NR_mq_timedreceive 183
|
||||
#define TARGET_NR_mq_notify 184
|
||||
#define TARGET_NR_mq_getsetattr 185
|
||||
#define TARGET_NR_msgget 186
|
||||
#define TARGET_NR_msgctl 187
|
||||
#define TARGET_NR_msgrcv 188
|
||||
#define TARGET_NR_msgsnd 189
|
||||
#define TARGET_NR_semget 190
|
||||
#define TARGET_NR_semctl 191
|
||||
#define TARGET_NR_semtimedop 192
|
||||
#define TARGET_NR_semop 193
|
||||
#define TARGET_NR_shmget 194
|
||||
#define TARGET_NR_shmctl 195
|
||||
#define TARGET_NR_shmat 196
|
||||
#define TARGET_NR_shmdt 197
|
||||
#define TARGET_NR_socket 198
|
||||
#define TARGET_NR_socketpair 199
|
||||
#define TARGET_NR_bind 200
|
||||
#define TARGET_NR_listen 201
|
||||
#define TARGET_NR_accept 202
|
||||
#define TARGET_NR_connect 203
|
||||
#define TARGET_NR_getsockname 204
|
||||
#define TARGET_NR_getpeername 205
|
||||
#define TARGET_NR_sendto 206
|
||||
#define TARGET_NR_recvfrom 207
|
||||
#define TARGET_NR_setsockopt 208
|
||||
#define TARGET_NR_getsockopt 209
|
||||
#define TARGET_NR_shutdown 210
|
||||
#define TARGET_NR_sendmsg 211
|
||||
#define TARGET_NR_recvmsg 212
|
||||
#define TARGET_NR_readahead 213
|
||||
#define TARGET_NR_brk 214
|
||||
#define TARGET_NR_munmap 215
|
||||
#define TARGET_NR_mremap 216
|
||||
#define TARGET_NR_add_key 217
|
||||
#define TARGET_NR_request_key 218
|
||||
#define TARGET_NR_keyctl 219
|
||||
#define TARGET_NR_clone 220
|
||||
#define TARGET_NR_execve 221
|
||||
#define TARGET_NR_mmap2 222
|
||||
#define TARGET_NR_fadvise64_64 223
|
||||
#define TARGET_NR_swapon 224
|
||||
#define TARGET_NR_swapoff 225
|
||||
#define TARGET_NR_mprotect 226
|
||||
#define TARGET_NR_msync 227
|
||||
#define TARGET_NR_mlock 228
|
||||
#define TARGET_NR_munlock 229
|
||||
#define TARGET_NR_mlockall 230
|
||||
#define TARGET_NR_munlockall 231
|
||||
#define TARGET_NR_mincore 232
|
||||
#define TARGET_NR_madvise 233
|
||||
#define TARGET_NR_remap_file_pages 234
|
||||
#define TARGET_NR_mbind 235
|
||||
#define TARGET_NR_get_mempolicy 236
|
||||
#define TARGET_NR_set_mempolicy 237
|
||||
#define TARGET_NR_migrate_pages 238
|
||||
#define TARGET_NR_move_pages 239
|
||||
#define TARGET_NR_rt_tgsigqueueinfo 240
|
||||
#define TARGET_NR_perf_event_open 241
|
||||
#define TARGET_NR_accept4 242
|
||||
#define TARGET_NR_recvmmsg 243
|
||||
#define TARGET_NR_arch_specific_syscall 244
|
||||
#define TARGET_NR_wait4 260
|
||||
#define TARGET_NR_prlimit64 261
|
||||
#define TARGET_NR_fanotify_init 262
|
||||
#define TARGET_NR_fanotify_mark 263
|
||||
#define TARGET_NR_name_to_handle_at 264
|
||||
#define TARGET_NR_open_by_handle_at 265
|
||||
#define TARGET_NR_clock_adjtime 266
|
||||
#define TARGET_NR_syncfs 267
|
||||
#define TARGET_NR_setns 268
|
||||
#define TARGET_NR_sendmmsg 269
|
||||
#define TARGET_NR_process_vm_readv 270
|
||||
#define TARGET_NR_process_vm_writev 271
|
||||
#define TARGET_NR_kcmp 272
|
||||
#define TARGET_NR_finit_module 273
|
||||
#define TARGET_NR_sched_setattr 274
|
||||
#define TARGET_NR_sched_getattr 275
|
||||
#define TARGET_NR_renameat2 276
|
||||
#define TARGET_NR_seccomp 277
|
||||
#define TARGET_NR_getrandom 278
|
||||
#define TARGET_NR_memfd_create 279
|
||||
#define TARGET_NR_bpf 280
|
||||
#define TARGET_NR_execveat 281
|
||||
#define TARGET_NR_userfaultfd 282
|
||||
#define TARGET_NR_membarrier 283
|
||||
#define TARGET_NR_mlock2 284
|
||||
#define TARGET_NR_copy_file_range 285
|
||||
#define TARGET_NR_preadv2 286
|
||||
#define TARGET_NR_pwritev2 287
|
||||
#define TARGET_NR_pkey_mprotect 288
|
||||
#define TARGET_NR_pkey_alloc 289
|
||||
#define TARGET_NR_pkey_free 290
|
||||
#define TARGET_NR_statx 291
|
||||
#define TARGET_NR_io_pgetevents 292
|
||||
#define TARGET_NR_rseq 293
|
||||
#define TARGET_NR_kexec_file_load 294
|
||||
#define TARGET_NR_clock_gettime64 403
|
||||
#define TARGET_NR_clock_settime64 404
|
||||
#define TARGET_NR_clock_adjtime64 405
|
||||
#define TARGET_NR_clock_getres_time64 406
|
||||
#define TARGET_NR_clock_nanosleep_time64 407
|
||||
#define TARGET_NR_timer_gettime64 408
|
||||
#define TARGET_NR_timer_settime64 409
|
||||
#define TARGET_NR_timerfd_gettime64 410
|
||||
#define TARGET_NR_timerfd_settime64 411
|
||||
#define TARGET_NR_utimensat_time64 412
|
||||
#define TARGET_NR_pselect6_time64 413
|
||||
#define TARGET_NR_ppoll_time64 414
|
||||
#define TARGET_NR_io_pgetevents_time64 416
|
||||
#define TARGET_NR_recvmmsg_time64 417
|
||||
#define TARGET_NR_mq_timedsend_time64 418
|
||||
#define TARGET_NR_mq_timedreceive_time64 419
|
||||
#define TARGET_NR_semtimedop_time64 420
|
||||
#define TARGET_NR_rt_sigtimedwait_time64 421
|
||||
#define TARGET_NR_futex_time64 422
|
||||
#define TARGET_NR_sched_rr_get_interval_time64 423
|
||||
#define TARGET_NR_pidfd_send_signal 424
|
||||
#define TARGET_NR_io_uring_setup 425
|
||||
#define TARGET_NR_io_uring_enter 426
|
||||
#define TARGET_NR_io_uring_register 427
|
||||
#define TARGET_NR_open_tree 428
|
||||
#define TARGET_NR_move_mount 429
|
||||
#define TARGET_NR_fsopen 430
|
||||
#define TARGET_NR_fsconfig 431
|
||||
#define TARGET_NR_fsmount 432
|
||||
#define TARGET_NR_fspick 433
|
||||
#define TARGET_NR_pidfd_open 434
|
||||
#define TARGET_NR_close_range 436
|
||||
#define TARGET_NR_openat2 437
|
||||
#define TARGET_NR_pidfd_getfd 438
|
||||
#define TARGET_NR_faccessat2 439
|
||||
#define TARGET_NR_process_madvise 440
|
||||
#define TARGET_NR_epoll_pwait2 441
|
||||
#define TARGET_NR_mount_setattr 442
|
||||
#define TARGET_NR_landlock_create_ruleset 444
|
||||
#define TARGET_NR_landlock_add_rule 445
|
||||
#define TARGET_NR_landlock_restrict_self 446
|
||||
#define TARGET_NR_syscalls 447
|
||||
|
||||
#endif /* LINUX_USER_NIOS2_SYSCALL_NR_H */
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Nios2 specific CPU ABI and functions for linux-user
|
||||
*
|
||||
* Copyright (c) 2016 Marek Vasut <marex@denx.de>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NIOS2_TARGET_CPU_H
|
||||
#define NIOS2_TARGET_CPU_H
|
||||
|
||||
static inline void cpu_clone_regs_child(CPUNios2State *env, target_ulong newsp,
|
||||
unsigned flags)
|
||||
{
|
||||
if (newsp) {
|
||||
env->regs[R_SP] = newsp;
|
||||
}
|
||||
env->regs[R_RET0] = 0;
|
||||
env->regs[7] = 0;
|
||||
}
|
||||
|
||||
static inline void cpu_clone_regs_parent(CPUNios2State *env, unsigned flags)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void cpu_set_tls(CPUNios2State *env, target_ulong newtls)
|
||||
{
|
||||
/*
|
||||
* Linux kernel 3.10 does not pay any attention to CLONE_SETTLS
|
||||
* in copy_thread(), so QEMU need not do so either.
|
||||
*/
|
||||
}
|
||||
|
||||
static inline abi_ulong get_sp_from_cpustate(CPUNios2State *state)
|
||||
{
|
||||
return state->regs[R_SP];
|
||||
}
|
||||
#endif
|
|
@ -1,14 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef NIOS2_TARGET_ELF_H
|
||||
#define NIOS2_TARGET_ELF_H
|
||||
static inline const char *cpu_get_model(uint32_t eflags)
|
||||
{
|
||||
return "any";
|
||||
}
|
||||
#endif
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef NIOS2_TARGET_ERRNO_DEFS_H
|
||||
#define NIOS2_TARGET_ERRNO_DEFS_H
|
||||
|
||||
/* Target uses generic errno */
|
||||
#include "../generic/target_errno_defs.h"
|
||||
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation, or (at your option) any
|
||||
* later version. See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef NIOS2_TARGET_FCNTL_H
|
||||
#define NIOS2_TARGET_FCNTL_H
|
||||
#include "../generic/fcntl.h"
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* arch/nios2/include/asm/processor.h:
|
||||
* TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3)
|
||||
* TASK_SIZE 0x7FFF0000UL
|
||||
*/
|
||||
#define TASK_UNMAPPED_BASE TARGET_PAGE_ALIGN(0x7FFF0000 / 3)
|
||||
|
||||
/* arch/nios2/include/asm/elf.h */
|
||||
#define ELF_ET_DYN_BASE 0xD0000000
|
||||
|
||||
#include "../generic/target_mman.h"
|
|
@ -1 +0,0 @@
|
|||
/* No special prctl support required. */
|
|
@ -1 +0,0 @@
|
|||
/* No target-specific /proc support */
|
|
@ -1 +0,0 @@
|
|||
#include "../generic/target_resource.h"
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef NIOS2_TARGET_SIGNAL_H
|
||||
#define NIOS2_TARGET_SIGNAL_H
|
||||
|
||||
#include "../generic/signal.h"
|
||||
|
||||
/* Nios2 uses a fixed address on the kuser page for sigreturn. */
|
||||
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
|
||||
|
||||
#endif /* NIOS2_TARGET_SIGNAL_H */
|
|
@ -1 +0,0 @@
|
|||
#include "../generic/target_structs.h"
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef NIOS2_TARGET_SYSCALL_H
|
||||
#define NIOS2_TARGET_SYSCALL_H
|
||||
|
||||
#define UNAME_MACHINE "nios2"
|
||||
#define UNAME_MINIMUM_RELEASE "3.19.0"
|
||||
|
||||
struct target_pt_regs {
|
||||
unsigned long r8; /* r8-r15 Caller-saved GP registers */
|
||||
unsigned long r9;
|
||||
unsigned long r10;
|
||||
unsigned long r11;
|
||||
unsigned long r12;
|
||||
unsigned long r13;
|
||||
unsigned long r14;
|
||||
unsigned long r15;
|
||||
unsigned long r1; /* Assembler temporary */
|
||||
unsigned long r2; /* Retval LS 32bits */
|
||||
unsigned long r3; /* Retval MS 32bits */
|
||||
unsigned long r4; /* r4-r7 Register arguments */
|
||||
unsigned long r5;
|
||||
unsigned long r6;
|
||||
unsigned long r7;
|
||||
unsigned long orig_r2; /* Copy of r2 ?? */
|
||||
unsigned long ra; /* Return address */
|
||||
unsigned long fp; /* Frame pointer */
|
||||
unsigned long sp; /* Stack pointer */
|
||||
unsigned long gp; /* Global pointer */
|
||||
unsigned long estatus;
|
||||
unsigned long ea; /* Exception return address (pc) */
|
||||
unsigned long orig_r7;
|
||||
};
|
||||
|
||||
#define TARGET_MCL_CURRENT 1
|
||||
#define TARGET_MCL_FUTURE 2
|
||||
#define TARGET_MCL_ONFAULT 4
|
||||
|
||||
#endif /* NIOS2_TARGET_SYSCALL_H */
|
|
@ -1 +0,0 @@
|
|||
#include "../generic/termbits.h"
|
|
@ -73,7 +73,7 @@
|
|||
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \
|
||||
|| defined(TARGET_M68K) || defined(TARGET_CRIS) \
|
||||
|| defined(TARGET_S390X) || defined(TARGET_OPENRISC) \
|
||||
|| defined(TARGET_NIOS2) || defined(TARGET_RISCV) \
|
||||
|| defined(TARGET_RISCV) \
|
||||
|| defined(TARGET_XTENSA) || defined(TARGET_LOONGARCH64)
|
||||
|
||||
#define TARGET_IOC_SIZEBITS 14
|
||||
|
@ -1974,7 +1974,7 @@ struct target_stat64 {
|
|||
abi_ulong __unused5;
|
||||
};
|
||||
|
||||
#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) \
|
||||
#elif defined(TARGET_OPENRISC) \
|
||||
|| defined(TARGET_RISCV) || defined(TARGET_HEXAGON)
|
||||
|
||||
/* These are the asm-generic versions of the stat and stat64 structures */
|
||||
|
|
|
@ -2971,7 +2971,6 @@ disassemblers = {
|
|||
'm68k' : ['CONFIG_M68K_DIS'],
|
||||
'microblaze' : ['CONFIG_MICROBLAZE_DIS'],
|
||||
'mips' : ['CONFIG_MIPS_DIS'],
|
||||
'nios2' : ['CONFIG_NIOS2_DIS'],
|
||||
'or1k' : ['CONFIG_OPENRISC_DIS'],
|
||||
'ppc' : ['CONFIG_PPC_DIS'],
|
||||
'riscv' : ['CONFIG_RISCV_DIS'],
|
||||
|
@ -3398,7 +3397,6 @@ if have_system or have_user
|
|||
'target/i386/kvm',
|
||||
'target/loongarch',
|
||||
'target/mips/tcg',
|
||||
'target/nios2',
|
||||
'target/ppc',
|
||||
'target/riscv',
|
||||
'target/s390x',
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
{ 'enum' : 'SysEmuTarget',
|
||||
'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386',
|
||||
'loongarch64', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
|
||||
'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc',
|
||||
'mips64el', 'mipsel', 'or1k', 'ppc',
|
||||
'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
|
||||
'sh4eb', 'sparc', 'sparc64', 'tricore',
|
||||
'x86_64', 'xtensa', 'xtensaeb' ] }
|
||||
|
|
|
@ -4849,10 +4849,10 @@ ERST
|
|||
DEF("semihosting", 0, QEMU_OPTION_semihosting,
|
||||
"-semihosting semihosting mode\n",
|
||||
QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA |
|
||||
QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
|
||||
QEMU_ARCH_MIPS | QEMU_ARCH_RISCV)
|
||||
SRST
|
||||
``-semihosting``
|
||||
Enable :ref:`Semihosting` mode (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V only).
|
||||
Enable :ref:`Semihosting` mode (ARM, M68K, Xtensa, MIPS, RISC-V only).
|
||||
|
||||
.. warning::
|
||||
Note that this allows guest direct access to the host filesystem, so
|
||||
|
@ -4865,10 +4865,10 @@ DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
|
|||
"-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,userspace=on|off][,arg=str[,...]]\n" \
|
||||
" semihosting configuration\n",
|
||||
QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA |
|
||||
QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
|
||||
QEMU_ARCH_MIPS | QEMU_ARCH_RISCV)
|
||||
SRST
|
||||
``-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,userspace=on|off][,arg=str[,...]]``
|
||||
Enable and configure :ref:`Semihosting` (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V
|
||||
Enable and configure :ref:`Semihosting` (ARM, M68K, Xtensa, MIPS, RISC-V
|
||||
only).
|
||||
|
||||
.. warning::
|
||||
|
|
|
@ -36,9 +36,6 @@ microblaze
|
|||
mips
|
||||
~ (/qemu)?((/include)?/hw/mips/.*|/target/mips/.*)
|
||||
|
||||
nios2
|
||||
~ (/qemu)?((/include)?/hw/nios2/.*|/target/nios2/.*)
|
||||
|
||||
openrisc
|
||||
~ (/qemu)?((/include)?/hw/openrisc/.*|/target/openrisc/.*)
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ mkdir "$TMP/asm"
|
|||
> "$TMP/asm/bitsperlong.h"
|
||||
|
||||
generate_syscall_nr arm64 64 "$output/linux-user/aarch64/syscall_nr.h"
|
||||
generate_syscall_nr nios2 32 "$output/linux-user/nios2/syscall_nr.h"
|
||||
generate_syscall_nr openrisc 32 "$output/linux-user/openrisc/syscall_nr.h"
|
||||
|
||||
generate_syscall_nr riscv 32 "$output/linux-user/riscv/syscall32_nr.h"
|
||||
|
|
|
@ -37,7 +37,6 @@ mappings = {
|
|||
"m68k" : "m68k",
|
||||
"MicroBlaze" : "microblaze",
|
||||
"mips:isa64" : ["mips64", "mips64el"],
|
||||
"nios2" : "nios2",
|
||||
"or1k" : "or1k",
|
||||
"powerpc:common" : "ppc",
|
||||
"powerpc:common64" : ["ppc64", "ppc64le"],
|
||||
|
|
|
@ -8,7 +8,6 @@ source loongarch/Kconfig
|
|||
source m68k/Kconfig
|
||||
source microblaze/Kconfig
|
||||
source mips/Kconfig
|
||||
source nios2/Kconfig
|
||||
source openrisc/Kconfig
|
||||
source ppc/Kconfig
|
||||
source riscv/Kconfig
|
||||
|
|
|
@ -9,7 +9,6 @@ subdir('loongarch')
|
|||
subdir('m68k')
|
||||
subdir('microblaze')
|
||||
subdir('mips')
|
||||
subdir('nios2')
|
||||
subdir('openrisc')
|
||||
subdir('ppc')
|
||||
subdir('riscv')
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
config NIOS2
|
||||
bool
|
||||
select SEMIHOSTING
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Altera Nios II cpu parameters for qemu.
|
||||
*
|
||||
* Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#ifndef NIOS2_CPU_PARAM_H
|
||||
#define NIOS2_CPU_PARAM_H
|
||||
|
||||
#define TARGET_LONG_BITS 32
|
||||
#define TARGET_PAGE_BITS 12
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 32
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
# define TARGET_VIRT_ADDR_SPACE_BITS 31
|
||||
#else
|
||||
# define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
* QEMU Nios II CPU QOM header (target agnostic)
|
||||
*
|
||||
* Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef QEMU_NIOS2_CPU_QOM_H
|
||||
#define QEMU_NIOS2_CPU_QOM_H
|
||||
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
#define TYPE_NIOS2_CPU "nios2-cpu"
|
||||
|
||||
OBJECT_DECLARE_CPU_TYPE(Nios2CPU, Nios2CPUClass, NIOS2_CPU)
|
||||
|
||||
#endif
|
|
@ -1,410 +0,0 @@
|
|||
/*
|
||||
* QEMU Nios II CPU
|
||||
*
|
||||
* Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/log.h"
|
||||
#include "gdbstub/helpers.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
|
||||
static void nios2_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
{
|
||||
cpu_env(cs)->pc = value;
|
||||
}
|
||||
|
||||
static vaddr nios2_cpu_get_pc(CPUState *cs)
|
||||
{
|
||||
return cpu_env(cs)->pc;
|
||||
}
|
||||
|
||||
static void nios2_restore_state_to_opc(CPUState *cs,
|
||||
const TranslationBlock *tb,
|
||||
const uint64_t *data)
|
||||
{
|
||||
cpu_env(cs)->pc = data[0];
|
||||
}
|
||||
|
||||
static bool nios2_cpu_has_work(CPUState *cs)
|
||||
{
|
||||
return cs->interrupt_request & CPU_INTERRUPT_HARD;
|
||||
}
|
||||
|
||||
static int nios2_cpu_mmu_index(CPUState *cs, bool ifetch)
|
||||
{
|
||||
return (cpu_env(cs)->ctrl[CR_STATUS] & CR_STATUS_U
|
||||
? MMU_USER_IDX : MMU_SUPERVISOR_IDX);
|
||||
}
|
||||
|
||||
static void nios2_cpu_reset_hold(Object *obj)
|
||||
{
|
||||
CPUState *cs = CPU(obj);
|
||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(obj);
|
||||
CPUNios2State *env = &cpu->env;
|
||||
|
||||
if (ncc->parent_phases.hold) {
|
||||
ncc->parent_phases.hold(obj);
|
||||
}
|
||||
|
||||
memset(env->ctrl, 0, sizeof(env->ctrl));
|
||||
env->pc = cpu->reset_addr;
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* Start in user mode with interrupts enabled. */
|
||||
env->ctrl[CR_STATUS] = CR_STATUS_RSIE | CR_STATUS_U | CR_STATUS_PIE;
|
||||
memset(env->regs, 0, sizeof(env->regs));
|
||||
#else
|
||||
env->ctrl[CR_STATUS] = CR_STATUS_RSIE;
|
||||
nios2_update_crs(env);
|
||||
memset(env->shadow_regs, 0, sizeof(env->shadow_regs));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static void eic_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
Nios2CPU *cpu = opaque;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
if (level) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
}
|
||||
|
||||
static void iic_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
Nios2CPU *cpu = opaque;
|
||||
CPUNios2State *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
env->ctrl[CR_IPENDING] = deposit32(env->ctrl[CR_IPENDING], irq, 1, !!level);
|
||||
|
||||
if (env->ctrl[CR_IPENDING]) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void nios2_cpu_initfn(Object *obj)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
Nios2CPU *cpu = NIOS2_CPU(obj);
|
||||
|
||||
mmu_init(&cpu->env);
|
||||
#endif
|
||||
}
|
||||
|
||||
static ObjectClass *nios2_cpu_class_by_name(const char *cpu_model)
|
||||
{
|
||||
return object_class_by_name(TYPE_NIOS2_CPU);
|
||||
}
|
||||
|
||||
static void realize_cr_status(CPUState *cs)
|
||||
{
|
||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
|
||||
/* Begin with all fields of all registers are reserved. */
|
||||
memset(cpu->cr_state, 0, sizeof(cpu->cr_state));
|
||||
|
||||
/*
|
||||
* The combination of writable and readonly is the set of all
|
||||
* non-reserved fields. We apply writable as a mask to bits,
|
||||
* and merge in existing readonly bits, before storing.
|
||||
*/
|
||||
#define WR_REG(C) cpu->cr_state[C].writable = -1
|
||||
#define RO_REG(C) cpu->cr_state[C].readonly = -1
|
||||
#define WR_FIELD(C, F) cpu->cr_state[C].writable |= R_##C##_##F##_MASK
|
||||
#define RO_FIELD(C, F) cpu->cr_state[C].readonly |= R_##C##_##F##_MASK
|
||||
|
||||
WR_FIELD(CR_STATUS, PIE);
|
||||
WR_REG(CR_ESTATUS);
|
||||
WR_REG(CR_BSTATUS);
|
||||
RO_REG(CR_CPUID);
|
||||
RO_REG(CR_EXCEPTION);
|
||||
WR_REG(CR_BADADDR);
|
||||
|
||||
if (cpu->eic_present) {
|
||||
WR_FIELD(CR_STATUS, RSIE);
|
||||
RO_FIELD(CR_STATUS, NMI);
|
||||
WR_FIELD(CR_STATUS, PRS);
|
||||
RO_FIELD(CR_STATUS, CRS);
|
||||
WR_FIELD(CR_STATUS, IL);
|
||||
WR_FIELD(CR_STATUS, IH);
|
||||
} else {
|
||||
RO_FIELD(CR_STATUS, RSIE);
|
||||
WR_REG(CR_IENABLE);
|
||||
RO_REG(CR_IPENDING);
|
||||
}
|
||||
|
||||
if (cpu->mmu_present) {
|
||||
WR_FIELD(CR_STATUS, U);
|
||||
WR_FIELD(CR_STATUS, EH);
|
||||
|
||||
WR_FIELD(CR_PTEADDR, VPN);
|
||||
WR_FIELD(CR_PTEADDR, PTBASE);
|
||||
|
||||
RO_FIELD(CR_TLBMISC, D);
|
||||
RO_FIELD(CR_TLBMISC, PERM);
|
||||
RO_FIELD(CR_TLBMISC, BAD);
|
||||
RO_FIELD(CR_TLBMISC, DBL);
|
||||
WR_FIELD(CR_TLBMISC, PID);
|
||||
WR_FIELD(CR_TLBMISC, WE);
|
||||
WR_FIELD(CR_TLBMISC, RD);
|
||||
WR_FIELD(CR_TLBMISC, WAY);
|
||||
|
||||
WR_REG(CR_TLBACC);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: ECC (config, eccinj) and MPU (config, mpubase, mpuacc) are
|
||||
* unimplemented, so their corresponding control regs remain reserved.
|
||||
*/
|
||||
|
||||
#undef WR_REG
|
||||
#undef RO_REG
|
||||
#undef WR_FIELD
|
||||
#undef RO_FIELD
|
||||
}
|
||||
|
||||
static void nios2_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
Nios2CPUClass *ncc = NIOS2_CPU_GET_CLASS(dev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
realize_cr_status(cs);
|
||||
qemu_init_vcpu(cs);
|
||||
cpu_reset(cs);
|
||||
|
||||
/* We have reserved storage for cpuid; might as well use it. */
|
||||
cpu->env.ctrl[CR_CPUID] = cs->cpu_index;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (cpu->eic_present) {
|
||||
qdev_init_gpio_in_named(DEVICE(cpu), eic_set_irq, "EIC", 1);
|
||||
} else {
|
||||
qdev_init_gpio_in_named(DEVICE(cpu), iic_set_irq, "IRQ", 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
ncc->parent_realize(dev, errp);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static bool eic_take_interrupt(Nios2CPU *cpu)
|
||||
{
|
||||
CPUNios2State *env = &cpu->env;
|
||||
const uint32_t status = env->ctrl[CR_STATUS];
|
||||
|
||||
if (cpu->rnmi) {
|
||||
return !(status & CR_STATUS_NMI);
|
||||
}
|
||||
if (!(status & CR_STATUS_PIE)) {
|
||||
return false;
|
||||
}
|
||||
if (cpu->ril <= FIELD_EX32(status, CR_STATUS, IL)) {
|
||||
return false;
|
||||
}
|
||||
if (cpu->rrs != FIELD_EX32(status, CR_STATUS, CRS)) {
|
||||
return true;
|
||||
}
|
||||
return status & CR_STATUS_RSIE;
|
||||
}
|
||||
|
||||
static bool iic_take_interrupt(Nios2CPU *cpu)
|
||||
{
|
||||
CPUNios2State *env = &cpu->env;
|
||||
|
||||
if (!(env->ctrl[CR_STATUS] & CR_STATUS_PIE)) {
|
||||
return false;
|
||||
}
|
||||
return env->ctrl[CR_IPENDING] & env->ctrl[CR_IENABLE];
|
||||
}
|
||||
|
||||
static bool nios2_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
{
|
||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
|
||||
if (interrupt_request & CPU_INTERRUPT_HARD) {
|
||||
if (cpu->eic_present
|
||||
? eic_take_interrupt(cpu)
|
||||
: iic_take_interrupt(cpu)) {
|
||||
cs->exception_index = EXCP_IRQ;
|
||||
nios2_cpu_do_interrupt(cs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
static void nios2_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
|
||||
{
|
||||
/* NOTE: NiosII R2 is not supported yet. */
|
||||
info->mach = bfd_arch_nios2;
|
||||
info->print_insn = print_insn_nios2;
|
||||
}
|
||||
|
||||
static int nios2_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
CPUNios2State *env = &cpu->env;
|
||||
uint32_t val;
|
||||
|
||||
if (n < 32) { /* GP regs */
|
||||
val = env->regs[n];
|
||||
} else if (n == 32) { /* PC */
|
||||
val = env->pc;
|
||||
} else if (n < 49) { /* Status regs */
|
||||
unsigned cr = n - 33;
|
||||
if (nios2_cr_reserved(&cpu->cr_state[cr])) {
|
||||
val = 0;
|
||||
} else {
|
||||
val = env->ctrl[n - 33];
|
||||
}
|
||||
} else {
|
||||
/* Invalid regs */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gdb_get_reg32(mem_buf, val);
|
||||
}
|
||||
|
||||
static int nios2_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
{
|
||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
CPUClass *cc = CPU_GET_CLASS(cs);
|
||||
CPUNios2State *env = &cpu->env;
|
||||
uint32_t val;
|
||||
|
||||
if (n > cc->gdb_num_core_regs) {
|
||||
return 0;
|
||||
}
|
||||
val = ldl_p(mem_buf);
|
||||
|
||||
if (n < 32) { /* GP regs */
|
||||
env->regs[n] = val;
|
||||
} else if (n == 32) { /* PC */
|
||||
env->pc = val;
|
||||
} else if (n < 49) { /* Status regs */
|
||||
unsigned cr = n - 33;
|
||||
/* ??? Maybe allow the debugger to write to readonly fields. */
|
||||
val &= cpu->cr_state[cr].writable;
|
||||
val |= cpu->cr_state[cr].readonly & env->ctrl[cr];
|
||||
env->ctrl[cr] = val;
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
static Property nios2_properties[] = {
|
||||
DEFINE_PROP_BOOL("diverr_present", Nios2CPU, diverr_present, true),
|
||||
DEFINE_PROP_BOOL("mmu_present", Nios2CPU, mmu_present, true),
|
||||
/* ALTR,pid-num-bits */
|
||||
DEFINE_PROP_UINT32("mmu_pid_num_bits", Nios2CPU, pid_num_bits, 8),
|
||||
/* ALTR,tlb-num-ways */
|
||||
DEFINE_PROP_UINT32("mmu_tlb_num_ways", Nios2CPU, tlb_num_ways, 16),
|
||||
/* ALTR,tlb-num-entries */
|
||||
DEFINE_PROP_UINT32("mmu_pid_num_entries", Nios2CPU, tlb_num_entries, 256),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "hw/core/sysemu-cpu-ops.h"
|
||||
|
||||
static const struct SysemuCPUOps nios2_sysemu_ops = {
|
||||
.get_phys_page_debug = nios2_cpu_get_phys_page_debug,
|
||||
};
|
||||
#endif
|
||||
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
|
||||
static const TCGCPUOps nios2_tcg_ops = {
|
||||
.initialize = nios2_tcg_init,
|
||||
.restore_state_to_opc = nios2_restore_state_to_opc,
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.tlb_fill = nios2_cpu_tlb_fill,
|
||||
.cpu_exec_interrupt = nios2_cpu_exec_interrupt,
|
||||
.do_interrupt = nios2_cpu_do_interrupt,
|
||||
.do_unaligned_access = nios2_cpu_do_unaligned_access,
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
};
|
||||
|
||||
static void nios2_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
Nios2CPUClass *ncc = NIOS2_CPU_CLASS(oc);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(oc);
|
||||
|
||||
device_class_set_parent_realize(dc, nios2_cpu_realizefn,
|
||||
&ncc->parent_realize);
|
||||
device_class_set_props(dc, nios2_properties);
|
||||
resettable_class_set_parent_phases(rc, NULL, nios2_cpu_reset_hold, NULL,
|
||||
&ncc->parent_phases);
|
||||
|
||||
cc->class_by_name = nios2_cpu_class_by_name;
|
||||
cc->has_work = nios2_cpu_has_work;
|
||||
cc->mmu_index = nios2_cpu_mmu_index;
|
||||
cc->dump_state = nios2_cpu_dump_state;
|
||||
cc->set_pc = nios2_cpu_set_pc;
|
||||
cc->get_pc = nios2_cpu_get_pc;
|
||||
cc->disas_set_info = nios2_cpu_disas_set_info;
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
cc->sysemu_ops = &nios2_sysemu_ops;
|
||||
#endif
|
||||
cc->gdb_read_register = nios2_cpu_gdb_read_register;
|
||||
cc->gdb_write_register = nios2_cpu_gdb_write_register;
|
||||
cc->gdb_num_core_regs = 49;
|
||||
cc->tcg_ops = &nios2_tcg_ops;
|
||||
}
|
||||
|
||||
static const TypeInfo nios2_cpu_type_info = {
|
||||
.name = TYPE_NIOS2_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(Nios2CPU),
|
||||
.instance_align = __alignof(Nios2CPU),
|
||||
.instance_init = nios2_cpu_initfn,
|
||||
.class_size = sizeof(Nios2CPUClass),
|
||||
.class_init = nios2_cpu_class_init,
|
||||
};
|
||||
|
||||
static void nios2_cpu_register_types(void)
|
||||
{
|
||||
type_register_static(&nios2_cpu_type_info);
|
||||
}
|
||||
|
||||
type_init(nios2_cpu_register_types)
|
|
@ -1,301 +0,0 @@
|
|||
/*
|
||||
* Altera Nios II virtual CPU header
|
||||
*
|
||||
* Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#ifndef NIOS2_CPU_H
|
||||
#define NIOS2_CPU_H
|
||||
|
||||
#include "cpu-qom.h"
|
||||
#include "exec/cpu-defs.h"
|
||||
#include "hw/registerfields.h"
|
||||
|
||||
typedef struct CPUArchState CPUNios2State;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#include "mmu.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Nios2CPUClass:
|
||||
* @parent_phases: The parent class' reset phase handlers.
|
||||
*
|
||||
* A Nios2 CPU model.
|
||||
*/
|
||||
struct Nios2CPUClass {
|
||||
CPUClass parent_class;
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
ResettablePhases parent_phases;
|
||||
};
|
||||
|
||||
#define TARGET_HAS_ICE 1
|
||||
|
||||
/* Configuration options for Nios II */
|
||||
#define RESET_ADDRESS 0x00000000
|
||||
#define EXCEPTION_ADDRESS 0x00000004
|
||||
#define FAST_TLB_MISS_ADDRESS 0x00000008
|
||||
|
||||
#define NUM_GP_REGS 32
|
||||
#define NUM_CR_REGS 32
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* 63 shadow register sets; index 0 is the primary register set. */
|
||||
#define NUM_REG_SETS 64
|
||||
#endif
|
||||
|
||||
/* General purpose register aliases */
|
||||
enum {
|
||||
R_ZERO = 0,
|
||||
R_AT = 1,
|
||||
R_RET0 = 2,
|
||||
R_RET1 = 3,
|
||||
R_ARG0 = 4,
|
||||
R_ARG1 = 5,
|
||||
R_ARG2 = 6,
|
||||
R_ARG3 = 7,
|
||||
R_ET = 24,
|
||||
R_BT = 25,
|
||||
R_GP = 26,
|
||||
R_SP = 27,
|
||||
R_FP = 28,
|
||||
R_EA = 29,
|
||||
R_BA = 30,
|
||||
R_SSTATUS = 30,
|
||||
R_RA = 31,
|
||||
};
|
||||
|
||||
/* Control register aliases */
|
||||
enum {
|
||||
CR_STATUS = 0,
|
||||
CR_ESTATUS = 1,
|
||||
CR_BSTATUS = 2,
|
||||
CR_IENABLE = 3,
|
||||
CR_IPENDING = 4,
|
||||
CR_CPUID = 5,
|
||||
CR_EXCEPTION = 7,
|
||||
CR_PTEADDR = 8,
|
||||
CR_TLBACC = 9,
|
||||
CR_TLBMISC = 10,
|
||||
CR_ENCINJ = 11,
|
||||
CR_BADADDR = 12,
|
||||
CR_CONFIG = 13,
|
||||
CR_MPUBASE = 14,
|
||||
CR_MPUACC = 15,
|
||||
};
|
||||
|
||||
FIELD(CR_STATUS, PIE, 0, 1)
|
||||
FIELD(CR_STATUS, U, 1, 1)
|
||||
FIELD(CR_STATUS, EH, 2, 1)
|
||||
FIELD(CR_STATUS, IH, 3, 1)
|
||||
FIELD(CR_STATUS, IL, 4, 6)
|
||||
FIELD(CR_STATUS, CRS, 10, 6)
|
||||
FIELD(CR_STATUS, PRS, 16, 6)
|
||||
FIELD(CR_STATUS, NMI, 22, 1)
|
||||
FIELD(CR_STATUS, RSIE, 23, 1)
|
||||
FIELD(CR_STATUS, SRS, 31, 1) /* only in sstatus */
|
||||
|
||||
#define CR_STATUS_PIE R_CR_STATUS_PIE_MASK
|
||||
#define CR_STATUS_U R_CR_STATUS_U_MASK
|
||||
#define CR_STATUS_EH R_CR_STATUS_EH_MASK
|
||||
#define CR_STATUS_IH R_CR_STATUS_IH_MASK
|
||||
#define CR_STATUS_NMI R_CR_STATUS_NMI_MASK
|
||||
#define CR_STATUS_RSIE R_CR_STATUS_RSIE_MASK
|
||||
#define CR_STATUS_SRS R_CR_STATUS_SRS_MASK
|
||||
|
||||
FIELD(CR_EXCEPTION, CAUSE, 2, 5)
|
||||
FIELD(CR_EXCEPTION, ECCFTL, 31, 1)
|
||||
|
||||
FIELD(CR_PTEADDR, VPN, 2, 20)
|
||||
FIELD(CR_PTEADDR, PTBASE, 22, 10)
|
||||
|
||||
FIELD(CR_TLBACC, PFN, 0, 20)
|
||||
FIELD(CR_TLBACC, G, 20, 1)
|
||||
FIELD(CR_TLBACC, X, 21, 1)
|
||||
FIELD(CR_TLBACC, W, 22, 1)
|
||||
FIELD(CR_TLBACC, R, 23, 1)
|
||||
FIELD(CR_TLBACC, C, 24, 1)
|
||||
FIELD(CR_TLBACC, IG, 25, 7)
|
||||
|
||||
#define CR_TLBACC_C R_CR_TLBACC_C_MASK
|
||||
#define CR_TLBACC_R R_CR_TLBACC_R_MASK
|
||||
#define CR_TLBACC_W R_CR_TLBACC_W_MASK
|
||||
#define CR_TLBACC_X R_CR_TLBACC_X_MASK
|
||||
#define CR_TLBACC_G R_CR_TLBACC_G_MASK
|
||||
|
||||
FIELD(CR_TLBMISC, D, 0, 1)
|
||||
FIELD(CR_TLBMISC, PERM, 1, 1)
|
||||
FIELD(CR_TLBMISC, BAD, 2, 1)
|
||||
FIELD(CR_TLBMISC, DBL, 3, 1)
|
||||
FIELD(CR_TLBMISC, PID, 4, 14)
|
||||
FIELD(CR_TLBMISC, WE, 18, 1)
|
||||
FIELD(CR_TLBMISC, RD, 19, 1)
|
||||
FIELD(CR_TLBMISC, WAY, 20, 4)
|
||||
FIELD(CR_TLBMISC, EE, 24, 1)
|
||||
|
||||
#define CR_TLBMISC_EE R_CR_TLBMISC_EE_MASK
|
||||
#define CR_TLBMISC_RD R_CR_TLBMISC_RD_MASK
|
||||
#define CR_TLBMISC_WE R_CR_TLBMISC_WE_MASK
|
||||
#define CR_TLBMISC_DBL R_CR_TLBMISC_DBL_MASK
|
||||
#define CR_TLBMISC_BAD R_CR_TLBMISC_BAD_MASK
|
||||
#define CR_TLBMISC_PERM R_CR_TLBMISC_PERM_MASK
|
||||
#define CR_TLBMISC_D R_CR_TLBMISC_D_MASK
|
||||
|
||||
/* Exceptions */
|
||||
#define EXCP_BREAK 0x1000
|
||||
#define EXCP_SEMIHOST 0x1001
|
||||
#define EXCP_RESET 0
|
||||
#define EXCP_PRESET 1
|
||||
#define EXCP_IRQ 2
|
||||
#define EXCP_TRAP 3
|
||||
#define EXCP_UNIMPL 4
|
||||
#define EXCP_ILLEGAL 5
|
||||
#define EXCP_UNALIGN 6
|
||||
#define EXCP_UNALIGND 7
|
||||
#define EXCP_DIV 8
|
||||
#define EXCP_SUPERA_X 9
|
||||
#define EXCP_SUPERI 10
|
||||
#define EXCP_SUPERA_D 11
|
||||
#define EXCP_TLB_X 12
|
||||
#define EXCP_TLB_D (0x1000 | EXCP_TLB_X)
|
||||
#define EXCP_PERM_X 13
|
||||
#define EXCP_PERM_R 14
|
||||
#define EXCP_PERM_W 15
|
||||
#define EXCP_MPUI 16
|
||||
#define EXCP_MPUD 17
|
||||
|
||||
struct CPUArchState {
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
uint32_t regs[NUM_GP_REGS];
|
||||
#else
|
||||
uint32_t shadow_regs[NUM_REG_SETS][NUM_GP_REGS];
|
||||
/* Pointer into shadow_regs for the current register set. */
|
||||
uint32_t *regs;
|
||||
#endif
|
||||
uint32_t ctrl[NUM_CR_REGS];
|
||||
uint32_t pc;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
Nios2MMU mmu;
|
||||
#endif
|
||||
int error_code;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t writable;
|
||||
uint32_t readonly;
|
||||
} ControlRegState;
|
||||
|
||||
/**
|
||||
* Nios2CPU:
|
||||
* @env: #CPUNios2State
|
||||
*
|
||||
* A Nios2 CPU.
|
||||
*/
|
||||
struct ArchCPU {
|
||||
CPUState parent_obj;
|
||||
|
||||
CPUNios2State env;
|
||||
|
||||
bool diverr_present;
|
||||
bool mmu_present;
|
||||
bool eic_present;
|
||||
|
||||
uint32_t pid_num_bits;
|
||||
uint32_t tlb_num_ways;
|
||||
uint32_t tlb_num_entries;
|
||||
|
||||
/* Addresses that are hard-coded in the FPGA build settings */
|
||||
uint32_t reset_addr;
|
||||
uint32_t exception_addr;
|
||||
uint32_t fast_tlb_miss_addr;
|
||||
|
||||
/* Bits within each control register which are reserved or readonly. */
|
||||
ControlRegState cr_state[NUM_CR_REGS];
|
||||
|
||||
/* External Interrupt Controller Interface */
|
||||
uint32_t rha; /* Requested handler address */
|
||||
uint32_t ril; /* Requested interrupt level */
|
||||
uint32_t rrs; /* Requested register set */
|
||||
bool rnmi; /* Requested nonmaskable interrupt */
|
||||
};
|
||||
|
||||
|
||||
static inline bool nios2_cr_reserved(const ControlRegState *s)
|
||||
{
|
||||
return (s->writable | s->readonly) == 0;
|
||||
}
|
||||
|
||||
static inline void nios2_update_crs(CPUNios2State *env)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
unsigned crs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, CRS);
|
||||
env->regs = env->shadow_regs[crs];
|
||||
#endif
|
||||
}
|
||||
|
||||
void nios2_tcg_init(void);
|
||||
void nios2_cpu_do_interrupt(CPUState *cs);
|
||||
void dump_mmu(CPUNios2State *env);
|
||||
void nios2_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
|
||||
G_NORETURN void nios2_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
uintptr_t retaddr);
|
||||
G_NORETURN void nios2_cpu_loop_exit_advance(CPUNios2State *env,
|
||||
uintptr_t retaddr);
|
||||
|
||||
void do_nios2_semihosting(CPUNios2State *env);
|
||||
|
||||
#define CPU_RESOLVING_TYPE TYPE_NIOS2_CPU
|
||||
|
||||
#define cpu_gen_code cpu_nios2_gen_code
|
||||
|
||||
#define CPU_SAVE_VERSION 1
|
||||
|
||||
/* MMU modes definitions */
|
||||
#define MMU_SUPERVISOR_IDX 0
|
||||
#define MMU_USER_IDX 1
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
hwaddr nios2_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr);
|
||||
#endif
|
||||
|
||||
typedef CPUNios2State CPUArchState;
|
||||
typedef Nios2CPU ArchCPU;
|
||||
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
FIELD(TBFLAGS, CRS0, 0, 1) /* Set if CRS == 0. */
|
||||
FIELD(TBFLAGS, U, 1, 1) /* Overlaps CR_STATUS_U */
|
||||
FIELD(TBFLAGS, R0_0, 2, 1) /* Set if R0 == 0. */
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUNios2State *env, vaddr *pc,
|
||||
uint64_t *cs_base, uint32_t *flags)
|
||||
{
|
||||
unsigned crs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, CRS);
|
||||
|
||||
*pc = env->pc;
|
||||
*cs_base = 0;
|
||||
*flags = (env->ctrl[CR_STATUS] & CR_STATUS_U)
|
||||
| (crs ? 0 : R_TBFLAGS_CRS0_MASK)
|
||||
| (env->regs[0] ? 0 : R_TBFLAGS_R0_0_MASK);
|
||||
}
|
||||
|
||||
#endif /* NIOS2_CPU_H */
|
|
@ -1,371 +0,0 @@
|
|||
/*
|
||||
* Altera Nios II helper routines.
|
||||
*
|
||||
* Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "cpu.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "semihosting/semihost.h"
|
||||
|
||||
|
||||
static void do_exception(Nios2CPU *cpu, uint32_t exception_addr,
|
||||
uint32_t tlbmisc_set, bool is_break)
|
||||
{
|
||||
CPUNios2State *env = &cpu->env;
|
||||
CPUState *cs = CPU(cpu);
|
||||
uint32_t old_status = env->ctrl[CR_STATUS];
|
||||
uint32_t new_status = old_status;
|
||||
|
||||
/* With shadow regs, exceptions are always taken into CRS 0. */
|
||||
new_status &= ~R_CR_STATUS_CRS_MASK;
|
||||
env->regs = env->shadow_regs[0];
|
||||
|
||||
if ((old_status & CR_STATUS_EH) == 0) {
|
||||
int r_ea = R_EA, cr_es = CR_ESTATUS;
|
||||
|
||||
if (is_break) {
|
||||
r_ea = R_BA;
|
||||
cr_es = CR_BSTATUS;
|
||||
}
|
||||
env->ctrl[cr_es] = old_status;
|
||||
env->regs[r_ea] = env->pc;
|
||||
|
||||
if (cpu->mmu_present) {
|
||||
new_status |= CR_STATUS_EH;
|
||||
|
||||
/*
|
||||
* There are 4 bits that are always written.
|
||||
* Explicitly clear them, to be set via the argument.
|
||||
*/
|
||||
env->ctrl[CR_TLBMISC] &= ~(CR_TLBMISC_D |
|
||||
CR_TLBMISC_PERM |
|
||||
CR_TLBMISC_BAD |
|
||||
CR_TLBMISC_DBL);
|
||||
env->ctrl[CR_TLBMISC] |= tlbmisc_set;
|
||||
}
|
||||
|
||||
/*
|
||||
* With shadow regs, and EH == 0, PRS is set from CRS.
|
||||
* At least, so says Table 3-9, and some other text,
|
||||
* though Table 3-38 says otherwise.
|
||||
*/
|
||||
new_status = FIELD_DP32(new_status, CR_STATUS, PRS,
|
||||
FIELD_EX32(old_status, CR_STATUS, CRS));
|
||||
}
|
||||
|
||||
new_status &= ~(CR_STATUS_PIE | CR_STATUS_U);
|
||||
|
||||
env->ctrl[CR_STATUS] = new_status;
|
||||
if (!is_break) {
|
||||
env->ctrl[CR_EXCEPTION] = FIELD_DP32(0, CR_EXCEPTION, CAUSE,
|
||||
cs->exception_index);
|
||||
}
|
||||
env->pc = exception_addr;
|
||||
}
|
||||
|
||||
static void do_iic_irq(Nios2CPU *cpu)
|
||||
{
|
||||
do_exception(cpu, cpu->exception_addr, 0, false);
|
||||
}
|
||||
|
||||
static void do_eic_irq(Nios2CPU *cpu)
|
||||
{
|
||||
CPUNios2State *env = &cpu->env;
|
||||
uint32_t old_status = env->ctrl[CR_STATUS];
|
||||
uint32_t new_status = old_status;
|
||||
uint32_t old_rs = FIELD_EX32(old_status, CR_STATUS, CRS);
|
||||
uint32_t new_rs = cpu->rrs;
|
||||
|
||||
new_status = FIELD_DP32(new_status, CR_STATUS, CRS, new_rs);
|
||||
new_status = FIELD_DP32(new_status, CR_STATUS, IL, cpu->ril);
|
||||
new_status = FIELD_DP32(new_status, CR_STATUS, NMI, cpu->rnmi);
|
||||
new_status &= ~(CR_STATUS_RSIE | CR_STATUS_U);
|
||||
new_status |= CR_STATUS_IH;
|
||||
|
||||
if (!(new_status & CR_STATUS_EH)) {
|
||||
new_status = FIELD_DP32(new_status, CR_STATUS, PRS, old_rs);
|
||||
if (new_rs == 0) {
|
||||
env->ctrl[CR_ESTATUS] = old_status;
|
||||
} else {
|
||||
if (new_rs != old_rs) {
|
||||
old_status |= CR_STATUS_SRS;
|
||||
}
|
||||
env->shadow_regs[new_rs][R_SSTATUS] = old_status;
|
||||
}
|
||||
env->shadow_regs[new_rs][R_EA] = env->pc;
|
||||
}
|
||||
|
||||
env->ctrl[CR_STATUS] = new_status;
|
||||
nios2_update_crs(env);
|
||||
|
||||
env->pc = cpu->rha;
|
||||
}
|
||||
|
||||
void nios2_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
CPUNios2State *env = &cpu->env;
|
||||
uint32_t tlbmisc_set = 0;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_INT)) {
|
||||
const char *name = NULL;
|
||||
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_IRQ:
|
||||
name = "interrupt";
|
||||
break;
|
||||
case EXCP_TLB_X:
|
||||
case EXCP_TLB_D:
|
||||
if (env->ctrl[CR_STATUS] & CR_STATUS_EH) {
|
||||
name = "TLB MISS (double)";
|
||||
} else {
|
||||
name = "TLB MISS (fast)";
|
||||
}
|
||||
break;
|
||||
case EXCP_PERM_R:
|
||||
case EXCP_PERM_W:
|
||||
case EXCP_PERM_X:
|
||||
name = "TLB PERM";
|
||||
break;
|
||||
case EXCP_SUPERA_X:
|
||||
case EXCP_SUPERA_D:
|
||||
name = "SUPERVISOR (address)";
|
||||
break;
|
||||
case EXCP_SUPERI:
|
||||
name = "SUPERVISOR (insn)";
|
||||
break;
|
||||
case EXCP_ILLEGAL:
|
||||
name = "ILLEGAL insn";
|
||||
break;
|
||||
case EXCP_UNALIGN:
|
||||
name = "Misaligned (data)";
|
||||
break;
|
||||
case EXCP_UNALIGND:
|
||||
name = "Misaligned (destination)";
|
||||
break;
|
||||
case EXCP_DIV:
|
||||
name = "DIV error";
|
||||
break;
|
||||
case EXCP_TRAP:
|
||||
name = "TRAP insn";
|
||||
break;
|
||||
case EXCP_BREAK:
|
||||
name = "BREAK insn";
|
||||
break;
|
||||
case EXCP_SEMIHOST:
|
||||
name = "SEMIHOST insn";
|
||||
break;
|
||||
}
|
||||
if (name) {
|
||||
qemu_log("%s at pc=0x%08x\n", name, env->pc);
|
||||
} else {
|
||||
qemu_log("Unknown exception %d at pc=0x%08x\n",
|
||||
cs->exception_index, env->pc);
|
||||
}
|
||||
}
|
||||
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_IRQ:
|
||||
/* Note that PC is advanced for interrupts as well. */
|
||||
env->pc += 4;
|
||||
if (cpu->eic_present) {
|
||||
do_eic_irq(cpu);
|
||||
} else {
|
||||
do_iic_irq(cpu);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCP_TLB_D:
|
||||
tlbmisc_set = CR_TLBMISC_D;
|
||||
/* fall through */
|
||||
case EXCP_TLB_X:
|
||||
if (env->ctrl[CR_STATUS] & CR_STATUS_EH) {
|
||||
tlbmisc_set |= CR_TLBMISC_DBL;
|
||||
/*
|
||||
* Normally, we don't write to tlbmisc unless !EH,
|
||||
* so do it manually for the double-tlb miss exception.
|
||||
*/
|
||||
env->ctrl[CR_TLBMISC] &= ~(CR_TLBMISC_D |
|
||||
CR_TLBMISC_PERM |
|
||||
CR_TLBMISC_BAD);
|
||||
env->ctrl[CR_TLBMISC] |= tlbmisc_set;
|
||||
do_exception(cpu, cpu->exception_addr, 0, false);
|
||||
} else {
|
||||
tlbmisc_set |= CR_TLBMISC_WE;
|
||||
do_exception(cpu, cpu->fast_tlb_miss_addr, tlbmisc_set, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCP_PERM_R:
|
||||
case EXCP_PERM_W:
|
||||
tlbmisc_set = CR_TLBMISC_D;
|
||||
/* fall through */
|
||||
case EXCP_PERM_X:
|
||||
tlbmisc_set |= CR_TLBMISC_PERM;
|
||||
if (!(env->ctrl[CR_STATUS] & CR_STATUS_EH)) {
|
||||
tlbmisc_set |= CR_TLBMISC_WE;
|
||||
}
|
||||
do_exception(cpu, cpu->exception_addr, tlbmisc_set, false);
|
||||
break;
|
||||
|
||||
case EXCP_SUPERA_D:
|
||||
case EXCP_UNALIGN:
|
||||
tlbmisc_set = CR_TLBMISC_D;
|
||||
/* fall through */
|
||||
case EXCP_SUPERA_X:
|
||||
case EXCP_UNALIGND:
|
||||
tlbmisc_set |= CR_TLBMISC_BAD;
|
||||
do_exception(cpu, cpu->exception_addr, tlbmisc_set, false);
|
||||
break;
|
||||
|
||||
case EXCP_SUPERI:
|
||||
case EXCP_ILLEGAL:
|
||||
case EXCP_DIV:
|
||||
case EXCP_TRAP:
|
||||
do_exception(cpu, cpu->exception_addr, 0, false);
|
||||
break;
|
||||
|
||||
case EXCP_BREAK:
|
||||
do_exception(cpu, cpu->exception_addr, 0, true);
|
||||
break;
|
||||
|
||||
case EXCP_SEMIHOST:
|
||||
do_nios2_semihosting(env);
|
||||
break;
|
||||
|
||||
default:
|
||||
cpu_abort(cs, "unhandled exception type=%d\n", cs->exception_index);
|
||||
}
|
||||
}
|
||||
|
||||
hwaddr nios2_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||
{
|
||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
CPUNios2State *env = &cpu->env;
|
||||
target_ulong vaddr, paddr = 0;
|
||||
Nios2MMULookup lu;
|
||||
unsigned int hit;
|
||||
|
||||
if (cpu->mmu_present && (addr < 0xC0000000)) {
|
||||
hit = mmu_translate(env, &lu, addr, 0, 0);
|
||||
if (hit) {
|
||||
vaddr = addr & TARGET_PAGE_MASK;
|
||||
paddr = lu.paddr + vaddr - lu.vaddr;
|
||||
} else {
|
||||
paddr = -1;
|
||||
qemu_log("cpu_get_phys_page debug MISS: %#" PRIx64 "\n", addr);
|
||||
}
|
||||
} else {
|
||||
paddr = addr & TARGET_PAGE_MASK;
|
||||
}
|
||||
|
||||
return paddr;
|
||||
}
|
||||
|
||||
void nios2_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
|
||||
MMUAccessType access_type,
|
||||
int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
CPUNios2State *env = cpu_env(cs);
|
||||
|
||||
env->ctrl[CR_BADADDR] = addr;
|
||||
cs->exception_index = EXCP_UNALIGN;
|
||||
nios2_cpu_loop_exit_advance(env, retaddr);
|
||||
}
|
||||
|
||||
bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr)
|
||||
{
|
||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
||||
CPUNios2State *env = &cpu->env;
|
||||
unsigned int excp;
|
||||
target_ulong vaddr, paddr;
|
||||
Nios2MMULookup lu;
|
||||
unsigned int hit;
|
||||
|
||||
if (!cpu->mmu_present) {
|
||||
/* No MMU */
|
||||
address &= TARGET_PAGE_MASK;
|
||||
tlb_set_page(cs, address, address, PAGE_BITS,
|
||||
mmu_idx, TARGET_PAGE_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (MMU_SUPERVISOR_IDX == mmu_idx) {
|
||||
if (address >= 0xC0000000) {
|
||||
/* Kernel physical page - TLB bypassed */
|
||||
address &= TARGET_PAGE_MASK;
|
||||
tlb_set_page(cs, address, address, PAGE_BITS,
|
||||
mmu_idx, TARGET_PAGE_SIZE);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (address >= 0x80000000) {
|
||||
/* Illegal access from user mode */
|
||||
if (probe) {
|
||||
return false;
|
||||
}
|
||||
cs->exception_index = (access_type == MMU_INST_FETCH
|
||||
? EXCP_SUPERA_X : EXCP_SUPERA_D);
|
||||
env->ctrl[CR_BADADDR] = address;
|
||||
nios2_cpu_loop_exit_advance(env, retaddr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Virtual page. */
|
||||
hit = mmu_translate(env, &lu, address, access_type, mmu_idx);
|
||||
if (hit) {
|
||||
vaddr = address & TARGET_PAGE_MASK;
|
||||
paddr = lu.paddr + vaddr - lu.vaddr;
|
||||
|
||||
if (((access_type == MMU_DATA_LOAD) && (lu.prot & PAGE_READ)) ||
|
||||
((access_type == MMU_DATA_STORE) && (lu.prot & PAGE_WRITE)) ||
|
||||
((access_type == MMU_INST_FETCH) && (lu.prot & PAGE_EXEC))) {
|
||||
tlb_set_page(cs, vaddr, paddr, lu.prot,
|
||||
mmu_idx, TARGET_PAGE_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Permission violation */
|
||||
excp = (access_type == MMU_DATA_LOAD ? EXCP_PERM_R :
|
||||
access_type == MMU_DATA_STORE ? EXCP_PERM_W : EXCP_PERM_X);
|
||||
} else {
|
||||
excp = (access_type == MMU_INST_FETCH ? EXCP_TLB_X: EXCP_TLB_D);
|
||||
}
|
||||
|
||||
if (probe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
env->ctrl[CR_TLBMISC] = FIELD_DP32(env->ctrl[CR_TLBMISC], CR_TLBMISC, D,
|
||||
access_type != MMU_INST_FETCH);
|
||||
env->ctrl[CR_PTEADDR] = FIELD_DP32(env->ctrl[CR_PTEADDR], CR_PTEADDR, VPN,
|
||||
address >> TARGET_PAGE_BITS);
|
||||
env->mmu.pteaddr_wr = env->ctrl[CR_PTEADDR];
|
||||
|
||||
cs->exception_index = excp;
|
||||
env->ctrl[CR_BADADDR] = address;
|
||||
nios2_cpu_loop_exit_advance(env, retaddr);
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Altera Nios II helper routines header.
|
||||
*
|
||||
* Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_WG, noreturn, env, i32)
|
||||
DEF_HELPER_FLAGS_3(divs, TCG_CALL_NO_WG, s32, env, s32, s32)
|
||||
DEF_HELPER_FLAGS_3(divu, TCG_CALL_NO_WG, i32, env, i32, i32)
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
DEF_HELPER_3(eret, noreturn, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(rdprs, TCG_CALL_NO_WG, i32, env, i32)
|
||||
DEF_HELPER_3(wrprs, void, env, i32, i32)
|
||||
DEF_HELPER_2(mmu_write_tlbacc, void, env, i32)
|
||||
DEF_HELPER_2(mmu_write_tlbmisc, void, env, i32)
|
||||
DEF_HELPER_2(mmu_write_pteaddr, void, env, i32)
|
||||
#endif
|
|
@ -1,17 +0,0 @@
|
|||
nios2_ss = ss.source_set()
|
||||
nios2_ss.add(files(
|
||||
'cpu.c',
|
||||
'op_helper.c',
|
||||
'translate.c',
|
||||
))
|
||||
|
||||
nios2_system_ss = ss.source_set()
|
||||
nios2_system_ss.add(files(
|
||||
'helper.c',
|
||||
'monitor.c',
|
||||
'mmu.c',
|
||||
'nios2-semi.c',
|
||||
))
|
||||
|
||||
target_arch += {'nios2': nios2_ss}
|
||||
target_system_arch += {'nios2': nios2_system_ss}
|
|
@ -1,216 +0,0 @@
|
|||
/*
|
||||
* Altera Nios II MMU emulation for qemu.
|
||||
*
|
||||
* Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "mmu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "trace/trace-target_nios2.h"
|
||||
|
||||
|
||||
/* rw - 0 = read, 1 = write, 2 = fetch. */
|
||||
unsigned int mmu_translate(CPUNios2State *env,
|
||||
Nios2MMULookup *lu,
|
||||
target_ulong vaddr, int rw, int mmu_idx)
|
||||
{
|
||||
Nios2CPU *cpu = env_archcpu(env);
|
||||
int pid = FIELD_EX32(env->mmu.tlbmisc_wr, CR_TLBMISC, PID);
|
||||
int vpn = vaddr >> 12;
|
||||
int way, n_ways = cpu->tlb_num_ways;
|
||||
|
||||
for (way = 0; way < n_ways; way++) {
|
||||
uint32_t index = (way * n_ways) + (vpn & env->mmu.tlb_entry_mask);
|
||||
Nios2TLBEntry *entry = &env->mmu.tlb[index];
|
||||
|
||||
if (((entry->tag >> 12) != vpn) ||
|
||||
(((entry->tag & (1 << 11)) == 0) &&
|
||||
((entry->tag & ((1 << cpu->pid_num_bits) - 1)) != pid))) {
|
||||
trace_nios2_mmu_translate_miss(vaddr, pid, index, entry->tag);
|
||||
continue;
|
||||
}
|
||||
|
||||
lu->vaddr = vaddr & TARGET_PAGE_MASK;
|
||||
lu->paddr = FIELD_EX32(entry->data, CR_TLBACC, PFN) << TARGET_PAGE_BITS;
|
||||
lu->prot = ((entry->data & CR_TLBACC_R) ? PAGE_READ : 0) |
|
||||
((entry->data & CR_TLBACC_W) ? PAGE_WRITE : 0) |
|
||||
((entry->data & CR_TLBACC_X) ? PAGE_EXEC : 0);
|
||||
|
||||
trace_nios2_mmu_translate_hit(vaddr, pid, index, lu->paddr, lu->prot);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mmu_flush_pid(CPUNios2State *env, uint32_t pid)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
Nios2CPU *cpu = env_archcpu(env);
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < cpu->tlb_num_entries; idx++) {
|
||||
Nios2TLBEntry *entry = &env->mmu.tlb[idx];
|
||||
|
||||
if ((entry->tag & (1 << 10)) && (!(entry->tag & (1 << 11))) &&
|
||||
((entry->tag & ((1 << cpu->pid_num_bits) - 1)) == pid)) {
|
||||
uint32_t vaddr = entry->tag & TARGET_PAGE_MASK;
|
||||
|
||||
trace_nios2_mmu_flush_pid_hit(pid, idx, vaddr);
|
||||
tlb_flush_page(cs, vaddr);
|
||||
} else {
|
||||
trace_nios2_mmu_flush_pid_miss(pid, idx, entry->tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void helper_mmu_write_tlbacc(CPUNios2State *env, uint32_t v)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
Nios2CPU *cpu = env_archcpu(env);
|
||||
|
||||
trace_nios2_mmu_write_tlbacc(FIELD_EX32(v, CR_TLBACC, IG),
|
||||
(v & CR_TLBACC_C) ? 'C' : '.',
|
||||
(v & CR_TLBACC_R) ? 'R' : '.',
|
||||
(v & CR_TLBACC_W) ? 'W' : '.',
|
||||
(v & CR_TLBACC_X) ? 'X' : '.',
|
||||
(v & CR_TLBACC_G) ? 'G' : '.',
|
||||
FIELD_EX32(v, CR_TLBACC, PFN));
|
||||
|
||||
/* if tlbmisc.WE == 1 then trigger a TLB write on writes to TLBACC */
|
||||
if (env->ctrl[CR_TLBMISC] & CR_TLBMISC_WE) {
|
||||
int way = FIELD_EX32(env->ctrl[CR_TLBMISC], CR_TLBMISC, WAY);
|
||||
int vpn = FIELD_EX32(env->mmu.pteaddr_wr, CR_PTEADDR, VPN);
|
||||
int pid = FIELD_EX32(env->mmu.tlbmisc_wr, CR_TLBMISC, PID);
|
||||
int g = FIELD_EX32(v, CR_TLBACC, G);
|
||||
int valid = FIELD_EX32(vpn, CR_TLBACC, PFN) < 0xC0000;
|
||||
Nios2TLBEntry *entry =
|
||||
&env->mmu.tlb[(way * cpu->tlb_num_ways) +
|
||||
(vpn & env->mmu.tlb_entry_mask)];
|
||||
uint32_t newTag = (vpn << 12) | (g << 11) | (valid << 10) | pid;
|
||||
uint32_t newData = v & (CR_TLBACC_C | CR_TLBACC_R | CR_TLBACC_W |
|
||||
CR_TLBACC_X | R_CR_TLBACC_PFN_MASK);
|
||||
|
||||
if ((entry->tag != newTag) || (entry->data != newData)) {
|
||||
if (entry->tag & (1 << 10)) {
|
||||
/* Flush existing entry */
|
||||
tlb_flush_page(cs, entry->tag & TARGET_PAGE_MASK);
|
||||
}
|
||||
entry->tag = newTag;
|
||||
entry->data = newData;
|
||||
}
|
||||
/* Auto-increment tlbmisc.WAY */
|
||||
env->ctrl[CR_TLBMISC] = FIELD_DP32(env->ctrl[CR_TLBMISC],
|
||||
CR_TLBMISC, WAY,
|
||||
(way + 1) & (cpu->tlb_num_ways - 1));
|
||||
}
|
||||
|
||||
/* Writes to TLBACC don't change the read-back value */
|
||||
env->mmu.tlbacc_wr = v;
|
||||
}
|
||||
|
||||
void helper_mmu_write_tlbmisc(CPUNios2State *env, uint32_t v)
|
||||
{
|
||||
Nios2CPU *cpu = env_archcpu(env);
|
||||
uint32_t new_pid = FIELD_EX32(v, CR_TLBMISC, PID);
|
||||
uint32_t old_pid = FIELD_EX32(env->mmu.tlbmisc_wr, CR_TLBMISC, PID);
|
||||
uint32_t way = FIELD_EX32(v, CR_TLBMISC, WAY);
|
||||
|
||||
trace_nios2_mmu_write_tlbmisc(way,
|
||||
(v & CR_TLBMISC_RD) ? 'R' : '.',
|
||||
(v & CR_TLBMISC_WE) ? 'W' : '.',
|
||||
(v & CR_TLBMISC_DBL) ? '2' : '.',
|
||||
(v & CR_TLBMISC_BAD) ? 'B' : '.',
|
||||
(v & CR_TLBMISC_PERM) ? 'P' : '.',
|
||||
(v & CR_TLBMISC_D) ? 'D' : '.',
|
||||
new_pid);
|
||||
|
||||
if (new_pid != old_pid) {
|
||||
mmu_flush_pid(env, old_pid);
|
||||
}
|
||||
|
||||
/* if tlbmisc.RD == 1 then trigger a TLB read on writes to TLBMISC */
|
||||
if (v & CR_TLBMISC_RD) {
|
||||
int vpn = FIELD_EX32(env->mmu.pteaddr_wr, CR_PTEADDR, VPN);
|
||||
Nios2TLBEntry *entry =
|
||||
&env->mmu.tlb[(way * cpu->tlb_num_ways) +
|
||||
(vpn & env->mmu.tlb_entry_mask)];
|
||||
|
||||
env->ctrl[CR_TLBACC] &= R_CR_TLBACC_IG_MASK;
|
||||
env->ctrl[CR_TLBACC] |= entry->data;
|
||||
env->ctrl[CR_TLBACC] |= (entry->tag & (1 << 11)) ? CR_TLBACC_G : 0;
|
||||
env->ctrl[CR_TLBMISC] = FIELD_DP32(v, CR_TLBMISC, PID,
|
||||
entry->tag &
|
||||
((1 << cpu->pid_num_bits) - 1));
|
||||
env->ctrl[CR_PTEADDR] = FIELD_DP32(env->ctrl[CR_PTEADDR],
|
||||
CR_PTEADDR, VPN,
|
||||
entry->tag >> TARGET_PAGE_BITS);
|
||||
} else {
|
||||
env->ctrl[CR_TLBMISC] = v;
|
||||
}
|
||||
|
||||
env->mmu.tlbmisc_wr = v;
|
||||
}
|
||||
|
||||
void helper_mmu_write_pteaddr(CPUNios2State *env, uint32_t v)
|
||||
{
|
||||
trace_nios2_mmu_write_pteaddr(FIELD_EX32(v, CR_PTEADDR, PTBASE),
|
||||
FIELD_EX32(v, CR_PTEADDR, VPN));
|
||||
|
||||
/* Writes to PTEADDR don't change the read-back VPN value */
|
||||
env->ctrl[CR_PTEADDR] = ((v & ~R_CR_PTEADDR_VPN_MASK) |
|
||||
(env->ctrl[CR_PTEADDR] & R_CR_PTEADDR_VPN_MASK));
|
||||
env->mmu.pteaddr_wr = v;
|
||||
}
|
||||
|
||||
void mmu_init(CPUNios2State *env)
|
||||
{
|
||||
Nios2CPU *cpu = env_archcpu(env);
|
||||
Nios2MMU *mmu = &env->mmu;
|
||||
|
||||
mmu->tlb_entry_mask = (cpu->tlb_num_entries / cpu->tlb_num_ways) - 1;
|
||||
mmu->tlb = g_new0(Nios2TLBEntry, cpu->tlb_num_entries);
|
||||
}
|
||||
|
||||
void dump_mmu(CPUNios2State *env)
|
||||
{
|
||||
Nios2CPU *cpu = env_archcpu(env);
|
||||
int i;
|
||||
|
||||
qemu_printf("MMU: ways %d, entries %d, pid bits %d\n",
|
||||
cpu->tlb_num_ways, cpu->tlb_num_entries,
|
||||
cpu->pid_num_bits);
|
||||
|
||||
for (i = 0; i < cpu->tlb_num_entries; i++) {
|
||||
Nios2TLBEntry *entry = &env->mmu.tlb[i];
|
||||
qemu_printf("TLB[%d] = %08X %08X %c VPN %05X "
|
||||
"PID %02X %c PFN %05X %c%c%c%c\n",
|
||||
i, entry->tag, entry->data,
|
||||
(entry->tag & (1 << 10)) ? 'V' : '-',
|
||||
entry->tag >> 12,
|
||||
entry->tag & ((1 << cpu->pid_num_bits) - 1),
|
||||
(entry->tag & (1 << 11)) ? 'G' : '-',
|
||||
FIELD_EX32(entry->data, CR_TLBACC, PFN),
|
||||
(entry->data & CR_TLBACC_C) ? 'C' : '-',
|
||||
(entry->data & CR_TLBACC_R) ? 'R' : '-',
|
||||
(entry->data & CR_TLBACC_W) ? 'W' : '-',
|
||||
(entry->data & CR_TLBACC_X) ? 'X' : '-');
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Altera Nios II MMU emulation for qemu.
|
||||
*
|
||||
* Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#ifndef NIOS2_MMU_H
|
||||
#define NIOS2_MMU_H
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
typedef struct Nios2TLBEntry {
|
||||
target_ulong tag;
|
||||
target_ulong data;
|
||||
} Nios2TLBEntry;
|
||||
|
||||
typedef struct Nios2MMU {
|
||||
int tlb_entry_mask;
|
||||
uint32_t pteaddr_wr;
|
||||
uint32_t tlbacc_wr;
|
||||
uint32_t tlbmisc_wr;
|
||||
Nios2TLBEntry *tlb;
|
||||
} Nios2MMU;
|
||||
|
||||
typedef struct Nios2MMULookup {
|
||||
target_ulong vaddr;
|
||||
target_ulong paddr;
|
||||
int prot;
|
||||
} Nios2MMULookup;
|
||||
|
||||
void mmu_flip_um(CPUNios2State *env, unsigned int um);
|
||||
unsigned int mmu_translate(CPUNios2State *env,
|
||||
Nios2MMULookup *lu,
|
||||
target_ulong vaddr, int rw, int mmu_idx);
|
||||
void mmu_write(CPUNios2State *env, uint32_t rn, uint32_t v);
|
||||
void mmu_init(CPUNios2State *env);
|
||||
|
||||
#endif /* NIOS2_MMU_H */
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* QEMU monitor
|
||||
*
|
||||
* Copyright (c) 2003-2004 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "monitor/hmp-target.h"
|
||||
#include "monitor/hmp.h"
|
||||
|
||||
void hmp_info_tlb(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
CPUArchState *env1 = mon_get_cpu_env(mon);
|
||||
|
||||
dump_mmu(env1);
|
||||
}
|
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
* Nios II Semihosting syscall interface.
|
||||
* This code is derived from m68k-semi.c.
|
||||
* The semihosting protocol implemented here is described in the
|
||||
* libgloss sources:
|
||||
* https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=libgloss/nios2/nios2-semi.txt;hb=HEAD
|
||||
*
|
||||
* Copyright (c) 2017-2019 Mentor Graphics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "gdbstub/syscalls.h"
|
||||
#include "gdbstub/helpers.h"
|
||||
#include "semihosting/syscalls.h"
|
||||
#include "semihosting/uaccess.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
#define HOSTED_EXIT 0
|
||||
#define HOSTED_INIT_SIM 1
|
||||
#define HOSTED_OPEN 2
|
||||
#define HOSTED_CLOSE 3
|
||||
#define HOSTED_READ 4
|
||||
#define HOSTED_WRITE 5
|
||||
#define HOSTED_LSEEK 6
|
||||
#define HOSTED_RENAME 7
|
||||
#define HOSTED_UNLINK 8
|
||||
#define HOSTED_STAT 9
|
||||
#define HOSTED_FSTAT 10
|
||||
#define HOSTED_GETTIMEOFDAY 11
|
||||
#define HOSTED_ISATTY 12
|
||||
#define HOSTED_SYSTEM 13
|
||||
|
||||
static int host_to_gdb_errno(int err)
|
||||
{
|
||||
#define E(X) case E##X: return GDB_E##X
|
||||
switch (err) {
|
||||
E(PERM);
|
||||
E(NOENT);
|
||||
E(INTR);
|
||||
E(BADF);
|
||||
E(ACCES);
|
||||
E(FAULT);
|
||||
E(BUSY);
|
||||
E(EXIST);
|
||||
E(NODEV);
|
||||
E(NOTDIR);
|
||||
E(ISDIR);
|
||||
E(INVAL);
|
||||
E(NFILE);
|
||||
E(MFILE);
|
||||
E(FBIG);
|
||||
E(NOSPC);
|
||||
E(SPIPE);
|
||||
E(ROFS);
|
||||
E(NAMETOOLONG);
|
||||
default:
|
||||
return GDB_EUNKNOWN;
|
||||
}
|
||||
#undef E
|
||||
}
|
||||
|
||||
static void nios2_semi_u32_cb(CPUState *cs, uint64_t ret, int err)
|
||||
{
|
||||
CPUNios2State *env = cpu_env(cs);
|
||||
target_ulong args = env->regs[R_ARG1];
|
||||
|
||||
if (put_user_u32(ret, args) ||
|
||||
put_user_u32(host_to_gdb_errno(err), args + 4)) {
|
||||
/*
|
||||
* The nios2 semihosting ABI does not provide any way to report this
|
||||
* error to the guest, so the best we can do is log it in qemu.
|
||||
* It is always a guest error not to pass us a valid argument block.
|
||||
*/
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "nios2-semihosting: return value "
|
||||
"discarded because argument block not writable\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void nios2_semi_u64_cb(CPUState *cs, uint64_t ret, int err)
|
||||
{
|
||||
CPUNios2State *env = cpu_env(cs);
|
||||
target_ulong args = env->regs[R_ARG1];
|
||||
|
||||
if (put_user_u32(ret >> 32, args) ||
|
||||
put_user_u32(ret, args + 4) ||
|
||||
put_user_u32(host_to_gdb_errno(err), args + 8)) {
|
||||
/* No way to report this via nios2 semihosting ABI; just log it */
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "nios2-semihosting: return value "
|
||||
"discarded because argument block not writable\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the input value from the argument block; fail the semihosting
|
||||
* call if the memory read fails.
|
||||
*/
|
||||
#define GET_ARG(n) do { \
|
||||
if (get_user_ual(arg ## n, args + (n) * 4)) { \
|
||||
goto failed; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define GET_ARG64(n) do { \
|
||||
if (get_user_ual(arg ## n, args + (n) * 4)) { \
|
||||
goto failed64; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void do_nios2_semihosting(CPUNios2State *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int nr;
|
||||
uint32_t args;
|
||||
target_ulong arg0, arg1, arg2, arg3;
|
||||
|
||||
nr = env->regs[R_ARG0];
|
||||
args = env->regs[R_ARG1];
|
||||
switch (nr) {
|
||||
case HOSTED_EXIT:
|
||||
gdb_exit(env->regs[R_ARG1]);
|
||||
exit(env->regs[R_ARG1]);
|
||||
|
||||
case HOSTED_OPEN:
|
||||
GET_ARG(0);
|
||||
GET_ARG(1);
|
||||
GET_ARG(2);
|
||||
GET_ARG(3);
|
||||
semihost_sys_open(cs, nios2_semi_u32_cb, arg0, arg1, arg2, arg3);
|
||||
break;
|
||||
|
||||
case HOSTED_CLOSE:
|
||||
GET_ARG(0);
|
||||
semihost_sys_close(cs, nios2_semi_u32_cb, arg0);
|
||||
break;
|
||||
|
||||
case HOSTED_READ:
|
||||
GET_ARG(0);
|
||||
GET_ARG(1);
|
||||
GET_ARG(2);
|
||||
semihost_sys_read(cs, nios2_semi_u32_cb, arg0, arg1, arg2);
|
||||
break;
|
||||
|
||||
case HOSTED_WRITE:
|
||||
GET_ARG(0);
|
||||
GET_ARG(1);
|
||||
GET_ARG(2);
|
||||
semihost_sys_write(cs, nios2_semi_u32_cb, arg0, arg1, arg2);
|
||||
break;
|
||||
|
||||
case HOSTED_LSEEK:
|
||||
GET_ARG64(0);
|
||||
GET_ARG64(1);
|
||||
GET_ARG64(2);
|
||||
GET_ARG64(3);
|
||||
semihost_sys_lseek(cs, nios2_semi_u64_cb, arg0,
|
||||
deposit64(arg2, 32, 32, arg1), arg3);
|
||||
break;
|
||||
|
||||
case HOSTED_RENAME:
|
||||
GET_ARG(0);
|
||||
GET_ARG(1);
|
||||
GET_ARG(2);
|
||||
GET_ARG(3);
|
||||
semihost_sys_rename(cs, nios2_semi_u32_cb, arg0, arg1, arg2, arg3);
|
||||
break;
|
||||
|
||||
case HOSTED_UNLINK:
|
||||
GET_ARG(0);
|
||||
GET_ARG(1);
|
||||
semihost_sys_remove(cs, nios2_semi_u32_cb, arg0, arg1);
|
||||
break;
|
||||
|
||||
case HOSTED_STAT:
|
||||
GET_ARG(0);
|
||||
GET_ARG(1);
|
||||
GET_ARG(2);
|
||||
semihost_sys_stat(cs, nios2_semi_u32_cb, arg0, arg1, arg2);
|
||||
break;
|
||||
|
||||
case HOSTED_FSTAT:
|
||||
GET_ARG(0);
|
||||
GET_ARG(1);
|
||||
semihost_sys_fstat(cs, nios2_semi_u32_cb, arg0, arg1);
|
||||
break;
|
||||
|
||||
case HOSTED_GETTIMEOFDAY:
|
||||
GET_ARG(0);
|
||||
GET_ARG(1);
|
||||
semihost_sys_gettimeofday(cs, nios2_semi_u32_cb, arg0, arg1);
|
||||
break;
|
||||
|
||||
case HOSTED_ISATTY:
|
||||
GET_ARG(0);
|
||||
semihost_sys_isatty(cs, nios2_semi_u32_cb, arg0);
|
||||
break;
|
||||
|
||||
case HOSTED_SYSTEM:
|
||||
GET_ARG(0);
|
||||
GET_ARG(1);
|
||||
semihost_sys_system(cs, nios2_semi_u32_cb, arg0, arg1);
|
||||
break;
|
||||
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "nios2-semihosting: unsupported "
|
||||
"semihosting syscall %d\n", nr);
|
||||
nios2_semi_u32_cb(cs, -1, ENOSYS);
|
||||
break;
|
||||
|
||||
failed:
|
||||
nios2_semi_u32_cb(cs, -1, EFAULT);
|
||||
break;
|
||||
failed64:
|
||||
nios2_semi_u64_cb(cs, -1, EFAULT);
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Altera Nios II helper routines.
|
||||
*
|
||||
* Copyright (C) 2012 Chris Wulff <crwulff@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see
|
||||
* <http://www.gnu.org/licenses/lgpl-2.1.html>
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
void helper_raise_exception(CPUNios2State *env, uint32_t index)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
cs->exception_index = index;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
void nios2_cpu_loop_exit_advance(CPUNios2State *env, uintptr_t retaddr)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
/*
|
||||
* Note that PC is advanced for all hardware exceptions.
|
||||
* Do this here, rather than in restore_state_to_opc(),
|
||||
* lest we affect QEMU internal exceptions, like EXCP_DEBUG.
|
||||
*/
|
||||
cpu_restore_state(cs, retaddr);
|
||||
env->pc += 4;
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
static void maybe_raise_div(CPUNios2State *env, uintptr_t ra)
|
||||
{
|
||||
Nios2CPU *cpu = env_archcpu(env);
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
if (cpu->diverr_present) {
|
||||
cs->exception_index = EXCP_DIV;
|
||||
nios2_cpu_loop_exit_advance(env, ra);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t helper_divs(CPUNios2State *env, int32_t num, int32_t den)
|
||||
{
|
||||
if (unlikely(den == 0) || unlikely(den == -1 && num == INT32_MIN)) {
|
||||
maybe_raise_div(env, GETPC());
|
||||
return num; /* undefined */
|
||||
}
|
||||
return num / den;
|
||||
}
|
||||
|
||||
uint32_t helper_divu(CPUNios2State *env, uint32_t num, uint32_t den)
|
||||
{
|
||||
if (unlikely(den == 0)) {
|
||||
maybe_raise_div(env, GETPC());
|
||||
return num; /* undefined */
|
||||
}
|
||||
return num / den;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
void helper_eret(CPUNios2State *env, uint32_t new_status, uint32_t new_pc)
|
||||
{
|
||||
Nios2CPU *cpu = env_archcpu(env);
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
if (unlikely(new_pc & 3)) {
|
||||
env->ctrl[CR_BADADDR] = new_pc;
|
||||
cs->exception_index = EXCP_UNALIGND;
|
||||
nios2_cpu_loop_exit_advance(env, GETPC());
|
||||
}
|
||||
|
||||
/*
|
||||
* None of estatus, bstatus, or sstatus have constraints on write;
|
||||
* do not allow reserved fields in status to be set.
|
||||
* When shadow registers are enabled, eret *does* restore CRS.
|
||||
* Rather than testing eic_present to decide, mask CRS out of
|
||||
* the set of readonly fields.
|
||||
*/
|
||||
new_status &= cpu->cr_state[CR_STATUS].writable |
|
||||
(cpu->cr_state[CR_STATUS].readonly & R_CR_STATUS_CRS_MASK);
|
||||
|
||||
env->ctrl[CR_STATUS] = new_status;
|
||||
env->pc = new_pc;
|
||||
nios2_update_crs(env);
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
/*
|
||||
* RDPRS and WRPRS are implemented out of line so that if PRS == CRS,
|
||||
* all of the tcg global temporaries are synced back to ENV.
|
||||
*/
|
||||
uint32_t helper_rdprs(CPUNios2State *env, uint32_t regno)
|
||||
{
|
||||
unsigned prs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, PRS);
|
||||
return env->shadow_regs[prs][regno];
|
||||
}
|
||||
|
||||
void helper_wrprs(CPUNios2State *env, uint32_t regno, uint32_t val)
|
||||
{
|
||||
unsigned prs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, PRS);
|
||||
env->shadow_regs[prs][regno] = val;
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
|
@ -1,10 +0,0 @@
|
|||
# mmu.c
|
||||
nios2_mmu_translate_miss(uint32_t vaddr, uint32_t pid, uint32_t index, uint32_t tag) "mmu_translate: MISS vaddr=0x%08x pid=%u TLB[%u] tag=0x%08x"
|
||||
nios2_mmu_translate_hit(uint32_t vaddr, uint32_t pid, uint32_t index, uint32_t paddr, uint32_t prot) "mmu_translate: HIT vaddr=0x%08x pid=%u TLB[%u] paddr=0x%08x prot=0x%x"
|
||||
|
||||
nios2_mmu_flush_pid_miss(uint32_t pid, uint32_t index, uint32_t vaddr) "mmu_flush: MISS pid=%u TLB[%u] tag=0x%08x"
|
||||
nios2_mmu_flush_pid_hit(uint32_t pid, uint32_t index, uint32_t vaddr) "mmu_flush: HIT pid=%u TLB[%u] vaddr=0x%08x"
|
||||
|
||||
nios2_mmu_write_tlbacc(uint32_t ig, char c, char r, char w, char x, char g, uint32_t pfn) "mmu_write_tlbacc: ig=0x%02x flags=%c%c%c%c%c pfn=0x%08x"
|
||||
nios2_mmu_write_tlbmisc(uint32_t way, char r, char w, char t, char b, char p, char d, uint32_t pid) "mmu_write_tlbmisc: way=0x%x flags=%c%c%c%c%c%c pid=%u"
|
||||
nios2_mmu_write_pteaddr(uint32_t ptb, uint32_t vpn) "mmu_write_pteaddr: ptbase=0x%03x vpn=0x%05x"
|
File diff suppressed because it is too large
Load Diff
|
@ -1426,14 +1426,6 @@ class BootLinuxConsole(LinuxKernelTest):
|
|||
tar_hash = '20334cdaf386108c530ff0badaecc955693027dd'
|
||||
self.do_test_advcal_2018('20', tar_hash, 'vmlinux')
|
||||
|
||||
def test_nios2_10m50(self):
|
||||
"""
|
||||
:avocado: tags=arch:nios2
|
||||
:avocado: tags=machine:10m50-ghrd
|
||||
"""
|
||||
tar_hash = 'e4251141726c412ac0407c5a6bceefbbff018918'
|
||||
self.do_test_advcal_2018('14', tar_hash, 'vmlinux.elf')
|
||||
|
||||
def test_ppc64_e500(self):
|
||||
"""
|
||||
:avocado: tags=arch:ppc64
|
||||
|
|
|
@ -382,17 +382,6 @@ class ReplayKernelNormal(ReplayKernelBase):
|
|||
file_path = self.fetch_asset(tar_url, asset_hash=tar_hash)
|
||||
self.do_test_advcal_2018(file_path, 'vmlinux')
|
||||
|
||||
def test_nios2_10m50(self):
|
||||
"""
|
||||
:avocado: tags=arch:nios2
|
||||
:avocado: tags=machine:10m50-ghrd
|
||||
"""
|
||||
tar_hash = 'e4251141726c412ac0407c5a6bceefbbff018918'
|
||||
tar_url = ('https://qemu-advcal.gitlab.io'
|
||||
'/qac-best-of-multiarch/download/day14.tar.xz')
|
||||
file_path = self.fetch_asset(tar_url, asset_hash=tar_hash)
|
||||
self.do_test_advcal_2018(file_path, 'vmlinux.elf')
|
||||
|
||||
def test_ppc_g3beige(self):
|
||||
"""
|
||||
:avocado: tags=arch:ppc
|
||||
|
|
|
@ -114,13 +114,8 @@ docker-image-debian-microblaze-cross: $(DOCKER_FILES_DIR)/debian-toolchain.docke
|
|||
$(DOCKER_FILES_DIR)/debian-microblaze-cross.d/build-toolchain.sh
|
||||
$(call debian-toolchain, $@)
|
||||
|
||||
docker-image-debian-nios2-cross: $(DOCKER_FILES_DIR)/debian-toolchain.docker \
|
||||
$(DOCKER_FILES_DIR)/debian-nios2-cross.d/build-toolchain.sh
|
||||
$(call debian-toolchain, $@)
|
||||
|
||||
# These images may be good enough for building tests but not for test builds
|
||||
DOCKER_PARTIAL_IMAGES += debian-microblaze-cross
|
||||
DOCKER_PARTIAL_IMAGES += debian-nios2-cross
|
||||
DOCKER_PARTIAL_IMAGES += debian-xtensa-cross
|
||||
DOCKER_PARTIAL_IMAGES += fedora-cris-cross
|
||||
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
TARGET=nios2-linux-gnu
|
||||
LINUX_ARCH=nios2
|
||||
|
||||
J=$(expr $(nproc) / 2)
|
||||
TOOLCHAIN_INSTALL=/usr/local
|
||||
TOOLCHAIN_BIN=${TOOLCHAIN_INSTALL}/bin
|
||||
CROSS_SYSROOT=${TOOLCHAIN_INSTALL}/$TARGET/sys-root
|
||||
|
||||
export PATH=${TOOLCHAIN_BIN}:$PATH
|
||||
|
||||
#
|
||||
# Grab all of the source for the toolchain bootstrap.
|
||||
#
|
||||
|
||||
wget https://ftp.gnu.org/gnu/binutils/binutils-2.37.tar.xz
|
||||
wget https://ftp.gnu.org/gnu/gcc/gcc-11.2.0/gcc-11.2.0.tar.xz
|
||||
wget https://ftp.gnu.org/gnu/glibc/glibc-2.34.tar.xz
|
||||
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.70.tar.xz
|
||||
|
||||
tar axf binutils-2.37.tar.xz
|
||||
tar axf gcc-11.2.0.tar.xz
|
||||
tar axf glibc-2.34.tar.xz
|
||||
tar axf linux-5.10.70.tar.xz
|
||||
|
||||
mv binutils-2.37 src-binu
|
||||
mv gcc-11.2.0 src-gcc
|
||||
mv glibc-2.34 src-glibc
|
||||
mv linux-5.10.70 src-linux
|
||||
|
||||
mkdir -p bld-hdr bld-binu bld-gcc bld-glibc
|
||||
mkdir -p ${CROSS_SYSROOT}/usr/include
|
||||
|
||||
#
|
||||
# Install kernel and glibc headers
|
||||
#
|
||||
|
||||
cd src-linux
|
||||
make headers_install ARCH=${LINUX_ARCH} INSTALL_HDR_PATH=${CROSS_SYSROOT}/usr
|
||||
cd ..
|
||||
|
||||
cd bld-hdr
|
||||
../src-glibc/configure --prefix=/usr --host=${TARGET}
|
||||
make install-headers DESTDIR=${CROSS_SYSROOT}
|
||||
touch ${CROSS_SYSROOT}/usr/include/gnu/stubs.h
|
||||
cd ..
|
||||
|
||||
#
|
||||
# Build binutils
|
||||
#
|
||||
|
||||
cd bld-binu
|
||||
../src-binu/configure --disable-werror \
|
||||
--prefix=${TOOLCHAIN_INSTALL} --with-sysroot --target=${TARGET}
|
||||
make -j${J}
|
||||
make install
|
||||
cd ..
|
||||
|
||||
#
|
||||
# Build gcc, without shared libraries, because we do not yet
|
||||
# have a shared libc against which to link.
|
||||
#
|
||||
|
||||
cd bld-gcc
|
||||
../src-gcc/configure --disable-werror --disable-shared \
|
||||
--prefix=${TOOLCHAIN_INSTALL} --with-sysroot --target=${TARGET} \
|
||||
--enable-languages=c --disable-libssp --disable-libsanitizer \
|
||||
--disable-libatomic --disable-libgomp --disable-libquadmath
|
||||
make -j${J}
|
||||
make install
|
||||
cd ..
|
||||
|
||||
#
|
||||
# Build glibc
|
||||
# There are a few random things that use c++ but we didn't build that
|
||||
# cross-compiler. We can get away without them. Disable CXX so that
|
||||
# glibc doesn't try to use the host c++ compiler.
|
||||
#
|
||||
|
||||
cd bld-glibc
|
||||
CXX=false ../src-glibc/configure --prefix=/usr --host=${TARGET}
|
||||
make -j${j}
|
||||
make install DESTDIR=${CROSS_SYSROOT}
|
||||
cd ..
|
|
@ -38,7 +38,6 @@ static struct arch2cpu cpus_map[] = {
|
|||
{ "mipsel", "I7200" },
|
||||
{ "mips64", "20Kc" },
|
||||
{ "mips64el", "I6500" },
|
||||
{ "nios2", "FIXME" },
|
||||
{ "or1k", "or1200" },
|
||||
{ "ppc", "604" },
|
||||
{ "ppc64", "power8e_v2.1" },
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Link script for the Nios2 10m50-ghrd board.
|
||||
*
|
||||
* Copyright Linaro Ltd 2022
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
tpf (rx) : ORIGIN = 0xc0000000, LENGTH = 1K
|
||||
ram (rwx) : ORIGIN = 0xc8000000, LENGTH = 128M
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
RAM PT_LOAD;
|
||||
}
|
||||
|
||||
ENTRY(_start)
|
||||
EXTERN(_start)
|
||||
EXTERN(_interrupt)
|
||||
EXTERN(_fast_tlb_miss)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Begin at the (hardcoded) _interrupt entry point. */
|
||||
.text 0xc8000120 : {
|
||||
*(.text.intr)
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
} >ram :RAM
|
||||
|
||||
.rodata : ALIGN(4) {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
} > ram :RAM
|
||||
|
||||
.eh_frame_hdr : ALIGN (4) {
|
||||
KEEP (*(.eh_frame_hdr))
|
||||
*(.eh_frame_entry .eh_frame_entry.*)
|
||||
} >ram :RAM
|
||||
.eh_frame : ALIGN (4) {
|
||||
KEEP (*(.eh_frame)) *(.eh_frame.*)
|
||||
} >ram :RAM
|
||||
|
||||
.data : ALIGN(4) {
|
||||
*(.shdata)
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
} >ram :RAM
|
||||
|
||||
HIDDEN (_gp = ALIGN(16) + 0x7ff0);
|
||||
PROVIDE_HIDDEN (gp = _gp);
|
||||
.got : ALIGN(4) {
|
||||
*(.got.plt) *(.igot.plt) *(.got) *(.igot)
|
||||
} >ram :RAM
|
||||
|
||||
.sdata : ALIGN(4) {
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
} >ram :RAM
|
||||
|
||||
.bss : ALIGN(4) {
|
||||
__bss_start = ABSOLUTE(.);
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end = ABSOLUTE(.);
|
||||
} >ram :RAM
|
||||
|
||||
__stack = ORIGIN(ram) + LENGTH(ram);
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#
|
||||
# Nios2 system tests
|
||||
#
|
||||
# Copyright Linaro Ltd 2022
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
|
||||
NIOS2_SYSTEM_SRC = $(SRC_PATH)/tests/tcg/nios2
|
||||
VPATH += $(NIOS2_SYSTEM_SRC)
|
||||
|
||||
# These objects provide the basic boot code and helper functions for all tests
|
||||
CRT_OBJS = boot.o intr.o $(MINILIB_OBJS)
|
||||
LINK_SCRIPT = $(NIOS2_SYSTEM_SRC)/10m50-ghrd.ld
|
||||
|
||||
CFLAGS += -nostdlib -g -O0 $(MINILIB_INC)
|
||||
LDFLAGS += -Wl,-T$(LINK_SCRIPT) -static -nostdlib $(CRT_OBJS) -lgcc
|
||||
|
||||
%.o: %.S
|
||||
$(call quiet-command, $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@, AS, $@)
|
||||
|
||||
%.o: %.c
|
||||
$(call quiet-command, $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c $< -o $@, CC, $@)
|
||||
|
||||
# Build and link the tests
|
||||
%: %.o $(LINK_SCRIPT) $(CRT_OBJS)
|
||||
$(call quiet-command, $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS), LD, $@)
|
||||
|
||||
QEMU_OPTS = -M 10m50-ghrd,vic=on -semihosting-config enable=on,target=native,chardev=output -kernel
|
||||
|
||||
memory: CFLAGS+=-DCHECK_UNALIGNED=0
|
||||
TESTS += $(MULTIARCH_TESTS)
|
||||
TESTS += test-shadow-1
|
|
@ -1,11 +0,0 @@
|
|||
# nios2 specific test tweaks
|
||||
|
||||
# Currently nios2 signal handling is broken
|
||||
run-signals: signals
|
||||
$(call skip-test, $<, "BROKEN")
|
||||
run-plugin-signals-with-%:
|
||||
$(call skip-test, $<, "BROKEN")
|
||||
run-linux-test: linux-test
|
||||
$(call skip-test, $<, "BROKEN")
|
||||
run-plugin-linux-test-with-%:
|
||||
$(call skip-test, $<, "BROKEN")
|
|
@ -1,218 +0,0 @@
|
|||
/*
|
||||
* Minimal Nios2 system boot code.
|
||||
*
|
||||
* Copyright Linaro Ltd 2022
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "semicall.h"
|
||||
|
||||
.text
|
||||
.set noat
|
||||
|
||||
_start:
|
||||
/* Linker script defines stack at end of ram. */
|
||||
movia sp, __stack
|
||||
|
||||
/* Install trampoline to _fast_tlb_miss at hardcoded vector. */
|
||||
movia r4, 0xc0000100
|
||||
movia r5, _ftm_tramp
|
||||
movi r6, .L__ftm_end - _ftm_tramp
|
||||
call memcpy
|
||||
|
||||
/* Zero the bss to satisfy C. */
|
||||
movia r4, __bss_start
|
||||
movia r6, __bss_end
|
||||
sub r6, r6, r4
|
||||
movi r5, 0
|
||||
call memset
|
||||
|
||||
/* Test! */
|
||||
call main
|
||||
|
||||
/* Exit with main's return value. */
|
||||
movi r4, HOSTED_EXIT
|
||||
mov r5, r2
|
||||
semihosting_call
|
||||
|
||||
.globl _start
|
||||
.type _start, @function
|
||||
.size _start, . - _start
|
||||
|
||||
_ftm_tramp:
|
||||
movia et, _fast_tlb_miss
|
||||
jmp et
|
||||
.L__ftm_end:
|
||||
|
||||
.type _ftm_tramp, @function
|
||||
.size _ftm_tramp, . - _ftm_tramp
|
||||
|
||||
#define dst r4
|
||||
#define src r5
|
||||
#define len r6
|
||||
|
||||
memcpy:
|
||||
/* Store return value right away, per API */
|
||||
mov r2, dst
|
||||
|
||||
/* Check for both dst and src aligned. */
|
||||
or at, dst, src
|
||||
andi at, at, 3
|
||||
bne at, zero, .L_mc_test1
|
||||
|
||||
/* Copy blocks of 8. */
|
||||
|
||||
movi at, 8
|
||||
bltu len, at, .L_mc_test4
|
||||
|
||||
.L_mc_loop8:
|
||||
ldw r8, 0(src)
|
||||
ldw r9, 4(src)
|
||||
addi src, src, 8
|
||||
addi dst, dst, 8
|
||||
subi len, len, 8
|
||||
stw r8, -8(dst)
|
||||
stw r9, -4(dst)
|
||||
bgeu len, at, .L_mc_loop8
|
||||
|
||||
/* Copy final aligned block of 4. */
|
||||
|
||||
.L_mc_test4:
|
||||
movi at, 4
|
||||
bltu len, at, .L_mc_test1
|
||||
|
||||
ldw r8, 0(src)
|
||||
addi src, src, 4
|
||||
addi dst, dst, 4
|
||||
subi len, len, 4
|
||||
stw r8, -4(dst)
|
||||
|
||||
/* Copy single bytes to finish. */
|
||||
|
||||
.L_mc_test1:
|
||||
beq len, zero, .L_mc_done
|
||||
|
||||
.L_mc_loop1:
|
||||
ldb r8, 0(src)
|
||||
addi src, src, 1
|
||||
addi dst, dst, 1
|
||||
subi len, len, 1
|
||||
stb r8, -1(dst)
|
||||
bne len, zero, .L_mc_loop1
|
||||
|
||||
.L_mc_done:
|
||||
ret
|
||||
|
||||
#undef dst
|
||||
#undef src
|
||||
#undef len
|
||||
|
||||
.global memcpy
|
||||
.type memcpy, @function
|
||||
.size memcpy, . - memcpy
|
||||
|
||||
#define dst r4
|
||||
#define val r5
|
||||
#define len r6
|
||||
|
||||
memset:
|
||||
/* Store return value right away, per API */
|
||||
mov r2, dst
|
||||
|
||||
/* Check for small blocks; fall back to bytewise. */
|
||||
movi r3, 8
|
||||
bltu len, r3, .L_ms_test1
|
||||
|
||||
/* Replicate the byte across the word. */
|
||||
andi val, val, 0xff
|
||||
slli at, val, 8
|
||||
or val, val, at
|
||||
slli at, val, 16
|
||||
or val, val, at
|
||||
|
||||
/* Check for destination alignment; realign if needed. */
|
||||
andi at, dst, 3
|
||||
bne at, zero, .L_ms_align
|
||||
|
||||
/* Set blocks of 8. */
|
||||
|
||||
.L_ms_loop8:
|
||||
stw val, 0(dst)
|
||||
stw val, 4(dst)
|
||||
addi dst, dst, 8
|
||||
subi len, len, 8
|
||||
bgeu len, r3, .L_ms_loop8
|
||||
|
||||
/* Set final aligned block of 4. */
|
||||
|
||||
.L_ms_test4:
|
||||
movi at, 4
|
||||
bltu len, at, .L_ms_test1
|
||||
|
||||
stw r8, 0(dst)
|
||||
addi dst, dst, 4
|
||||
subi len, len, 4
|
||||
stw r8, -4(dst)
|
||||
|
||||
/* Set single bytes to finish. */
|
||||
|
||||
.L_ms_test1:
|
||||
beq len, zero, .L_ms_done
|
||||
|
||||
.L_ms_loop1:
|
||||
stb r8, 0(dst)
|
||||
addi dst, dst, 1
|
||||
subi len, len, 1
|
||||
bne len, zero, .L_ms_loop1
|
||||
|
||||
.L_ms_done:
|
||||
ret
|
||||
|
||||
/* Realign for a large block, len >= 8. */
|
||||
.L_ms_align:
|
||||
andi at, dst, 1
|
||||
beq at, zero, 2f
|
||||
|
||||
stb val, 0(dst)
|
||||
addi dst, dst, 1
|
||||
subi len, len, 1
|
||||
|
||||
2: andi at, dst, 2
|
||||
beq at, zero, 4f
|
||||
|
||||
sth val, 0(dst)
|
||||
addi dst, dst, 2
|
||||
subi len, len, 2
|
||||
|
||||
4: bgeu len, r3, .L_ms_loop8
|
||||
br .L_ms_test4
|
||||
|
||||
#undef dst
|
||||
#undef val
|
||||
#undef len
|
||||
|
||||
.global memset
|
||||
.type memset, @function
|
||||
.size memset, . - memset
|
||||
|
||||
/*
|
||||
* void __sys_outc(char c);
|
||||
*/
|
||||
__sys_outc:
|
||||
subi sp, sp, 16
|
||||
stb r4, 0(sp) /* buffer[0] = c */
|
||||
movi at, 1
|
||||
stw at, 4(sp) /* STDOUT_FILENO */
|
||||
stw sp, 8(sp) /* buffer */
|
||||
stw at, 12(sp) /* len */
|
||||
|
||||
movi r4, HOSTED_WRITE
|
||||
addi r5, sp, 4
|
||||
semihosting_call
|
||||
|
||||
addi sp, sp, 16
|
||||
ret
|
||||
|
||||
.global __sys_outc
|
||||
.type __sys_outc, @function
|
||||
.size __sys_outc, . - __sys_outc
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Minimal Nios2 system boot code -- exit on interrupt.
|
||||
*
|
||||
* Copyright Linaro Ltd 2022
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "semicall.h"
|
||||
|
||||
.section .text.intr, "ax"
|
||||
.global _interrupt
|
||||
.type _interrupt, @function
|
||||
|
||||
_interrupt:
|
||||
rdctl r5, exception /* extract exception.CAUSE */
|
||||
srli r5, r5, 2
|
||||
movi r4, HOSTED_EXIT
|
||||
semihosting_call
|
||||
|
||||
.size _interrupt, . - _interrupt
|
||||
|
||||
.text
|
||||
.global _fast_tlb_miss
|
||||
.type _fast_tlb_miss, @function
|
||||
|
||||
_fast_tlb_miss:
|
||||
movi r5, 32
|
||||
movi r4, HOSTED_EXIT
|
||||
semihosting_call
|
||||
|
||||
.size _fast_tlb_miss, . - _fast_tlb_miss
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Nios2 semihosting interface.
|
||||
*
|
||||
* Copyright Linaro Ltd 2022
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef SEMICALL_H
|
||||
#define SEMICALL_H
|
||||
|
||||
#define HOSTED_EXIT 0
|
||||
#define HOSTED_INIT_SIM 1
|
||||
#define HOSTED_OPEN 2
|
||||
#define HOSTED_CLOSE 3
|
||||
#define HOSTED_READ 4
|
||||
#define HOSTED_WRITE 5
|
||||
#define HOSTED_LSEEK 6
|
||||
#define HOSTED_RENAME 7
|
||||
#define HOSTED_UNLINK 8
|
||||
#define HOSTED_STAT 9
|
||||
#define HOSTED_FSTAT 10
|
||||
#define HOSTED_GETTIMEOFDAY 11
|
||||
#define HOSTED_ISATTY 12
|
||||
#define HOSTED_SYSTEM 13
|
||||
|
||||
#define semihosting_call break 1
|
||||
|
||||
#endif /* SEMICALL_H */
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Regression test for TCG indirect global lowering.
|
||||
*
|
||||
* Copyright Linaro Ltd 2022
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "semicall.h"
|
||||
|
||||
.text
|
||||
.set noat
|
||||
.align 2
|
||||
.globl main
|
||||
.type main, @function
|
||||
|
||||
main:
|
||||
/* Initialize r0 in shadow register set 1. */
|
||||
movhi at, 1 /* PRS=1, CRS=0, RSIE=0, PIE=0 */
|
||||
wrctl status, at
|
||||
wrprs zero, zero
|
||||
|
||||
/* Change current register set to 1. */
|
||||
movi at, 1 << 10 /* PRS=0, CRS=1, RSIE=0, PIE=0 */
|
||||
wrctl estatus, at
|
||||
movia ea, 1f
|
||||
eret
|
||||
|
||||
/* Load address for callr, then end TB. */
|
||||
1: movia at, 3f
|
||||
br 2f
|
||||
|
||||
/* Test case! TCG abort on indirect lowering across brcond. */
|
||||
2: callr at
|
||||
|
||||
/* exit(0) */
|
||||
3: movi r4, HOSTED_EXIT
|
||||
movi r5, 0
|
||||
semihosting_call
|
||||
|
||||
.size main, . - main
|
Loading…
Reference in New Issue