Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bd062c258 | ||
|
|
d2160cbf4a | ||
|
|
9a3aa3c9c3 | ||
|
|
137ebbc43f | ||
|
|
a520506076 | ||
|
|
2758c33e39 | ||
|
|
2fa7a7e977 | ||
|
|
dbfc2ebc6b | ||
|
|
82083a90cc | ||
|
|
341681f312 | ||
|
|
3f4221db6f | ||
|
|
4d949eebef | ||
|
|
8e8ba2396c | ||
|
|
0e51f8bd79 | ||
|
|
3e91120f2b | ||
|
|
fb244f7542 | ||
|
|
f7ac49efe6 | ||
|
|
fce4c9e317 | ||
|
|
385f88242e | ||
|
|
4e8e72bd4c | ||
|
|
eee10e9aff | ||
|
|
b7e7153b95 | ||
|
|
525500123a | ||
|
|
ff39065ed4 | ||
|
|
1b253c2dba | ||
|
|
37c46e3cf5 | ||
|
|
c5f9a2d2bc | ||
|
|
7e4bcff791 | ||
|
|
ee4006e42e | ||
|
|
bec2a497b9 | ||
|
|
2295af0f05 | ||
|
|
8e12b42af2 | ||
|
|
a3c2a72c6c | ||
|
|
c2e829ba8c | ||
|
|
b83d9a5eea | ||
|
|
a69cdb31ca | ||
|
|
d39cb42d09 | ||
|
|
9d83a7cd27 |
@@ -1,7 +1,7 @@
|
||||
--emacs
|
||||
--summary-file
|
||||
--show-types
|
||||
--max-line-length=100
|
||||
--max-line-length=80
|
||||
--min-conf-desc-length=1
|
||||
--typedefsfile=scripts/checkpatch/typedefsfile
|
||||
|
||||
@@ -10,23 +10,10 @@
|
||||
--ignore SPLIT_STRING
|
||||
--ignore VOLATILE
|
||||
--ignore CONFIG_EXPERIMENTAL
|
||||
--ignore PREFER_KERNEL_TYPES
|
||||
--ignore PREFER_SECTION
|
||||
--ignore AVOID_EXTERNS
|
||||
--ignore NETWORKING_BLOCK_COMMENT_STYLE
|
||||
--ignore DATE_TIME
|
||||
--ignore MINMAX
|
||||
--ignore CONST_STRUCT
|
||||
--ignore FILE_PATH_CHANGES
|
||||
--ignore SPDX_LICENSE_TAG
|
||||
--ignore C99_COMMENT_TOLERANCE
|
||||
--ignore REPEATED_WORD
|
||||
--ignore UNDOCUMENTED_DT_STRING
|
||||
--ignore DT_SPLIT_BINDING_PATCH
|
||||
--ignore DT_SCHEMA_BINDING_PATCH
|
||||
--ignore TRAILING_SEMICOLON
|
||||
--ignore COMPLEX_MACRO
|
||||
--ignore MULTISTATEMENT_MACRO_USE_DO_WHILE
|
||||
--ignore ENOSYS
|
||||
--ignore IS_ENABLED_CONFIG
|
||||
--exclude ext
|
||||
|
||||
@@ -52,7 +52,7 @@ BreakConstructorInitializersBeforeComma: false
|
||||
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 100
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
#CompactNamespaces: false # Unknown to clang-format-4.0
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
@@ -65,12 +65,18 @@ ExperimentalAutoDetectBinPacking: false
|
||||
#FixNamespaceComments: false # Unknown to clang-format-4.0
|
||||
|
||||
# Taken from:
|
||||
# git grep -h '^#define [^[:space:]]*FOR_EACH[^[:space:]]*(' include/ \
|
||||
# | sed "s,^#define \([^[:space:]]*FOR_EACH[^[:space:]]*\)(.*$, - '\1'," \
|
||||
# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
|
||||
# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
|
||||
# | sort | uniq
|
||||
ForEachMacros:
|
||||
- 'FOR_EACH'
|
||||
- 'FOR_EACH_FIXED_ARG'
|
||||
- 'for_each_linux_bus'
|
||||
- 'for_each_linux_driver'
|
||||
- 'metal_bitmap_for_each_clear_bit'
|
||||
- 'metal_bitmap_for_each_set_bit'
|
||||
- 'metal_for_each_page_size_down'
|
||||
- 'metal_for_each_page_size_up'
|
||||
- 'metal_list_for_each'
|
||||
- 'RB_FOR_EACH'
|
||||
- 'RB_FOR_EACH_CONTAINER'
|
||||
- 'SYS_DLIST_FOR_EACH_CONTAINER'
|
||||
@@ -85,11 +91,11 @@ ForEachMacros:
|
||||
- 'SYS_SLIST_FOR_EACH_CONTAINER_SAFE'
|
||||
- 'SYS_SLIST_FOR_EACH_NODE'
|
||||
- 'SYS_SLIST_FOR_EACH_NODE_SAFE'
|
||||
- '_WAIT_Q_FOR_EACH'
|
||||
- 'Z_GENLIST_FOR_EACH_CONTAINER'
|
||||
- 'Z_GENLIST_FOR_EACH_CONTAINER_SAFE'
|
||||
- 'Z_GENLIST_FOR_EACH_NODE'
|
||||
- 'Z_GENLIST_FOR_EACH_NODE_SAFE'
|
||||
- '_WAIT_Q_FOR_EACH'
|
||||
|
||||
#IncludeBlocks: Preserve # Unknown to clang-format-5.0
|
||||
IncludeCategories:
|
||||
|
||||
@@ -11,11 +11,6 @@ insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
max_line_length = 80
|
||||
|
||||
# Assembly
|
||||
[*.S]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
# C
|
||||
[*.{c,h}]
|
||||
indent_style = tab
|
||||
@@ -32,7 +27,7 @@ indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
# YAML
|
||||
[*.{yml,yaml}]
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
@@ -60,16 +55,3 @@ indent_size = 2
|
||||
# Makefile
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
# Device tree
|
||||
[*.{dts,dtsi,overlay}]
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
# Git commit messages
|
||||
[COMMIT_EDITMSG]
|
||||
max_line_length = 72
|
||||
|
||||
# Kconfig
|
||||
[Kconfig*]
|
||||
indent_style=tab
|
||||
|
||||
8
.gitattributes
vendored
8
.gitattributes
vendored
@@ -3,11 +3,3 @@
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.mailmap export-ignore
|
||||
|
||||
# Tell git to not diff certain files
|
||||
*.svg -diff
|
||||
|
||||
# Tell linguist that generated test pattern files should not be included in the
|
||||
# language statistics.
|
||||
*.pat linguist-generated
|
||||
*.svg linguist-generated
|
||||
|
||||
20
.github/ISSUE_TEMPLATE/bug_report.md
vendored
20
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -9,12 +9,7 @@ assignees: ''
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
Please also mention any information which could help others to understand
|
||||
the problem you're facing:
|
||||
- What target platform are you using?
|
||||
- What have you tried to diagnose or workaround this issue?
|
||||
- ...
|
||||
What have you tried to diagnose or workaround this issue?
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
@@ -29,17 +24,16 @@ A clear and concise description of what you expected to happen.
|
||||
**Impact**
|
||||
What impact does this issue have on your progress (e.g., annoyance, showstopper)
|
||||
|
||||
**Logs and console output**
|
||||
If applicable, add console logs or other types of debug information
|
||||
e.g Wireshark capture or Logic analyzer capture (upload in zip archive).
|
||||
copy-and-paste text and put a code fence (\`\`\`) before and after, to help
|
||||
explain the issue. (if unable to obtain text log, add a screenshot)
|
||||
**Screenshots or console output**
|
||||
If applicable, add a screenshot (drag-and-drop an image), or console logs
|
||||
(cut-and-paste text and put a code fence (\`\`\`) before and after, to help
|
||||
explain the issue.
|
||||
|
||||
**Environment (please complete the following information):**
|
||||
- OS: (e.g. Linux, MacOS, Windows)
|
||||
- Toolchain (e.g Zephyr SDK, ...)
|
||||
- Commit SHA or Version used
|
||||
|
||||
|
||||
**Additional context**
|
||||
Add any other context that could be relevant to your issue, such as pin setting,
|
||||
target configuration, ...
|
||||
Add any other context about the problem here.
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/enhancement.md
vendored
2
.github/ISSUE_TEMPLATE/enhancement.md
vendored
@@ -2,7 +2,7 @@
|
||||
name: Enhancement
|
||||
about: Suggest enhancements to existing features
|
||||
title: ''
|
||||
labels: Enhancement
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
62
.github/ISSUE_TEMPLATE/ext-source.md
vendored
62
.github/ISSUE_TEMPLATE/ext-source.md
vendored
@@ -1,62 +0,0 @@
|
||||
---
|
||||
name: External Source Code
|
||||
about: Submit a proposal to integrate external source code
|
||||
title: ''
|
||||
labels: TSC
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Origin
|
||||
|
||||
Name of project hosting the original open source code
|
||||
Provide a link to the source
|
||||
|
||||
## Purpose
|
||||
|
||||
Brief description of what this software does
|
||||
|
||||
## Mode of integration
|
||||
|
||||
Describe whether you'd like to integrate this exernal component in the main tree
|
||||
or as a module, and why. If the mode of integration is a module, suggest a
|
||||
repository name for the module
|
||||
|
||||
## Pull Request
|
||||
|
||||
Pull request (if any) with the actual implementation of the integration, be it
|
||||
in the main tree or as a module (pointing to your own fork for now). Make sure
|
||||
the PR is correctly labeled as "DNM"
|
||||
|
||||
## Description
|
||||
|
||||
Long description that will help reviewers discuss suitability of the
|
||||
component to solve the problem at hand (there may be a better options
|
||||
available.)
|
||||
|
||||
What is its primary functionality (e.g., SQLLite is a lightweight
|
||||
database)?
|
||||
|
||||
What problem are you trying to solve? (e.g., a state store is
|
||||
required to maintain ...)
|
||||
|
||||
Why is this the right component to solve it (e.g., SQLite is small,
|
||||
easy to use, and has a very liberal license.)
|
||||
|
||||
# Dependencies
|
||||
|
||||
What other components does this package depend on?
|
||||
|
||||
Will the Zephyr project have a direct dependency on the component, or
|
||||
will it be included via an abstraction layer with this component as a
|
||||
replaceable implementation?
|
||||
|
||||
## Revision
|
||||
|
||||
Version or SHA you would like to integrate initially
|
||||
|
||||
## License
|
||||
|
||||
Please use an SPDX identifier (https://spdx.org/licenses/), such as
|
||||
``BSD-3-Clause``
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -2,7 +2,7 @@
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: Feature Request
|
||||
labels: feature request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
19
.github/ISSUE_TEMPLATE/hardware_support.md
vendored
19
.github/ISSUE_TEMPLATE/hardware_support.md
vendored
@@ -1,19 +0,0 @@
|
||||
---
|
||||
name: Hardware Support
|
||||
about: Suggest adding hardware support
|
||||
title: ''
|
||||
labels: Hardware Support
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is this request related to a missing driver support for a particular hardware platform, SoC or board? Please describe.**
|
||||
Describe in details the hardware support being requested and why this support benefits Zephyr.
|
||||
|
||||
**Describe why you are asking for this support?**
|
||||
Describe why you are asking for this support instead of contributing it directly to the tree
|
||||
|
||||
If this is a new board or SoC, please state whether you are willing to maintain the Zephyr support for it if it is included in the main tree
|
||||
|
||||
**Additional context**
|
||||
Add any other context or graphics (drag-and-drop an image) about the hardware here.
|
||||
41
.github/ISSUE_TEMPLATE/nomination.md
vendored
41
.github/ISSUE_TEMPLATE/nomination.md
vendored
@@ -1,41 +0,0 @@
|
||||
---
|
||||
name: Contributor Nomination
|
||||
about: Nominate a GitHub user for additional rights on the Zephyr Project
|
||||
title: ''
|
||||
labels: Role Nomination
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Background
|
||||
|
||||
The [TSC Project Roles] defines the main roles for the Zephyr Project, including
|
||||
Maintainer, Collaborator, and Contributor.
|
||||
|
||||
By default anyone that contributes code or documentation is a Contributor, but
|
||||
with the lowest [GitHub Permission Level] of Read. For example, Contributors
|
||||
with Read permission do not have the permission to add reviewers to a pull
|
||||
request.
|
||||
|
||||
Use this template to nominate a GitHub user for an elevated permission level in
|
||||
the Contributor role.
|
||||
|
||||
# Nomination
|
||||
|
||||
## GitHub User
|
||||
|
||||
Provide the following information about the GitHub user:
|
||||
|
||||
1. Full Name
|
||||
1. GitHub username
|
||||
1. Organization (optional)
|
||||
|
||||
## Supporting Documents
|
||||
|
||||
Add links to 3-5 GitHub pull requests, in the Zephyr project, authored or
|
||||
reviewed by the GitHub user that demonstrate the user's dedication to the
|
||||
Zephyr project.
|
||||
|
||||
|
||||
[TSC Project Roles]: <https://docs.zephyrproject.org/latest/development_process/project_roles.html#tsc-project-roles>
|
||||
[GitHub Permission Level]: <https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization>
|
||||
22
.github/SECURITY.md
vendored
22
.github/SECURITY.md
vendored
@@ -1,22 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported versions
|
||||
|
||||
The Zephyr project supports the following versions with security
|
||||
updates:
|
||||
|
||||
- The most recent release, and the release prior to that.
|
||||
- Active LTS releases.
|
||||
|
||||
At this time, with the latest release of v3.0.0, the supported
|
||||
versions are:
|
||||
|
||||
- v2.7.0: Current LTS
|
||||
- v2.7.0: Prior release
|
||||
- v3.0.0: Current release
|
||||
|
||||
## Reporting process
|
||||
|
||||
Please see our [Security Vulnerability
|
||||
Reporting](https://docs.zephyrproject.org/latest/security/reporting.html)
|
||||
page for details on the process.
|
||||
171
.github/labeler.yml
vendored
171
.github/labeler.yml
vendored
@@ -1,171 +0,0 @@
|
||||
"Release Notes":
|
||||
- "doc/releases/**/*"
|
||||
"area: Modem":
|
||||
- "drivers/modem/**/*"
|
||||
"area: PWM":
|
||||
- "drivers/pwm/**/*"
|
||||
"area: Watchdog":
|
||||
- "drivers/watchdog/**/*"
|
||||
"area: Sensors":
|
||||
- "drivers/sensors/**/*"
|
||||
"area: ADC":
|
||||
- "drivers/adc/**/*"
|
||||
"area: Counter":
|
||||
- "drivers/counter/**/*"
|
||||
"area: CAN":
|
||||
- "include/drivers/can.h"
|
||||
- "include/canbus/*/**"
|
||||
- "drivers/can/**/*"
|
||||
- "subsys/canbus/*/**"
|
||||
"area: EEPROM":
|
||||
- "include/drivers/eeprom.h"
|
||||
- "drivers/eeprom/**/*"
|
||||
"area: Timer":
|
||||
- "drivers/timer/**/*"
|
||||
"area: I2S":
|
||||
- "drivers/i2s/**/*"
|
||||
"area: C Library":
|
||||
- "lib/libc/**/*"
|
||||
"area: Devicetree":
|
||||
- "dts/**/*"
|
||||
- "**/*.dts"
|
||||
- "**/*.dtsi"
|
||||
- "include/devicetree.h"
|
||||
- "include/devicetree/*"
|
||||
- "doc/guides/dts/**/*"
|
||||
"area: Devicetree Binding":
|
||||
- "include/dt-bindings/**/*"
|
||||
- "dts/bindings/**/*"
|
||||
"area: Devicetree Tooling":
|
||||
- "scripts/dts/**/*"
|
||||
"area: I2C":
|
||||
- "drivers/i2c/**/*"
|
||||
"area: SPI":
|
||||
- "drivers/spi/**/*"
|
||||
"area: Boards":
|
||||
- "boards/**/*"
|
||||
"area: POSIX":
|
||||
- "lib/posix/**/*"
|
||||
"area: native port":
|
||||
- "arch/posix/**/*"
|
||||
- "include/arch/posix/**/*"
|
||||
- "soc/posix/**/*"
|
||||
- "**/*native_posix*"
|
||||
"area: X86":
|
||||
- "arch/x86/**/*"
|
||||
- "include/arch/x86/**/*"
|
||||
"area: ARM":
|
||||
- "arch/arm/**/*"
|
||||
- "include/arch/arm/**/*"
|
||||
"area: ARM64":
|
||||
- "arch/arm64/**/*"
|
||||
- "include/arch/arm64/**/*"
|
||||
"area: MIPS":
|
||||
- "arch/mips/**/*"
|
||||
- "include/arch/mips/**/*"
|
||||
"area: NIOS2":
|
||||
- "arch/nios2/**/*"
|
||||
- "include/arch/nios2/**/*"
|
||||
"area: Xtensa":
|
||||
- "arch/xtensa/**/*"
|
||||
- "include/arch/xtensa/**/*"
|
||||
"area: RISCV":
|
||||
- "arch/risv/**/*"
|
||||
- "include/arch/riscv/**/*"
|
||||
"area: ARC":
|
||||
- "arch/arc/**/*"
|
||||
- "include/arch/arc/**/*"
|
||||
"area: Networking":
|
||||
- "subsys/net/**/*"
|
||||
- "samples/net/**/*"
|
||||
- "tests/net/**/*"
|
||||
- "include/net/**/*"
|
||||
- "include/drivers/ieee802154/**/*"
|
||||
- "drivers/ethernet/**/*"
|
||||
- "drivers/ieee802154/**/*"
|
||||
- "drivers/wifi/**/*"
|
||||
- "drivers/ptp_clock/**/*"
|
||||
- "drivers/net/**/*"
|
||||
"area: Logging":
|
||||
- "subsys/logging/**/*"
|
||||
"area: Shell":
|
||||
- "subsys/shell/**/*"
|
||||
"area: Console":
|
||||
- "subsys/console/**/*"
|
||||
"area: Test Framework":
|
||||
- "subsys/testsuite/**/*"
|
||||
"area: Settings":
|
||||
- "subsys/settings/**/*"
|
||||
"area: File System":
|
||||
- "subsys/fs/**/*"
|
||||
"area: Storage":
|
||||
- "subsys/storage/**/*"
|
||||
"area: Bluetooth":
|
||||
- "subsys/bluetooth/**/*"
|
||||
- "**/*bluetooth*"
|
||||
"area: Bluetooth Mesh":
|
||||
- "subsys/bluetooth/mesh/**/*"
|
||||
"area: Bluetooth Audio":
|
||||
- "subsys/bluetooth/audio/**/*"
|
||||
"area: Bluetooth Controller":
|
||||
- "subsys/bluetooth/controller/**/*"
|
||||
"area: Bluetooth Host":
|
||||
- "subsys/bluetooth/host/**/*"
|
||||
- "subsys/bluetooth/services/**/*"
|
||||
"area: API":
|
||||
- "include/**/*"
|
||||
"area: Samples":
|
||||
- "samples/**/*"
|
||||
"area: Tests":
|
||||
- "tests/**/*"
|
||||
"area: Kernel":
|
||||
- "kernel/**/*"
|
||||
- "tests/kernel/**/*"
|
||||
"area: Documentation":
|
||||
- "**/*.rst"
|
||||
- "**/*.md"
|
||||
"area: Build System":
|
||||
- "cmake/**/*"
|
||||
- "CmakeLists.txt"
|
||||
"area: Kconfig":
|
||||
- "scripts/kconfig/**/*"
|
||||
- "Kconfig"
|
||||
- "Kconfig.zephyr"
|
||||
"area: Twister":
|
||||
- "scripts/twister"
|
||||
- "scripts/pylib/twister/**/*"
|
||||
"area: Modules":
|
||||
- "west.yml"
|
||||
- "modules/**/*"
|
||||
"area: Shields":
|
||||
- "boards/shields/**"
|
||||
- "samples/shields/**"
|
||||
"area: Power Management":
|
||||
- "subsys/pm/**/*"
|
||||
- "include/pm/**/*"
|
||||
- "tests/subsys/pm/**/*"
|
||||
- "samples/subsys/pm/**/*"
|
||||
"platform: NXP":
|
||||
- "boards/arm/frdm*/**"
|
||||
- "boards/arm/hexiwear*/**"
|
||||
- "boards/arm/lpcxpresso*/**"
|
||||
- "boards/arm/*imx*/**"
|
||||
- "drivers/**/*imx*"
|
||||
- "drivers/**/*mcux*"
|
||||
- "dts/arm/nxp/*/*"
|
||||
- "dts/bindings/**/nxp*"
|
||||
- "soc/arm/nxp*/**"
|
||||
"platform: STM32":
|
||||
- "boards/arm/nucleo_*/**"
|
||||
- "boards/arm/*stm32*/**"
|
||||
- "drivers/**/*stm32*"
|
||||
- "dts/arm/st/*/*"
|
||||
- "include/drivers/*/*stm32*"
|
||||
- "soc/arm/st_stm32/**"
|
||||
"platform: SiLabs":
|
||||
- "boards/arm/efr32_*/**/*"
|
||||
- "boards/arm/efm32_*/**/*"
|
||||
- "drivers/**/*gecko*"
|
||||
- "dts/arm/silabs/**/*"
|
||||
- "dts/bindings/**/silabs,gecko*"
|
||||
- "soc/arm/silabs_exx32/**/*"
|
||||
19
.github/workflows/backport.yml
vendored
19
.github/workflows/backport.yml
vendored
@@ -1,19 +0,0 @@
|
||||
name: Backport
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- closed
|
||||
- labeled
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
backport:
|
||||
runs-on: ubuntu-18.04
|
||||
name: Backport
|
||||
steps:
|
||||
- name: Backport
|
||||
uses: zephyrproject-rtos/action-backport@v1.1.1-1
|
||||
with:
|
||||
github_token: ${{ secrets.ZB_GITHUB_TOKEN }}
|
||||
issue_labels: backport
|
||||
85
.github/workflows/bluetooth.yaml
vendored
85
.github/workflows/bluetooth.yaml
vendored
@@ -1,85 +0,0 @@
|
||||
name: Bluetooth Tests
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- "west.yml"
|
||||
- "subsys/bluetooth/**"
|
||||
- "tests/bluetooth/bsim_bt/**"
|
||||
- "boards/posix/**"
|
||||
- "soc/posix/**"
|
||||
- "arch/posix/**"
|
||||
|
||||
jobs:
|
||||
bluetooth-test-prep:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
bluetooth-test-build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: bluetooth-test-prep
|
||||
container:
|
||||
image: zephyrprojectrtos/ci:v0.21.0
|
||||
options: '--entrypoint /bin/bash'
|
||||
env:
|
||||
ZEPHYR_TOOLCHAIN_VARIANT: zephyr
|
||||
ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.13.2
|
||||
CLANG_ROOT_DIR: /usr/lib/llvm-12
|
||||
BSIM_OUT_PATH: /opt/bsim/
|
||||
BSIM_COMPONENTS_PATH: /opt/bsim/components
|
||||
EDTT_PATH: ../tools/edtt
|
||||
bsim_bt_test_results_file: ./bsim_bt_out/bsim_results.xml
|
||||
steps:
|
||||
- name: Update PATH for west
|
||||
run: |
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: west setup
|
||||
run: |
|
||||
west init -l . || true
|
||||
west config --global update.narrow true
|
||||
west update 2>&1 1> west.update.log || west update 2>&1 1> west.update2.log
|
||||
|
||||
- name: Run Bluetooth Tests with BSIM
|
||||
run: |
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
WORK_DIR=${ZEPHYR_BASE}/bsim_bt_out tests/bluetooth/bsim_bt/compile.sh
|
||||
RESULTS_FILE=${ZEPHYR_BASE}/${bsim_bt_test_results_file} \
|
||||
SEARCH_PATH=tests/bluetooth/bsim_bt/ tests/bluetooth/bsim_bt/run_parallel.sh
|
||||
|
||||
- name: Upload Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Bluetooth Test Results
|
||||
path: ./bsim_bt_out/bsim_results.xml
|
||||
|
||||
bluetooth-test-results:
|
||||
name: "Publish Bluetooth Test Results"
|
||||
needs: bluetooth-test-build
|
||||
runs-on: ubuntu-20.04
|
||||
# the build-and-test job might be skipped, we don't need to run this job then
|
||||
if: success() || failure()
|
||||
|
||||
steps:
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Publish Bluetooth Test Results
|
||||
uses: EnricoMi/publish-unit-test-result-action@v1
|
||||
with:
|
||||
check_name: Bluetooth Test Results
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: "**/bsim_results.xml"
|
||||
comment_mode: off
|
||||
154
.github/workflows/clang.yaml
vendored
154
.github/workflows/clang.yaml
vendored
@@ -1,154 +0,0 @@
|
||||
name: Build with Clang/LLVM
|
||||
|
||||
on: pull_request_target
|
||||
|
||||
jobs:
|
||||
clang-build-prep:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
clang-build:
|
||||
runs-on: zephyr_runner
|
||||
needs: clang-build-prep
|
||||
container:
|
||||
image: zephyrprojectrtos/ci:v0.21.0
|
||||
options: '--entrypoint /bin/bash'
|
||||
volumes:
|
||||
- /home/runners/zephyrproject:/github/cache/zephyrproject
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: ["native_posix"]
|
||||
env:
|
||||
ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.13.2
|
||||
CLANG_ROOT_DIR: /usr/lib/llvm-12
|
||||
COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
outputs:
|
||||
report_needed: ${{ steps.twister.outputs.report_needed }}
|
||||
steps:
|
||||
- name: Cleanup
|
||||
run: |
|
||||
# hotfix, until we have a better way to deal with existing data
|
||||
rm -rf zephyr zephyr-testing
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Environment Setup
|
||||
run: |
|
||||
pip3 install GitPython
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
git config --global user.email "bot@zephyrproject.org"
|
||||
git config --global user.name "Zephyr Bot"
|
||||
rm -fr ".git/rebase-apply"
|
||||
git rebase origin/${BASE_REF}
|
||||
git log --pretty=oneline | head -n 10
|
||||
west init -l . || true
|
||||
west config --global update.narrow true
|
||||
# In some cases modules are left in a state where they can't be
|
||||
# updated (i.e. when we cancel a job and the builder is killed),
|
||||
# So first retry to update, if that does not work, remove all modules
|
||||
# and start over. (Workaround until we implement more robust module
|
||||
# west caching).
|
||||
west update --path-cache /github/cache/zephyrproject 2>&1 1> west.log || west update --path-cache /github/cache/zephyrproject 2>&1 1> west2.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /github/cache/zephyrproject)
|
||||
|
||||
- name: Check Environment
|
||||
run: |
|
||||
cmake --version
|
||||
${CLANG_ROOT_DIR}/bin/clang --version
|
||||
gcc --version
|
||||
ls -la
|
||||
|
||||
- name: Prepare ccache timestamp/data
|
||||
id: ccache_cache_timestamp
|
||||
shell: cmake -P {0}
|
||||
run: |
|
||||
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
|
||||
string(REPLACE "/" "_" repo ${{github.repository}})
|
||||
string(REPLACE "-" "_" repo2 ${repo})
|
||||
message("::set-output name=repo::${repo2}")
|
||||
- name: use cache
|
||||
id: cache-ccache
|
||||
uses: nashif/action-s3-cache@master
|
||||
with:
|
||||
key: ${{ steps.ccache_cache_timestamp.outputs.repo }}-${{ github.ref_name }}-clang-${{ matrix.platform }}-ccache
|
||||
path: /github/home/.ccache
|
||||
aws-s3-bucket: ccache.zephyrproject.org
|
||||
aws-access-key-id: ${{ secrets.CCACHE_S3_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.CCACHE_S3_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
|
||||
- name: ccache stats initial
|
||||
run: |
|
||||
test -d github/home/.ccache && rm -rf /github/home/.ccache && mv github/home/.ccache /github/home/.ccache
|
||||
ccache -M 10G -s
|
||||
|
||||
- name: Run Tests with Twister
|
||||
id: twister
|
||||
run: |
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
export ZEPHYR_TOOLCHAIN_VARIANT=llvm
|
||||
|
||||
# check if we need to run a full twister or not based on files changed
|
||||
python3 ./scripts/ci/test_plan.py --platform ${{ matrix.platform }} -c origin/${BASE_REF}..
|
||||
|
||||
# We can limit scope to just what has changed
|
||||
if [ -s testplan.csv ]; then
|
||||
echo "::set-output name=report_needed::1";
|
||||
# Full twister but with options based on changes
|
||||
./scripts/twister --inline-logs -M -N -v --load-tests testplan.csv --retry-failed 2
|
||||
else
|
||||
# if nothing is run, skip reporting step
|
||||
echo "::set-output name=report_needed::0";
|
||||
fi
|
||||
|
||||
- name: ccache stats post
|
||||
run: |
|
||||
ccache -s
|
||||
|
||||
- name: Upload Unit Test Results
|
||||
if: always() && steps.twister.outputs.report_needed != 0
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Unit Test Results (Subset ${{ matrix.platform }})
|
||||
path: twister-out/twister.xml
|
||||
|
||||
clang-build-results:
|
||||
name: "Publish Unit Tests Results"
|
||||
needs: clang-build
|
||||
runs-on: ubuntu-20.04
|
||||
if: (success() || failure() ) && needs.clang-build.outputs.report_needed != 0
|
||||
steps:
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: artifacts
|
||||
- name: Merge Test Results
|
||||
run: |
|
||||
pip3 install junitparser junit2html
|
||||
junitparser merge artifacts/*/twister.xml junit.xml
|
||||
junit2html junit.xml junit-clang.html
|
||||
|
||||
- name: Upload Unit Test Results in HTML
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: HTML Unit Test Results
|
||||
if-no-files-found: ignore
|
||||
path: |
|
||||
junit-clang.html
|
||||
|
||||
- name: Publish Unit Test Results
|
||||
uses: EnricoMi/publish-unit-test-result-action@v1
|
||||
if: always()
|
||||
with:
|
||||
check_name: Unit Test Results
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: "**/twister.xml"
|
||||
comment_mode: off
|
||||
165
.github/workflows/codecov.yaml
vendored
165
.github/workflows/codecov.yaml
vendored
@@ -1,165 +0,0 @@
|
||||
name: Code Coverage with codecov
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '25 */3 * * 1-5'
|
||||
|
||||
jobs:
|
||||
codecov-prep:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'zephyrproject-rtos/zephyr'
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
codecov:
|
||||
runs-on: zephyr_runner
|
||||
needs: codecov-prep
|
||||
container:
|
||||
image: zephyrprojectrtos/ci:v0.21.0
|
||||
options: '--entrypoint /bin/bash'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform: ["native_posix", "qemu_x86", "unit_testing"]
|
||||
env:
|
||||
ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.13.2
|
||||
CLANG_ROOT_DIR: /usr/lib/llvm-12
|
||||
steps:
|
||||
- name: Update PATH for west
|
||||
run: |
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: west setup
|
||||
run: |
|
||||
west init -l . || true
|
||||
west update 1> west.update.log || west update 1> west.update-2.log
|
||||
|
||||
- name: Check Environment
|
||||
run: |
|
||||
cmake --version
|
||||
${CLANG_ROOT_DIR}/bin/clang --version
|
||||
gcc --version
|
||||
ls -la
|
||||
- name: Prepare ccache keys
|
||||
id: ccache_cache_prop
|
||||
shell: cmake -P {0}
|
||||
run: |
|
||||
string(REPLACE "/" "_" repo ${{github.repository}})
|
||||
string(REPLACE "-" "_" repo2 ${repo})
|
||||
message("::set-output name=repo::${repo2}")
|
||||
|
||||
- name: use cache
|
||||
id: cache-ccache
|
||||
uses: nashif/action-s3-cache@master
|
||||
with:
|
||||
key: ${{ steps.ccache_cache_prop.outputs.repo }}-${{github.event_name}}-${{matrix.platform}}-codecov-ccache
|
||||
path: /github/home/.ccache
|
||||
aws-s3-bucket: ccache.zephyrproject.org
|
||||
aws-access-key-id: ${{ secrets.CCACHE_S3_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.CCACHE_S3_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
|
||||
- name: ccache stats initial
|
||||
run: |
|
||||
test -d github/home/.ccache && mv github/home/.ccache /github/home/.ccache
|
||||
ccache -M 10G -s
|
||||
|
||||
- name: Run Tests with Twister (Push)
|
||||
continue-on-error: true
|
||||
run: |
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
|
||||
mkdir -p coverage/reports
|
||||
./scripts/twister -N -v --filter runnable -p ${{ matrix.platform }} --coverage -T tests
|
||||
|
||||
- name: Generate Coverage Report
|
||||
run: |
|
||||
mv twister-out/coverage.info lcov.pre.info
|
||||
lcov -q --remove lcov.pre.info mylib.c --remove lcov.pre.info tests/\* \
|
||||
--remove lcov.pre.info samples/\* --remove lcov.pre.info ext/\* \
|
||||
--remove lcov.pre.info *generated* \
|
||||
-o coverage/reports/${{ matrix.platform }}.info --rc lcov_branch_coverage=1
|
||||
|
||||
- name: ccache stats post
|
||||
run: |
|
||||
ccache -s
|
||||
|
||||
- name: Upload Coverage Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Coverage Data (Subset ${{ matrix.platform }})
|
||||
path: coverage/reports/${{ matrix.platform }}.info
|
||||
|
||||
codecov-results:
|
||||
name: "Publish Coverage Results"
|
||||
needs: codecov
|
||||
runs-on: ubuntu-latest
|
||||
# the codecov job might be skipped, we don't need to run this job then
|
||||
if: success() || failure()
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: coverage/reports
|
||||
|
||||
- name: Move coverage files
|
||||
run: |
|
||||
mv ./coverage/reports/*/*.info ./coverage/reports
|
||||
ls -la ./coverage/reports
|
||||
|
||||
- name: Generate list of coverage files
|
||||
id: get-coverage-files
|
||||
shell: cmake -P {0}
|
||||
run: |
|
||||
file(GLOB INPUT_FILES_LIST "coverage/reports/*.info")
|
||||
set(MERGELIST "")
|
||||
set(FILELIST "")
|
||||
foreach(ITEM ${INPUT_FILES_LIST})
|
||||
get_filename_component(f ${ITEM} NAME)
|
||||
if(FILELIST STREQUAL "")
|
||||
set(FILELIST "${f}")
|
||||
else()
|
||||
set(FILELIST "${FILELIST},${f}")
|
||||
endif()
|
||||
endforeach()
|
||||
foreach(ITEM ${INPUT_FILES_LIST})
|
||||
get_filename_component(f ${ITEM} NAME)
|
||||
if(MERGELIST STREQUAL "")
|
||||
set(MERGELIST "-a ${f}")
|
||||
else()
|
||||
set(MERGELIST "${MERGELIST} -a ${f}")
|
||||
endif()
|
||||
endforeach()
|
||||
message("::set-output name=mergefiles::${MERGELIST}")
|
||||
message("::set-output name=covfiles::${FILELIST}")
|
||||
|
||||
- name: Merge coverage files
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y lcov
|
||||
cd ./coverage/reports
|
||||
lcov ${{ steps.get-coverage-files.outputs.mergefiles }} -o merged.info --rc lcov_branch_coverage=1
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
if: always()
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
directory: ./coverage/reports
|
||||
env_vars: OS,PYTHON
|
||||
fail_ci_if_error: false
|
||||
verbose: true
|
||||
files: merged.info
|
||||
61
.github/workflows/coding_guidelines.yml
vendored
61
.github/workflows/coding_guidelines.yml
vendored
@@ -1,61 +0,0 @@
|
||||
name: Coding Guidelines
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
compliance_job:
|
||||
runs-on: ubuntu-latest
|
||||
name: Run coding guidelines checks on patch series (PR)
|
||||
steps:
|
||||
- name: Checkout the code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: cache-pip
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-doc-pip
|
||||
|
||||
- name: Install python dependencies
|
||||
run: |
|
||||
pip3 install unidiff
|
||||
pip3 install wheel
|
||||
pip3 install sh
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install ocaml-base-nox
|
||||
wget https://launchpad.net/~npalix/+archive/ubuntu/coccinelle/+files/coccinelle_1.0.8~20.04npalix1_amd64.deb
|
||||
sudo dpkg -i coccinelle_1.0.8~20.04npalix1_amd64.deb
|
||||
|
||||
- name: Run Coding Guildeines Checks
|
||||
continue-on-error: true
|
||||
id: coding_guidelines
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
run: |
|
||||
export ZEPHYR_BASE=$PWD
|
||||
git config --global user.email "actions@zephyrproject.org"
|
||||
git config --global user.name "Github Actions"
|
||||
git remote -v
|
||||
git rebase origin/${BASE_REF}
|
||||
source zephyr-env.sh
|
||||
# debug
|
||||
ls -la
|
||||
git log --pretty=oneline | head -n 10
|
||||
./scripts/ci/guideline_check.py --output output.txt -c origin/${BASE_REF}..
|
||||
|
||||
- name: check-warns
|
||||
run: |
|
||||
if [[ -s "output.txt" ]]; then
|
||||
errors=$(cat output.txt)
|
||||
errors="${errors//'%'/'%25'}"
|
||||
errors="${errors//$'\n'/'%0A'}"
|
||||
errors="${errors//$'\r'/'%0D'}"
|
||||
echo "::error file=output.txt::$errors"
|
||||
exit 1;
|
||||
fi
|
||||
100
.github/workflows/compliance.yml
vendored
100
.github/workflows/compliance.yml
vendored
@@ -1,100 +0,0 @@
|
||||
name: Compliance Checks
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
maintainer_check:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check MAINTAINERS file
|
||||
steps:
|
||||
- name: Checkout the code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
- name: Run Maintainers Script
|
||||
id: maintainer
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
run: |
|
||||
python3 ./scripts/get_maintainer.py path CMakeLists.txt
|
||||
|
||||
check_compliance:
|
||||
runs-on: ubuntu-latest
|
||||
name: Run compliance checks on patch series (PR)
|
||||
steps:
|
||||
- name: Update PATH for west
|
||||
run: |
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Checkout the code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: cache-pip
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-doc-pip
|
||||
|
||||
- name: Install python dependencies
|
||||
run: |
|
||||
pip3 install setuptools
|
||||
pip3 install wheel
|
||||
pip3 install python-magic junitparser==1.6.3 gitlint pylint pykwalify
|
||||
pip3 install west
|
||||
|
||||
- name: west setup
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
run: |
|
||||
git config --global user.email "you@example.com"
|
||||
git config --global user.name "Your Name"
|
||||
git remote -v
|
||||
git rebase origin/${BASE_REF}
|
||||
# debug
|
||||
git log --pretty=oneline | head -n 10
|
||||
west init -l . || true
|
||||
west update 2>&1 1> west.update.log || west update 2>&1 1> west.update2.log
|
||||
|
||||
- name: Run Compliance Tests
|
||||
continue-on-error: true
|
||||
id: compliance
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
run: |
|
||||
export ZEPHYR_BASE=$PWD
|
||||
# debug
|
||||
ls -la
|
||||
git log --pretty=oneline | head -n 10
|
||||
./scripts/ci/check_compliance.py -m Codeowners -m Devicetree -m Gitlint -m Identity -m Nits -m pylint -m checkpatch -m Kconfig -c origin/${BASE_REF}..
|
||||
|
||||
- name: upload-results
|
||||
uses: actions/upload-artifact@master
|
||||
continue-on-error: True
|
||||
with:
|
||||
name: compliance.xml
|
||||
path: compliance.xml
|
||||
|
||||
- name: check-warns
|
||||
run: |
|
||||
if [[ ! -s "compliance.xml" ]]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
for file in Nits.txt checkpatch.txt Identity.txt Gitlint.txt pylint.txt Devicetree.txt Kconfig.txt Codeowners.txt; do
|
||||
if [[ -s $file ]]; then
|
||||
errors=$(cat $file)
|
||||
errors="${errors//'%'/'%25'}"
|
||||
errors="${errors//$'\n'/'%0A'}"
|
||||
errors="${errors//$'\r'/'%0D'}"
|
||||
echo "::error file=${file}::$errors"
|
||||
exit=1
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${exit}" == "1" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
14
.github/workflows/conflict.yml
vendored
14
.github/workflows/conflict.yml
vendored
@@ -1,14 +0,0 @@
|
||||
name: Conflict Finder
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- '**'
|
||||
jobs:
|
||||
conflict:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: mschilde/auto-label-merge-conflicts@v2
|
||||
with:
|
||||
CONFLICT_LABEL_NAME: "has conflicts"
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
38
.github/workflows/daily_test_version.yml
vendored
38
.github/workflows/daily_test_version.yml
vendored
@@ -1,38 +0,0 @@
|
||||
# Copyright (c) 2020 Intel Corp.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: Publish commit for daily testing
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '50 22 * * *'
|
||||
push:
|
||||
branches:
|
||||
- refs/tags/*
|
||||
|
||||
jobs:
|
||||
get_version:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'zephyrproject-rtos/zephyr'
|
||||
|
||||
steps:
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_TESTING }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_TESTING }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: install-pip
|
||||
run: |
|
||||
pip3 install gitpython
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Upload to AWS S3
|
||||
run: |
|
||||
python3 scripts/ci/version_mgr.py --update .
|
||||
aws s3 cp versions.json s3://testing.zephyrproject.org/daily_tests/versions.json
|
||||
69
.github/workflows/devicetree_checks.yml
vendored
69
.github/workflows/devicetree_checks.yml
vendored
@@ -1,69 +0,0 @@
|
||||
# Copyright (c) 2020 Linaro Limited.
|
||||
# Copyright (c) 2020 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: Devicetree script tests
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'scripts/dts/**'
|
||||
- '.github/workflows/devicetree_checks.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'scripts/dts/**'
|
||||
- '.github/workflows/devicetree_checks.yml'
|
||||
|
||||
jobs:
|
||||
devicetree-checks:
|
||||
name: Devicetree script tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.6, 3.7, 3.8]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
python-version: 3.6
|
||||
- os: windows-latest
|
||||
python-version: 3.6
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: cache-pip-linux
|
||||
if: startsWith(runner.os, 'Linux')
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ matrix.python-version }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-${{ matrix.python-version }}
|
||||
- name: cache-pip-mac
|
||||
if: startsWith(runner.os, 'macOS')
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/Library/Caches/pip
|
||||
# Trailing '-' was just to get a different cache name
|
||||
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-${{ matrix.python-version }}-
|
||||
- name: cache-pip-win
|
||||
if: startsWith(runner.os, 'Windows')
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~\AppData\Local\pip\Cache
|
||||
key: ${{ runner.os }}-pip-${{ matrix.python-version }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-${{ matrix.python-version }}
|
||||
- name: install python dependencies
|
||||
run: |
|
||||
pip3 install wheel
|
||||
pip3 install pytest pyyaml tox
|
||||
- name: run tox
|
||||
working-directory: scripts/dts/python-devicetree
|
||||
run: |
|
||||
tox
|
||||
143
.github/workflows/doc-build.yml
vendored
143
.github/workflows/doc-build.yml
vendored
@@ -1,148 +1,65 @@
|
||||
# Copyright (c) 2020 Linaro Limited.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: Documentation Build
|
||||
name: Documentation GitHub Workflow
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 */3 * * *'
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
pull_request:
|
||||
paths:
|
||||
- 'doc/**'
|
||||
- '**.rst'
|
||||
- 'include/**'
|
||||
- 'kernel/include/kernel_arch_interface.h'
|
||||
- 'lib/libc/**'
|
||||
- 'subsys/testsuite/ztest/include/**'
|
||||
- 'tests/**'
|
||||
- '**/Kconfig*'
|
||||
- 'west.yml'
|
||||
- '.github/workflows/doc-build.yml'
|
||||
- 'scripts/dts/**'
|
||||
- 'scripts/requirements-doc.txt'
|
||||
|
||||
env:
|
||||
# NOTE: west docstrings will be extracted from the version listed here
|
||||
WEST_VERSION: 0.12.0
|
||||
# The latest CMake available directly with apt is 3.18, but we need >=3.20
|
||||
# so we fetch that through pip.
|
||||
CMAKE_VERSION: 3.20.5
|
||||
DOXYGEN_VERSION: 1.9.2
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
doc-build-html:
|
||||
name: "Documentation Build (HTML)"
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
concurrency:
|
||||
group: doc-build-html-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- name: Update PATH for west
|
||||
run: |
|
||||
echo "::add-path::$HOME/.local/bin"
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: install-pkgs
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ninja-build graphviz libclang1-9 libclang-cpp9
|
||||
wget --no-verbose https://www.doxygen.nl/files/doxygen-${DOXYGEN_VERSION}.linux.bin.tar.gz
|
||||
tar xf doxygen-${DOXYGEN_VERSION}.linux.bin.tar.gz
|
||||
echo "${PWD}/doxygen-${DOXYGEN_VERSION}/bin" >> $GITHUB_PATH
|
||||
sudo apt-get install -y ninja-build doxygen
|
||||
|
||||
- name: cache-pip
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: pip-${{ hashFiles('scripts/requirements-doc.txt') }}
|
||||
key: ${{ runner.os }}-doc-pip
|
||||
|
||||
- name: install-pip
|
||||
run: |
|
||||
sudo pip3 install -U setuptools wheel pip
|
||||
pip3 install -r scripts/requirements-doc.txt
|
||||
pip3 install west==${WEST_VERSION}
|
||||
pip3 install cmake==${CMAKE_VERSION}
|
||||
pip3 install setuptools
|
||||
pip3 install 'breathe>=4.9.1,<4.15.0' 'docutils>=0.14' \
|
||||
'sphinx>=1.7.5,<3.0' sphinx_rtd_theme sphinx-tabs \
|
||||
sphinxcontrib-svg2pdfconverter 'west>=0.6.2'
|
||||
pip3 install pyelftools
|
||||
|
||||
- name: west setup
|
||||
run: |
|
||||
west init -l .
|
||||
west init -l . || true
|
||||
|
||||
- name: build-docs
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" =~ "refs/tags/v" ]]; then
|
||||
DOC_TAG="release"
|
||||
else
|
||||
DOC_TAG="development"
|
||||
fi
|
||||
|
||||
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
DOC_TARGET="html-fast"
|
||||
else
|
||||
DOC_TARGET="html"
|
||||
fi
|
||||
|
||||
DOC_TAG=${DOC_TAG} SPHINXOPTS="-q -W -t publish" make -C doc ${DOC_TARGET}
|
||||
|
||||
- name: compress-docs
|
||||
run: |
|
||||
tar cfJ html-output.tar.xz --directory=doc/_build html
|
||||
source zephyr-env.sh
|
||||
make htmldocs
|
||||
tar cvf htmldocs.tar --directory=./doc/_build html
|
||||
|
||||
- name: upload-build
|
||||
uses: actions/upload-artifact@master
|
||||
continue-on-error: True
|
||||
with:
|
||||
name: html-output
|
||||
path: html-output.tar.xz
|
||||
name: htmldocs.tar
|
||||
path: htmldocs.tar
|
||||
|
||||
doc-build-pdf:
|
||||
name: "Documentation Build (PDF)"
|
||||
runs-on: ubuntu-latest
|
||||
container: texlive/texlive:latest
|
||||
timeout-minutes: 30
|
||||
concurrency:
|
||||
group: doc-build-pdf-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: install-pkgs
|
||||
- name: check-warns
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y python3-pip ninja-build doxygen graphviz librsvg2-bin
|
||||
|
||||
- name: cache-pip
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: pip-${{ hashFiles('scripts/requirements-doc.txt') }}
|
||||
|
||||
- name: install-pip
|
||||
run: |
|
||||
pip3 install -U setuptools wheel pip
|
||||
pip3 install -r scripts/requirements-doc.txt
|
||||
pip3 install west==${WEST_VERSION}
|
||||
pip3 install cmake==${CMAKE_VERSION}
|
||||
|
||||
- name: west setup
|
||||
run: |
|
||||
west init -l .
|
||||
|
||||
- name: build-docs
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" =~ "refs/tags/v" ]]; then
|
||||
DOC_TAG="release"
|
||||
else
|
||||
DOC_TAG="development"
|
||||
if [ -s doc/_build/doc.warnings ]; then
|
||||
docwarn=$(cat doc/_build/doc.warnings)
|
||||
docwarn="${docwarn//'%'/'%25'}"
|
||||
docwarn="${docwarn//$'\n'/'%0A'}"
|
||||
docwarn="${docwarn//$'\r'/'%0D'}"
|
||||
# We treat doc warnings as errors
|
||||
echo "::error file=doc.warnings::$docwarn"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DOC_TAG=${DOC_TAG} SPHINXOPTS="-q -j auto" LATEXMKOPTS="-quiet -halt-on-error" make -C doc pdf
|
||||
|
||||
- name: upload-build
|
||||
uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: pdf-output
|
||||
path: doc/_build/latex/zephyr.pdf
|
||||
|
||||
122
.github/workflows/doc-publish.yml
vendored
122
.github/workflows/doc-publish.yml
vendored
@@ -1,38 +1,42 @@
|
||||
# Copyright (c) 2020 Linaro Limited.
|
||||
# Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: Publish Documentation
|
||||
name: Doc build for Release or Daily
|
||||
|
||||
# Either a daily based on schedule/cron or only on tag push
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Documentation Build"]
|
||||
branches:
|
||||
- main
|
||||
- v*
|
||||
schedule:
|
||||
- cron: '50 22 * * *'
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
types:
|
||||
- completed
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
doc-publish:
|
||||
name: Publish Documentation
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.event.workflow_run.conclusion == 'success' &&
|
||||
github.repository == 'zephyrproject-rtos/zephyr'
|
||||
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
workflow: doc-build.yml
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
|
||||
- name: Uncompress HTML docs
|
||||
- name: Update PATH for west
|
||||
run: |
|
||||
tar xf html-output/html-output.tar.xz -C html-output
|
||||
echo "::add-path::$HOME/.local/bin"
|
||||
|
||||
- name: Determine tag
|
||||
id: tag
|
||||
run: |
|
||||
# We expect to get here either due to a schedule event in which
|
||||
# case we are doing a daily build of the docs, or because a new
|
||||
# tag was pushed, in which case we are building docs for a release
|
||||
if [ ${GITHUB_EVENT_NAME} == "schedule" ]; then
|
||||
echo ::set-output name=TYPE::daily;
|
||||
echo ::set-output name=RELEASE::latest;
|
||||
elif [ ${GITHUB_EVENT_NAME} == "push" ]; then
|
||||
# If push due to a tag GITHUB_REF will look like refs/tags/TAG-FOO
|
||||
# chop of 'refs/tags' so RELEASE=TAG-FOO
|
||||
echo ::set-output name=TYPE::release;
|
||||
echo ::set-output name=RELEASE::${GITHUB_REF/refs\/tags\//};
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
@@ -41,16 +45,68 @@ jobs:
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Upload to AWS S3
|
||||
env:
|
||||
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: install-pkgs
|
||||
run: |
|
||||
if [ "${HEAD_BRANCH:0:1}" == "v" ]; then
|
||||
VERSION=${HEAD_BRANCH:1}
|
||||
else
|
||||
VERSION="latest"
|
||||
sudo apt-get install -y ninja-build doxygen
|
||||
|
||||
- name: cache-pip
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-doc-pip
|
||||
|
||||
- name: install-pip
|
||||
run: |
|
||||
pip3 install setuptools
|
||||
pip3 install 'breathe>=4.9.1,<4.15.0' 'docutils>=0.14' \
|
||||
'sphinx>=1.7.5,<3.0' sphinx_rtd_theme sphinx-tabs \
|
||||
sphinxcontrib-svg2pdfconverter 'west>=0.6.2'
|
||||
pip3 install pyelftools
|
||||
|
||||
- name: west setup
|
||||
run: |
|
||||
west init -l . || true
|
||||
|
||||
- name: build-docs
|
||||
env:
|
||||
DOC_TAG: ${{ steps.tag.outputs.TYPE }}
|
||||
run: |
|
||||
source zephyr-env.sh
|
||||
make DOC_TAG=${DOC_TAG} htmldocs
|
||||
|
||||
- name: check-warns
|
||||
run: |
|
||||
if [ -s doc/_build/doc.warnings ]; then
|
||||
docwarn=$(cat doc/_build/doc.warnings)
|
||||
docwarn="${docwarn//'%'/'%25'}"
|
||||
docwarn="${docwarn//$'\n'/'%0A'}"
|
||||
docwarn="${docwarn//$'\r'/'%0D'}"
|
||||
# We treat doc warnings as errors
|
||||
echo "::error file=doc.warnings::$docwarn"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
aws s3 sync --quiet html-output/html s3://docs.zephyrproject.org/${VERSION} --delete
|
||||
aws s3 sync --quiet html-output/html/doxygen/html s3://docs.zephyrproject.org/apidoc/${VERSION} --delete
|
||||
aws s3 cp --quiet pdf-output/zephyr.pdf s3://docs.zephyrproject.org/${VERSION}/zephyr.pdf
|
||||
- name: Upload to AWS S3
|
||||
env:
|
||||
RELEASE: ${{ steps.tag.outputs.RELEASE }}
|
||||
run: |
|
||||
echo "DOC_RELEASE=[$RELEASE]"
|
||||
if [ "$RELEASE" == "latest" ]; then
|
||||
export
|
||||
echo "publish latest docs"
|
||||
aws s3 sync --quiet doc/_build/html s3://docs.zephyrproject.org/latest --delete
|
||||
echo "success sync of latest docs"
|
||||
else
|
||||
DOC_RELEASE=${RELEASE}.0
|
||||
echo "publish release docs: ${DOC_RELEASE}"
|
||||
aws s3 sync --quiet doc/_build/html s3://docs.zephyrproject.org/${DOC_RELEASE}
|
||||
echo "success sync of rel docs"
|
||||
fi
|
||||
if [ -d doc/_build/doxygen/html ]; then
|
||||
echo "publish doxygen"
|
||||
aws s3 sync --quiet doc/_build/doxygen/html s3://docs.zephyrproject.org/apidoc/${RELEASE} --delete
|
||||
echo "success publish of doxygen"
|
||||
fi
|
||||
|
||||
20
.github/workflows/errno.yml
vendored
20
.github/workflows/errno.yml
vendored
@@ -1,20 +0,0 @@
|
||||
name: Error numbers
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'lib/libc/minimal/include/errno.h'
|
||||
|
||||
jobs:
|
||||
check-errno:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: zephyrprojectrtos/ci:v0.21.0
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Run errno.py
|
||||
run: |
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
./scripts/ci/errno.py
|
||||
71
.github/workflows/footprint-tracking.yml
vendored
71
.github/workflows/footprint-tracking.yml
vendored
@@ -1,71 +0,0 @@
|
||||
name: Footprint Tracking
|
||||
|
||||
# Run every 12 hours and on tags
|
||||
on:
|
||||
schedule:
|
||||
- cron: '50 1/12 * * *'
|
||||
push:
|
||||
paths:
|
||||
- 'VERSION'
|
||||
- '.github/workflows/footprint-tracking.yml'
|
||||
tags:
|
||||
# only publish v* tags, do not care about zephyr-v* which point to the
|
||||
# same commit
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
footprint-tracking-cancel:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'zephyrproject-rtos/zephyr'
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
footprint-tracking:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'zephyrproject-rtos/zephyr'
|
||||
needs: footprint-tracking-cancel
|
||||
container:
|
||||
image: zephyrprojectrtos/ci:v0.21.0
|
||||
options: '--entrypoint /bin/bash'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
env:
|
||||
ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.13.2
|
||||
CLANG_ROOT_DIR: /usr/lib/llvm-12
|
||||
ZEPHYR_TOOLCHAIN_VARIANT: zephyr
|
||||
steps:
|
||||
- name: Update PATH for west
|
||||
run: |
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
- name: Install pip packages
|
||||
run: |
|
||||
sudo pip3 install -U setuptools wheel pip gitpython
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: west setup
|
||||
run: |
|
||||
west init -l . || true
|
||||
west config --global update.narrow true
|
||||
west update 2>&1 1> west.update.log || west update 2>&1 1> west.update2.log
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.FOOTPRINT_AWS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.FOOTPRINT_AWS_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Record Footprint
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
run: |
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
./scripts/footprint/track.py -p scripts/footprint/plan.txt
|
||||
aws s3 sync --quiet footprint_data/ s3://testing.zephyrproject.org/footprint_data/
|
||||
72
.github/workflows/footprint.yml
vendored
72
.github/workflows/footprint.yml
vendored
@@ -1,72 +0,0 @@
|
||||
name: Footprint Delta
|
||||
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
footprint-cancel:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'zephyrproject-rtos/zephyr'
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
footprint-delta:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'zephyrproject-rtos/zephyr'
|
||||
needs: footprint-cancel
|
||||
container:
|
||||
image: zephyrprojectrtos/ci:v0.21.0
|
||||
options: '--entrypoint /bin/bash'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
env:
|
||||
ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.13.2
|
||||
CLANG_ROOT_DIR: /usr/lib/llvm-12
|
||||
ZEPHYR_TOOLCHAIN_VARIANT: zephyr
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Update PATH for west
|
||||
run: |
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: west setup
|
||||
run: |
|
||||
west init -l . || true
|
||||
west config --global update.narrow true
|
||||
west update 2>&1 1> west.update.log || west update 2>&1 1> west.update.log
|
||||
|
||||
- name: Detect Changes in Footprint
|
||||
env:
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
run: |
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
git config --global user.email "actions@zephyrproject.org"
|
||||
git config --global user.name "Github Actions"
|
||||
git remote -v
|
||||
git rebase origin/${BASE_REF}
|
||||
git checkout -b this_pr
|
||||
west build -b frdm_k64f tests/benchmarks/footprints -t ram_report
|
||||
cp build/ram.json ram2.json
|
||||
west build -b frdm_k64f tests/benchmarks/footprints -t rom_report
|
||||
cp build/rom.json rom2.json
|
||||
|
||||
git checkout origin/${BASE_REF}
|
||||
west update
|
||||
west build -p always -b frdm_k64f tests/benchmarks/footprints -t ram_report
|
||||
west build -b frdm_k64f tests/benchmarks/footprints -t rom_report
|
||||
cp build/ram.json ram1.json
|
||||
cp build/rom.json rom1.json
|
||||
|
||||
git checkout this_pr
|
||||
./scripts/footprint/fpdiff.py ram1.json ram2.json
|
||||
./scripts/footprint/fpdiff.py rom1.json rom2.json
|
||||
54
.github/workflows/issue_count.yml
vendored
54
.github/workflows/issue_count.yml
vendored
@@ -1,54 +0,0 @@
|
||||
name: Issue Tracker
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '*/10 * * * *'
|
||||
|
||||
env:
|
||||
OUTPUT_FILE_NAME: IssuesReport.md
|
||||
COMMITTER_EMAIL: actions@github.com
|
||||
COMMITTER_NAME: github-actions
|
||||
COMMITTER_USERNAME: github-actions
|
||||
|
||||
|
||||
jobs:
|
||||
track-issues:
|
||||
name: "Collect Issue Stats"
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'zephyrproject-rtos/zephyr'
|
||||
|
||||
steps:
|
||||
- name: Download configuration file
|
||||
run: |
|
||||
wget -q https://raw.githubusercontent.com/$GITHUB_REPOSITORY/master/.github/workflows/issues-report-config.json
|
||||
|
||||
- name: install-packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install discount
|
||||
|
||||
- uses: brcrista/summarize-issues@v3
|
||||
with:
|
||||
title: 'Issues Report for ${{ github.repository }}'
|
||||
configPath: 'issues-report-config.json'
|
||||
outputPath: ${{ env.OUTPUT_FILE_NAME }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: upload-stats
|
||||
uses: actions/upload-artifact@master
|
||||
continue-on-error: True
|
||||
with:
|
||||
name: ${{ env.OUTPUT_FILE_NAME }}
|
||||
path: ${{ env.OUTPUT_FILE_NAME }}
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_TESTING }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_TESTING }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Post Results
|
||||
run: |
|
||||
mkd2html IssuesReport.md IssuesReport.html
|
||||
aws s3 cp --quiet IssuesReport.html s3://testing.zephyrproject.org/issues/$GITHUB_REPOSITORY/index.html
|
||||
37
.github/workflows/issues-report-config.json
vendored
37
.github/workflows/issues-report-config.json
vendored
@@ -1,37 +0,0 @@
|
||||
[
|
||||
{
|
||||
"section": "High Priority Bugs",
|
||||
"labels": ["bug", "priority: high"],
|
||||
"threshold": 0
|
||||
},
|
||||
{
|
||||
"section": "Medium Priority Bugs",
|
||||
"labels": ["bug", "priority: medium"],
|
||||
"threshold": 20
|
||||
},
|
||||
{
|
||||
"section": "Low Priority Bugs",
|
||||
"labels": ["bug", "priority: low"],
|
||||
"threshold": 100
|
||||
},
|
||||
{
|
||||
"section": "Enhancements",
|
||||
"labels": ["Enhancement"],
|
||||
"threshold": 500
|
||||
},
|
||||
{
|
||||
"section": "Features",
|
||||
"labels": ["Feature"],
|
||||
"threshold": 100
|
||||
},
|
||||
{
|
||||
"section": "Questions",
|
||||
"labels": ["question"],
|
||||
"threshold": 100
|
||||
},
|
||||
{
|
||||
"section": "Static Analysis",
|
||||
"labels": ["Coverity"],
|
||||
"threshold": 100
|
||||
}
|
||||
]
|
||||
12
.github/workflows/labeler.yml
vendored
12
.github/workflows/labeler.yml
vendored
@@ -1,12 +0,0 @@
|
||||
name: 'Pull Request Labeler'
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
name: Pull Request Labeler
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v2.1.1
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
28
.github/workflows/manifest.yml
vendored
28
.github/workflows/manifest.yml
vendored
@@ -1,28 +0,0 @@
|
||||
name: Manifest
|
||||
on:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- 'west.yml'
|
||||
|
||||
jobs:
|
||||
contribs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Manifest
|
||||
steps:
|
||||
- name: Checkout the code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: zephyrproject/zephyr
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Manifest
|
||||
uses: zephyrproject-rtos/action-manifest@2f1ad2908599d4fe747f886f9d733dd7eebae4ef
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
manifest-path: 'west.yml'
|
||||
checkout-path: 'zephyrproject/zephyr'
|
||||
label-prefix: 'manifest-'
|
||||
verbosity-level: '1'
|
||||
labels: 'manifest, west'
|
||||
dnm-labels: 'DNM'
|
||||
61
.github/workflows/release.yml
vendored
61
.github/workflows/release.yml
vendored
@@ -1,61 +0,0 @@
|
||||
name: Create a Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get the version
|
||||
id: get_version
|
||||
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}
|
||||
|
||||
- name: REUSE Compliance Check
|
||||
uses: fsfe/reuse-action@v1
|
||||
with:
|
||||
args: spdx -o zephyr-${{ steps.get_version.outputs.VERSION }}.spdx
|
||||
|
||||
- name: upload-results
|
||||
uses: actions/upload-artifact@master
|
||||
continue-on-error: True
|
||||
with:
|
||||
name: zephyr-${{ steps.get_version.outputs.VERSION }}.spdx
|
||||
path: zephyr-${{ steps.get_version.outputs.VERSION }}.spdx
|
||||
|
||||
- name: Get Diff since last tag
|
||||
run: |
|
||||
oldtag=$(git describe --abbrev=0 ${{ github.ref }}^)
|
||||
echo "Changes since ${oldtag}:" > release-notes.txt
|
||||
echo "" >> release-notes.txt
|
||||
echo "" >> release-notes.txt
|
||||
git shortlog ${oldtag}..${{ github.ref }} >> release-notes.txt
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Zephyr ${{ github.ref }}
|
||||
body_path: release-notes.txt
|
||||
draft: true
|
||||
prerelease: true
|
||||
|
||||
- name: Upload Release Assets
|
||||
id: upload-release-asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: zephyr-${{ steps.get_version.outputs.VERSION }}.spdx
|
||||
asset_name: zephyr-${{ steps.get_version.outputs.VERSION }}.spdx
|
||||
asset_content_type: text/plain
|
||||
23
.github/workflows/stale_issue.yml
vendored
23
.github/workflows/stale_issue.yml
vendored
@@ -1,23 +0,0 @@
|
||||
name: "Close stale pull requests/issues"
|
||||
on:
|
||||
schedule:
|
||||
- cron: "16 00 * * *"
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
name: Find Stale issues and PRs
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'zephyrproject-rtos/zephyr'
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-pr-message: 'This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.'
|
||||
stale-issue-message: 'This issue has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this issue will automatically be closed in 14 days. Note, that you can always re-open a closed issue at any time.'
|
||||
days-before-stale: 60
|
||||
days-before-close: 14
|
||||
stale-issue-label: 'Stale'
|
||||
stale-pr-label: 'Stale'
|
||||
exempt-pr-labels: 'Blocked,In progress'
|
||||
exempt-issue-labels: 'In progress,Enhancement,Feature,Feature Request,RFC,Meta,Process'
|
||||
operations-per-run: 400
|
||||
282
.github/workflows/twister.yaml
vendored
282
.github/workflows/twister.yaml
vendored
@@ -1,282 +0,0 @@
|
||||
name: Run tests with twister
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request_target:
|
||||
branches:
|
||||
- main
|
||||
schedule:
|
||||
# Run at 00:00 on Wednesday and Saturday
|
||||
- cron: '0 0 * * 3,6'
|
||||
|
||||
jobs:
|
||||
twister-build-cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.6.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
twister-build-prep:
|
||||
|
||||
runs-on: zephyr_runner
|
||||
needs: twister-build-cleanup
|
||||
container:
|
||||
image: zephyrprojectrtos/ci:v0.21.0
|
||||
options: '--entrypoint /bin/bash'
|
||||
volumes:
|
||||
- /home/runners/zephyrproject:/github/cache/zephyrproject
|
||||
outputs:
|
||||
subset: ${{ steps.output-services.outputs.subset }}
|
||||
size: ${{ steps.output-services.outputs.size }}
|
||||
fullrun: ${{ steps.output-services.outputs.fullrun }}
|
||||
env:
|
||||
MATRIX_SIZE: 10
|
||||
PUSH_MATRIX_SIZE: 15
|
||||
DAILY_MATRIX_SIZE: 80
|
||||
ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.13.2
|
||||
CLANG_ROOT_DIR: /usr/lib/llvm-12
|
||||
TESTS_PER_BUILDER: 700
|
||||
COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
steps:
|
||||
- name: Cleanup
|
||||
run: |
|
||||
# hotfix, until we have a better way to deal with existing data
|
||||
rm -rf zephyr zephyr-testing
|
||||
|
||||
- name: Checkout
|
||||
if: github.event_name == 'pull_request_target'
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Environment Setup
|
||||
if: github.event_name == 'pull_request_target'
|
||||
run: |
|
||||
pip3 install GitPython
|
||||
git config --global user.email "bot@zephyrproject.org"
|
||||
git config --global user.name "Zephyr Bot"
|
||||
rm -fr ".git/rebase-apply"
|
||||
git rebase origin/${BASE_REF}
|
||||
git log --pretty=oneline | head -n 10
|
||||
west init -l . || true
|
||||
# no need for west update here
|
||||
|
||||
- name: Generate Test Plan with Twister
|
||||
if: github.event_name == 'pull_request_target'
|
||||
id: test-plan
|
||||
run: |
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
|
||||
python3 ./scripts/ci/test_plan.py -c origin/${BASE_REF}.. --pull-request -t $TESTS_PER_BUILDER
|
||||
if [ -s .testplan ]; then
|
||||
cat .testplan >> $GITHUB_ENV
|
||||
else
|
||||
echo "TWISTER_NODES=${MATRIX_SIZE}" >> $GITHUB_ENV
|
||||
fi
|
||||
rm -f testplan.csv .testplan
|
||||
|
||||
- name: Determine matrix size
|
||||
id: output-services
|
||||
run: |
|
||||
if [ "${{github.event_name}}" = "pull_request_target" ]; then
|
||||
if [ -n "${TWISTER_NODES}" ]; then
|
||||
subset="[$(seq -s',' 1 ${TWISTER_NODES})]"
|
||||
else
|
||||
subset="[$(seq -s',' 1 ${MATRIX_SIZE})]"
|
||||
fi
|
||||
size=${TWISTER_NODES}
|
||||
elif [ "${{github.event_name}}" = "push" ]; then
|
||||
subset="[$(seq -s',' 1 ${PUSH_MATRIX_SIZE})]"
|
||||
size=${MATRIX_SIZE}
|
||||
elif [ "${{github.event_name}}" = "schedule" -a "${{github.repository}}" = "zephyrproject-rtos/zephyr" ]; then
|
||||
subset="[$(seq -s',' 1 ${DAILY_MATRIX_SIZE})]"
|
||||
size=${DAILY_MATRIX_SIZE}
|
||||
else
|
||||
size=0
|
||||
fi
|
||||
echo "::set-output name=subset::${subset}";
|
||||
echo "::set-output name=size::${size}";
|
||||
echo "::set-output name=fullrun::${TWISTER_FULL}";
|
||||
|
||||
twister-build:
|
||||
runs-on: zephyr_runner
|
||||
needs: twister-build-prep
|
||||
if: needs.twister-build-prep.outputs.size != 0
|
||||
container:
|
||||
image: zephyrprojectrtos/ci:v0.21.0
|
||||
options: '--entrypoint /bin/bash'
|
||||
volumes:
|
||||
- /home/runners/zephyrproject:/github/cache/zephyrproject
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
subset: ${{fromJSON(needs.twister-build-prep.outputs.subset)}}
|
||||
env:
|
||||
ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains/zephyr-sdk-0.13.2
|
||||
CLANG_ROOT_DIR: /usr/lib/llvm-12
|
||||
TWISTER_COMMON: ' --inline-logs -v -N -M --retry-failed 3 '
|
||||
DAILY_OPTIONS: ' -M --build-only --all '
|
||||
PR_OPTIONS: ' --clobber-output --integration '
|
||||
PUSH_OPTIONS: ' --clobber-output -M '
|
||||
COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
|
||||
BASE_REF: ${{ github.base_ref }}
|
||||
steps:
|
||||
- name: Cleanup
|
||||
run: |
|
||||
# hotfix, until we have a better way to deal with existing data
|
||||
rm -rf zephyr zephyr-testing
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Environment Setup
|
||||
run: |
|
||||
pip3 install GitPython
|
||||
if [ "${{github.event_name}}" = "pull_request_target" ]; then
|
||||
git config --global user.email "bot@zephyrproject.org"
|
||||
git config --global user.name "Zephyr Builder"
|
||||
rm -fr ".git/rebase-apply"
|
||||
git rebase origin/${BASE_REF}
|
||||
git log --pretty=oneline | head -n 10
|
||||
fi
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
west init -l . || true
|
||||
west config --global update.narrow true
|
||||
west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || west update --path-cache /github/cache/zephyrproject 2>&1 1> west.update.log || ( rm -rf ../modules ../bootloader ../tools && west update --path-cache /github/cache/zephyrproject)
|
||||
west forall -c 'git reset --hard HEAD'
|
||||
|
||||
- name: Check Environment
|
||||
run: |
|
||||
cmake --version
|
||||
${CLANG_ROOT_DIR}/bin/clang --version
|
||||
gcc --version
|
||||
ls -la
|
||||
echo "github.ref: ${{ github.ref }}"
|
||||
echo "github.base_ref: ${{ github.base_ref }}"
|
||||
echo "github.ref_name: ${{ github.ref_name }}"
|
||||
|
||||
- name: Prepare ccache timestamp/data
|
||||
id: ccache_cache_timestamp
|
||||
shell: cmake -P {0}
|
||||
run: |
|
||||
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
|
||||
string(REPLACE "/" "_" repo ${{github.repository}})
|
||||
string(REPLACE "-" "_" repo2 ${repo})
|
||||
message("::set-output name=repo::${repo2}")
|
||||
|
||||
- name: use cache
|
||||
id: cache-ccache
|
||||
uses: nashif/action-s3-cache@master
|
||||
with:
|
||||
key: ${{ steps.ccache_cache_timestamp.outputs.repo }}-${{ github.ref_name }}-${{github.event_name}}-${{ matrix.subset }}-ccache
|
||||
path: /github/home/.ccache
|
||||
aws-s3-bucket: ccache.zephyrproject.org
|
||||
aws-access-key-id: ${{ secrets.CCACHE_S3_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.CCACHE_S3_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-2
|
||||
|
||||
- name: ccache stats initial
|
||||
run: |
|
||||
test -d github/home/.ccache && rm -rf /github/home/.ccache && mv github/home/.ccache /github/home/.ccache
|
||||
ccache -M 10G -s
|
||||
|
||||
- if: github.event_name == 'push'
|
||||
name: Run Tests with Twister (Push)
|
||||
run: |
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
|
||||
./scripts/twister --subset ${{matrix.subset}}/${{ strategy.job-total }} ${TWISTER_COMMON} ${PUSH_OPTIONS}
|
||||
if [ "${{matrix.subset}}" = "1" ]; then
|
||||
./scripts/zephyr_module.py --twister-out module_tests.args
|
||||
if [ -s module_tests.args ]; then
|
||||
./scripts/twister +module_tests.args --outdir module_tests ${TWISTER_COMMON} ${PUSH_OPTIONS}
|
||||
fi
|
||||
fi
|
||||
|
||||
- if: github.event_name == 'pull_request_target'
|
||||
name: Run Tests with Twister (Pull Request)
|
||||
run: |
|
||||
rm -f testplan.csv
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
|
||||
python3 ./scripts/ci/test_plan.py -c origin/${BASE_REF}.. --pull-request
|
||||
./scripts/twister --subset ${{matrix.subset}}/${{ strategy.job-total }} --load-tests testplan.csv ${TWISTER_COMMON} ${PR_OPTIONS}
|
||||
if [ "${{matrix.subset}}" = "1" -a ${{needs.twister-build-prep.outputs.fullrun}} = 'True' ]; then
|
||||
./scripts/zephyr_module.py --twister-out module_tests.args
|
||||
if [ -s module_tests.args ]; then
|
||||
./scripts/twister +module_tests.args --outdir module_tests ${TWISTER_COMMON} ${PR_OPTIONS}
|
||||
fi
|
||||
fi
|
||||
|
||||
- if: github.event_name == 'schedule'
|
||||
name: Run Tests with Twister (Daily)
|
||||
run: |
|
||||
export ZEPHYR_BASE=${PWD}
|
||||
export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
|
||||
./scripts/twister --subset ${{matrix.subset}}/${{ strategy.job-total }} ${TWISTER_COMMON} ${DAILY_OPTIONS}
|
||||
if [ "${{matrix.subset}}" = "1" ]; then
|
||||
./scripts/zephyr_module.py --twister-out module_tests.args
|
||||
if [ -s module_tests.args ]; then
|
||||
./scripts/twister +module_tests.args --outdir module_tests ${TWISTER_COMMON} ${DAILY_OPTIONS}
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: ccache stats post
|
||||
run: |
|
||||
ccache -s
|
||||
|
||||
- name: Upload Unit Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Unit Test Results (Subset ${{ matrix.subset }})
|
||||
if-no-files-found: ignore
|
||||
path: |
|
||||
twister-out/twister.xml
|
||||
testplan.csv
|
||||
|
||||
twister-test-results:
|
||||
name: "Publish Unit Tests Results"
|
||||
needs: twister-build
|
||||
runs-on: ubuntu-latest
|
||||
# the build-and-test job might be skipped, we don't need to run this job then
|
||||
if: success() || failure()
|
||||
|
||||
steps:
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Merge Test Results
|
||||
run: |
|
||||
pip3 install junitparser junit2html
|
||||
junitparser merge artifacts/*/*/twister.xml junit.xml
|
||||
junit2html junit.xml junit.html
|
||||
|
||||
- name: Upload Unit Test Results in HTML
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: HTML Unit Test Results
|
||||
if-no-files-found: ignore
|
||||
path: |
|
||||
junit.html
|
||||
|
||||
- name: Publish Unit Test Results
|
||||
uses: EnricoMi/publish-unit-test-result-action@v1
|
||||
with:
|
||||
check_name: Unit Test Results
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
files: "**/twister.xml"
|
||||
comment_mode: off
|
||||
52
.github/workflows/twister_tests.yml
vendored
52
.github/workflows/twister_tests.yml
vendored
@@ -1,52 +0,0 @@
|
||||
# Copyright (c) 2020 Intel Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
name: Twister TestSuite
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'scripts/pylib/twister/**'
|
||||
- 'scripts/twister'
|
||||
- 'scripts/tests/twister/**'
|
||||
- '.github/workflows/twister_tests.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'scripts/pylib/twister/**'
|
||||
- 'scripts/twister'
|
||||
- 'scripts/tests/twister/**'
|
||||
- '.github/workflows/twister_tests.yml'
|
||||
|
||||
jobs:
|
||||
twister-tests:
|
||||
name: Twister Unit Tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.6, 3.7, 3.8]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: cache-pip-linux
|
||||
if: startsWith(runner.os, 'Linux')
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ matrix.python-version }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-${{ matrix.python-version }}
|
||||
- name: install-packages
|
||||
run: |
|
||||
pip3 install pytest colorama pyyaml ply mock
|
||||
- name: Run pytest
|
||||
env:
|
||||
ZEPHYR_BASE: ./
|
||||
ZEPHYR_TOOLCHAIN_VARIANT: zephyr
|
||||
run: |
|
||||
echo "Run twister tests"
|
||||
PYTHONPATH=./scripts/tests pytest ./scripts/tests/twister
|
||||
17
.github/workflows/west_cmds.yml
vendored
17
.github/workflows/west_cmds.yml
vendored
@@ -8,26 +8,18 @@ on:
|
||||
paths:
|
||||
- 'scripts/west-commands.yml'
|
||||
- 'scripts/west_commands/**'
|
||||
- '.github/workflows/west_cmds.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'scripts/west-commands.yml'
|
||||
- 'scripts/west_commands/**'
|
||||
- '.github/workflows/west_cmds.yml'
|
||||
|
||||
jobs:
|
||||
west-commnads:
|
||||
name: West Command Tests
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.6, 3.7, 3.8]
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
python-version: 3.6
|
||||
- os: windows-latest
|
||||
python-version: 3.6
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
@@ -62,13 +54,12 @@ jobs:
|
||||
${{ runner.os }}-pip-${{ matrix.python-version }}
|
||||
- name: install pytest
|
||||
run: |
|
||||
pip3 install wheel
|
||||
pip3 install pytest west pyelftools canopen progress mypy intelhex psutil
|
||||
pip3 install pytest west pyelftools
|
||||
- name: run pytest-win
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
python ./scripts/west_commands/run_tests.py
|
||||
cmd /C "set PYTHONPATH=.\scripts\west_commands && pytest ./scripts/west_commands/tests/"
|
||||
- name: run pytest-mac-linux
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
./scripts/west_commands/run_tests.py
|
||||
PYTHONPATH=./scripts/west_commands pytest ./scripts/west_commands/tests/
|
||||
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -9,7 +9,6 @@
|
||||
*~
|
||||
build*/
|
||||
!doc/guides/build
|
||||
!tests/drivers/build_all
|
||||
cscope.*
|
||||
.dir
|
||||
|
||||
@@ -32,7 +31,6 @@ doc/samples
|
||||
doc/latex
|
||||
doc/themes/zephyr-docs-theme
|
||||
sanity-out*
|
||||
twister-out*
|
||||
bsim_bt_out
|
||||
scripts/grub
|
||||
doc/reference/kconfig/*.rst
|
||||
@@ -42,13 +40,6 @@ doc/doc.warnings
|
||||
.envrc
|
||||
.vscode
|
||||
hide-defaults-note
|
||||
venv
|
||||
.venv
|
||||
.DS_Store
|
||||
|
||||
# CI output
|
||||
compliance.xml
|
||||
_error.types
|
||||
|
||||
# Tag files
|
||||
GPATH
|
||||
|
||||
7
.gitlint
7
.gitlint
@@ -4,10 +4,7 @@ ignore=title-trailing-punctuation, T3, title-max-length, T1, body-hard-tab, B3,
|
||||
# verbosity should be a value between 1 and 3, the commandline -v flags take precedence over this
|
||||
verbosity = 3
|
||||
# By default gitlint will ignore merge commits. Set to 'false' to disable.
|
||||
ignore-merge-commits=false
|
||||
ignore-revert-commits=false
|
||||
ignore-fixup-commits=false
|
||||
ignore-squash-commits=false
|
||||
ignore-merge-commits=true
|
||||
# Enable debug mode (prints more output). Disabled by default
|
||||
debug = false
|
||||
|
||||
@@ -42,7 +39,7 @@ words=wip
|
||||
|
||||
[max-line-length-with-exceptions]
|
||||
# B1 = body-max-line-length
|
||||
line-length=75
|
||||
line-length=72
|
||||
|
||||
[body-min-length]
|
||||
min-length=3
|
||||
|
||||
55
.known-issues/README
Normal file
55
.known-issues/README
Normal file
@@ -0,0 +1,55 @@
|
||||
This directory contains configuration files to ignore errors found in
|
||||
the build and test process which are known to the developers and for
|
||||
now can be safely ignored.
|
||||
|
||||
To use:
|
||||
|
||||
$ cd zephyr
|
||||
$ make SOMETHING >& result
|
||||
$ scripts/filter-known-issues.py result
|
||||
|
||||
It is included in the source tree so if anyone has to submit anything
|
||||
that triggers some kind of error that is a false positive, it can
|
||||
include the "ignore me" file, properly documented.
|
||||
|
||||
Each file can contain one or more multiline Python regular expressions
|
||||
(https://docs.python.org/2/library/re.html#regular-expression-syntax)
|
||||
that match an error message. Multiple regular expressions are
|
||||
separated by comment blocks (that start with #). Note that an empty
|
||||
line still is considered part of the multiline regular expression.
|
||||
|
||||
For example
|
||||
|
||||
---beginning---
|
||||
#
|
||||
# This testcase always fails, pending fix ZEP-1234
|
||||
#
|
||||
.*/tests/kernel/grumpy .* FAIL
|
||||
#
|
||||
# Documentation issue, masks:
|
||||
#
|
||||
# /home/e/inaky/z/kernel.git/doc/api/io_interfaces.rst:28: WARNING: Invalid definition: Expected identifier in nested name. [error at 19]
|
||||
# struct dev_config::@65 dev_config::bits
|
||||
# -------------------^
|
||||
#
|
||||
^(?P<filename>.+/doc/api/io_interfaces.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^\s+struct dev_config::@[0-9]+ dev_config::bits.*
|
||||
^\s+-+\^
|
||||
---end---
|
||||
|
||||
Note you want to:
|
||||
|
||||
- use relateive paths; instead of
|
||||
/home/me/mydir/zephyr/something/somewhere.c you will want
|
||||
^.*/something/somewhere.c (as they will depend on where it is being
|
||||
built)
|
||||
|
||||
- Replace line numbers with [0-9]+, as they will change
|
||||
|
||||
- (?P<filename>[-._/\w]+/something/somewhere.c) saves the match on
|
||||
that file path in a "variable" called 'filename' that later you can
|
||||
match with (?P=filename) if you want to match multiple lines of the
|
||||
same error message.
|
||||
|
||||
Can get really twisted and interesting in terms of regexps; they are
|
||||
powerful, so start small :)
|
||||
68
.known-issues/doc/bluetooth.conf
Normal file
68
.known-issues/doc/bluetooth.conf
Normal file
@@ -0,0 +1,68 @@
|
||||
#
|
||||
# Bluetooth unnamed struct definition
|
||||
#
|
||||
# FIXME: all these should match the relative filename
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]bluetooth.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]$
|
||||
^[ \t]*$
|
||||
^[ \t]*\^$
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]$
|
||||
^[ \t]*$
|
||||
^[ \t]*\^$
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]$
|
||||
^.*bt_conn_info.__unnamed__.*$
|
||||
^[- \t]*\^$
|
||||
#
|
||||
# bt_gatt_discover_params unnamed struct definition
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]bluetooth.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*bt_gatt_discover_params.__unnamed__.*
|
||||
^[- \t]*\^
|
||||
#
|
||||
# Bluetooth GATT unnamed struct definition
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]bluetooth.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*bt_gatt_read_params.__unnamed__.*
|
||||
^[- \t]*\^
|
||||
#
|
||||
# Bluetooth mesh unnamed struct definition
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]bluetooth.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*bt_mesh_model.__unnamed__.*
|
||||
^[- \t]*\^
|
||||
#
|
||||
# Bluetooth mesh pub struct definition
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]bluetooth[/\\]mesh[/\\]access.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*bt_mesh_model_pub.*
|
||||
^[- \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*bt_mesh_model_pub.*
|
||||
^[- \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*bt_mesh_model_pub.*
|
||||
^[- \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*bt_mesh_model_pub.*
|
||||
^[- \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*bt_mesh_model_pub.*
|
||||
^[- \t]*\^
|
||||
15
.known-issues/doc/display.conf
Normal file
15
.known-issues/doc/display.conf
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Display
|
||||
#
|
||||
#
|
||||
# include
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]display_api.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*mb_image.__unnamed__
|
||||
^[- \t]*\^
|
||||
6
.known-issues/doc/duplicate.conf
Normal file
6
.known-issues/doc/duplicate.conf
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]file_system[/\\]index.rst):(?P<lineno>[0-9]+): WARNING: Duplicate declaration(.*)
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]peripherals[/\\]dma.rst):(?P<lineno>[0-9]+): WARNING: Duplicate declaration(.*)
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]peripherals[/\\]sensor.rst):(?P<lineno>[0-9]+): WARNING: Duplicate declaration(.*)
|
||||
15
.known-issues/doc/misc.conf
Normal file
15
.known-issues/doc/misc.conf
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Display
|
||||
#
|
||||
#
|
||||
# include
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]misc_api.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*json_obj_descr.__unnamed__
|
||||
^[- \t]*\^
|
||||
70
.known-issues/doc/networking.conf
Normal file
70
.known-issues/doc/networking.conf
Normal file
@@ -0,0 +1,70 @@
|
||||
#
|
||||
# Networking
|
||||
#
|
||||
#
|
||||
# include/net/net_ip.h warnings
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]networking.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*in[_6]+addr.in[46]_u
|
||||
^[- \t]*\^
|
||||
#
|
||||
# include/net/net_mgmt.h
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]networking.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*net_mgmt_event_callback.__unnamed__
|
||||
^[- \t]*\^
|
||||
#
|
||||
# include/net/buf.h
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]networking.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*net_buf.__unnamed__
|
||||
^[- \t]*\^
|
||||
#
|
||||
# include/net/ieee802154.h
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]networking.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*ieee802154_req_params.__unnamed__
|
||||
^[- \t]*\^
|
||||
#
|
||||
# include/net/net_context.h
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]networking[/\\]net_context.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*net_context.options
|
||||
^[- \t]*\^
|
||||
#
|
||||
# include/net/net_stats.h
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]networking[/\\]net_stats.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*net_stats_tc.[a-z]+
|
||||
^[- \t]*\^
|
||||
#
|
||||
# stray duplicate definition warnings
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]networking[/\\]net_if.rst):(?P<lineno>[0-9]+): WARNING: Duplicate declaration(.*)
|
||||
31
.known-issues/doc/uart.conf
Normal file
31
.known-issues/doc/uart.conf
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# UART unnamed struct definition
|
||||
#doc/api/peripherals/uart.rst
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]peripherals[/\\]uart.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*uart_device_config.__unnamed__.*
|
||||
^[- \t]*\^
|
||||
#
|
||||
^(?P<filename>([\-:\\/\w\.])+[/\\]doc[/\\]reference[/\\]peripherals[/\\]uart.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
|
||||
^[ \t]*
|
||||
^[ \t]*\^
|
||||
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*uart_event.data
|
||||
^[- \t]*\^
|
||||
6
.known-issues/make.conf
Normal file
6
.known-issues/make.conf
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# When filtering output of the build process, ignore lines that don't
|
||||
# provide any information that helps the invoker tell if there was an
|
||||
# error.
|
||||
#
|
||||
^make: (Entering|Leaving) directory .*
|
||||
11
.known-issues/testcases/block.conf
Normal file
11
.known-issues/testcases/block.conf
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# When executing test cases, ignore the following messages as they are
|
||||
# not to be considered hard errors.
|
||||
#
|
||||
# Block line when test case cannot run in the HW due to server or connection issues
|
||||
#
|
||||
^BLCK0/[-a-z0-9:]+ (.+)#test @[^/]+/[^:]+:[^:]+: evaluation blocked(.*)$
|
||||
#
|
||||
# Block line when there is an issue with the YKUSH serial connection
|
||||
#
|
||||
^BLCK0/[-a-z0-9:]+ (.+)#test @[^/]+/(?P<board>[^:]+):[^:]+: exception: 400: (?P=board): Cannot find YKUSH serial '[A-Z0-9]+'$
|
||||
18
.known-issues/testcases/makefile.conf
Normal file
18
.known-issues/testcases/makefile.conf
Normal file
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# When executing test cases under TCF, ignore the following messages
|
||||
# as they are not to be considered hard errors.
|
||||
#
|
||||
# TCF is run under make for taking advantage of the jobserver; when
|
||||
# the testcase execution fail, make will complain, which we can
|
||||
# ignore ('sommersault' was the old name of the target).
|
||||
#
|
||||
^/tmp/tcf-[a-zA-Z0-9]+.mk:[0-9]+: recipe for target ('tcf-jobserver-run'|'sommersault') failed$
|
||||
#
|
||||
# More of the same
|
||||
#
|
||||
^make: \*\*\* \[(tcf-jobserver-run|sommersault)\] Error 1$
|
||||
#
|
||||
# TCF's summary line. We don't need to consider it to determine if the
|
||||
# run failed or passed.
|
||||
#
|
||||
^[A-Z]+0/\S+:\s+\S+\s+@\S+: [0-9]+ tests \([0-9]+ passed, [0-9]+ failed, [0-9]+ blocked, [0-9]+ skipped\).*$
|
||||
4
.known-issues/testcases/skip.conf
Normal file
4
.known-issues/testcases/skip.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# Skip line when test case is eliminated due to filters
|
||||
#
|
||||
^SKIP0/\S+\s+\S+: No targets can be used \(all [0-9]+ selected from [0-9]+ available eliminated by testcase filtering\)$
|
||||
3
.mailmap
3
.mailmap
@@ -30,6 +30,3 @@ Yannis Damigos <giannis.damigos@gmail.com> <ydamigos@iccs.gr>
|
||||
Vinayak Kariappa Chettimada <vinayak.kariappa.chettimada@nordicsemi.no> <vinayak.kariappa.chettimada@nordicsemi.no> <vich@nordicsemi.no> <vinayak.kariappa@gmail.com>
|
||||
Sean Nyekjaer <sean@geanix.com> <sean.nyekjaer@prevas.dk>
|
||||
Sean Nyekjaer <sean@geanix.com> <sean@nyekjaer.dk>
|
||||
Marc Herbert <marc.herbert@intel.com> <46978960+marc-hb@users.noreply.github.com>
|
||||
Martin Jäger <martin@libre.solar> <17674105+martinjaeger@users.noreply.github.com>
|
||||
Armand Ciejak <armand@riedonetworks.com> <armandciejak@users.noreply.github.com>
|
||||
|
||||
75
.shippable.yml
Normal file
75
.shippable.yml
Normal file
@@ -0,0 +1,75 @@
|
||||
language: c
|
||||
|
||||
compiler: gcc
|
||||
|
||||
env:
|
||||
global:
|
||||
- ZEPHYR_SDK_INSTALL_DIR=/opt/sdk/zephyr-sdk-0.11.2
|
||||
- ZEPHYR_TOOLCHAIN_VARIANT=zephyr
|
||||
- MATRIX_BUILDS="5"
|
||||
matrix:
|
||||
- MATRIX_BUILD="1"
|
||||
- MATRIX_BUILD="2"
|
||||
- MATRIX_BUILD="3"
|
||||
- MATRIX_BUILD="4"
|
||||
- MATRIX_BUILD="5"
|
||||
|
||||
build:
|
||||
cache: false
|
||||
cache_dir_list:
|
||||
- ${SHIPPABLE_BUILD_DIR}/ccache
|
||||
pre_ci_boot:
|
||||
image_name: zephyrprojectrtos/ci
|
||||
image_tag: v0.11.4
|
||||
pull: true
|
||||
options: "-e HOME=/home/buildslave --privileged=true --tty --net=bridge --user buildslave"
|
||||
|
||||
ci:
|
||||
- export CCACHE_DIR=${SHIPPABLE_BUILD_DIR}/ccache/.ccache
|
||||
- >
|
||||
if [ "$IS_PULL_REQUEST" = "true" ]; then
|
||||
./scripts/ci/run_ci.sh -c -b ${PULL_REQUEST_BASE_BRANCH} -r origin -m ${MATRIX_BUILD} -M ${MATRIX_BUILDS} -p ${PULL_REQUEST};
|
||||
else
|
||||
./scripts/ci/run_ci.sh -c -b ${BRANCH} -r origin -m ${MATRIX_BUILD} -M ${MATRIX_BUILDS};
|
||||
fi;
|
||||
- ccache -s
|
||||
on_failure:
|
||||
- >
|
||||
if [ "$IS_PULL_REQUEST" = "true" ]; then
|
||||
./scripts/ci/run_ci.sh -f -b ${PULL_REQUEST_BASE_BRANCH} -r origin -m ${MATRIX_BUILD} -M ${MATRIX_BUILDS} -p ${PULL_REQUEST};
|
||||
else
|
||||
./scripts/ci/run_ci.sh -f -b ${BRANCH} -r origin -m ${MATRIX_BUILD} -M ${MATRIX_BUILDS};
|
||||
fi;
|
||||
on_success:
|
||||
- >
|
||||
if [ "$IS_PULL_REQUEST" = "true" ]; then
|
||||
./scripts/ci/run_ci.sh -s -b ${PULL_REQUEST_BASE_BRANCH} -r origin -m ${MATRIX_BUILD} -M ${MATRIX_BUILDS} -p ${PULL_REQUEST};
|
||||
else
|
||||
./scripts/ci/run_ci.sh -s -b ${BRANCH} -r origin -m ${MATRIX_BUILD} -M ${MATRIX_BUILDS};
|
||||
fi;
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- v*-branch
|
||||
- topic-*
|
||||
integrations:
|
||||
notifications:
|
||||
- integrationName: slack_integration
|
||||
type: slack
|
||||
recipients:
|
||||
- "#ci"
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
on_success: never
|
||||
on_failure: never
|
||||
- integrationName: email
|
||||
type: email
|
||||
recipients:
|
||||
- builds@zephyrproject.org
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
on_success: never
|
||||
on_failure: always
|
||||
on_pull_request: never
|
||||
@@ -24,13 +24,6 @@ nl_func_var_def_blk = 1
|
||||
nl_fcall_brace = remove # "list_for_each() {" vs "list_for_each()\n{"
|
||||
nl_fdef_brace = add # "int foo() {" vs "int foo()\n{"
|
||||
|
||||
#
|
||||
# End of file behavior
|
||||
#
|
||||
|
||||
nl_end_of_file = force # string (add/force/ignore/remove)
|
||||
nl_end_of_file_min = 1 # The min number of newlines at end of file
|
||||
|
||||
#
|
||||
# Source code modifications
|
||||
#
|
||||
|
||||
1568
CMakeLists.txt
1568
CMakeLists.txt
File diff suppressed because it is too large
Load Diff
843
CODEOWNERS
843
CODEOWNERS
File diff suppressed because it is too large
Load Diff
525
Kconfig.zephyr
525
Kconfig.zephyr
@@ -4,6 +4,12 @@
|
||||
# Copyright (c) 2016 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menu "Modules"
|
||||
|
||||
source "$(CMAKE_BINARY_DIR)/Kconfig.modules"
|
||||
source "modules/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
# Include Kconfig.defconfig files first so that they can override defaults and
|
||||
# other symbol/choice properties by adding extra symbol/choice definitions.
|
||||
@@ -14,34 +20,19 @@
|
||||
# precedence over SoC defaults, so include them in that order.
|
||||
#
|
||||
# $ARCH and $BOARD_DIR will be glob patterns when building documentation.
|
||||
# This loads custom shields defconfigs (from BOARD_ROOT)
|
||||
osource "$(KCONFIG_BINARY_DIR)/Kconfig.shield.defconfig"
|
||||
# This loads Zephyr base shield defconfigs
|
||||
source "boards/shields/*/Kconfig.defconfig"
|
||||
|
||||
source "$(BOARD_DIR)/Kconfig.defconfig"
|
||||
|
||||
# This loads custom SoC root defconfigs
|
||||
osource "$(KCONFIG_BINARY_DIR)/Kconfig.soc.defconfig"
|
||||
# This loads Zephyr base SoC root defconfigs
|
||||
osource "soc/$(ARCH)/*/Kconfig.defconfig"
|
||||
# This loads the toolchain defconfigs
|
||||
osource "$(TOOLCHAIN_KCONFIG_DIR)/Kconfig.defconfig"
|
||||
|
||||
menu "Modules"
|
||||
|
||||
source "modules/Kconfig"
|
||||
|
||||
endmenu
|
||||
source "$(SOC_DIR)/$(ARCH)/*/Kconfig.defconfig"
|
||||
|
||||
source "boards/Kconfig"
|
||||
source "soc/Kconfig"
|
||||
source "$(SOC_DIR)/Kconfig"
|
||||
source "arch/Kconfig"
|
||||
source "kernel/Kconfig"
|
||||
source "dts/Kconfig"
|
||||
source "drivers/Kconfig"
|
||||
source "lib/Kconfig"
|
||||
source "subsys/Kconfig"
|
||||
source "ext/Kconfig"
|
||||
|
||||
osource "$(TOOLCHAIN_KCONFIG_DIR)/Kconfig"
|
||||
|
||||
@@ -72,6 +63,15 @@ config LINKER_ORPHAN_SECTION_ERROR
|
||||
|
||||
endchoice
|
||||
|
||||
config CODE_DATA_RELOCATION
|
||||
bool "Relocate code/data sections"
|
||||
depends on ARM
|
||||
help
|
||||
When selected this will relocate .text, data and .bss sections from
|
||||
the specified files and places it in the required memory region. The
|
||||
files should be specified in the CMakeList.txt file with
|
||||
a cmake API zephyr_code_relocate().
|
||||
|
||||
config HAS_FLASH_LOAD_OFFSET
|
||||
bool
|
||||
help
|
||||
@@ -119,51 +119,23 @@ config FLASH_LOAD_SIZE
|
||||
|
||||
endif # HAS_FLASH_LOAD_OFFSET
|
||||
|
||||
config ROM_START_OFFSET
|
||||
config TEXT_SECTION_OFFSET
|
||||
hex
|
||||
prompt "ROM start offset" if !BOOTLOADER_MCUBOOT
|
||||
prompt "TEXT section offset" if !BOOTLOADER_MCUBOOT
|
||||
default 0x200 if BOOTLOADER_MCUBOOT
|
||||
default 0
|
||||
help
|
||||
If the application is built for chain-loading by a bootloader this
|
||||
variable is required to be set to value that leaves sufficient
|
||||
space between the beginning of the image and the start of the first
|
||||
space between the beginning of the image and the start of the .text
|
||||
section to store an image header or any other metadata.
|
||||
In the particular case of the MCUboot bootloader this reserves enough
|
||||
space to store the image header, which should also meet vector table
|
||||
alignment requirements on most ARM targets, although some targets
|
||||
may require smaller or larger values.
|
||||
|
||||
config LD_LINKER_SCRIPT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
choice LINKER_SCRIPT
|
||||
prompt "Linker script"
|
||||
default LD_LINKER_TEMPLATE if LD_LINKER_SCRIPT_SUPPORTED
|
||||
|
||||
config LD_LINKER_TEMPLATE
|
||||
bool "LD template"
|
||||
depends on LD_LINKER_SCRIPT_SUPPORTED
|
||||
help
|
||||
Select this option to use the LD linker script templates.
|
||||
The templates are pre-processed by the C pre-processor to create the
|
||||
final LD linker script.
|
||||
|
||||
config CMAKE_LINKER_GENERATOR
|
||||
bool "CMake generator"
|
||||
depends on ARM
|
||||
help
|
||||
Select this option to use the Zephyr CMake linker script generator.
|
||||
The linker configuration is written in CMake and the final linker
|
||||
script will be generated by the toolchain specific linker generator.
|
||||
For LD based linkers, this will be the ld generator, for ARMClang /
|
||||
armlink based linkers it will be the scatter generator.
|
||||
|
||||
endchoice
|
||||
|
||||
config HAVE_CUSTOM_LINKER_SCRIPT
|
||||
bool "Custom linker script provided"
|
||||
bool "Custom linker scripts provided"
|
||||
help
|
||||
Set this option if you have a custom linker script which needed to
|
||||
be define in CUSTOM_LINKER_SCRIPT.
|
||||
@@ -182,6 +154,27 @@ config CUSTOM_LINKER_SCRIPT
|
||||
linker script and avoid having to change the script provided by
|
||||
Zephyr.
|
||||
|
||||
config CUSTOM_RODATA_LD
|
||||
bool "(DEPRECATED) Include custom-rodata.ld"
|
||||
help
|
||||
Note: This is deprecated, use Cmake function zephyr_linker_sources() instead.
|
||||
Include a customized linker script fragment for inserting additional
|
||||
data and linker directives into the rodata section.
|
||||
|
||||
config CUSTOM_RWDATA_LD
|
||||
bool "(DEPRECATED) Include custom-rwdata.ld"
|
||||
help
|
||||
Note: This is deprecated, use Cmake function zephyr_linker_sources() instead.
|
||||
Include a customized linker script fragment for inserting additional
|
||||
data and linker directives into the data section.
|
||||
|
||||
config CUSTOM_SECTIONS_LD
|
||||
bool "(DEPRECATED) Include custom-sections.ld"
|
||||
help
|
||||
Note: This is deprecated, use Cmake function zephyr_linker_sources() instead.
|
||||
Include a customized linker script fragment for inserting additional
|
||||
arbitrary sections.
|
||||
|
||||
config KERNEL_ENTRY
|
||||
string "Kernel entry symbol"
|
||||
default "__start"
|
||||
@@ -196,83 +189,17 @@ config LINKER_SORT_BY_ALIGNMENT
|
||||
in decreasing size of symbols. This helps to minimize
|
||||
padding between symbols.
|
||||
|
||||
config SRAM_VECTOR_TABLE
|
||||
bool "Place the vector table in SRAM instead of flash"
|
||||
help
|
||||
The option specifies that the vector table should be placed at the
|
||||
start of SRAM instead of the start of flash.
|
||||
|
||||
config HAS_SRAM_OFFSET
|
||||
bool
|
||||
help
|
||||
This option is selected by targets that require SRAM_OFFSET.
|
||||
|
||||
config SRAM_OFFSET
|
||||
hex "Kernel SRAM offset" if HAS_SRAM_OFFSET
|
||||
default 0
|
||||
help
|
||||
This option specifies the byte offset from the beginning of SRAM
|
||||
where the kernel begins. Changing this value from zero will affect
|
||||
the Zephyr image's link, and will decrease the total amount of
|
||||
SRAM available for use by application code.
|
||||
|
||||
If unsure, leave at the default value 0.
|
||||
|
||||
menu "Linker Sections"
|
||||
|
||||
config LINKER_USE_BOOT_SECTION
|
||||
bool "Enable Usage of Boot Linker Section"
|
||||
help
|
||||
If enabled, the symbols which are needed for the boot process
|
||||
will be put into another linker section reserved for these
|
||||
symbols.
|
||||
|
||||
Requires that boot sections exist in the architecture, SoC,
|
||||
board or custom linker script.
|
||||
|
||||
config LINKER_USE_PINNED_SECTION
|
||||
bool "Enable Usage of Pinned Linker Section"
|
||||
help
|
||||
If enabled, the symbols which need to be pinned in memory
|
||||
will be put into another linker section reserved for pinned
|
||||
symbols. During boot, the corresponding memory will be marked
|
||||
as pinned.
|
||||
|
||||
Requires that pinned sections exist in the architecture, SoC,
|
||||
board or custom linker script.
|
||||
|
||||
config LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT
|
||||
bool "Generic sections are present at boot" if DEMAND_PAGING && LINKER_USE_PINNED_SECTION
|
||||
default y
|
||||
help
|
||||
When disabled, the linker sections other than the boot and
|
||||
pinned sections will be marked as not present in the page
|
||||
tables. This allows kernel to pull in data pages on demand
|
||||
as required by current execution context when demand paging
|
||||
is enabled. There is no need to load all code and data into
|
||||
memory at once.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
endmenu # "Linker Sections"
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Compiler Options"
|
||||
|
||||
config CODING_GUIDELINE_CHECK
|
||||
bool "Enforce coding guideline rules"
|
||||
help
|
||||
Use available compiler flags to check coding guideline rules during
|
||||
the build.
|
||||
|
||||
config NATIVE_APPLICATION
|
||||
bool "Build as a native host application"
|
||||
help
|
||||
Build as a native application that can run on the host and using
|
||||
resources and libraries provided by the host.
|
||||
|
||||
choice COMPILER_OPTIMIZATIONS
|
||||
choice
|
||||
prompt "Optimization level"
|
||||
default NO_OPTIMIZATIONS if COVERAGE
|
||||
default DEBUG_OPTIMIZATIONS if DEBUG
|
||||
@@ -308,12 +235,6 @@ config NO_OPTIMIZATIONS
|
||||
|
||||
endchoice
|
||||
|
||||
config COMPILER_COLOR_DIAGNOSTICS
|
||||
bool "Enable colored diagnostics"
|
||||
default y
|
||||
help
|
||||
Compiler diagnostic messages are colorized.
|
||||
|
||||
config COMPILER_OPT
|
||||
string "Custom compiler options"
|
||||
help
|
||||
@@ -324,14 +245,6 @@ config COMPILER_OPT
|
||||
and can be used to change compiler optimization, warning and error
|
||||
messages, and so on.
|
||||
|
||||
config MISRA_SANE
|
||||
bool "MISRA standards compliance features"
|
||||
help
|
||||
Causes the source code to build in "MISRA" mode, which
|
||||
disallows some otherwise-permitted features of the C
|
||||
standard for safety reasons. Specifically variable length
|
||||
arrays are not permitted (and gcc will enforce this).
|
||||
|
||||
endmenu
|
||||
|
||||
choice
|
||||
@@ -376,14 +289,6 @@ config OUTPUT_DISASSEMBLY
|
||||
help
|
||||
Create an .lst file with the assembly listing of the firmware.
|
||||
|
||||
config OUTPUT_DISASSEMBLE_ALL
|
||||
bool "Disassemble all sections with source. Fill zeros."
|
||||
default n
|
||||
depends on OUTPUT_DISASSEMBLY
|
||||
help
|
||||
The .lst file will contain complete disassembly of the firmware
|
||||
not just those expected to contain instructions including zeros
|
||||
|
||||
config OUTPUT_PRINT_MEMORY_USAGE
|
||||
bool "Print memory usage to stdout"
|
||||
default y
|
||||
@@ -398,145 +303,39 @@ config OUTPUT_PRINT_MEMORY_USAGE
|
||||
ram_report and
|
||||
https://sourceware.org/binutils/docs/ld/MEMORY.html
|
||||
|
||||
config CLEANUP_INTERMEDIATE_FILES
|
||||
bool "Remove all intermediate files"
|
||||
help
|
||||
Delete intermediate files to save space and cleanup clutter resulting
|
||||
from the build process.
|
||||
|
||||
config BUILD_NO_GAP_FILL
|
||||
bool "Don't fill gaps in generated hex/bin/s19 files."
|
||||
|
||||
config BUILD_OUTPUT_HEX
|
||||
bool "Build a binary in HEX format"
|
||||
help
|
||||
Build an Intel HEX binary zephyr/zephyr.hex in the build directory.
|
||||
The name of this file can be customized with CONFIG_KERNEL_BIN_NAME.
|
||||
Build a binary in HEX format. This will build a zephyr.hex file need
|
||||
by some platforms.
|
||||
|
||||
config BUILD_OUTPUT_BIN
|
||||
bool "Build a binary in BIN format"
|
||||
default y
|
||||
help
|
||||
Build a "raw" binary zephyr/zephyr.bin in the build directory.
|
||||
The name of this file can be customized with CONFIG_KERNEL_BIN_NAME.
|
||||
|
||||
config BUILD_OUTPUT_EFI
|
||||
bool "Build as an EFI application"
|
||||
default n
|
||||
depends on X86_64
|
||||
help
|
||||
Build as an EFI application.
|
||||
|
||||
This works by creating a "zephyr.efi" EFI binary containing a zephyr
|
||||
image extracted from a built zephyr.elf file. EFI applications are
|
||||
relocatable, and cannot be placed at specific locations in memory.
|
||||
Instead, the stub code will copy the embedded zephyr sections to the
|
||||
appropriate locations at startup, clear any zero-filled (BSS, etc...)
|
||||
areas, then jump into the 64 bit entry point.
|
||||
Build a binary in BIN format. This will build a zephyr.bin file need
|
||||
by some platforms.
|
||||
|
||||
config BUILD_OUTPUT_EXE
|
||||
bool "Build a binary in ELF format with .exe extension"
|
||||
help
|
||||
Build an ELF binary that can run in the host system at
|
||||
zephyr/zephyr.exe in the build directory.
|
||||
The name of this file can be customized with CONFIG_KERNEL_BIN_NAME.
|
||||
Build a binary in ELF format that can run in the host system. This
|
||||
will build a zephyr.exe file.
|
||||
|
||||
config BUILD_OUTPUT_S19
|
||||
bool "Build a binary in S19 format"
|
||||
help
|
||||
Build an S19 binary zephyr/zephyr.s19 in the build directory.
|
||||
The name of this file can be customized with CONFIG_KERNEL_BIN_NAME.
|
||||
Build a binary in S19 format. This will build a zephyr.s19 file need
|
||||
by some platforms.
|
||||
|
||||
config BUILD_OUTPUT_UF2
|
||||
bool "Build a binary in UF2 format"
|
||||
depends on BUILD_OUTPUT_BIN
|
||||
help
|
||||
Build a UF2 binary zephyr/zephyr.uf2 in the build directory.
|
||||
The name of this file can be customized with CONFIG_KERNEL_BIN_NAME.
|
||||
|
||||
if BUILD_OUTPUT_UF2
|
||||
|
||||
config BUILD_OUTPUT_UF2_FAMILY_ID
|
||||
string "UF2 device family ID"
|
||||
default "0x1c5f21b0" if SOC_ESP32
|
||||
default "0xada52840" if SOC_NRF52840_QIAA
|
||||
default "0x4fb2d5bd" if SOC_SERIES_IMX_RT
|
||||
default "0x2abc77ec" if SOC_SERIES_LPC55XXX
|
||||
default "0xe48bff56" if SOC_SERIES_RP2XXX
|
||||
default "0x68ed2b88" if SOC_SERIES_SAMD21
|
||||
default "0x55114460" if SOC_SERIES_SAMD51
|
||||
default "0x647824b6" if SOC_SERIES_STM32F0X
|
||||
default "0x5d1a0a2e" if SOC_SERIES_STM32F2X
|
||||
default "0x6b846188" if SOC_SERIES_STM32F3X
|
||||
default "0x53b80f00" if SOC_SERIES_STM32F7X
|
||||
default "0x300f5633" if SOC_SERIES_STM32G0X
|
||||
default "0x4c71240a" if SOC_SERIES_STM32G4X
|
||||
default "0x6db66082" if SOC_SERIES_STM32H7X
|
||||
default "0x202e3a91" if SOC_SERIES_STM32L0X
|
||||
default "0x1e1f432d" if SOC_SERIES_STM32L1X
|
||||
default "0x00ff6919" if SOC_SERIES_STM32L4X
|
||||
default "0x04240bdf" if SOC_SERIES_STM32L5X
|
||||
default "0x70d16653" if SOC_SERIES_STM32WBX
|
||||
default "0x5ee21072" if SOC_STM32F103XE
|
||||
default "0x57755a57" if SOC_STM32F401XC || SOC_STM32F401XE
|
||||
default "0x6d0922fa" if SOC_STM32F407XE
|
||||
default "0x8fb060fe" if SOC_STM32F407XG
|
||||
help
|
||||
UF2 bootloaders only accept UF2 files with a matching family ID.
|
||||
This can be either a hex, e.g. 0x68ed2b88, or well-known family
|
||||
name string. If the SoC in use is known by UF2, the Family ID will
|
||||
be pre-filled with the known value.
|
||||
|
||||
config BUILD_OUTPUT_UF2_USE_FLASH_BASE
|
||||
bool
|
||||
default n
|
||||
|
||||
config BUILD_OUTPUT_UF2_USE_FLASH_OFFSET
|
||||
bool
|
||||
default n
|
||||
|
||||
endif # BUILD_OUTPUT_UF2
|
||||
config BUILD_NO_GAP_FILL
|
||||
bool "Don't fill gaps in generated hex/bin/s19 files."
|
||||
|
||||
config BUILD_OUTPUT_STRIPPED
|
||||
bool "Build a stripped binary"
|
||||
help
|
||||
Build a stripped binary zephyr/zephyr.strip in the build directory.
|
||||
The name of this file can be customized with CONFIG_KERNEL_BIN_NAME.
|
||||
|
||||
config BUILD_OUTPUT_ADJUST_LMA
|
||||
string
|
||||
help
|
||||
This will adjust the LMA address in the final ELF and hex files with
|
||||
the value provided.
|
||||
This will not affect the internal address symbols inside the image but
|
||||
can be useful when adjusting the LMA address for flash tools or multi
|
||||
stage loaders where a pre-loader may copy image to a second location
|
||||
before booting a second core.
|
||||
The value will be evaluated as a math expression, this means that
|
||||
following are valid expression
|
||||
- 1024
|
||||
- 0x1000
|
||||
- -0x1000
|
||||
- 0x20000000 - 0x10000000
|
||||
Note: negative numbers are valid.
|
||||
To adjust according to a chosen flash partition one can specify a
|
||||
default as:
|
||||
DT_CHOSEN_IMAGE_<name> := <name>,<name>-partition
|
||||
DT_CHOSEN_Z_FLASH := zephyr,flash
|
||||
config BUILD_OUTPUT_ADJUST_LMA
|
||||
default "$(dt_chosen_reg_addr_hex,$(DT_CHOSEN_IMAGE_M4))-\
|
||||
$(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_FLASH))"
|
||||
|
||||
config BUILD_OUTPUT_INFO_HEADER
|
||||
bool "Create a image information header"
|
||||
help
|
||||
Create an image information header which will contain image
|
||||
information from the Zephyr binary.
|
||||
Example of information contained in the header file:
|
||||
- Number of segments in the image
|
||||
- LMA address of each segment
|
||||
- VMA address of each segment
|
||||
- Size of each segment
|
||||
Build a stripped binary. This will build a zephyr.stripped file need
|
||||
by some platforms.
|
||||
|
||||
config APPLICATION_DEFINED_SYSCALL
|
||||
bool "Scan application folder for any syscall definition"
|
||||
@@ -550,56 +349,7 @@ config MAKEFILE_EXPORTS
|
||||
Generates a file with build information that can be read by
|
||||
third party Makefile-based build systems.
|
||||
|
||||
config BUILD_OUTPUT_META
|
||||
bool "Create a build meta file"
|
||||
help
|
||||
Create a build meta file in the build directory containing lists of:
|
||||
- Zephyr: path and revision (if git repo)
|
||||
- Zephyr modules: name, path, and revision (if git repo)
|
||||
- West:
|
||||
- manifest: path and revision
|
||||
- projects: path and revision
|
||||
- Workspace:
|
||||
- dirty: one or more repositories are marked dirty
|
||||
- extra: extra Zephyr modules are manually included in the build
|
||||
- off: the SHA of one or more west projects are not what the manifest
|
||||
defined when `west update` was run the last time (`manifest-rev`).
|
||||
The off state is only present if a west workspace is found.
|
||||
File extension is .meta
|
||||
|
||||
config BUILD_OUTPUT_META_STATE_PROPAGATE
|
||||
bool "Propagate module and project state"
|
||||
depends on BUILD_OUTPUT_META
|
||||
help
|
||||
Propagate to state of each module to the Zephyr revision field.
|
||||
If west is used the state of each west project is also propagated to
|
||||
the Zephyr revision field.
|
||||
West manifest repo revision field will also
|
||||
be marked with the same state as the Zephyr revision.
|
||||
The final revision will become: <SHA>-<state1>-<state2>-<state3>...
|
||||
If no states are appended to the SHA it means the build is of a clean
|
||||
tree.
|
||||
- dirty: one or more repositories are marked dirty
|
||||
- extra: extra Zephyr modules are manually included in the build
|
||||
- off: the SHA of one or more west projects are not what the manifest
|
||||
defined when `west update` was run the last time (`manifest-rev`).
|
||||
The off state is only present if a west workspace is found.
|
||||
|
||||
endmenu
|
||||
|
||||
config EXPERIMENTAL
|
||||
bool
|
||||
help
|
||||
Symbol that must be selected by a feature if it is considered to be
|
||||
at an experimental implementation stage.
|
||||
|
||||
config WARN_EXPERIMENTAL
|
||||
bool
|
||||
prompt "Warn on experimental usage"
|
||||
help
|
||||
Print a warning when the Kconfig tree is parsed if any experimental
|
||||
features are enabled.
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -625,16 +375,9 @@ config BOOTLOADER_SRAM_SIZE
|
||||
- Zephyr is a !XIP image, which implicitly assumes existence of a
|
||||
bootloader that loads the Zephyr !XIP image onto SRAM.
|
||||
|
||||
config MCUBOOT
|
||||
bool
|
||||
help
|
||||
Hidden option used to indicate that the current image is MCUBoot
|
||||
|
||||
config BOOTLOADER_MCUBOOT
|
||||
bool "MCUboot bootloader support"
|
||||
select USE_DT_CODE_PARTITION
|
||||
imply INIT_ARCH_HW_AT_BOOT if ARCH_SUPPORTS_ARCH_HW_INIT
|
||||
depends on !MCUBOOT
|
||||
help
|
||||
This option signifies that the target uses MCUboot as a bootloader,
|
||||
or in other words that the image is to be chain-loaded by MCUboot.
|
||||
@@ -642,150 +385,50 @@ config BOOTLOADER_MCUBOOT
|
||||
order for the image generated to be bootable using the MCUboot open
|
||||
source bootloader. Currently this includes:
|
||||
|
||||
* Setting ROM_START_OFFSET to a default value that allows space
|
||||
* Setting TEXT_SECTION_OFFSET to a default value that allows space
|
||||
for the MCUboot image header
|
||||
* Activating SW_VECTOR_RELAY_CLIENT on Cortex-M0
|
||||
(or Armv8-M baseline) targets with no built-in vector relocation
|
||||
mechanisms
|
||||
|
||||
By default, this option instructs Zephyr to initialize the core
|
||||
architecture HW registers during boot, when this is supported by
|
||||
the application. This removes the need by MCUboot to reset
|
||||
the core registers' state itself.
|
||||
|
||||
if BOOTLOADER_MCUBOOT
|
||||
|
||||
config MCUBOOT_SIGNATURE_KEY_FILE
|
||||
string "Path to the mcuboot signing key file"
|
||||
default ""
|
||||
depends on !MCUBOOT_GENERATE_UNSIGNED_IMAGE
|
||||
help
|
||||
The file contains a key pair whose public half is verified
|
||||
by your target's MCUboot image. The file is in PEM format.
|
||||
|
||||
If set to a non-empty value, the build system tries to
|
||||
sign the final binaries using a 'west sign -t imgtool' command.
|
||||
The signed binaries are placed in the build directory
|
||||
at zephyr/zephyr.signed.bin and zephyr/zephyr.signed.hex.
|
||||
|
||||
The file names can be customized with CONFIG_KERNEL_BIN_NAME.
|
||||
The existence of bin and hex files depends on CONFIG_BUILD_OUTPUT_BIN
|
||||
and CONFIG_BUILD_OUTPUT_HEX.
|
||||
|
||||
This option should contain a path to the same file as the
|
||||
BOOT_SIGNATURE_KEY_FILE option in your MCUboot .config. The path
|
||||
may be absolute or relative to the west workspace topdir. (The MCUboot
|
||||
config option is used for the MCUboot bootloader image; this option is
|
||||
for your application which is to be loaded by MCUboot. The MCUboot
|
||||
config option can be a relative path from the MCUboot repository
|
||||
root.)
|
||||
|
||||
If left empty, you must sign the Zephyr binaries manually.
|
||||
|
||||
config MCUBOOT_ENCRYPTION_KEY_FILE
|
||||
string "Path to the mcuboot encryption key file"
|
||||
default ""
|
||||
depends on MCUBOOT_SIGNATURE_KEY_FILE != ""
|
||||
help
|
||||
The file contains the public key that is used to encrypt the
|
||||
ephemeral key that encrypts the image. The corresponding
|
||||
private key is hard coded in the MCUboot source code and is
|
||||
used to decrypt the ephemeral key that is embedded in the
|
||||
image. The file is in PEM format.
|
||||
|
||||
If set to a non-empty value, the build system tries to
|
||||
sign and encrypt the final binaries using a 'west sign -t imgtool'
|
||||
command. The binaries are placed in the build directory at
|
||||
zephyr/zephyr.signed.encrypted.bin and
|
||||
zephyr/zephyr.signed.encrypted.hex.
|
||||
|
||||
The file names can be customized with CONFIG_KERNEL_BIN_NAME.
|
||||
The existence of bin and hex files depends on CONFIG_BUILD_OUTPUT_BIN
|
||||
and CONFIG_BUILD_OUTPUT_HEX.
|
||||
|
||||
This option should either be an absolute path or a path relative to
|
||||
the west workspace topdir.
|
||||
Example: './bootloader/mcuboot/enc-rsa2048-pub.pem'
|
||||
|
||||
If left empty, you must encrypt the Zephyr binaries manually.
|
||||
|
||||
config MCUBOOT_EXTRA_IMGTOOL_ARGS
|
||||
string "Extra arguments to pass to imgtool"
|
||||
default ""
|
||||
help
|
||||
If CONFIG_MCUBOOT_SIGNATURE_KEY_FILE is a non-empty string,
|
||||
you can use this option to pass extra options to imgtool.
|
||||
For example, you could set this to "--version 1.2".
|
||||
|
||||
config MCUBOOT_GENERATE_UNSIGNED_IMAGE
|
||||
bool "Generate unsigned binary image bootable with MCUboot"
|
||||
help
|
||||
Enabling this configuration allows automatic unsigned binary image
|
||||
generation when MCUboot signing key is not provided,
|
||||
i.e., MCUBOOT_SIGNATURE_KEY_FILE is left empty.
|
||||
|
||||
config MCUBOOT_GENERATE_CONFIRMED_IMAGE
|
||||
bool "Also generate a padded, confirmed image"
|
||||
help
|
||||
The signed, padded, and confirmed binaries are placed in the build
|
||||
directory at zephyr/zephyr.signed.confirmed.bin and
|
||||
zephyr/zephyr.signed.confirmed.hex.
|
||||
|
||||
The file names can be customized with CONFIG_KERNEL_BIN_NAME.
|
||||
The existence of bin and hex files depends on CONFIG_BUILD_OUTPUT_BIN
|
||||
and CONFIG_BUILD_OUTPUT_HEX.
|
||||
|
||||
endif # BOOTLOADER_MCUBOOT
|
||||
* Activating SW_VECTOR_RELAY on Cortex-M0 (or Armv8-M baseline)
|
||||
targets with no built-in vector relocation mechanisms
|
||||
|
||||
config BOOTLOADER_ESP_IDF
|
||||
bool "ESP-IDF bootloader support"
|
||||
depends on (SOC_ESP32 || SOC_ESP32S2 || SOC_ESP32C3) && !BOOTLOADER_MCUBOOT
|
||||
default y
|
||||
depends on SOC_ESP32
|
||||
help
|
||||
This option will trigger the compilation of the ESP-IDF bootloader
|
||||
inside the build folder.
|
||||
At flash time, the bootloader will be flashed with the zephyr image
|
||||
|
||||
config BOOTLOADER_BOSSA
|
||||
bool "BOSSA bootloader support"
|
||||
select USE_DT_CODE_PARTITION
|
||||
|
||||
config BOOTLOADER_KEXEC
|
||||
bool "Boot using Linux kexec() system call"
|
||||
depends on X86
|
||||
help
|
||||
Signifies that the target uses a BOSSA compatible bootloader. If CDC
|
||||
ACM USB support is also enabled then the board will reboot into the
|
||||
bootloader automatically when bossac is run.
|
||||
This option signifies that Linux boots the kernel using kexec system call
|
||||
and utility. This method is used to boot the kernel over the network.
|
||||
|
||||
config BOOTLOADER_BOSSA_DEVICE_NAME
|
||||
string "BOSSA CDC ACM device name"
|
||||
depends on BOOTLOADER_BOSSA && CDC_ACM_DTE_RATE_CALLBACK_SUPPORT
|
||||
default "CDC_ACM_0"
|
||||
config BOOTLOADER_CONTEXT_RESTORE
|
||||
bool "Boot loader has context restore support"
|
||||
default y
|
||||
depends on SYS_POWER_DEEP_SLEEP_STATES && BOOTLOADER_CONTEXT_RESTORE_SUPPORTED
|
||||
help
|
||||
Sets the CDC ACM port to watch for reboot commands.
|
||||
This option signifies that the target has a bootloader
|
||||
that restores CPU context upon resuming from deep sleep
|
||||
power state.
|
||||
|
||||
choice
|
||||
prompt "BOSSA bootloader variant"
|
||||
depends on BOOTLOADER_BOSSA
|
||||
|
||||
config BOOTLOADER_BOSSA_LEGACY
|
||||
bool "Legacy"
|
||||
config REBOOT
|
||||
bool "Reboot functionality"
|
||||
select SYSTEM_CLOCK_DISABLE
|
||||
help
|
||||
Select the Legacy variant of the BOSSA bootloader. This is defined
|
||||
for compatibility mode only. The recommendation is use newer
|
||||
versions like Arduino or Adafruit UF2.
|
||||
Enable the sys_reboot() API. Enabling this can drag in other subsystems
|
||||
needed to perform a "safe" reboot (e.g. SYSTEM_CLOCK_DISABLE, to stop the
|
||||
system clock before issuing a reset).
|
||||
|
||||
config BOOTLOADER_BOSSA_ARDUINO
|
||||
bool "Arduino"
|
||||
config MISRA_SANE
|
||||
bool "MISRA standards compliance features"
|
||||
help
|
||||
Select the Arduino variant of the BOSSA bootloader. Uses 0x07738135
|
||||
as the magic value to enter the bootloader.
|
||||
|
||||
config BOOTLOADER_BOSSA_ADAFRUIT_UF2
|
||||
bool "Adafruit UF2"
|
||||
help
|
||||
Select the Adafruit UF2 variant of the BOSSA bootloader. Uses
|
||||
0xf01669ef as the magic value to enter the bootloader.
|
||||
|
||||
endchoice
|
||||
Causes the source code to build in "MISRA" mode, which
|
||||
disallows some otherwise-permitted features of the C
|
||||
standard for safety reasons. Specifically variable length
|
||||
arrays are not permitted (and gcc will enforce this).
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
1824
MAINTAINERS.yml
1824
MAINTAINERS.yml
File diff suppressed because it is too large
Load Diff
25
Makefile
Normal file
25
Makefile
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Top level makefile for documentation build
|
||||
#
|
||||
|
||||
ifndef ZEPHYR_BASE
|
||||
$(error The ZEPHYR_BASE environment variable must be set)
|
||||
endif
|
||||
|
||||
BUILDDIR ?= doc/_build
|
||||
DOC_TAG ?= development
|
||||
SPHINXOPTS ?= -q
|
||||
|
||||
# Documentation targets
|
||||
# ---------------------------------------------------------------------------
|
||||
clean:
|
||||
rm -rf ${BUILDDIR}
|
||||
|
||||
htmldocs:
|
||||
mkdir -p ${BUILDDIR} && cmake -GNinja -DDOC_TAG=${DOC_TAG} -DSPHINXOPTS=${SPHINXOPTS} -B${BUILDDIR} -Hdoc/ && ninja -C ${BUILDDIR} htmldocs
|
||||
|
||||
htmldocs-fast:
|
||||
mkdir -p ${BUILDDIR} && cmake -GNinja -DKCONFIG_TURBO_MODE=1 -DDOC_TAG=${DOC_TAG} -DSPHINXOPTS=${SPHINXOPTS} -B${BUILDDIR} -Hdoc/ && ninja -C ${BUILDDIR} htmldocs
|
||||
|
||||
pdfdocs:
|
||||
mkdir -p ${BUILDDIR} && cmake -GNinja -DDOC_TAG=${DOC_TAG} -DSPHINXOPTS=${SPHINXOPTS} -B${BUILDDIR} -Hdoc/ && ninja -C ${BUILDDIR} pdfdocs
|
||||
24
README.rst
24
README.rst
@@ -2,16 +2,14 @@
|
||||
|
||||
<a href="https://www.zephyrproject.org">
|
||||
<p align="center">
|
||||
<img src="doc/_static/images/logo-readme.svg">
|
||||
<img src="doc/images/Zephyr-Project.png">
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<a href="https://bestpractices.coreinfrastructure.org/projects/74"><img
|
||||
src="https://bestpractices.coreinfrastructure.org/projects/74/badge"></a>
|
||||
<a
|
||||
href="https://github.com/zephyrproject-rtos/zephyr/actions/workflows/twister.yaml?query=branch%3Amain">
|
||||
<img
|
||||
src="https://github.com/zephyrproject-rtos/zephyr/actions/workflows/twister.yaml/badge.svg?event=push"></a>
|
||||
src="https://api.shippable.com/projects/58ffb2b8baa5e307002e1d79/badge?branch=master">
|
||||
|
||||
|
||||
The Zephyr Project is a scalable real-time operating system (RTOS) supporting
|
||||
@@ -28,6 +26,7 @@ Intel x86, ARC, Nios II, Tensilica Xtensa, and RISC-V, and a large number of
|
||||
|
||||
.. below included in doc/introduction/introduction.rst
|
||||
|
||||
.. start_include_here
|
||||
|
||||
Getting Started
|
||||
***************
|
||||
@@ -35,12 +34,10 @@ Getting Started
|
||||
Welcome to Zephyr! See the `Introduction to Zephyr`_ for a high-level overview,
|
||||
and the documentation's `Getting Started Guide`_ to start developing.
|
||||
|
||||
.. start_include_here
|
||||
|
||||
Community Support
|
||||
*****************
|
||||
|
||||
Community support is provided via mailing lists and Discord; see the Resources
|
||||
Community support is provided via mailing lists and Slack; see the Resources
|
||||
below for details.
|
||||
|
||||
.. _project-resources:
|
||||
@@ -55,7 +52,7 @@ Here's a quick summary of resources to help you find your way around:
|
||||
* **Source Code**: https://github.com/zephyrproject-rtos/zephyr is the main
|
||||
repository; https://elixir.bootlin.com/zephyr/latest/source contains a
|
||||
searchable index
|
||||
* **Releases**: https://github.com/zephyrproject-rtos/zephyr/releases
|
||||
* **Releases**: https://zephyrproject.org/developers/#downloads
|
||||
* **Samples and example code**: see `Sample and Demo Code Examples`_
|
||||
* **Mailing Lists**: users@lists.zephyrproject.org and
|
||||
devel@lists.zephyrproject.org are the main user and developer mailing lists,
|
||||
@@ -63,9 +60,10 @@ Here's a quick summary of resources to help you find your way around:
|
||||
`Zephyr Development mailing list`_. The other `Zephyr mailing list
|
||||
subgroups`_ have their own archives and sign-up pages.
|
||||
* **Nightly CI Build Status**: https://lists.zephyrproject.org/g/builds
|
||||
The builds@lists.zephyrproject.org mailing list archives the CI nightly build results.
|
||||
* **Chat**: Real-time chat happens in Zephyr's Discord Server. Use
|
||||
this `Discord Invite`_ to register.
|
||||
The builds@lists.zephyrproject.org mailing list archives the CI
|
||||
(shippable) nightly build results.
|
||||
* **Chat**: Zephyr's Slack workspace is https://zephyrproject.slack.com. Use
|
||||
this `Slack Invite`_ to register.
|
||||
* **Contributing**: see the `Contribution Guide`_
|
||||
* **Wiki**: `Zephyr GitHub wiki`_
|
||||
* **Issues**: https://github.com/zephyrproject-rtos/zephyr/issues
|
||||
@@ -74,7 +72,7 @@ Here's a quick summary of resources to help you find your way around:
|
||||
tracked separately at https://zephyrprojectsec.atlassian.net.
|
||||
* **Zephyr Project Website**: https://zephyrproject.org
|
||||
|
||||
.. _Discord Invite: https://chat.zephyrproject.org
|
||||
.. _Slack Invite: https://tinyurl.com/y5glwylp
|
||||
.. _supported boards: http://docs.zephyrproject.org/latest/boards/index.html
|
||||
.. _Zephyr Documentation: http://docs.zephyrproject.org
|
||||
.. _Introduction to Zephyr: http://docs.zephyrproject.org/latest/introduction/index.html
|
||||
@@ -85,4 +83,4 @@ Here's a quick summary of resources to help you find your way around:
|
||||
.. _Zephyr mailing list subgroups: https://lists.zephyrproject.org/g/main/subgroups
|
||||
.. _Sample and Demo Code Examples: http://docs.zephyrproject.org/latest/samples/index.html
|
||||
.. _Security: http://docs.zephyrproject.org/latest/security/index.html
|
||||
.. _Asking for Help Tips: https://docs.zephyrproject.org/latest/getting_started/index.html#asking-for-help
|
||||
.. _Asking for Help Tips: https://docs.zephyrproject.org/latest/guides/getting-help.html
|
||||
|
||||
6
VERSION
6
VERSION
@@ -1,5 +1,5 @@
|
||||
VERSION_MAJOR = 3
|
||||
VERSION_MINOR = 0
|
||||
PATCHLEVEL = 0
|
||||
VERSION_MAJOR = 2
|
||||
VERSION_MINOR = 2
|
||||
PATCHLEVEL = 1
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION =
|
||||
|
||||
@@ -4,7 +4,7 @@ add_definitions(-D__ZEPHYR_SUPERVISOR__)
|
||||
|
||||
include_directories(
|
||||
${ZEPHYR_BASE}/kernel/include
|
||||
${ARCH_DIR}/${ARCH}/include
|
||||
${ZEPHYR_BASE}/arch/${ARCH}/include
|
||||
)
|
||||
|
||||
add_subdirectory(common)
|
||||
|
||||
436
arch/Kconfig
436
arch/Kconfig
@@ -20,73 +20,21 @@ config ARC
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
select HAS_DTS
|
||||
imply XIP
|
||||
select ARCH_HAS_THREAD_LOCAL_STORAGE
|
||||
help
|
||||
ARC architecture
|
||||
|
||||
config ARM
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
select ARCH_SUPPORTS_COREDUMP if CPU_CORTEX_M
|
||||
select HAS_DTS
|
||||
# FIXME: current state of the code for all ARM requires this, but
|
||||
# is really only necessary for Cortex-M with ARM MPU!
|
||||
select GEN_PRIV_STACKS
|
||||
select ARCH_HAS_THREAD_LOCAL_STORAGE if CPU_CORTEX_R || CPU_CORTEX_M
|
||||
help
|
||||
ARM architecture
|
||||
|
||||
config ARM64
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
select 64BIT
|
||||
select HAS_DTS
|
||||
select HAS_ARM_SMCCC
|
||||
select ARCH_HAS_THREAD_LOCAL_STORAGE
|
||||
select USE_SWITCH
|
||||
select USE_SWITCH_SUPPORTED
|
||||
help
|
||||
ARM64 (AArch64) architecture
|
||||
|
||||
config MIPS
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
select ATOMIC_OPERATIONS_C
|
||||
select HAS_DTS
|
||||
help
|
||||
MIPS architecture
|
||||
|
||||
config SPARC
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
select HAS_DTS
|
||||
select USE_SWITCH
|
||||
select USE_SWITCH_SUPPORTED
|
||||
select BIG_ENDIAN
|
||||
select ATOMIC_OPERATIONS_BUILTIN if SPARC_CASA
|
||||
select ATOMIC_OPERATIONS_C if !SPARC_CASA
|
||||
select ARCH_HAS_THREAD_LOCAL_STORAGE
|
||||
select ARCH_HAS_EXTRA_EXCEPTION_INFO
|
||||
help
|
||||
SPARC architecture
|
||||
|
||||
config X86
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
select ATOMIC_OPERATIONS_BUILTIN
|
||||
select HAS_DTS
|
||||
select ARCH_SUPPORTS_COREDUMP
|
||||
select CPU_HAS_MMU
|
||||
select ARCH_MEM_DOMAIN_DATA if USERSPACE && !X86_COMMON_PAGE_TABLE
|
||||
select ARCH_MEM_DOMAIN_SYNCHRONOUS_API if USERSPACE
|
||||
select ARCH_HAS_GDBSTUB if !X86_64
|
||||
select ARCH_HAS_TIMING_FUNCTIONS
|
||||
select ARCH_HAS_THREAD_LOCAL_STORAGE
|
||||
select ARCH_HAS_DEMAND_PAGING
|
||||
select NEED_LIBC_MEM_PARTITION if USERSPACE && TIMING_FUNCTIONS \
|
||||
&& !BOARD_HAS_TIMING_FUNCTIONS \
|
||||
&& !SOC_HAS_TIMING_FUNCTIONS
|
||||
help
|
||||
x86 architecture
|
||||
|
||||
@@ -95,8 +43,6 @@ config NIOS2
|
||||
select ARCH_IS_SET
|
||||
select ATOMIC_OPERATIONS_C
|
||||
select HAS_DTS
|
||||
imply XIP
|
||||
select ARCH_HAS_TIMING_FUNCTIONS
|
||||
help
|
||||
Nios II Gen 2 architecture
|
||||
|
||||
@@ -104,9 +50,6 @@ config RISCV
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
select HAS_DTS
|
||||
select ARCH_SUPPORTS_COREDUMP
|
||||
select ARCH_HAS_THREAD_LOCAL_STORAGE
|
||||
imply XIP
|
||||
help
|
||||
RISCV architecture
|
||||
|
||||
@@ -116,14 +59,13 @@ config XTENSA
|
||||
select HAS_DTS
|
||||
select USE_SWITCH
|
||||
select USE_SWITCH_SUPPORTED
|
||||
imply ATOMIC_OPERATIONS_ARCH
|
||||
select XTENSA_HAL if "$(ZEPHYR_TOOLCHAIN_VARIANT)" != "xcc"
|
||||
help
|
||||
Xtensa architecture
|
||||
|
||||
config ARCH_POSIX
|
||||
bool
|
||||
select ARCH_IS_SET
|
||||
select HAS_DTS
|
||||
select ATOMIC_OPERATIONS_BUILTIN
|
||||
select ARCH_HAS_CUSTOM_SWAP_TO_MAIN
|
||||
select ARCH_HAS_CUSTOM_BUSY_WAIT
|
||||
@@ -187,14 +129,14 @@ config SRAM_BASE_ADDRESS
|
||||
/chosen/zephyr,sram in devicetree. The user should generally avoid
|
||||
changing it via menuconfig or in configuration files.
|
||||
|
||||
if ARC || ARM || ARM64 || NIOS2 || X86
|
||||
if ARC || ARM || NIOS2 || X86
|
||||
|
||||
# Workaround for not being able to have commas in macro arguments
|
||||
DT_CHOSEN_Z_FLASH := zephyr,flash
|
||||
|
||||
config FLASH_SIZE
|
||||
int "Flash Size in kB"
|
||||
default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_FLASH),0,K) if (XIP && (ARM ||ARM64)) || !ARM
|
||||
default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_FLASH),0,K) if (XIP && ARM) || !ARM
|
||||
help
|
||||
This option specifies the size of the flash in kB. It is normally set by
|
||||
the board's defconfig file and the user should generally avoid modifying
|
||||
@@ -202,13 +144,13 @@ config FLASH_SIZE
|
||||
|
||||
config FLASH_BASE_ADDRESS
|
||||
hex "Flash Base Address"
|
||||
default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_FLASH)) if (XIP && (ARM || ARM64)) || !ARM
|
||||
default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_FLASH)) if (XIP && ARM) || !ARM
|
||||
help
|
||||
This option specifies the base address of the flash on the board. It is
|
||||
normally set by the board's defconfig file and the user should generally
|
||||
avoid modifying it via the menu configuration.
|
||||
|
||||
endif # ARM || ARM64 || ARC || NIOS2 || X86
|
||||
endif # ARM || ARC || NIOS2 || X86
|
||||
|
||||
if ARCH_HAS_TRUSTED_EXECUTION
|
||||
|
||||
@@ -256,13 +198,11 @@ config USERSPACE
|
||||
bool "User mode threads"
|
||||
depends on ARCH_HAS_USERSPACE
|
||||
depends on RUNTIME_ERROR_CHECKS
|
||||
depends on SRAM_REGION_PERMISSIONS
|
||||
select THREAD_STACK_INFO
|
||||
help
|
||||
When enabled, threads may be created or dropped down to user mode,
|
||||
which has significantly restricted permissions and must interact
|
||||
with the kernel via system calls. See Zephyr documentation for more
|
||||
details about this feature.
|
||||
details about this feature.
|
||||
|
||||
If a user thread overflows its stack, this will be caught and the
|
||||
kernel itself will be shielded from harm. Enabling this option
|
||||
@@ -278,52 +218,25 @@ config PRIVILEGED_STACK_SIZE
|
||||
This option sets the privileged stack region size that will be used
|
||||
in addition to the user mode thread stack. During normal execution,
|
||||
this region will be inaccessible from user mode. During system calls,
|
||||
this region will be utilized by the system call. This value must be
|
||||
a multiple of the minimum stack alignment.
|
||||
this region will be utilized by the system call.
|
||||
|
||||
config PRIVILEGED_STACK_TEXT_AREA
|
||||
int "Privileged stacks text area"
|
||||
default 512 if COVERAGE_GCOV
|
||||
default 256
|
||||
depends on ARCH_HAS_USERSPACE
|
||||
help
|
||||
Stack text area size for privileged stacks.
|
||||
|
||||
config KOBJECT_TEXT_AREA
|
||||
int "Size of kobject text area"
|
||||
int "Size if kobject text area"
|
||||
default 512 if COVERAGE_GCOV
|
||||
default 512 if NO_OPTIMIZATIONS
|
||||
default 512 if STACK_CANARIES && RISCV
|
||||
default 256
|
||||
depends on ARCH_HAS_USERSPACE
|
||||
help
|
||||
Size of kernel object text area. Used in linker script.
|
||||
|
||||
config KOBJECT_DATA_AREA_RESERVE_EXTRA_PERCENT
|
||||
int "Reserve extra kobject data area (in percentage)"
|
||||
default 100
|
||||
depends on ARCH_HAS_USERSPACE
|
||||
help
|
||||
Multiplication factor used to calculate the size of placeholder to
|
||||
reserve space for kobject metadata hash table. The hash table is
|
||||
generated via gperf is highly dependent on the absolute addresses of
|
||||
kobjects which might change between prebuilts. To reserve enough
|
||||
space for the hash table during final linking passes to keep
|
||||
kobjects in same place, the size of reserved space is calculated
|
||||
from the first prebuilt plus additional space calculated with
|
||||
this percentage (of the kobject data area in first prebuilt).
|
||||
|
||||
config KOBJECT_RODATA_AREA_EXTRA_BYTES
|
||||
int "Reserve extra bytes for kobject rodata area"
|
||||
default 16
|
||||
depends on ARCH_HAS_USERSPACE
|
||||
help
|
||||
Reserve a few more bytes for the RODATA region for kobject metadata.
|
||||
This is to account for the uncertainty of tables generated by gperf.
|
||||
|
||||
config GEN_PRIV_STACKS
|
||||
bool
|
||||
help
|
||||
Selected if the architecture requires that privilege elevation stacks
|
||||
be allocated in a separate memory area. This is typical of arches
|
||||
whose MPUs require regions to be power-of-two aligned/sized.
|
||||
|
||||
FIXME: This should be removed and replaced with checks against
|
||||
CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT, but both ARM and ARC
|
||||
changes will be necessary for this.
|
||||
|
||||
config STACK_GROWS_UP
|
||||
bool "Stack grows towards higher memory addresses"
|
||||
help
|
||||
@@ -438,47 +351,14 @@ config IRQ_OFFLOAD
|
||||
run in interrupt context. Only useful for test cases that need
|
||||
to validate the correctness of kernel objects in IRQ context.
|
||||
|
||||
|
||||
config EXTRA_EXCEPTION_INFO
|
||||
bool "Collect extra exception info"
|
||||
depends on ARCH_HAS_EXTRA_EXCEPTION_INFO
|
||||
help
|
||||
This option enables the collection of extra information, such as
|
||||
register state, when a fault occurs. This information can be useful
|
||||
to collect for post-mortem analysis and debug of issues.
|
||||
|
||||
endmenu # Interrupt configuration
|
||||
|
||||
config INIT_ARCH_HW_AT_BOOT
|
||||
bool "Initialize internal architecture state at boot"
|
||||
depends on ARCH_SUPPORTS_ARCH_HW_INIT
|
||||
help
|
||||
This option instructs Zephyr to force the initialization
|
||||
of the internal architectural state (for example ARCH-level
|
||||
HW registers and system control blocks) during boot to
|
||||
the reset values as specified by the corresponding
|
||||
architecture manual. The option is useful when the Zephyr
|
||||
firmware image is chain-loaded, for example, by a debugger
|
||||
or a bootloader, and we need to guarantee that the internal
|
||||
states of the architecture core blocks are restored to the
|
||||
reset values (as specified by the architecture).
|
||||
|
||||
Note: the functionality is architecture-specific. For the
|
||||
implementation details refer to each architecture where
|
||||
this feature is supported.
|
||||
|
||||
endmenu
|
||||
|
||||
#
|
||||
# Architecture Capabilities
|
||||
#
|
||||
|
||||
config ARCH_HAS_SINGLE_THREAD_SUPPORT
|
||||
bool
|
||||
|
||||
config ARCH_HAS_TIMING_FUNCTIONS
|
||||
bool
|
||||
|
||||
config ARCH_HAS_TRUSTED_EXECUTION
|
||||
bool
|
||||
|
||||
@@ -500,28 +380,6 @@ config ARCH_HAS_RAMFUNC_SUPPORT
|
||||
config ARCH_HAS_NESTED_EXCEPTION_DETECTION
|
||||
bool
|
||||
|
||||
config ARCH_SUPPORTS_COREDUMP
|
||||
bool
|
||||
|
||||
config ARCH_SUPPORTS_ARCH_HW_INIT
|
||||
bool
|
||||
|
||||
config ARCH_HAS_EXTRA_EXCEPTION_INFO
|
||||
bool
|
||||
|
||||
config ARCH_HAS_GDBSTUB
|
||||
bool
|
||||
|
||||
config ARCH_HAS_COHERENCE
|
||||
bool
|
||||
help
|
||||
When selected, the architecture supports the
|
||||
arch_mem_coherent() API and can link into incoherent/cached
|
||||
memory using the ".cached" linker section.
|
||||
|
||||
config ARCH_HAS_THREAD_LOCAL_STORAGE
|
||||
bool
|
||||
|
||||
#
|
||||
# Other architecture related options
|
||||
#
|
||||
@@ -529,6 +387,53 @@ config ARCH_HAS_THREAD_LOCAL_STORAGE
|
||||
config ARCH_HAS_THREAD_ABORT
|
||||
bool
|
||||
|
||||
#
|
||||
# Hidden PM feature configs which are to be selected by
|
||||
# individual SoC.
|
||||
#
|
||||
|
||||
config HAS_SYS_POWER_STATE_SLEEP_1
|
||||
bool
|
||||
help
|
||||
This option signifies that the target supports the SYS_POWER_STATE_SLEEP_1
|
||||
configuration option.
|
||||
|
||||
config HAS_SYS_POWER_STATE_SLEEP_2
|
||||
bool
|
||||
help
|
||||
This option signifies that the target supports the SYS_POWER_STATE_SLEEP_2
|
||||
configuration option.
|
||||
|
||||
config HAS_SYS_POWER_STATE_SLEEP_3
|
||||
bool
|
||||
help
|
||||
This option signifies that the target supports the SYS_POWER_STATE_SLEEP_3
|
||||
configuration option.
|
||||
|
||||
config HAS_SYS_POWER_STATE_DEEP_SLEEP_1
|
||||
bool
|
||||
help
|
||||
This option signifies that the target supports the SYS_POWER_STATE_DEEP_SLEEP_1
|
||||
configuration option.
|
||||
|
||||
config HAS_SYS_POWER_STATE_DEEP_SLEEP_2
|
||||
bool
|
||||
help
|
||||
This option signifies that the target supports the SYS_POWER_STATE_DEEP_SLEEP_2
|
||||
configuration option.
|
||||
|
||||
config HAS_SYS_POWER_STATE_DEEP_SLEEP_3
|
||||
bool
|
||||
help
|
||||
This option signifies that the target supports the SYS_POWER_STATE_DEEP_SLEEP_3
|
||||
configuration option.
|
||||
|
||||
config BOOTLOADER_CONTEXT_RESTORE_SUPPORTED
|
||||
bool
|
||||
help
|
||||
This option signifies that the target has options of bootloaders
|
||||
that support context restore upon resume from deep sleep
|
||||
|
||||
#
|
||||
# Hidden CPU family configs
|
||||
#
|
||||
@@ -552,66 +457,18 @@ config CPU_HAS_FPU
|
||||
This option is enabled when the CPU has hardware floating point
|
||||
unit.
|
||||
|
||||
config CPU_HAS_FPU_DOUBLE_PRECISION
|
||||
bool
|
||||
select CPU_HAS_FPU
|
||||
help
|
||||
When enabled, this indicates that the CPU has a double floating point
|
||||
precision unit.
|
||||
|
||||
config CPU_HAS_MPU
|
||||
bool
|
||||
help
|
||||
This option is enabled when the CPU has a Memory Protection Unit (MPU).
|
||||
|
||||
config CPU_HAS_MMU
|
||||
config MEMORY_PROTECTION
|
||||
bool
|
||||
help
|
||||
This hidden option is selected when the CPU has a Memory Management Unit
|
||||
(MMU).
|
||||
This option is enabled when Memory Protection features are supported.
|
||||
Memory protection support is currently available on ARC, ARM, and x86
|
||||
architectures.
|
||||
|
||||
config ARCH_HAS_DEMAND_PAGING
|
||||
bool
|
||||
help
|
||||
This hidden configuration should be selected by the architecture if
|
||||
demand paging is supported.
|
||||
|
||||
config ARCH_HAS_RESERVED_PAGE_FRAMES
|
||||
bool
|
||||
help
|
||||
This hidden configuration should be selected by the architecture if
|
||||
certain RAM page frames need to be marked as reserved and never used for
|
||||
memory mappings. The architecture will need to implement
|
||||
arch_reserved_pages_update().
|
||||
|
||||
config ARCH_MAPS_ALL_RAM
|
||||
bool
|
||||
help
|
||||
This hidden option is selected by the architecture to inform the kernel
|
||||
that all RAM is mapped at boot, and not just the bounds of the Zephyr image.
|
||||
If RAM starts at 0x0, the first page must remain un-mapped to catch NULL
|
||||
pointer dereferences. With this enabled, the kernel will not assume that
|
||||
virtual memory addresses past the kernel image are available for mappings,
|
||||
but instead takes into account an entire RAM mapping instead.
|
||||
|
||||
This is typically set by architectures which need direct access to all memory.
|
||||
It is the architecture's responsibility to mark reserved memory regions
|
||||
as such in arch_reserved_pages_update().
|
||||
|
||||
Although the kernel will not disturb this RAM mapping by re-mapping the associated
|
||||
virtual addresses elsewhere, this is limited to only management of the
|
||||
virtual address space. The kernel's page frame ontology will not consider
|
||||
this mapping at all; non-kernel pages will be considered free (unless marked
|
||||
as reserved) and Z_PAGE_FRAME_MAPPED will not be set.
|
||||
|
||||
menuconfig MPU
|
||||
bool "Enable MPU features"
|
||||
depends on CPU_HAS_MPU
|
||||
help
|
||||
This option, when enabled, indicates to the core kernel that an MPU
|
||||
is enabled.
|
||||
|
||||
if MPU
|
||||
config MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT
|
||||
bool
|
||||
help
|
||||
@@ -649,152 +506,23 @@ config MPU_GAP_FILLING
|
||||
documentation for more information on how this option is
|
||||
used.
|
||||
|
||||
endif # MPU
|
||||
|
||||
config SRAM_REGION_PERMISSIONS
|
||||
bool "Assign appropriate permissions to kernel areas in SRAM"
|
||||
depends on MMU || MPU
|
||||
default y
|
||||
help
|
||||
This option indicates that memory protection hardware
|
||||
is present, enabled, and regions have been configured at boot for memory
|
||||
ranges within the kernel image.
|
||||
|
||||
If this option is turned on, certain areas of the kernel image will
|
||||
have the following access policies applied for all threads, including
|
||||
supervisor threads:
|
||||
|
||||
1) All program text will be have read-only, execute memory permission
|
||||
2) All read-only data will have read-only permission, and execution
|
||||
disabled if the hardware supports it.
|
||||
3) All other RAM addresses will have read-write permission, and
|
||||
execution disabled if the hardware supports it.
|
||||
|
||||
Options such as USERSPACE or HW_STACK_PROTECTION may additionally
|
||||
impose additional policies on the memory map, which may be global
|
||||
or local to the current running thread.
|
||||
|
||||
This option may consume additional memory to satisfy memory protection
|
||||
hardware alignment constraints.
|
||||
|
||||
If this option is disabled, the entire kernel will have default memory
|
||||
access permissions set, typically read/write/execute. It may be desirable
|
||||
to turn this off on MMU systems which are using the MMU for demand
|
||||
paging, do not need memory protection, and would rather not use up
|
||||
RAM for the alignment between regions.
|
||||
|
||||
menu "Floating Point Options"
|
||||
|
||||
config FPU
|
||||
bool "Enable floating point unit (FPU)"
|
||||
menuconfig FLOAT
|
||||
bool "Floating point"
|
||||
depends on CPU_HAS_FPU
|
||||
depends on ARM || X86 || ARC
|
||||
help
|
||||
This option enables the hardware Floating Point Unit (FPU), in order to
|
||||
support using the floating point registers and instructions.
|
||||
This option allows threads to use the floating point registers.
|
||||
By default, only a single thread may use the registers.
|
||||
|
||||
When this option is enabled, by default, threads may use the floating
|
||||
point registers only in an exclusive manner, and this usually means that
|
||||
only one thread may perform floating point operations.
|
||||
Disabling this option means that any thread that uses a
|
||||
floating point register will get a fatal exception.
|
||||
|
||||
If it is necessary for multiple threads to perform concurrent floating
|
||||
point operations, the "FPU register sharing" option must be enabled to
|
||||
preserve the floating point registers across context switches.
|
||||
|
||||
Note that this option cannot be selected for the platforms that do not
|
||||
include a hardware floating point unit; the floating point support for
|
||||
those platforms is dependent on the availability of the toolchain-
|
||||
provided software floating point library.
|
||||
|
||||
config FPU_SHARING
|
||||
bool "FPU register sharing"
|
||||
depends on FPU && MULTITHREADING
|
||||
config FP_SHARING
|
||||
bool "Floating point register sharing"
|
||||
depends on FLOAT
|
||||
help
|
||||
This option enables preservation of the hardware floating point registers
|
||||
across context switches to allow multiple threads to perform concurrent
|
||||
floating point operations.
|
||||
|
||||
Note that some compiler configurations may activate a floating point
|
||||
context by generating FP instructions for any thread, and that
|
||||
context must be preserved when switching such threads in and out.
|
||||
The developers can still disable the FP sharing mode in their
|
||||
application projects, and switch to Unshared FP registers mode,
|
||||
if it is guaranteed that the image code does not generate FP
|
||||
instructions outside the single thread context that is allowed
|
||||
to do so.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Cache Options"
|
||||
|
||||
config CACHE_MANAGEMENT
|
||||
bool "Enable cache management features"
|
||||
help
|
||||
This links in the cache management functions (for d-cache and i-cache
|
||||
where possible).
|
||||
|
||||
config DCACHE_LINE_SIZE_DETECT
|
||||
bool "Detect d-cache line size at runtime"
|
||||
depends on CACHE_MANAGEMENT
|
||||
help
|
||||
This option enables querying some architecture-specific hardware for
|
||||
finding the d-cache line size at the expense of taking more memory and
|
||||
code and a slightly increased boot time.
|
||||
|
||||
If the CPU's d-cache line size is known in advance, disable this option and
|
||||
manually enter the value for DCACHE_LINE_SIZE or set it in the DT
|
||||
using the 'd-cache-line-size' property.
|
||||
|
||||
config DCACHE_LINE_SIZE
|
||||
int "d-cache line size" if !DCACHE_LINE_SIZE_DETECT
|
||||
depends on CACHE_MANAGEMENT
|
||||
default 0
|
||||
help
|
||||
Size in bytes of a CPU d-cache line. If this is set to 0 the value is
|
||||
obtained from the 'd-cache-line-size' DT property instead if present.
|
||||
|
||||
|
||||
Detect automatically at runtime by selecting DCACHE_LINE_SIZE_DETECT.
|
||||
|
||||
config ICACHE_LINE_SIZE_DETECT
|
||||
bool "Detect i-cache line size at runtime"
|
||||
depends on CACHE_MANAGEMENT
|
||||
help
|
||||
This option enables querying some architecture-specific hardware for
|
||||
finding the i-cache line size at the expense of taking more memory and
|
||||
code and a slightly increased boot time.
|
||||
|
||||
If the CPU's i-cache line size is known in advance, disable this option and
|
||||
manually enter the value for ICACHE_LINE_SIZE or set it in the DT
|
||||
using the 'i-cache-line-size' property.
|
||||
|
||||
config ICACHE_LINE_SIZE
|
||||
int "i-cache line size" if !ICACHE_LINE_SIZE_DETECT
|
||||
depends on CACHE_MANAGEMENT
|
||||
default 0
|
||||
help
|
||||
Size in bytes of a CPU i-cache line. If this is set to 0 the value is
|
||||
obtained from the 'i-cache-line-size' DT property instead if present.
|
||||
|
||||
Detect automatically at runtime by selecting ICACHE_LINE_SIZE_DETECT.
|
||||
|
||||
choice CACHE_TYPE
|
||||
prompt "Cache type"
|
||||
depends on CACHE_MANAGEMENT
|
||||
default HAS_ARCH_CACHE
|
||||
|
||||
config HAS_ARCH_CACHE
|
||||
bool "Integrated cache controller"
|
||||
help
|
||||
"Integrade on-core cache controller"
|
||||
|
||||
config HAS_EXTERNAL_CACHE
|
||||
bool "External cache controller"
|
||||
help
|
||||
"External cache controller or cache management system"
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
This option allows multiple threads to use the floating point
|
||||
registers.
|
||||
|
||||
config ARCH
|
||||
string
|
||||
@@ -830,9 +558,3 @@ config BOARD
|
||||
The Board is the first location where we search for a linker.ld file,
|
||||
if not found we look for the linker file in
|
||||
soc/<arch>/<family>/<series>
|
||||
|
||||
config TOOLCHAIN_HAS_BUILTIN_FFS
|
||||
bool
|
||||
default y if !(64BIT && RISCV)
|
||||
help
|
||||
Hidden option to signal that toolchain has __builtin_ffs*().
|
||||
|
||||
@@ -12,15 +12,4 @@ zephyr_cc_option(-fno-delete-null-pointer-checks)
|
||||
|
||||
zephyr_cc_option_ifdef(CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS -munaligned-access)
|
||||
|
||||
if(CONFIG_ISA_ARCV2)
|
||||
# Instruct compiler to use register R26 as thread pointer
|
||||
# for thread local storage.
|
||||
# For ARCv3 the register is fixed to r30, so we don't need to specify it
|
||||
zephyr_cc_option_ifdef(CONFIG_THREAD_LOCAL_STORAGE -mtp-regno=26)
|
||||
endif()
|
||||
|
||||
add_subdirectory(core)
|
||||
|
||||
if(COMPILER STREQUAL arcmwdt)
|
||||
add_subdirectory(arcmwdt)
|
||||
endif()
|
||||
|
||||
150
arch/arc/Kconfig
150
arch/arc/Kconfig
@@ -9,109 +9,67 @@ menu "ARC Options"
|
||||
config ARCH
|
||||
default "arc"
|
||||
|
||||
choice
|
||||
prompt "ARC core family"
|
||||
default CPU_ARCEM
|
||||
|
||||
config CPU_ARCEM
|
||||
bool
|
||||
bool "ARC EM cores"
|
||||
select CPU_ARCV2
|
||||
select ATOMIC_OPERATIONS_C
|
||||
help
|
||||
This option signifies the use of an ARC EM CPU
|
||||
|
||||
config CPU_ARCHS
|
||||
bool
|
||||
bool "ARC HS cores"
|
||||
select CPU_ARCV2
|
||||
select ATOMIC_OPERATIONS_BUILTIN
|
||||
help
|
||||
This option signifies the use of an ARC HS CPU
|
||||
|
||||
|
||||
choice
|
||||
prompt "ARC Instruction Set"
|
||||
default ISA_ARCV2
|
||||
|
||||
config ISA_ARCV2
|
||||
bool "ARC ISA v2"
|
||||
select ARCH_HAS_STACK_PROTECTION if ARC_HAS_STACK_CHECKING || (ARC_MPU && ARC_MPU_VER !=2)
|
||||
select ARCH_HAS_USERSPACE if ARC_MPU
|
||||
select USE_SWITCH
|
||||
select USE_SWITCH_SUPPORTED
|
||||
help
|
||||
v2 ISA for the ARC-HS & ARC-EM cores
|
||||
|
||||
config ISA_ARCV3
|
||||
bool "ARC ISA v3"
|
||||
select USE_SWITCH
|
||||
select USE_SWITCH_SUPPORTED
|
||||
|
||||
endchoice
|
||||
|
||||
if ISA_ARCV2
|
||||
|
||||
config CPU_EM4
|
||||
bool
|
||||
select CPU_ARCEM
|
||||
help
|
||||
If y, the SoC uses an ARC EM4 CPU
|
||||
|
||||
config CPU_EM4_DMIPS
|
||||
bool
|
||||
select CPU_ARCEM
|
||||
help
|
||||
If y, the SoC uses an ARC EM4 DMIPS CPU
|
||||
|
||||
config CPU_EM4_FPUS
|
||||
bool
|
||||
select CPU_ARCEM
|
||||
help
|
||||
If y, the SoC uses an ARC EM4 DMIPS CPU with the single-precision
|
||||
floating-point extension
|
||||
|
||||
config CPU_EM4_FPUDA
|
||||
bool
|
||||
select CPU_ARCEM
|
||||
help
|
||||
If y, the SoC uses an ARC EM4 DMIPS CPU with single-precision
|
||||
floating-point and double assist instructions
|
||||
|
||||
config CPU_EM6
|
||||
bool
|
||||
select CPU_ARCEM
|
||||
help
|
||||
If y, the SoC uses an ARC EM6 CPU
|
||||
|
||||
config CPU_HS3X
|
||||
bool
|
||||
select CPU_ARCHS
|
||||
help
|
||||
If y, the SoC uses an ARC HS3x or HS4x CPU
|
||||
|
||||
endif #ISA_ARCV2
|
||||
|
||||
if ISA_ARCV3
|
||||
|
||||
config CPU_HS6X
|
||||
bool
|
||||
select CPU_ARCHS
|
||||
select 64BIT
|
||||
help
|
||||
If y, the SoC uses an ARC HS6x CPU
|
||||
|
||||
endif #ISA_ARCV3
|
||||
|
||||
config FP_FPU_DA
|
||||
bool
|
||||
|
||||
menu "ARC CPU Options"
|
||||
menu "ARCv2 Family Options"
|
||||
|
||||
config ARC_HAS_ZOL
|
||||
config CPU_ARCV2
|
||||
bool
|
||||
depends on ISA_ARCV2
|
||||
select ARCH_HAS_STACK_PROTECTION if ARC_HAS_STACK_CHECKING || ARC_MPU
|
||||
select ARCH_HAS_USERSPACE if ARC_MPU
|
||||
select USE_SWITCH
|
||||
select USE_SWITCH_SUPPORTED
|
||||
default y
|
||||
help
|
||||
ARCv2 CPUs have ZOL hardware loop mechanism which the ARCv3 ISA drops.
|
||||
Architecturally ZOL provides
|
||||
- LPcc instruction
|
||||
- LP_COUNT core reg
|
||||
- LP_START, LP_END aux regs
|
||||
Disabling this option removes usage of ZOL regs from code
|
||||
This option signifies the use of a CPU of the ARCv2 family.
|
||||
|
||||
config NUM_IRQ_PRIO_LEVELS
|
||||
int "Number of supported interrupt priority levels"
|
||||
@@ -135,8 +93,7 @@ config NUM_IRQS
|
||||
|
||||
config RGF_NUM_BANKS
|
||||
int "Number of General Purpose Register Banks"
|
||||
depends on ARC_FIRQ
|
||||
depends on NUM_IRQ_PRIO_LEVELS > 1
|
||||
depends on CPU_ARCV2
|
||||
range 1 2
|
||||
default 2
|
||||
help
|
||||
@@ -146,15 +103,9 @@ config RGF_NUM_BANKS
|
||||
If fast interrupts are supported but there is only 1
|
||||
register bank, the fast interrupt handler must save
|
||||
and restore general purpose registers.
|
||||
NOTE: it's required to have more than one interrupt priority level
|
||||
to use second register bank - otherwise all interrupts will use
|
||||
same register bank. Such configuration isn't supported in software
|
||||
and it is not beneficial from the performance point of view.
|
||||
|
||||
config ARC_FIRQ
|
||||
bool "FIRQ enable"
|
||||
depends on ISA_ARCV2
|
||||
depends on NUM_IRQ_PRIO_LEVELS > 1
|
||||
default y
|
||||
help
|
||||
Fast interrupts are supported (FIRQ). If FIRQ enabled, for interrupts
|
||||
@@ -162,10 +113,6 @@ config ARC_FIRQ
|
||||
other regs will be saved according to the number of register bank;
|
||||
If FIRQ is disabled, the handle of interrupts with highest priority
|
||||
will be same with other interrupts.
|
||||
NOTE: we don't allow the configuration with FIRQ enabled and only one
|
||||
interrupt priority level (so all interrupts are FIRQ). Such
|
||||
configuration isn't supported in software and it is not beneficial
|
||||
from the performance point of view.
|
||||
|
||||
config ARC_FIRQ_STACK
|
||||
bool "Enable separate firq stack"
|
||||
@@ -183,7 +130,6 @@ config ARC_FIRQ_STACK_SIZE
|
||||
|
||||
config ARC_HAS_STACK_CHECKING
|
||||
bool "ARC has STACK_CHECKING"
|
||||
depends on ISA_ARCV2
|
||||
default y
|
||||
help
|
||||
ARC is configured with STACK_CHECKING which is a mechanism for
|
||||
@@ -207,7 +153,7 @@ config ARC_STACK_PROTECTION
|
||||
bool
|
||||
default y if HW_STACK_PROTECTION
|
||||
select ARC_STACK_CHECKING if ARC_HAS_STACK_CHECKING
|
||||
select MPU_STACK_GUARD if (!ARC_STACK_CHECKING && ARC_MPU && ARC_MPU_VER !=2)
|
||||
select MPU_STACK_GUARD if (!ARC_STACK_CHECKING && ARC_MPU)
|
||||
select THREAD_STACK_INFO
|
||||
help
|
||||
This option enables either:
|
||||
@@ -243,6 +189,9 @@ config FAULT_DUMP
|
||||
|
||||
0: Off.
|
||||
|
||||
config XIP
|
||||
default y if !UART_NSIM
|
||||
|
||||
config GEN_ISR_TABLES
|
||||
default y
|
||||
|
||||
@@ -262,7 +211,7 @@ config CODE_DENSITY
|
||||
|
||||
config ARC_HAS_ACCL_REGS
|
||||
bool "Reg Pair ACCL:ACCH (FPU and/or MPY > 6)"
|
||||
default y if CPU_HS3X
|
||||
default y if FLOAT
|
||||
help
|
||||
Depending on the configuration, CPU can contain accumulator reg-pair
|
||||
(also referred to as r58:r59). These can also be used by gcc as GPR so
|
||||
@@ -270,7 +219,6 @@ config ARC_HAS_ACCL_REGS
|
||||
|
||||
config ARC_HAS_SECURE
|
||||
bool "ARC has SecureShield"
|
||||
depends on ISA_ARCV2
|
||||
select CPU_HAS_TEE
|
||||
select ARCH_HAS_TRUSTED_EXECUTION
|
||||
help
|
||||
@@ -334,13 +282,38 @@ source "arch/arc/core/mpu/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
config DCACHE_LINE_SIZE
|
||||
config CACHE_LINE_SIZE_DETECT
|
||||
bool "Detect d-cache line size at runtime"
|
||||
help
|
||||
This option enables querying the d-cache build register for finding
|
||||
the d-cache line size at the expense of taking more memory and code
|
||||
and a slightly increased boot time.
|
||||
|
||||
If the CPU's d-cache line size is known in advance, disable this
|
||||
option and manually enter the value for CACHE_LINE_SIZE.
|
||||
|
||||
config CACHE_LINE_SIZE
|
||||
int "Cache line size" if !CACHE_LINE_SIZE_DETECT
|
||||
default 32
|
||||
help
|
||||
Size in bytes of a CPU d-cache line.
|
||||
|
||||
Detect automatically at runtime by selecting CACHE_LINE_SIZE_DETECT.
|
||||
|
||||
config ARCH_CACHE_FLUSH_DETECT
|
||||
bool
|
||||
|
||||
config CACHE_FLUSHING
|
||||
bool "Enable d-cache flushing mechanism"
|
||||
help
|
||||
This links in the sys_cache_flush() function, which provides a
|
||||
way to flush multiple lines of the d-cache.
|
||||
If the d-cache is present, set this to y.
|
||||
If the d-cache is NOT present, set this to n.
|
||||
|
||||
config ARC_EXCEPTION_STACK_SIZE
|
||||
int "ARC exception handling stack size"
|
||||
default 768 if !64BIT
|
||||
default 2048 if 64BIT
|
||||
default 768
|
||||
help
|
||||
Size in bytes of exception handling stack which is at the top of
|
||||
interrupt stack to get smaller memory footprint because exception
|
||||
@@ -359,30 +332,3 @@ config ARC_EXCEPTION_DEBUG
|
||||
strings.
|
||||
|
||||
endmenu
|
||||
|
||||
config MAIN_STACK_SIZE
|
||||
default 4096 if 64BIT
|
||||
|
||||
config ISR_STACK_SIZE
|
||||
default 4096 if 64BIT
|
||||
|
||||
config SYSTEM_WORKQUEUE_STACK_SIZE
|
||||
default 4096 if 64BIT
|
||||
|
||||
config IDLE_STACK_SIZE
|
||||
default 1024 if 64BIT
|
||||
|
||||
config IPM_CONSOLE_STACK_SIZE
|
||||
default 2048 if 64BIT
|
||||
|
||||
config TEST_EXTRA_STACKSIZE
|
||||
default 2048 if 64BIT
|
||||
|
||||
config CMSIS_THREAD_MAX_STACK_SIZE
|
||||
default 2048 if 64BIT
|
||||
|
||||
config CMSIS_V2_THREAD_MAX_STACK_SIZE
|
||||
default 2048 if 64BIT
|
||||
|
||||
config CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE
|
||||
default 2048 if 64BIT
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if(CONFIG_ARCMWDT_LIBC OR CONFIG_CPLUSPLUS)
|
||||
zephyr_sources(arcmwdt-dtr-stubs.c)
|
||||
endif()
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <toolchain.h>
|
||||
|
||||
__weak void *__dso_handle;
|
||||
|
||||
int __cxa_atexit(void (*destructor)(void *), void *objptr, void *dso)
|
||||
{
|
||||
ARG_UNUSED(destructor);
|
||||
ARG_UNUSED(objptr);
|
||||
ARG_UNUSED(dso);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int atexit(void (*function)(void))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -19,17 +19,15 @@ zephyr_library_sources(
|
||||
vector_table.c
|
||||
)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_CACHE_MANAGEMENT cache.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CACHE_FLUSHING cache.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ARC_FIRQ fast_irq.S)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c)
|
||||
zephyr_library_sources_if_kconfig(irq_offload.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S)
|
||||
zephyr_library_sources_ifdef(CONFIG_ARC_CONNECT arc_connect.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ARC_CONNECT arc_smp.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c)
|
||||
|
||||
add_subdirectory_ifdef(CONFIG_ARC_CORE_MPU mpu)
|
||||
add_subdirectory_ifdef(CONFIG_ARC_SECURE_FIRMWARE secureshield)
|
||||
|
||||
|
||||
@@ -13,12 +13,18 @@
|
||||
#include <kernel.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <spinlock.h>
|
||||
#include <kernel_internal.h>
|
||||
|
||||
|
||||
static struct k_spinlock arc_connect_spinlock;
|
||||
|
||||
#define LOCKED(lck) for (k_spinlock_key_t __i = {}, \
|
||||
__key = k_spin_lock(lck); \
|
||||
!__i.key; \
|
||||
k_spin_unlock(lck, __key), __i.key = 1)
|
||||
|
||||
|
||||
/* Generate an inter-core interrupt to the target core */
|
||||
void z_arc_connect_ici_generate(uint32_t core)
|
||||
void z_arc_connect_ici_generate(u32_t core)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_GENERATE_IRQ, core);
|
||||
@@ -26,7 +32,7 @@ void z_arc_connect_ici_generate(uint32_t core)
|
||||
}
|
||||
|
||||
/* Acknowledge the inter-core interrupt raised by core */
|
||||
void z_arc_connect_ici_ack(uint32_t core)
|
||||
void z_arc_connect_ici_ack(u32_t core)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_GENERATE_ACK, core);
|
||||
@@ -34,9 +40,9 @@ void z_arc_connect_ici_ack(uint32_t core)
|
||||
}
|
||||
|
||||
/* Read inter-core interrupt status */
|
||||
uint32_t z_arc_connect_ici_read_status(uint32_t core)
|
||||
u32_t z_arc_connect_ici_read_status(u32_t core)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_READ_STATUS, core);
|
||||
@@ -47,9 +53,9 @@ uint32_t z_arc_connect_ici_read_status(uint32_t core)
|
||||
}
|
||||
|
||||
/* Check the source of inter-core interrupt */
|
||||
uint32_t z_arc_connect_ici_check_src(void)
|
||||
u32_t z_arc_connect_ici_check_src(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_CHECK_SOURCE, 0);
|
||||
@@ -62,7 +68,7 @@ uint32_t z_arc_connect_ici_check_src(void)
|
||||
/* Clear the inter-core interrupt */
|
||||
void z_arc_connect_ici_clear(void)
|
||||
{
|
||||
uint32_t cpu, c;
|
||||
u32_t cpu, c;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
|
||||
@@ -83,7 +89,7 @@ void z_arc_connect_ici_clear(void)
|
||||
}
|
||||
|
||||
/* Reset the cores in core_mask */
|
||||
void z_arc_connect_debug_reset(uint32_t core_mask)
|
||||
void z_arc_connect_debug_reset(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_RESET,
|
||||
@@ -92,7 +98,7 @@ void z_arc_connect_debug_reset(uint32_t core_mask)
|
||||
}
|
||||
|
||||
/* Halt the cores in core_mask */
|
||||
void z_arc_connect_debug_halt(uint32_t core_mask)
|
||||
void z_arc_connect_debug_halt(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_HALT,
|
||||
@@ -101,7 +107,7 @@ void z_arc_connect_debug_halt(uint32_t core_mask)
|
||||
}
|
||||
|
||||
/* Run the cores in core_mask */
|
||||
void z_arc_connect_debug_run(uint32_t core_mask)
|
||||
void z_arc_connect_debug_run(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_RUN,
|
||||
@@ -110,7 +116,7 @@ void z_arc_connect_debug_run(uint32_t core_mask)
|
||||
}
|
||||
|
||||
/* Set core mask */
|
||||
void z_arc_connect_debug_mask_set(uint32_t core_mask, uint32_t mask)
|
||||
void z_arc_connect_debug_mask_set(u32_t core_mask, u32_t mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_SET_MASK,
|
||||
@@ -119,9 +125,9 @@ void z_arc_connect_debug_mask_set(uint32_t core_mask, uint32_t mask)
|
||||
}
|
||||
|
||||
/* Read core mask */
|
||||
uint32_t z_arc_connect_debug_mask_read(uint32_t core_mask)
|
||||
u32_t z_arc_connect_debug_mask_read(u32_t core_mask)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_READ_MASK,
|
||||
@@ -135,7 +141,7 @@ uint32_t z_arc_connect_debug_mask_read(uint32_t core_mask)
|
||||
/*
|
||||
* Select cores that should be halted if the core issuing the command is halted
|
||||
*/
|
||||
void z_arc_connect_debug_select_set(uint32_t core_mask)
|
||||
void z_arc_connect_debug_select_set(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_SET_SELECT,
|
||||
@@ -144,9 +150,9 @@ void z_arc_connect_debug_select_set(uint32_t core_mask)
|
||||
}
|
||||
|
||||
/* Read the select value */
|
||||
uint32_t z_arc_connect_debug_select_read(void)
|
||||
u32_t z_arc_connect_debug_select_read(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_SELECT, 0);
|
||||
@@ -157,9 +163,9 @@ uint32_t z_arc_connect_debug_select_read(void)
|
||||
}
|
||||
|
||||
/* Read the status, halt or run of all cores in the system */
|
||||
uint32_t z_arc_connect_debug_en_read(void)
|
||||
u32_t z_arc_connect_debug_en_read(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_EN, 0);
|
||||
@@ -170,9 +176,9 @@ uint32_t z_arc_connect_debug_en_read(void)
|
||||
}
|
||||
|
||||
/* Read the last command sent */
|
||||
uint32_t z_arc_connect_debug_cmd_read(void)
|
||||
u32_t z_arc_connect_debug_cmd_read(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_CMD, 0);
|
||||
@@ -183,9 +189,9 @@ uint32_t z_arc_connect_debug_cmd_read(void)
|
||||
}
|
||||
|
||||
/* Read the value of internal MCD_CORE register */
|
||||
uint32_t z_arc_connect_debug_core_read(void)
|
||||
u32_t z_arc_connect_debug_core_read(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_CORE, 0);
|
||||
@@ -204,11 +210,11 @@ void z_arc_connect_gfrc_clear(void)
|
||||
}
|
||||
|
||||
/* Read total 64 bits of global free running counter */
|
||||
uint64_t z_arc_connect_gfrc_read(void)
|
||||
u64_t z_arc_connect_gfrc_read(void)
|
||||
{
|
||||
uint32_t low;
|
||||
uint32_t high;
|
||||
uint32_t key;
|
||||
u32_t low;
|
||||
u32_t high;
|
||||
u32_t key;
|
||||
|
||||
/*
|
||||
* each core has its own arc connect interface, i.e.,
|
||||
@@ -227,7 +233,7 @@ uint64_t z_arc_connect_gfrc_read(void)
|
||||
|
||||
arch_irq_unlock(key);
|
||||
|
||||
return (((uint64_t)high) << 32) | low;
|
||||
return (((u64_t)high) << 32) | low;
|
||||
}
|
||||
|
||||
/* Enable global free running counter */
|
||||
@@ -247,7 +253,7 @@ void z_arc_connect_gfrc_disable(void)
|
||||
}
|
||||
|
||||
/* Disable global free running counter */
|
||||
void z_arc_connect_gfrc_core_set(uint32_t core_mask)
|
||||
void z_arc_connect_gfrc_core_set(u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_GFRC_SET_CORE,
|
||||
@@ -256,9 +262,9 @@ void z_arc_connect_gfrc_core_set(uint32_t core_mask)
|
||||
}
|
||||
|
||||
/* Set the relevant cores to halt global free running counter */
|
||||
uint32_t z_arc_connect_gfrc_halt_read(void)
|
||||
u32_t z_arc_connect_gfrc_halt_read(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_READ_HALT, 0);
|
||||
@@ -269,9 +275,9 @@ uint32_t z_arc_connect_gfrc_halt_read(void)
|
||||
}
|
||||
|
||||
/* Read the internal CORE register */
|
||||
uint32_t z_arc_connect_gfrc_core_read(void)
|
||||
u32_t z_arc_connect_gfrc_core_read(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_READ_CORE, 0);
|
||||
@@ -298,9 +304,9 @@ void z_arc_connect_idu_disable(void)
|
||||
}
|
||||
|
||||
/* Read enable status of interrupt distribute unit */
|
||||
uint32_t z_arc_connect_idu_read_enable(void)
|
||||
u32_t z_arc_connect_idu_read_enable(void)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_ENABLE, 0);
|
||||
@@ -314,8 +320,8 @@ uint32_t z_arc_connect_idu_read_enable(void)
|
||||
* Set the triggering mode and distribution mode for the specified common
|
||||
* interrupt
|
||||
*/
|
||||
void z_arc_connect_idu_set_mode(uint32_t irq_num,
|
||||
uint16_t trigger_mode, uint16_t distri_mode)
|
||||
void z_arc_connect_idu_set_mode(u32_t irq_num,
|
||||
u16_t trigger_mode, u16_t distri_mode)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_IDU_SET_MODE,
|
||||
@@ -324,9 +330,9 @@ void z_arc_connect_idu_set_mode(uint32_t irq_num,
|
||||
}
|
||||
|
||||
/* Read the internal MODE register of the specified common interrupt */
|
||||
uint32_t z_arc_connect_idu_read_mode(uint32_t irq_num)
|
||||
u32_t z_arc_connect_idu_read_mode(u32_t irq_num)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_MODE, irq_num);
|
||||
@@ -340,7 +346,7 @@ uint32_t z_arc_connect_idu_read_mode(uint32_t irq_num)
|
||||
* Set the target cores to receive the specified common interrupt
|
||||
* when it is triggered
|
||||
*/
|
||||
void z_arc_connect_idu_set_dest(uint32_t irq_num, uint32_t core_mask)
|
||||
void z_arc_connect_idu_set_dest(u32_t irq_num, u32_t core_mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_IDU_SET_DEST,
|
||||
@@ -349,9 +355,9 @@ void z_arc_connect_idu_set_dest(uint32_t irq_num, uint32_t core_mask)
|
||||
}
|
||||
|
||||
/* Read the internal DEST register of the specified common interrupt */
|
||||
uint32_t z_arc_connect_idu_read_dest(uint32_t irq_num)
|
||||
u32_t z_arc_connect_idu_read_dest(u32_t irq_num)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_DEST, irq_num);
|
||||
@@ -362,7 +368,7 @@ uint32_t z_arc_connect_idu_read_dest(uint32_t irq_num)
|
||||
}
|
||||
|
||||
/* Assert the specified common interrupt */
|
||||
void z_arc_connect_idu_gen_cirq(uint32_t irq_num)
|
||||
void z_arc_connect_idu_gen_cirq(u32_t irq_num)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_GEN_CIRQ, irq_num);
|
||||
@@ -370,7 +376,7 @@ void z_arc_connect_idu_gen_cirq(uint32_t irq_num)
|
||||
}
|
||||
|
||||
/* Acknowledge the specified common interrupt */
|
||||
void z_arc_connect_idu_ack_cirq(uint32_t irq_num)
|
||||
void z_arc_connect_idu_ack_cirq(u32_t irq_num)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_ACK_CIRQ, irq_num);
|
||||
@@ -378,9 +384,9 @@ void z_arc_connect_idu_ack_cirq(uint32_t irq_num)
|
||||
}
|
||||
|
||||
/* Read the internal STATUS register of the specified common interrupt */
|
||||
uint32_t z_arc_connect_idu_check_status(uint32_t irq_num)
|
||||
u32_t z_arc_connect_idu_check_status(u32_t irq_num)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_CHECK_STATUS, irq_num);
|
||||
@@ -391,9 +397,9 @@ uint32_t z_arc_connect_idu_check_status(uint32_t irq_num)
|
||||
}
|
||||
|
||||
/* Read the internal SOURCE register of the specified common interrupt */
|
||||
uint32_t z_arc_connect_idu_check_source(uint32_t irq_num)
|
||||
u32_t z_arc_connect_idu_check_source(u32_t irq_num)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_CHECK_SOURCE, irq_num);
|
||||
@@ -404,7 +410,7 @@ uint32_t z_arc_connect_idu_check_source(uint32_t irq_num)
|
||||
}
|
||||
|
||||
/* Mask or unmask the specified common interrupt */
|
||||
void z_arc_connect_idu_set_mask(uint32_t irq_num, uint32_t mask)
|
||||
void z_arc_connect_idu_set_mask(u32_t irq_num, u32_t mask)
|
||||
{
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd_data(ARC_CONNECT_CMD_IDU_SET_MASK,
|
||||
@@ -413,9 +419,9 @@ void z_arc_connect_idu_set_mask(uint32_t irq_num, uint32_t mask)
|
||||
}
|
||||
|
||||
/* Read the internal MASK register of the specified common interrupt */
|
||||
uint32_t z_arc_connect_idu_read_mask(uint32_t irq_num)
|
||||
u32_t z_arc_connect_idu_read_mask(u32_t irq_num)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_MASK, irq_num);
|
||||
@@ -429,9 +435,9 @@ uint32_t z_arc_connect_idu_read_mask(uint32_t irq_num)
|
||||
* Check if it is the first-acknowledging core to the common interrupt
|
||||
* if IDU is programmed in the first-acknowledged mode
|
||||
*/
|
||||
uint32_t z_arc_connect_idu_check_first(uint32_t irq_num)
|
||||
u32_t z_arc_connect_idu_check_first(u32_t irq_num)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
u32_t ret = 0;
|
||||
|
||||
LOCKED(&arc_connect_spinlock) {
|
||||
z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_CHECK_FIRST, irq_num);
|
||||
|
||||
@@ -35,7 +35,7 @@ volatile struct {
|
||||
* master core that it's waken
|
||||
*
|
||||
*/
|
||||
volatile uint32_t arc_cpu_wake_flag;
|
||||
volatile u32_t arc_cpu_wake_flag;
|
||||
|
||||
volatile char *arc_cpu_sp;
|
||||
/*
|
||||
@@ -61,45 +61,18 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
|
||||
arc_cpu_wake_flag = cpu_num;
|
||||
|
||||
/* wait slave cpu to start */
|
||||
while (arc_cpu_wake_flag != 0U) {
|
||||
while (arc_cpu_wake_flag != 0) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static void arc_connect_debug_mask_update(int cpu_num)
|
||||
{
|
||||
uint32_t core_mask = 1 << cpu_num;
|
||||
|
||||
core_mask |= z_arc_connect_debug_select_read();
|
||||
z_arc_connect_debug_select_set(core_mask);
|
||||
/* Debugger halts cores at all conditions:
|
||||
* ARC_CONNECT_CMD_DEBUG_MASK_H: Core global halt.
|
||||
* ARC_CONNECT_CMD_DEBUG_MASK_AH: Actionpoint halt.
|
||||
* ARC_CONNECT_CMD_DEBUG_MASK_BH: Software breakpoint halt.
|
||||
* ARC_CONNECT_CMD_DEBUG_MASK_SH: Self halt.
|
||||
*/
|
||||
z_arc_connect_debug_mask_set(core_mask, (ARC_CONNECT_CMD_DEBUG_MASK_SH
|
||||
| ARC_CONNECT_CMD_DEBUG_MASK_BH | ARC_CONNECT_CMD_DEBUG_MASK_AH
|
||||
| ARC_CONNECT_CMD_DEBUG_MASK_H));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* the C entry of slave cores */
|
||||
void z_arc_slave_start(int cpu_num)
|
||||
{
|
||||
arch_cpustart_t fn;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
struct arc_connect_bcr bcr;
|
||||
|
||||
bcr.val = z_arc_v2_aux_reg_read(_ARC_V2_CONNECT_BCR);
|
||||
|
||||
if (bcr.dbg) {
|
||||
/* configure inter-core debug unit if available */
|
||||
arc_connect_debug_mask_update(cpu_num);
|
||||
}
|
||||
|
||||
z_icache_setup();
|
||||
z_irq_setup();
|
||||
|
||||
z_arc_connect_ici_clear();
|
||||
@@ -114,7 +87,7 @@ void z_arc_slave_start(int cpu_num)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
static void sched_ipi_handler(const void *unused)
|
||||
static void sched_ipi_handler(void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
@@ -122,34 +95,63 @@ static void sched_ipi_handler(const void *unused)
|
||||
z_sched_ipi();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether need to do thread switch in isr context
|
||||
*
|
||||
* @details u64_t is used to let compiler use (r0, r1) as return register.
|
||||
* use register r0 and register r1 as return value, r0 has
|
||||
* new thread, r1 has old thread. If r0 == 0, it means no thread switch.
|
||||
*/
|
||||
u64_t z_arc_smp_switch_in_isr(void)
|
||||
{
|
||||
u64_t ret = 0;
|
||||
u32_t new_thread;
|
||||
u32_t old_thread;
|
||||
|
||||
old_thread = (u32_t)_current;
|
||||
|
||||
new_thread = (u32_t)z_get_next_ready_thread();
|
||||
|
||||
if (new_thread != old_thread) {
|
||||
#ifdef CONFIG_TIMESLICING
|
||||
z_reset_time_slice();
|
||||
#endif
|
||||
_current_cpu->swap_ok = 0;
|
||||
((struct k_thread *)new_thread)->base.cpu =
|
||||
arch_curr_cpu()->id;
|
||||
_current_cpu->current = (struct k_thread *) new_thread;
|
||||
ret = new_thread | ((u64_t)(old_thread) << 32);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* arch implementation of sched_ipi */
|
||||
void arch_sched_ipi(void)
|
||||
{
|
||||
uint32_t i;
|
||||
u32_t i;
|
||||
|
||||
/* broadcast sched_ipi request to other cores
|
||||
* if the target is current core, hardware will ignore it
|
||||
*/
|
||||
for (i = 0U; i < CONFIG_MP_NUM_CPUS; i++) {
|
||||
for (i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
|
||||
z_arc_connect_ici_generate(i);
|
||||
}
|
||||
}
|
||||
|
||||
static int arc_smp_init(const struct device *dev)
|
||||
static int arc_smp_init(struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
struct arc_connect_bcr bcr;
|
||||
|
||||
/* necessary master core init */
|
||||
_kernel.cpus[0].id = 0;
|
||||
_kernel.cpus[0].irq_stack = Z_THREAD_STACK_BUFFER(_interrupt_stack)
|
||||
+ CONFIG_ISR_STACK_SIZE;
|
||||
_curr_cpu[0] = &(_kernel.cpus[0]);
|
||||
|
||||
bcr.val = z_arc_v2_aux_reg_read(_ARC_V2_CONNECT_BCR);
|
||||
|
||||
if (bcr.dbg) {
|
||||
/* configure inter-core debug unit if available */
|
||||
arc_connect_debug_mask_update(0);
|
||||
}
|
||||
|
||||
if (bcr.ipi) {
|
||||
/* register ici interrupt, just need master core to register once */
|
||||
z_arc_connect_ici_clear();
|
||||
|
||||
@@ -25,8 +25,14 @@
|
||||
#include <init.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#if defined(CONFIG_DCACHE_LINE_SIZE_DETECT)
|
||||
size_t sys_cache_line_size;
|
||||
#if (CONFIG_CACHE_LINE_SIZE == 0) && !defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||
#error Cannot use this implementation with a cache line size of 0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||
#define DCACHE_LINE_SIZE sys_cache_line_size
|
||||
#else
|
||||
#define DCACHE_LINE_SIZE CONFIG_CACHE_LINE_SIZE
|
||||
#endif
|
||||
|
||||
#define DC_CTRL_DC_ENABLE 0x0 /* enable d-cache */
|
||||
@@ -49,40 +55,54 @@ static bool dcache_available(void)
|
||||
return (val == 0) ? false : true;
|
||||
}
|
||||
|
||||
static void dcache_dc_ctrl(uint32_t dcache_en_mask)
|
||||
static void dcache_dc_ctrl(u32_t dcache_en_mask)
|
||||
{
|
||||
if (dcache_available()) {
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_DC_CTRL, dcache_en_mask);
|
||||
}
|
||||
}
|
||||
|
||||
void arch_dcache_enable(void)
|
||||
static void dcache_enable(void)
|
||||
{
|
||||
dcache_dc_ctrl(DC_CTRL_DC_ENABLE);
|
||||
}
|
||||
|
||||
static void arch_dcache_flush(void *start_addr_ptr, size_t size)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Flush multiple d-cache lines to memory
|
||||
*
|
||||
* No alignment is required for either <start_addr> or <size>, but since
|
||||
* dcache_flush_mlines() iterates on the d-cache lines, a cache line
|
||||
* alignment for both is optimal.
|
||||
*
|
||||
* The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE
|
||||
* kconfig option or it is detected at runtime.
|
||||
*
|
||||
* @param start_addr the pointer to start the multi-line flush
|
||||
* @param size the number of bytes that are to be flushed
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static void dcache_flush_mlines(u32_t start_addr, u32_t size)
|
||||
{
|
||||
size_t line_size = sys_cache_data_line_size_get();
|
||||
uintptr_t start_addr = (uintptr_t)start_addr_ptr;
|
||||
uintptr_t end_addr;
|
||||
u32_t end_addr;
|
||||
unsigned int key;
|
||||
|
||||
if (!dcache_available() || (size == 0U) || line_size == 0U) {
|
||||
if (!dcache_available() || (size == 0U)) {
|
||||
return;
|
||||
}
|
||||
|
||||
end_addr = start_addr + size;
|
||||
end_addr = start_addr + size - 1;
|
||||
start_addr &= (u32_t)(~(DCACHE_LINE_SIZE - 1));
|
||||
|
||||
start_addr = ROUND_DOWN(start_addr, line_size);
|
||||
|
||||
key = arch_irq_lock(); /* --enter critical section-- */
|
||||
key = irq_lock(); /* --enter critical section-- */
|
||||
|
||||
do {
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_DC_FLDL, start_addr);
|
||||
__builtin_arc_nop();
|
||||
__builtin_arc_nop();
|
||||
__builtin_arc_nop();
|
||||
__asm__ volatile("nop_s");
|
||||
__asm__ volatile("nop_s");
|
||||
__asm__ volatile("nop_s");
|
||||
/* wait for flush completion */
|
||||
do {
|
||||
if ((z_arc_v2_aux_reg_read(_ARC_V2_DC_CTRL) &
|
||||
@@ -90,59 +110,42 @@ static void arch_dcache_flush(void *start_addr_ptr, size_t size)
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
start_addr += line_size;
|
||||
} while (start_addr < end_addr);
|
||||
start_addr += DCACHE_LINE_SIZE;
|
||||
} while (start_addr <= end_addr);
|
||||
|
||||
arch_irq_unlock(key); /* --exit critical section-- */
|
||||
irq_unlock(key); /* --exit critical section-- */
|
||||
|
||||
}
|
||||
|
||||
static void arch_dcache_invd(void *start_addr_ptr, size_t size)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Flush d-cache lines to main memory
|
||||
*
|
||||
* No alignment is required for either <virt> or <size>, but since
|
||||
* sys_cache_flush() iterates on the d-cache lines, a d-cache line alignment for
|
||||
* both is optimal.
|
||||
*
|
||||
* The d-cache line size is specified either via the CONFIG_CACHE_LINE_SIZE
|
||||
* kconfig option or it is detected at runtime.
|
||||
*
|
||||
* @param start_addr the pointer to start the multi-line flush
|
||||
* @param size the number of bytes that are to be flushed
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void sys_cache_flush(vaddr_t start_addr, size_t size)
|
||||
{
|
||||
size_t line_size = sys_cache_data_line_size_get();
|
||||
uintptr_t start_addr = (uintptr_t)start_addr_ptr;
|
||||
uintptr_t end_addr;
|
||||
unsigned int key;
|
||||
|
||||
if (!dcache_available() || (size == 0U) || line_size == 0U) {
|
||||
return;
|
||||
}
|
||||
end_addr = start_addr + size;
|
||||
start_addr = ROUND_DOWN(start_addr, line_size);
|
||||
|
||||
key = arch_irq_lock(); /* -enter critical section- */
|
||||
|
||||
do {
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_DC_IVDL, start_addr);
|
||||
__builtin_arc_nop();
|
||||
__builtin_arc_nop();
|
||||
__builtin_arc_nop();
|
||||
start_addr += line_size;
|
||||
} while (start_addr < end_addr);
|
||||
irq_unlock(key); /* -exit critical section- */
|
||||
dcache_flush_mlines((u32_t)start_addr, (u32_t)size);
|
||||
}
|
||||
|
||||
int arch_dcache_range(void *addr, size_t size, int op)
|
||||
{
|
||||
if (op == K_CACHE_INVD) {
|
||||
/*
|
||||
* TODO: On invalidate we can contextually flush by setting the
|
||||
* DC_CTRL_INVALID_FLUSH bit
|
||||
*/
|
||||
arch_dcache_invd(addr, size);
|
||||
} else if (op == K_CACHE_WB) {
|
||||
arch_dcache_flush(addr, size);
|
||||
} else {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DCACHE_LINE_SIZE_DETECT)
|
||||
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||
size_t sys_cache_line_size;
|
||||
static void init_dcache_line_size(void)
|
||||
{
|
||||
uint32_t val;
|
||||
u32_t val;
|
||||
|
||||
val = z_arc_v2_aux_reg_read(_ARC_V2_D_CACHE_BUILD);
|
||||
__ASSERT((val&0xff) != 0U, "d-cache is not present");
|
||||
@@ -150,20 +153,15 @@ static void init_dcache_line_size(void)
|
||||
val *= 16U;
|
||||
sys_cache_line_size = (size_t) val;
|
||||
}
|
||||
|
||||
size_t arch_dcache_line_size_get(void)
|
||||
{
|
||||
return sys_cache_line_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int init_dcache(const struct device *unused)
|
||||
static int init_dcache(struct device *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
arch_dcache_enable();
|
||||
dcache_enable();
|
||||
|
||||
#if defined(CONFIG_DCACHE_LINE_SIZE_DETECT)
|
||||
#if defined(CONFIG_CACHE_LINE_SIZE_DETECT)
|
||||
init_dcache_line_size();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,14 +16,13 @@
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <arch/arc/asm-compat/assembler.h>
|
||||
|
||||
GTEXT(arch_cpu_idle)
|
||||
GTEXT(arch_cpu_atomic_idle)
|
||||
GDATA(z_arc_cpu_sleep_mode)
|
||||
|
||||
SECTION_VAR(BSS, z_arc_cpu_sleep_mode)
|
||||
.align 4
|
||||
.balign 4
|
||||
.word 0
|
||||
|
||||
/*
|
||||
@@ -37,15 +36,26 @@ SECTION_VAR(BSS, z_arc_cpu_sleep_mode)
|
||||
SECTION_FUNC(TEXT, arch_cpu_idle)
|
||||
|
||||
#ifdef CONFIG_TRACING
|
||||
PUSHR blink
|
||||
push_s blink
|
||||
jl sys_trace_idle
|
||||
POPR blink
|
||||
pop_s blink
|
||||
#endif
|
||||
|
||||
/* z_arc_cpu_sleep_mode is 32 bit despite of platform bittnes */
|
||||
ld r1, [z_arc_cpu_sleep_mode]
|
||||
or r1, r1, (1 << 4) /* set IRQ-enabled bit */
|
||||
/*
|
||||
* It's found that (in nsim_hs_smp), when cpu
|
||||
* is sleeping, no response to inter-processor interrupt
|
||||
* although it's pending and interrupts are enabled.
|
||||
* here is a workround
|
||||
*/
|
||||
#if !defined(CONFIG_SOC_NSIM) && !defined(CONFIG_SMP)
|
||||
sleep r1
|
||||
#else
|
||||
seti r1
|
||||
_z_arc_idle_loop:
|
||||
b _z_arc_idle_loop
|
||||
#endif
|
||||
j_s [blink]
|
||||
nop
|
||||
|
||||
@@ -59,12 +69,11 @@ SECTION_FUNC(TEXT, arch_cpu_idle)
|
||||
SECTION_FUNC(TEXT, arch_cpu_atomic_idle)
|
||||
|
||||
#ifdef CONFIG_TRACING
|
||||
PUSHR blink
|
||||
push_s blink
|
||||
jl sys_trace_idle
|
||||
POPR blink
|
||||
pop_s blink
|
||||
#endif
|
||||
|
||||
/* z_arc_cpu_sleep_mode is 32 bit despite of platform bittnes */
|
||||
ld r1, [z_arc_cpu_sleep_mode]
|
||||
or r1, r1, (1 << 4) /* set IRQ-enabled bit */
|
||||
sleep r1
|
||||
|
||||
@@ -24,6 +24,7 @@ GTEXT(_firq_enter)
|
||||
GTEXT(_firq_exit)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Work to be done before handing control to a FIRQ ISR
|
||||
*
|
||||
* The processor switches to a second register bank so registers from the
|
||||
@@ -40,6 +41,8 @@ GTEXT(_firq_exit)
|
||||
* interrupt. An exception, however, can be taken.
|
||||
*
|
||||
* Assumption by _isr_demux: r3 is untouched by _firq_enter.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _firq_enter)
|
||||
@@ -123,12 +126,15 @@ firq_nest_1:
|
||||
firq_nest:
|
||||
#endif
|
||||
push_s r0
|
||||
j _isr_demux
|
||||
j @_isr_demux
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Work to be done exiting a FIRQ
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _firq_exit)
|
||||
@@ -143,24 +149,30 @@ SECTION_FUNC(TEXT, _firq_exit)
|
||||
|
||||
_check_nest_int_by_irq_act r0, r1
|
||||
|
||||
jne _firq_no_switch
|
||||
jne _firq_no_reschedule
|
||||
|
||||
/* sp is struct k_thread **old of z_arc_switch_in_isr
|
||||
* which is a wrapper of z_get_next_switch_handle.
|
||||
* r0 contains the 1st thread in ready queue. if
|
||||
* it equals _current(r2) ,then do swap, or no swap.
|
||||
*/
|
||||
_get_next_switch_handle
|
||||
#ifdef CONFIG_STACK_SENTINEL
|
||||
bl z_check_stack_sentinel
|
||||
#endif
|
||||
|
||||
cmp r0, r2
|
||||
bne _firq_switch
|
||||
#ifdef CONFIG_SMP
|
||||
bl z_arc_smp_switch_in_isr
|
||||
/* r0 points to new thread, r1 points to old thread */
|
||||
brne r0, 0, _firq_reschedule
|
||||
#else
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
/* fall to no switch */
|
||||
/* Check if the current thread (in r2) is the cached thread */
|
||||
ld_s r0, [r1, _kernel_offset_to_ready_q_cache]
|
||||
brne r0, r2, _firq_reschedule
|
||||
#endif
|
||||
/* fall to no rescheduling */
|
||||
|
||||
.align 4
|
||||
_firq_no_switch:
|
||||
/* restore interrupted context' sp */
|
||||
.balign 4
|
||||
_firq_no_reschedule:
|
||||
pop sp
|
||||
|
||||
/*
|
||||
* Keeping this code block close to those that use it allows using brxx
|
||||
* instruction instead of a pair of cmp and bxx
|
||||
@@ -170,20 +182,20 @@ _firq_no_switch:
|
||||
#endif
|
||||
rtie
|
||||
|
||||
.align 4
|
||||
_firq_switch:
|
||||
/* restore interrupted context' sp */
|
||||
.balign 4
|
||||
_firq_reschedule:
|
||||
pop sp
|
||||
|
||||
#if CONFIG_RGF_NUM_BANKS != 1
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* save r0, r2 in irq stack for a while, as they will be changed by register
|
||||
* save r0, r1 in irq stack for a while, as they will be changed by register
|
||||
* bank switch
|
||||
*/
|
||||
_get_curr_cpu_irq_stack r1
|
||||
st r0, [r1, -4]
|
||||
st r2, [r1, -8]
|
||||
|
||||
_get_curr_cpu_irq_stack r2
|
||||
st r0, [r2, -4]
|
||||
st r1, [r2, -8]
|
||||
#endif
|
||||
/*
|
||||
* We know there is no interrupted interrupt of lower priority at this
|
||||
* point, so when switching back to register bank 0, it will contain the
|
||||
@@ -231,56 +243,101 @@ _firq_create_irq_stack_frame:
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
|
||||
st ilink, [sp, ___isf_t_pc_OFFSET] /* ilink into pc */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/*
|
||||
* load r0, r2 from irq stack
|
||||
* load r0, r1 from irq stack
|
||||
*/
|
||||
_get_curr_cpu_irq_stack r1
|
||||
ld r0, [r1, -4]
|
||||
ld r2, [r1, -8]
|
||||
_get_curr_cpu_irq_stack r2
|
||||
ld r0, [r2, -4]
|
||||
ld r1, [r2, -8]
|
||||
#endif
|
||||
/* r2 is old thread */
|
||||
_irq_store_old_thread_callee_regs
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* need to remember the user/kernel status of interrupted thread, will be
|
||||
* restored when thread switched back
|
||||
*/
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
and r3, r3, 0x80000000
|
||||
push_s r3
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
mov_s r2, r1
|
||||
#else
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
_save_callee_saved_regs
|
||||
|
||||
st _CAUSE_FIRQ, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
/* mov new thread (r0) to r2 */
|
||||
#ifdef CONFIG_SMP
|
||||
mov_s r2, r0
|
||||
#else
|
||||
ld_s r2, [r1, _kernel_offset_to_ready_q_cache]
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
|
||||
mov r2, r0
|
||||
_load_new_thread_callee_regs
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
_load_stack_check_regs
|
||||
#endif
|
||||
/*
|
||||
* _load_callee_saved_regs expects incoming thread in r2.
|
||||
* _load_callee_saved_regs restores the stack pointer.
|
||||
*/
|
||||
_load_callee_saved_regs
|
||||
|
||||
breq r3, _CAUSE_RIRQ, _firq_switch_from_rirq
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
push_s r2
|
||||
mov_s r0, r2
|
||||
bl configure_mpu_thread
|
||||
pop_s r2
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* see comments in regular_irq.S
|
||||
*/
|
||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
bclr r0, r0, 31
|
||||
sr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
ld r3, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
breq r3, _CAUSE_RIRQ, _firq_return_from_rirq
|
||||
nop_s
|
||||
breq r3, _CAUSE_FIRQ, _firq_switch_from_firq
|
||||
breq r3, _CAUSE_FIRQ, _firq_return_from_firq
|
||||
nop_s
|
||||
|
||||
/* fall through */
|
||||
|
||||
.align 4
|
||||
_firq_switch_from_coop:
|
||||
|
||||
_set_misc_regs_irq_switch_from_coop
|
||||
|
||||
.balign 4
|
||||
_firq_return_from_coop:
|
||||
/* pc into ilink */
|
||||
pop_s r0
|
||||
mov ilink, r0
|
||||
mov_s ilink, r0
|
||||
|
||||
pop_s r0 /* status32 into r0 */
|
||||
sr r0, [_ARC_V2_STATUS32_P0]
|
||||
|
||||
#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING
|
||||
push_s blink
|
||||
|
||||
bl z_thread_mark_switched_in
|
||||
|
||||
pop_s blink
|
||||
#endif
|
||||
rtie
|
||||
|
||||
.align 4
|
||||
_firq_switch_from_rirq:
|
||||
_firq_switch_from_firq:
|
||||
.balign 4
|
||||
_firq_return_from_rirq:
|
||||
_firq_return_from_firq:
|
||||
|
||||
_set_misc_regs_irq_switch_from_irq
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* need to recover the user/kernel status of interrupted thread
|
||||
*/
|
||||
pop_s r3
|
||||
lr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
or r2, r2, r3
|
||||
sr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
|
||||
_pop_irq_stack_frame
|
||||
|
||||
@@ -288,12 +345,5 @@ _firq_switch_from_firq:
|
||||
sr ilink, [_ARC_V2_STATUS32_P0]
|
||||
ld ilink, [sp, -8] /* pc into ilink */
|
||||
|
||||
#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING
|
||||
push_s blink
|
||||
|
||||
bl z_thread_mark_switched_in
|
||||
|
||||
pop_s blink
|
||||
#endif
|
||||
/* LP registers are already restored, just switch back to bank 0 */
|
||||
rtie
|
||||
|
||||
@@ -16,47 +16,21 @@
|
||||
#include <offsets_short.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <logging/log.h>
|
||||
#include <kernel_arch_data.h>
|
||||
#include <arch/arc/v2/exc.h>
|
||||
|
||||
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
|
||||
|
||||
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
|
||||
static void dump_arc_esf(const z_arch_esf_t *esf)
|
||||
{
|
||||
LOG_ERR(" r0: 0x%" PRIxPTR " r1: 0x%" PRIxPTR " r2: 0x%" PRIxPTR " r3: 0x%" PRIxPTR "",
|
||||
esf->r0, esf->r1, esf->r2, esf->r3);
|
||||
LOG_ERR(" r4: 0x%" PRIxPTR " r5: 0x%" PRIxPTR " r6: 0x%" PRIxPTR " r7: 0x%" PRIxPTR "",
|
||||
esf->r4, esf->r5, esf->r6, esf->r7);
|
||||
LOG_ERR(" r8: 0x%" PRIxPTR " r9: 0x%" PRIxPTR " r10: 0x%" PRIxPTR " r11: 0x%" PRIxPTR "",
|
||||
esf->r8, esf->r9, esf->r10, esf->r11);
|
||||
LOG_ERR("r12: 0x%" PRIxPTR " r13: 0x%" PRIxPTR " pc: 0x%" PRIxPTR "",
|
||||
esf->r12, esf->r13, esf->pc);
|
||||
LOG_ERR(" blink: 0x%" PRIxPTR " status32: 0x%" PRIxPTR "", esf->blink, esf->status32);
|
||||
#ifdef CONFIG_ARC_HAS_ZOL
|
||||
LOG_ERR("lp_end: 0x%" PRIxPTR " lp_start: 0x%" PRIxPTR " lp_count: 0x%" PRIxPTR "",
|
||||
esf->lp_end, esf->lp_start, esf->lp_count);
|
||||
#endif /* CONFIG_ARC_HAS_ZOL */
|
||||
}
|
||||
#endif
|
||||
LOG_MODULE_DECLARE(os);
|
||||
|
||||
void z_arc_fatal_error(unsigned int reason, const z_arch_esf_t *esf)
|
||||
{
|
||||
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
|
||||
if (esf != NULL) {
|
||||
dump_arc_esf(esf);
|
||||
if (reason == K_ERR_CPU_EXCEPTION) {
|
||||
LOG_ERR("Faulting instruction address = 0x%lx",
|
||||
z_arc_v2_aux_reg_read(_ARC_V2_ERET));
|
||||
}
|
||||
#endif /* CONFIG_ARC_EXCEPTION_DEBUG */
|
||||
|
||||
z_fatal_error(reason, esf);
|
||||
}
|
||||
|
||||
FUNC_NORETURN void arch_syscall_oops(void *ssf_ptr)
|
||||
{
|
||||
/* TODO: convert ssf_ptr contents into an esf, they are not the same */
|
||||
ARG_UNUSED(ssf_ptr);
|
||||
|
||||
z_arc_fatal_error(K_ERR_KERNEL_OOPS, NULL);
|
||||
z_arc_fatal_error(K_ERR_KERNEL_OOPS, ssf_ptr);
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <kernel_structs.h>
|
||||
#include <exc_handle.h>
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
|
||||
LOG_MODULE_DECLARE(os);
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
Z_EXC_DECLARE(z_arc_user_string_nlen);
|
||||
@@ -31,74 +31,95 @@ static const struct z_exc_handle exceptions[] = {
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
|
||||
#define IS_MPU_GUARD_VIOLATION(guard_start, fault_addr, stack_ptr) \
|
||||
((fault_addr >= guard_start) && \
|
||||
(fault_addr < (guard_start + STACK_GUARD_SIZE)) && \
|
||||
(stack_ptr <= (guard_start + STACK_GUARD_SIZE)))
|
||||
|
||||
/**
|
||||
* @brief Assess occurrence of current thread's stack corruption
|
||||
*
|
||||
* This function performs an assessment whether a memory fault (on a given
|
||||
* memory address) is the result of a stack overflow of the current thread.
|
||||
* This function performs an assessment whether a memory fault (on a
|
||||
* given memory address) is the result of stack memory corruption of
|
||||
* the current thread.
|
||||
*
|
||||
* When called, we know at this point that we received an ARC
|
||||
* protection violation, with any cause code, with the protection access
|
||||
* error either "MPU" or "Secure MPU". In other words, an MPU fault of
|
||||
* some kind. Need to determine whether this is a general MPU access
|
||||
* exception or the specific case of a stack overflow.
|
||||
* Thread stack corruption for supervisor threads or user threads in
|
||||
* privilege mode (when User Space is supported) is reported upon an
|
||||
* attempt to access the stack guard area (if MPU Stack Guard feature
|
||||
* is supported). Additionally the current thread stack pointer
|
||||
* must be pointing inside or below the guard area.
|
||||
*
|
||||
* Thread stack corruption for user threads in user mode is reported,
|
||||
* if the current stack pointer is pointing below the start of the current
|
||||
* thread's stack.
|
||||
*
|
||||
* Notes:
|
||||
* - we assume a fully descending stack,
|
||||
* - we assume a stacking error has occurred,
|
||||
* - the function shall be called when handling MPU privilege violation
|
||||
*
|
||||
* If stack corruption is detected, the function returns the lowest
|
||||
* allowed address where the Stack Pointer can safely point to, to
|
||||
* prevent from errors when un-stacking the corrupted stack frame
|
||||
* upon exception return.
|
||||
*
|
||||
* @param fault_addr memory address on which memory access violation
|
||||
* has been reported.
|
||||
* @param sp stack pointer when exception comes out
|
||||
* @retval True if this appears to be a stack overflow
|
||||
* @retval False if this does not appear to be a stack overflow
|
||||
*
|
||||
* @return The lowest allowed stack frame pointer, if error is a
|
||||
* thread stack corruption, otherwise return 0.
|
||||
*/
|
||||
static bool z_check_thread_stack_fail(const uint32_t fault_addr, uint32_t sp)
|
||||
static u32_t z_check_thread_stack_fail(const u32_t fault_addr, u32_t sp)
|
||||
{
|
||||
const struct k_thread *thread = _current;
|
||||
uint32_t guard_end, guard_start;
|
||||
|
||||
if (!thread) {
|
||||
/* TODO: Under what circumstances could we get here ? */
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
if ((thread->base.user_options & K_USER) != 0) {
|
||||
if ((z_arc_v2_aux_reg_read(_ARC_V2_ERSTATUS) &
|
||||
_ARC_V2_STATUS32_U) != 0) {
|
||||
/* Normal user mode context. There is no specific
|
||||
* "guard" installed in this case, instead what's
|
||||
* happening is that the stack pointer is crashing
|
||||
* into the privilege mode stack buffer which
|
||||
* immediately precededs it.
|
||||
*/
|
||||
guard_end = thread->stack_info.start;
|
||||
guard_start = (uint32_t)thread->stack_obj;
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
if (thread->arch.priv_stack_start) {
|
||||
/* User thread */
|
||||
if (z_arc_v2_aux_reg_read(_ARC_V2_ERSTATUS)
|
||||
& _ARC_V2_STATUS32_U) {
|
||||
/* Thread's user stack corruption */
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
sp = z_arc_v2_aux_reg_read(_ARC_V2_SEC_U_SP);
|
||||
#else
|
||||
sp = z_arc_v2_aux_reg_read(_ARC_V2_USER_SP);
|
||||
#endif
|
||||
if (sp <= (u32_t)thread->stack_obj) {
|
||||
return (u32_t)thread->stack_obj;
|
||||
}
|
||||
} else {
|
||||
/* Special case: handling a syscall on privilege stack.
|
||||
* There is guard memory reserved immediately before
|
||||
* it.
|
||||
*/
|
||||
guard_end = thread->arch.priv_stack_start;
|
||||
guard_start = guard_end - Z_ARC_STACK_GUARD_SIZE;
|
||||
/* User thread in privilege mode */
|
||||
if (IS_MPU_GUARD_VIOLATION(
|
||||
thread->arch.priv_stack_start - STACK_GUARD_SIZE,
|
||||
fault_addr, sp)) {
|
||||
/* Thread's privilege stack corruption */
|
||||
return thread->arch.priv_stack_start;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
{
|
||||
} else {
|
||||
/* Supervisor thread */
|
||||
guard_end = thread->stack_info.start;
|
||||
guard_start = guard_end - Z_ARC_STACK_GUARD_SIZE;
|
||||
if (IS_MPU_GUARD_VIOLATION((u32_t)thread->stack_obj,
|
||||
fault_addr, sp)) {
|
||||
/* Supervisor thread stack corruption */
|
||||
return (u32_t)thread->stack_obj + STACK_GUARD_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
/* treat any MPU exceptions within the guard region as a stack
|
||||
* overflow.As some instrustions
|
||||
* (like enter_s {r13-r26, fp, blink}) push a collection of
|
||||
* registers on to the stack. In this situation, the fault_addr
|
||||
* will less than guard_end, but sp will greater than guard_end.
|
||||
*/
|
||||
if (fault_addr < guard_end && fault_addr >= guard_start) {
|
||||
return true;
|
||||
#else /* CONFIG_USERSPACE */
|
||||
if (IS_MPU_GUARD_VIOLATION(thread->stack_info.start,
|
||||
fault_addr, sp)) {
|
||||
/* Thread stack corruption */
|
||||
return thread->stack_info.start + STACK_GUARD_SIZE;
|
||||
}
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_EXCEPTION_DEBUG
|
||||
@@ -108,7 +129,7 @@ static bool z_check_thread_stack_fail(const uint32_t fault_addr, uint32_t sp)
|
||||
* These codes and parameters do not have associated* names in
|
||||
* the technical manual, just switch on the values in Table 6-5
|
||||
*/
|
||||
static const char *get_protv_access_err(uint32_t parameter)
|
||||
static const char *get_protv_access_err(u32_t parameter)
|
||||
{
|
||||
switch (parameter) {
|
||||
case 0x1:
|
||||
@@ -130,7 +151,7 @@ static const char *get_protv_access_err(uint32_t parameter)
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_protv_exception(uint32_t cause, uint32_t parameter)
|
||||
static void dump_protv_exception(u32_t cause, u32_t parameter)
|
||||
{
|
||||
switch (cause) {
|
||||
case 0x0:
|
||||
@@ -164,7 +185,7 @@ static void dump_protv_exception(uint32_t cause, uint32_t parameter)
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_machine_check_exception(uint32_t cause, uint32_t parameter)
|
||||
static void dump_machine_check_exception(u32_t cause, u32_t parameter)
|
||||
{
|
||||
switch (cause) {
|
||||
case 0x0:
|
||||
@@ -212,7 +233,7 @@ static void dump_machine_check_exception(uint32_t cause, uint32_t parameter)
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_privilege_exception(uint32_t cause, uint32_t parameter)
|
||||
static void dump_privilege_exception(u32_t cause, u32_t parameter)
|
||||
{
|
||||
switch (cause) {
|
||||
case 0x0:
|
||||
@@ -268,7 +289,7 @@ static void dump_privilege_exception(uint32_t cause, uint32_t parameter)
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_exception_info(uint32_t vector, uint32_t cause, uint32_t parameter)
|
||||
static void dump_exception_info(u32_t vector, u32_t cause, u32_t parameter)
|
||||
{
|
||||
if (vector >= 0x10 && vector <= 0xFF) {
|
||||
LOG_ERR("interrupt %u", vector);
|
||||
@@ -342,19 +363,19 @@ static void dump_exception_info(uint32_t vector, uint32_t cause, uint32_t parame
|
||||
* invokes the user provided routine k_sys_fatal_error_handler() which is
|
||||
* responsible for implementing the error handling policy.
|
||||
*/
|
||||
void _Fault(z_arch_esf_t *esf, uint32_t old_sp)
|
||||
void _Fault(z_arch_esf_t *esf, u32_t old_sp)
|
||||
{
|
||||
uint32_t vector, cause, parameter;
|
||||
uint32_t exc_addr = z_arc_v2_aux_reg_read(_ARC_V2_EFA);
|
||||
uint32_t ecr = z_arc_v2_aux_reg_read(_ARC_V2_ECR);
|
||||
u32_t vector, cause, parameter;
|
||||
u32_t exc_addr = z_arc_v2_aux_reg_read(_ARC_V2_EFA);
|
||||
u32_t ecr = z_arc_v2_aux_reg_read(_ARC_V2_ECR);
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
for (int i = 0; i < ARRAY_SIZE(exceptions); i++) {
|
||||
uint32_t start = (uint32_t)exceptions[i].start;
|
||||
uint32_t end = (uint32_t)exceptions[i].end;
|
||||
u32_t start = (u32_t)exceptions[i].start;
|
||||
u32_t end = (u32_t)exceptions[i].end;
|
||||
|
||||
if (esf->pc >= start && esf->pc < end) {
|
||||
esf->pc = (uint32_t)(exceptions[i].fixup);
|
||||
esf->pc = (u32_t)(exceptions[i].fixup);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
#include <arch/cpu.h>
|
||||
#include <swap_macros.h>
|
||||
#include <syscall.h>
|
||||
#include <arch/arc/asm-compat/assembler.h>
|
||||
|
||||
GTEXT(_Fault)
|
||||
GTEXT(z_do_kernel_oops)
|
||||
GTEXT(__reset)
|
||||
GTEXT(__memory_error)
|
||||
GTEXT(__instruction_error)
|
||||
@@ -38,17 +38,6 @@ GTEXT(__ev_maligned)
|
||||
GTEXT(z_irq_do_offload);
|
||||
#endif
|
||||
|
||||
.macro _save_exc_regs_into_stack
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/* ERSEC_STAT is IOW/RAZ in normal mode */
|
||||
lr r0,[_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
LRR r0, [_ARC_V2_ERET]
|
||||
STR r0, sp, ___isf_t_pc_OFFSET
|
||||
LRR r0, [_ARC_V2_ERSTATUS]
|
||||
STR r0, sp, ___isf_t_status32_OFFSET
|
||||
.endm
|
||||
|
||||
/*
|
||||
* The exception handling will use top part of interrupt stack to
|
||||
@@ -85,9 +74,9 @@ _exc_entry:
|
||||
* and exception is raised, then here it's guaranteed that
|
||||
* exception handling has necessary stack to use
|
||||
*/
|
||||
MOVR ilink, sp
|
||||
mov_s ilink, sp
|
||||
_get_curr_cpu_irq_stack sp
|
||||
SUBR sp, sp, (CONFIG_ISR_STACK_SIZE - CONFIG_ARC_EXCEPTION_STACK_SIZE)
|
||||
sub sp, sp, (CONFIG_ISR_STACK_SIZE - CONFIG_ARC_EXCEPTION_STACK_SIZE)
|
||||
|
||||
/*
|
||||
* save caller saved registers
|
||||
@@ -100,12 +89,20 @@ _exc_entry:
|
||||
*/
|
||||
_create_irq_stack_frame
|
||||
|
||||
_save_exc_regs_into_stack
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
/* ERSEC_STAT is IOW/RAZ in normal mode */
|
||||
lr r0,[_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
lr r0,[_ARC_V2_ERSTATUS]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
lr r0,[_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
|
||||
/* sp is parameter of _Fault */
|
||||
MOVR r0, sp
|
||||
mov_s r0, sp
|
||||
/* ilink is the thread's original sp */
|
||||
MOVR r1, ilink
|
||||
mov_s r1, ilink
|
||||
jl _Fault
|
||||
|
||||
_exc_return:
|
||||
@@ -117,11 +114,21 @@ _exc_return:
|
||||
* exception comes out, thread context?irq_context?nest irq context?
|
||||
*/
|
||||
|
||||
_get_next_switch_handle
|
||||
#ifdef CONFIG_SMP
|
||||
bl z_arc_smp_switch_in_isr
|
||||
breq r0, 0, _exc_return_from_exc
|
||||
mov_s r2, r0
|
||||
#else
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
BREQR r0, r2, _exc_return_from_exc
|
||||
/* check if the current thread needs to be rescheduled */
|
||||
ld_s r0, [r1, _kernel_offset_to_ready_q_cache]
|
||||
breq r0, r2, _exc_return_from_exc
|
||||
|
||||
MOVR r2, r0
|
||||
ld_s r2, [r1, _kernel_offset_to_ready_q_cache]
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/*
|
||||
@@ -144,10 +151,10 @@ _exc_return:
|
||||
/* save r2 in ilink because of the possible following reg
|
||||
* bank switch
|
||||
*/
|
||||
mov ilink, r2
|
||||
mov_s ilink, r2
|
||||
#endif
|
||||
LRR r3, [_ARC_V2_STATUS32]
|
||||
ANDR r3, r3, (~(_ARC_V2_STATUS32_AE | _ARC_V2_STATUS32_RB(7)))
|
||||
lr r3, [_ARC_V2_STATUS32]
|
||||
and r3,r3,(~(_ARC_V2_STATUS32_AE | _ARC_V2_STATUS32_RB(7)))
|
||||
kflag r3
|
||||
/* pretend lowest priority interrupt happened to use common handler
|
||||
* if exception is raised in irq, i.e., _ARC_V2_AUX_IRQ_ACT !=0,
|
||||
@@ -159,7 +166,7 @@ _exc_return:
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
mov_s r3, (1 << (ARC_N_IRQ_START_LEVEL - 1))
|
||||
#else
|
||||
MOVR r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
mov_s r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
@@ -170,37 +177,34 @@ _exc_return:
|
||||
sjli SJLI_CALL_ARC_SECURE
|
||||
pop_s r2
|
||||
#else
|
||||
SRR r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARC_FIRQ) && CONFIG_RGF_NUM_BANKS != 1
|
||||
mov r2, ilink
|
||||
#endif
|
||||
|
||||
/* Assumption: r2 has next thread */
|
||||
b _rirq_newthread_switch
|
||||
/* Assumption: r2 has current thread */
|
||||
b _rirq_common_interrupt_swap
|
||||
|
||||
_exc_return_from_exc:
|
||||
/* exception handler may change return address.
|
||||
* reload it
|
||||
*/
|
||||
LDR r0, sp, ___isf_t_pc_OFFSET
|
||||
SRR r0, [_ARC_V2_ERET]
|
||||
ld_s r0, [sp, ___isf_t_pc_OFFSET]
|
||||
sr r0, [_ARC_V2_ERET]
|
||||
|
||||
_pop_irq_stack_frame
|
||||
MOVR sp, ilink
|
||||
mov_s sp, ilink
|
||||
rtie
|
||||
|
||||
/* separated entry for trap which may be used by irq_offload, USERPSACE */
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT,__fault,__ev_trap)
|
||||
/* get the id of trap_s */
|
||||
LRR ilink, [_ARC_V2_ECR]
|
||||
ANDR ilink, ilink, 0x3f
|
||||
lr ilink, [_ARC_V2_ECR]
|
||||
and ilink, ilink, 0x3f
|
||||
#ifdef CONFIG_USERSPACE
|
||||
cmp ilink, _TRAP_S_CALL_SYSTEM_CALL
|
||||
bne _do_non_syscall_trap
|
||||
/* do sys_call */
|
||||
mov ilink, K_SYSCALL_LIMIT
|
||||
mov_s ilink, K_SYSCALL_LIMIT
|
||||
cmp r6, ilink
|
||||
blo valid_syscall_id
|
||||
|
||||
@@ -214,12 +218,15 @@ valid_syscall_id:
|
||||
*/
|
||||
_create_irq_stack_frame
|
||||
|
||||
_save_exc_regs_into_stack
|
||||
|
||||
/* exc return and do sys call in kernel mode,
|
||||
* so need to clear U bit, r0 is already loaded
|
||||
* with ERSTATUS in _save_exc_regs_into_stack
|
||||
*/
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* ERSEC_STAT is IOW/RAZ in normal mode */
|
||||
lr r0, [_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
lr r0,[_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
lr r0,[_ARC_V2_ERSTATUS]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
|
||||
bclr r0, r0, _ARC_V2_STATUS32_U_BIT
|
||||
sr r0, [_ARC_V2_ERSTATUS]
|
||||
@@ -237,32 +244,38 @@ _do_non_syscall_trap:
|
||||
* so its entry is different with normal exception handling, it is
|
||||
* handled in isr stack
|
||||
*/
|
||||
CMPR ilink, _TRAP_S_SCALL_IRQ_OFFLOAD
|
||||
cmp ilink, _TRAP_S_SCALL_IRQ_OFFLOAD
|
||||
bne _exc_entry
|
||||
/* save caller saved registers */
|
||||
_create_irq_stack_frame
|
||||
|
||||
_save_exc_regs_into_stack
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
lr r0,[_ARC_V2_ERSEC_STAT]
|
||||
st_s r0, [sp, ___isf_t_sec_stat_OFFSET]
|
||||
#endif
|
||||
lr r0,[_ARC_V2_ERSTATUS]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
lr r0,[_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET] /* eret into pc */
|
||||
|
||||
|
||||
/* check whether irq stack is used */
|
||||
_check_and_inc_int_nest_counter r0, r1
|
||||
|
||||
bne.d exc_nest_handle
|
||||
MOVR r0, sp
|
||||
mov_s r0, sp
|
||||
|
||||
_get_curr_cpu_irq_stack sp
|
||||
exc_nest_handle:
|
||||
PUSHR r0
|
||||
push_s r0
|
||||
|
||||
jl z_irq_do_offload
|
||||
|
||||
POPR sp
|
||||
pop sp
|
||||
|
||||
_dec_int_nest_counter r0, r1
|
||||
|
||||
_pop_irq_stack_frame
|
||||
|
||||
/* ERSTATUS, ERET are not changed, so ok to rtie */
|
||||
rtie
|
||||
#endif /* CONFIG_IRQ_OFFLOAD */
|
||||
b _exc_entry
|
||||
|
||||
@@ -32,78 +32,90 @@
|
||||
*/
|
||||
#if defined(CONFIG_ARC_FIRQ_STACK)
|
||||
#if defined(CONFIG_SMP)
|
||||
K_KERNEL_STACK_ARRAY_DEFINE(_firq_interrupt_stack, CONFIG_MP_NUM_CPUS,
|
||||
K_THREAD_STACK_ARRAY_DEFINE(_firq_interrupt_stack, CONFIG_MP_NUM_CPUS,
|
||||
CONFIG_ARC_FIRQ_STACK_SIZE);
|
||||
#else
|
||||
K_KERNEL_STACK_DEFINE(_firq_interrupt_stack, CONFIG_ARC_FIRQ_STACK_SIZE);
|
||||
K_THREAD_STACK_DEFINE(_firq_interrupt_stack, CONFIG_ARC_FIRQ_STACK_SIZE);
|
||||
#endif
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Set the stack pointer for firq handling
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void z_arc_firq_stack_set(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
char *firq_sp = Z_KERNEL_STACK_BUFFER(
|
||||
char *firq_sp = Z_THREAD_STACK_BUFFER(
|
||||
_firq_interrupt_stack[z_arc_v2_core_id()]) +
|
||||
CONFIG_ARC_FIRQ_STACK_SIZE;
|
||||
#else
|
||||
char *firq_sp = Z_KERNEL_STACK_BUFFER(_firq_interrupt_stack) +
|
||||
char *firq_sp = Z_THREAD_STACK_BUFFER(_firq_interrupt_stack) +
|
||||
CONFIG_ARC_FIRQ_STACK_SIZE;
|
||||
#endif
|
||||
|
||||
/* the z_arc_firq_stack_set must be called when irq diasbled, as
|
||||
* it can be called not only in the init phase but also other places
|
||||
*/
|
||||
unsigned int key = arch_irq_lock();
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
__asm__ volatile (
|
||||
/* only ilink will not be banked, so use ilink as channel
|
||||
* between 2 banks
|
||||
*/
|
||||
"mov %%ilink, %0\n\t"
|
||||
"lr %0, [%1]\n\t"
|
||||
"or %0, %0, %2\n\t"
|
||||
"kflag %0\n\t"
|
||||
"mov %%sp, %%ilink\n\t"
|
||||
"mov ilink, %0 \n\t"
|
||||
"lr %0, [%1] \n\t"
|
||||
"or %0, %0, %2 \n\t"
|
||||
"kflag %0 \n\t"
|
||||
"mov sp, ilink \n\t"
|
||||
/* switch back to bank0, use ilink to avoid the pollution of
|
||||
* bank1's gp regs.
|
||||
*/
|
||||
"lr %%ilink, [%1]\n\t"
|
||||
"and %%ilink, %%ilink, %3\n\t"
|
||||
"kflag %%ilink\n\t"
|
||||
"lr ilink, [%1] \n\t"
|
||||
"and ilink, ilink, %3 \n\t"
|
||||
"kflag ilink \n\t"
|
||||
:
|
||||
: "r"(firq_sp), "i"(_ARC_V2_STATUS32),
|
||||
"i"(_ARC_V2_STATUS32_RB(1)),
|
||||
"i"(~_ARC_V2_STATUS32_RB(7))
|
||||
);
|
||||
arch_irq_unlock(key);
|
||||
irq_unlock(key);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Enable an interrupt line
|
||||
*
|
||||
* Clear possible pending interrupts on the line, and enable the interrupt
|
||||
* line. After this call, the CPU will receive interrupts for the specified
|
||||
* @a irq.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void arch_irq_enable(unsigned int irq)
|
||||
{
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
z_arc_v2_irq_unit_int_enable(irq);
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Disable an interrupt line
|
||||
*
|
||||
* Disable an interrupt line. After this call, the CPU will stop receiving
|
||||
* interrupts for the specified @a irq.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void arch_irq_disable(unsigned int irq)
|
||||
{
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
z_arc_v2_irq_unit_int_disable(irq);
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +129,7 @@ int arch_irq_is_enabled(unsigned int irq)
|
||||
return z_arc_v2_irq_unit_int_enabled(irq);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @internal
|
||||
*
|
||||
* @brief Set an interrupt's priority
|
||||
@@ -127,12 +139,16 @@ int arch_irq_is_enabled(unsigned int irq)
|
||||
|
||||
* The priority is verified if ASSERT_ON is enabled; max priority level
|
||||
* depends on CONFIG_NUM_IRQ_PRIO_LEVELS.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void z_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
|
||||
void z_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags)
|
||||
{
|
||||
ARG_UNUSED(flags);
|
||||
|
||||
unsigned int key = irq_lock();
|
||||
|
||||
__ASSERT(prio < CONFIG_NUM_IRQ_PRIO_LEVELS,
|
||||
"invalid priority %d for irq %d", prio, irq);
|
||||
/* 0 -> CONFIG_NUM_IRQ_PRIO_LEVELS allocted to secure world
|
||||
@@ -146,16 +162,19 @@ void z_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags)
|
||||
ARC_N_IRQ_START_LEVEL : prio;
|
||||
#endif
|
||||
z_arc_v2_irq_unit_prio_set(irq, prio);
|
||||
irq_unlock(key);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Spurious interrupt handler
|
||||
*
|
||||
* Installed in all dynamic interrupt slots at boot time. Throws an error if
|
||||
* called.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void z_irq_spurious(const void *unused)
|
||||
void z_irq_spurious(void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
z_fatal_error(K_ERR_SPURIOUS_IRQ, NULL);
|
||||
@@ -163,8 +182,8 @@ void z_irq_spurious(const void *unused)
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_INTERRUPTS
|
||||
int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority,
|
||||
void (*routine)(const void *parameter),
|
||||
const void *parameter, uint32_t flags)
|
||||
void (*routine)(void *parameter), void *parameter,
|
||||
u32_t flags)
|
||||
{
|
||||
z_isr_install(irq, routine, parameter);
|
||||
z_irq_priority_set(irq, priority, flags);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <irq_offload.h>
|
||||
|
||||
static irq_offload_routine_t offload_routine;
|
||||
static const void *offload_param;
|
||||
static void *offload_param;
|
||||
|
||||
/* Called by trap_s exception handler */
|
||||
void z_irq_do_offload(void)
|
||||
@@ -20,7 +20,7 @@ void z_irq_do_offload(void)
|
||||
offload_routine(offload_param);
|
||||
}
|
||||
|
||||
void arch_irq_offload(irq_offload_routine_t routine, const void *parameter)
|
||||
void arch_irq_offload(irq_offload_routine_t routine, void *parameter)
|
||||
{
|
||||
|
||||
offload_routine = routine;
|
||||
|
||||
@@ -20,13 +20,12 @@
|
||||
#include <kernel_structs.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <swap_macros.h>
|
||||
#include <arch/arc/asm-compat/assembler.h>
|
||||
|
||||
GTEXT(_isr_wrapper)
|
||||
GTEXT(_isr_demux)
|
||||
|
||||
#if defined(CONFIG_PM)
|
||||
GTEXT(z_pm_save_idle_exit)
|
||||
#if defined(CONFIG_SYS_POWER_MANAGEMENT)
|
||||
GTEXT(z_sys_power_save_idle_exit)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -36,35 +35,37 @@ _rirq_enter/_firq_enter: they are jump points.
|
||||
The flow is the following:
|
||||
|
||||
ISR -> _isr_wrapper -- + -> _rirq_enter -> _isr_demux -> ISR -> _rirq_exit
|
||||
|
|
||||
+ -> _firq_enter -> _isr_demux -> ISR -> _firq_exit
|
||||
|
|
||||
+ -> _firq_enter -> _isr_demux -> ISR -> _firq_exit
|
||||
|
||||
Context switch explanation:
|
||||
|
||||
The context switch code is spread in these files:
|
||||
|
||||
isr_wrapper.s, switch.s, swap_macros.h, fast_irq.s, regular_irq.s
|
||||
isr_wrapper.s, switch.s, swap_macros.s, fast_irq.s, regular_irq.s
|
||||
|
||||
IRQ stack frame layout:
|
||||
|
||||
high address
|
||||
high address
|
||||
|
||||
status32
|
||||
pc
|
||||
lp_count
|
||||
lp_start
|
||||
lp_end
|
||||
blink
|
||||
r13
|
||||
...
|
||||
sp -> r0
|
||||
status32
|
||||
pc
|
||||
lp_count
|
||||
lp_start
|
||||
lp_end
|
||||
blink
|
||||
r13
|
||||
...
|
||||
sp -> r0
|
||||
|
||||
low address
|
||||
low address
|
||||
|
||||
The context switch code adopts this standard so that it is easier to follow:
|
||||
|
||||
- r2 contains _kernel.current ASAP, and the incoming thread when we
|
||||
transition from outgoing thread to incoming thread
|
||||
- r1 contains _kernel ASAP and is not overwritten over the lifespan of
|
||||
the functions.
|
||||
- r2 contains _kernel.current ASAP, and the incoming thread when we
|
||||
transition from outgoing thread to incoming thread
|
||||
|
||||
Not loading _kernel into r0 allows loading _kernel without stomping on
|
||||
the parameter in r0 in arch_switch().
|
||||
@@ -99,49 +100,47 @@ done upfront, and the rest is done when needed:
|
||||
|
||||
o RIRQ
|
||||
|
||||
All needed registers to run C code in the ISR are saved automatically
|
||||
on the outgoing thread's stack: loop, status32, pc, and the caller-
|
||||
saved GPRs. That stack frame layout is pre-determined. If returning
|
||||
to a thread, the stack is popped and no registers have to be saved by
|
||||
the kernel. If a context switch is required, the callee-saved GPRs
|
||||
are then saved in the thread's stack.
|
||||
All needed registers to run C code in the ISR are saved automatically
|
||||
on the outgoing thread's stack: loop, status32, pc, and the caller-
|
||||
saved GPRs. That stack frame layout is pre-determined. If returning
|
||||
to a thread, the stack is popped and no registers have to be saved by
|
||||
the kernel. If a context switch is required, the callee-saved GPRs
|
||||
are then saved in the thread control structure (TCS).
|
||||
|
||||
o FIRQ
|
||||
|
||||
First, a FIRQ can be interrupting a lower-priority RIRQ: if this is
|
||||
the case, the FIRQ does not take a scheduling decision and leaves it
|
||||
the RIRQ to handle. This limits the amount of code that has to run at
|
||||
interrupt-level.
|
||||
First, a FIRQ can be interrupting a lower-priority RIRQ: if this is the case,
|
||||
the FIRQ does not take a scheduling decision and leaves it the RIRQ to
|
||||
handle. This limits the amount of code that has to run at interrupt-level.
|
||||
|
||||
CONFIG_RGF_NUM_BANKS==1 case:
|
||||
Registers are saved on the stack frame just as they are for RIRQ.
|
||||
Context switch can happen just as it does in the RIRQ case, however,
|
||||
if the FIRQ interrupted a RIRQ, the FIRQ will return from interrupt
|
||||
and let the RIRQ do the context switch. At entry, one register is
|
||||
needed in order to have code to save other registers. r0 is saved
|
||||
first in the stack and restored later
|
||||
CONFIG_RGF_NUM_BANKS==1 case:
|
||||
Registers are saved on the stack frame just as they are for RIRQ.
|
||||
Context switch can happen just as it does in the RIRQ case, however,
|
||||
if the FIRQ interrupted a RIRQ, the FIRQ will return from interrupt and
|
||||
let the RIRQ do the context switch. At entry, one register is needed in order
|
||||
to have code to save other registers. r0 is saved first in a global called
|
||||
saved_r0.
|
||||
|
||||
CONFIG_RGF_NUM_BANKS!=1 case:
|
||||
During early initialization, the sp in the 2nd register bank is made to
|
||||
refer to _firq_stack. This allows for the FIRQ handler to use its own
|
||||
stack. GPRs are banked, loop registers are saved in unused callee saved
|
||||
regs upon interrupt entry. If returning to a thread, loop registers are
|
||||
restored and the CPU switches back to bank 0 for the GPRs. If a context
|
||||
switch is needed, at this point only are all the registers saved.
|
||||
First, a stack frame with the same layout as the automatic RIRQ one is
|
||||
created and then the callee-saved GPRs are saved in the stack.
|
||||
status32_p0 and ilink are saved in this case, not status32 and pc.
|
||||
To create the stack frame, the FIRQ handling code must first go back to
|
||||
using bank0 of registers, since that is where the registers containing
|
||||
the exiting thread are saved. Care must be taken not to touch any
|
||||
register before saving them: the only one usable at that point is the
|
||||
stack pointer.
|
||||
CONFIG_RGF_NUM_BANKS!=1 case:
|
||||
During early initialization, the sp in the 2nd register bank is made to
|
||||
refer to _firq_stack. This allows for the FIRQ handler to use its own stack.
|
||||
GPRs are banked, loop registers are saved in unused callee saved regs upon
|
||||
interrupt entry. If returning to a thread, loop registers are restored and the
|
||||
CPU switches back to bank 0 for the GPRs. If a context switch is
|
||||
needed, at this point only are all the registers saved. First, a
|
||||
stack frame with the same layout as the automatic RIRQ one is created
|
||||
and then the callee-saved GPRs are saved in the TCS. status32_p0 and
|
||||
ilink are saved in this case, not status32 and pc.
|
||||
To create the stack frame, the FIRQ handling code must first go back to using
|
||||
bank0 of registers, since that is where the registers containing the exiting
|
||||
thread are saved. Care must be taken not to touch any register before saving
|
||||
them: the only one usable at that point is the stack pointer.
|
||||
|
||||
o coop
|
||||
|
||||
When a coop context switch is done, the callee-saved registers are
|
||||
saved in the stack. The other GPRs do not need to be saved, since the
|
||||
compiler has already placed them on the stack.
|
||||
When a coop context switch is done, the callee-saved registers are
|
||||
saved in the TCS. The other GPRs do not need to be saved, since the
|
||||
compiler has already placed them on the stack.
|
||||
|
||||
For restoring the contexts, there are six cases. In all cases, the
|
||||
callee-saved registers of the incoming thread have to be restored. Then, there
|
||||
@@ -149,85 +148,86 @@ are specifics for each case:
|
||||
|
||||
From coop:
|
||||
|
||||
o to coop
|
||||
o to coop
|
||||
|
||||
Do a normal function call return.
|
||||
Do a normal function call return.
|
||||
|
||||
o to any irq
|
||||
o to any irq
|
||||
|
||||
The incoming interrupted thread has an IRQ stack frame containing the
|
||||
caller-saved registers that has to be popped. status32 has to be
|
||||
restored, then we jump to the interrupted instruction.
|
||||
The incoming interrupted thread has an IRQ stack frame containing the
|
||||
caller-saved registers that has to be popped. status32 has to be restored,
|
||||
then we jump to the interrupted instruction.
|
||||
|
||||
From FIRQ:
|
||||
|
||||
When CONFIG_RGF_NUM_BANKS==1, context switch is done as it is for RIRQ.
|
||||
When CONFIG_RGF_NUM_BANKS!=1, the processor is put back to using bank0,
|
||||
not bank1 anymore, because it had to save the outgoing context from
|
||||
bank0, and now has to load the incoming one into bank0.
|
||||
When CONFIG_RGF_NUM_BANKS==1, context switch is done as it is for RIRQ.
|
||||
When CONFIG_RGF_NUM_BANKS!=1, the processor is put back to using bank0,
|
||||
not bank1 anymore, because it had to save the outgoing context from bank0,
|
||||
and now has to load the incoming one
|
||||
into bank0.
|
||||
|
||||
o to coop
|
||||
o to coop
|
||||
|
||||
The address of the returning instruction from arch_switch() is loaded
|
||||
in ilink and the saved status32 in status32_p0.
|
||||
The address of the returning instruction from arch_switch() is loaded
|
||||
in ilink and the saved status32 in status32_p0.
|
||||
|
||||
o to any irq
|
||||
o to any irq
|
||||
|
||||
The IRQ has saved the caller-saved registers in a stack frame, which
|
||||
must be popped, and status32 and pc loaded in status32_p0 and ilink.
|
||||
The IRQ has saved the caller-saved registers in a stack frame, which must be
|
||||
popped, and status32 and pc loaded in status32_p0 and ilink.
|
||||
|
||||
From RIRQ:
|
||||
|
||||
o to coop
|
||||
o to coop
|
||||
|
||||
The interrupt return mechanism in the processor expects a stack frame,
|
||||
but the outgoing context did not create one. A fake one is created
|
||||
here, with only the relevant values filled in: pc, status32.
|
||||
The interrupt return mechanism in the processor expects a stack frame, but
|
||||
the outgoing context did not create one. A fake one is created here, with
|
||||
only the relevant values filled in: pc, status32.
|
||||
|
||||
There is a discrepancy between the ABI from the ARCv2 docs,
|
||||
including the way the processor pushes GPRs in pairs in the IRQ stack
|
||||
frame, and the ABI GCC uses. r13 should be a callee-saved register,
|
||||
but GCC treats it as caller-saved. This means that the processor pushes
|
||||
it in the stack frame along with r12, but the compiler does not save it
|
||||
before entering a function. So, it is saved as part of the callee-saved
|
||||
registers, and restored there, but the processor restores it _a second
|
||||
time_ when popping the IRQ stack frame. Thus, the correct value must
|
||||
also be put in the fake stack frame when returning to a thread that
|
||||
context switched out cooperatively.
|
||||
There is a discrepancy between the ABI from the ARCv2 docs, including the
|
||||
way the processor pushes GPRs in pairs in the IRQ stack frame, and the ABI
|
||||
GCC uses. r13 should be a callee-saved register, but GCC treats it as
|
||||
caller-saved. This means that the processor pushes it in the stack frame
|
||||
along with r12, but the compiler does not save it before entering a
|
||||
function. So, it is saved as part of the callee-saved registers, and
|
||||
restored there, but the processor restores it _a second time_ when popping
|
||||
the IRQ stack frame. Thus, the correct value must also be put in the fake
|
||||
stack frame when returning to a thread that context switched out
|
||||
cooperatively.
|
||||
|
||||
o to any irq
|
||||
o to any irq
|
||||
|
||||
Both types of IRQs already have an IRQ stack frame: simply return from
|
||||
interrupt.
|
||||
Both types of IRQs already have an IRQ stack frame: simply return from
|
||||
interrupt.
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _isr_wrapper)
|
||||
#ifdef CONFIG_ARC_FIRQ
|
||||
#if defined(CONFIG_ARC_FIRQ)
|
||||
#if CONFIG_RGF_NUM_BANKS == 1
|
||||
/* free r0 here, use r0 to check whether irq is firq.
|
||||
* for rirq, as sp will not change and r0 already saved, this action
|
||||
* in fact is useless
|
||||
* in fact is an action like nop.
|
||||
* for firq, r0 will be restored later
|
||||
*/
|
||||
push r0
|
||||
st_s r0, [sp]
|
||||
#endif
|
||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
ffs r0, r0
|
||||
cmp r0, 0
|
||||
#if CONFIG_RGF_NUM_BANKS == 1
|
||||
bnz rirq_path
|
||||
pop r0
|
||||
ld_s r0, [sp]
|
||||
/* 1-register bank FIRQ handling must save registers on stack */
|
||||
_create_irq_stack_frame
|
||||
lr r0, [_ARC_V2_STATUS32_P0]
|
||||
st_s r0, [sp, ___isf_t_status32_OFFSET]
|
||||
st ilink, [sp, ___isf_t_pc_OFFSET]
|
||||
lr r0, [_ARC_V2_ERET]
|
||||
st_s r0, [sp, ___isf_t_pc_OFFSET]
|
||||
|
||||
mov_s r3, _firq_exit
|
||||
mov_s r2, _firq_enter
|
||||
j_s [r2]
|
||||
rirq_path:
|
||||
add sp, sp, 4
|
||||
mov_s r3, _rirq_exit
|
||||
mov_s r2, _rirq_enter
|
||||
j_s [r2]
|
||||
@@ -239,50 +239,57 @@ rirq_path:
|
||||
j_s [r2]
|
||||
#endif
|
||||
#else
|
||||
MOVR r3, _rirq_exit
|
||||
MOVR r2, _rirq_enter
|
||||
mov_s r3, _rirq_exit
|
||||
mov_s r2, _rirq_enter
|
||||
j_s [r2]
|
||||
#endif
|
||||
|
||||
/* r0, r1, and r3 will be used in exit_tickless_idle macro */
|
||||
#if defined(CONFIG_TRACING)
|
||||
GTEXT(sys_trace_isr_enter)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SYS_POWER_MANAGEMENT)
|
||||
.macro exit_tickless_idle
|
||||
#if defined(CONFIG_PM)
|
||||
clri r0 /* do not interrupt exiting tickless idle operations */
|
||||
MOVR r1, _kernel
|
||||
breq r3, 0, _skip_pm_save_idle_exit
|
||||
push_s r1
|
||||
push_s r0
|
||||
mov_s r1, _kernel
|
||||
ld_s r0, [r1, _kernel_offset_to_idle] /* requested idle duration */
|
||||
breq r0, 0, _skip_sys_power_save_idle_exit
|
||||
|
||||
st 0, [r1, _kernel_offset_to_idle] /* zero idle duration */
|
||||
PUSHR blink
|
||||
jl z_pm_save_idle_exit
|
||||
POPR blink
|
||||
push_s blink
|
||||
jl z_sys_power_save_idle_exit
|
||||
pop_s blink
|
||||
|
||||
_skip_pm_save_idle_exit:
|
||||
_skip_sys_power_save_idle_exit:
|
||||
pop_s r0
|
||||
pop_s r1
|
||||
seti r0
|
||||
#endif
|
||||
.endm
|
||||
#else
|
||||
#define exit_tickless_idle
|
||||
#endif
|
||||
|
||||
/* when getting here, r3 contains the interrupt exit stub to call */
|
||||
SECTION_FUNC(TEXT, _isr_demux)
|
||||
PUSHR r3
|
||||
push_s r3
|
||||
|
||||
/* according to ARCv2 ISA, r25, r30, r58, r59 are caller-saved
|
||||
* scratch registers, possibly used by interrupt handlers
|
||||
*/
|
||||
PUSHR r25
|
||||
PUSHR r30
|
||||
push r25
|
||||
push r30
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
PUSHR r58
|
||||
PUSHR r59
|
||||
push r58
|
||||
push r59
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SCHED_THREAD_USAGE
|
||||
bl z_sched_usage_stop
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TRACING_ISR
|
||||
bl sys_trace_isr_enter
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
bl read_timer_start_of_isr
|
||||
#endif
|
||||
/* cannot be done before this point because we must be able to run C */
|
||||
/* r0 is available to be stomped here, and exit_tickless_idle uses it */
|
||||
exit_tickless_idle
|
||||
|
||||
lr r0, [_ARC_V2_ICAUSE]
|
||||
@@ -294,30 +301,29 @@ irq_hint_handled:
|
||||
|
||||
sub r0, r0, 16
|
||||
|
||||
MOVR r1, _sw_isr_table
|
||||
/* SW ISR table entries are 8-bytes wide for 32bit ISA and
|
||||
* 16-bytes wide for 64bit ISA */
|
||||
ASLR r0, r0, (ARC_REGSHIFT + 1)
|
||||
ADDR r0, r1, r0
|
||||
/* ISR into r1 */
|
||||
LDR r1, r0, ARC_REGSZ
|
||||
jl_s.d [r1]
|
||||
/* delay slot: ISR parameter into r0 */
|
||||
LDR r0, r0
|
||||
mov_s r1, _sw_isr_table
|
||||
add3 r0, r1, r0 /* table entries are 8-bytes wide */
|
||||
|
||||
#ifdef CONFIG_TRACING_ISR
|
||||
bl sys_trace_isr_exit
|
||||
ld_s r1, [r0, 4] /* ISR into r1 */
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
push_s r0
|
||||
push_s r1
|
||||
bl read_timer_end_of_isr
|
||||
pop_s r1
|
||||
pop_s r0
|
||||
#endif
|
||||
jl_s.d [r1]
|
||||
ld_s r0, [r0] /* delay slot: ISR parameter into r0 */
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
POPR r59
|
||||
POPR r58
|
||||
pop r59
|
||||
pop r58
|
||||
#endif
|
||||
|
||||
POPR r30
|
||||
POPR r25
|
||||
pop r30
|
||||
pop r25
|
||||
|
||||
/* back from ISR, jump to exit stub */
|
||||
POPR r3
|
||||
pop_s r3
|
||||
j_s [r3]
|
||||
nop_s
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_ARC_CORE_MPU arc_core_mpu.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_ARC_MPU arc_mpu.c)
|
||||
zephyr_library_sources_if_kconfig(arc_core_mpu.c)
|
||||
zephyr_library_sources_if_kconfig(arc_mpu.c)
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
|
||||
config ARC_MPU_VER
|
||||
int "ARC MPU version"
|
||||
range 2 6
|
||||
range 2 4
|
||||
default 2
|
||||
help
|
||||
ARC MPU has several versions. For MPU v2, the minimum region is 2048 bytes;
|
||||
For other versions, the minimum region is 32 bytes; v4 has secure features,
|
||||
v6 supports up to 32 regions.
|
||||
For MPU v3, the minimum region is 32 bytes
|
||||
|
||||
config ARC_CORE_MPU
|
||||
bool "ARC Core MPU functionalities"
|
||||
@@ -19,21 +18,16 @@ config ARC_CORE_MPU
|
||||
|
||||
config MPU_STACK_GUARD
|
||||
bool "Thread Stack Guards"
|
||||
depends on ARC_CORE_MPU && ARC_MPU_VER !=2
|
||||
depends on ARC_CORE_MPU
|
||||
help
|
||||
Enable thread stack guards via MPU. ARC supports built-in stack protection.
|
||||
If your core supports that, it is preferred over MPU stack guard.
|
||||
For ARC_MPU_VER == 2, it requires 2048 extra bytes and a strong start address
|
||||
alignment, this will bring big waste of memory, so no support for it.
|
||||
If your core supports that, it is preferred over MPU stack guard
|
||||
|
||||
config ARC_MPU
|
||||
bool "ARC MPU Support"
|
||||
select MPU
|
||||
select SRAM_REGION_PERMISSIONS
|
||||
select ARC_CORE_MPU
|
||||
select THREAD_STACK_INFO
|
||||
select GEN_PRIV_STACKS if ARC_MPU_VER != 4
|
||||
select MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT if ARC_MPU_VER !=4
|
||||
select MPU_REQUIRES_NON_OVERLAPPING_REGIONS if ARC_MPU_VER = 4
|
||||
select MEMORY_PROTECTION
|
||||
select MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT if ARC_MPU_VER = 2
|
||||
help
|
||||
Target has ARC MPU (currently only works for EMSK 2.2/2.3 ARCEM7D)
|
||||
|
||||
@@ -32,6 +32,64 @@ int arch_mem_domain_max_partitions_get(void)
|
||||
return arc_core_mpu_get_max_domain_partition_regions();
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset MPU region for a single memory partition
|
||||
*/
|
||||
void arch_mem_domain_partition_remove(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
{
|
||||
if (_current->mem_domain_info.mem_domain != domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
arc_core_mpu_disable();
|
||||
arc_core_mpu_remove_mem_partition(domain, partition_id);
|
||||
arc_core_mpu_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure MPU memory domain
|
||||
*/
|
||||
void arch_mem_domain_thread_add(struct k_thread *thread)
|
||||
{
|
||||
if (_current != thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
arc_core_mpu_disable();
|
||||
arc_core_mpu_configure_mem_domain(thread);
|
||||
arc_core_mpu_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy MPU regions for the mem domain
|
||||
*/
|
||||
void arch_mem_domain_destroy(struct k_mem_domain *domain)
|
||||
{
|
||||
if (_current->mem_domain_info.mem_domain != domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
arc_core_mpu_disable();
|
||||
arc_core_mpu_remove_mem_domain(domain);
|
||||
arc_core_mpu_enable();
|
||||
}
|
||||
|
||||
void arch_mem_domain_partition_add(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
{
|
||||
/* No-op on this architecture */
|
||||
}
|
||||
|
||||
void arch_mem_domain_thread_remove(struct k_thread *thread)
|
||||
{
|
||||
if (_current != thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
arch_mem_domain_destroy(thread->mem_domain_info.mem_domain);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate the given buffer is user accessible or not
|
||||
*/
|
||||
|
||||
@@ -21,20 +21,20 @@ LOG_MODULE_REGISTER(mpu);
|
||||
* @brief Get the number of supported MPU regions
|
||||
*
|
||||
*/
|
||||
static inline uint8_t get_num_regions(void)
|
||||
static inline u8_t get_num_regions(void)
|
||||
{
|
||||
uint32_t num = z_arc_v2_aux_reg_read(_ARC_V2_MPU_BUILD);
|
||||
u32_t num = z_arc_v2_aux_reg_read(_ARC_V2_MPU_BUILD);
|
||||
|
||||
num = (num & 0xFF00U) >> 8U;
|
||||
|
||||
return (uint8_t)num;
|
||||
return (u8_t)num;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function is utilized by the MPU driver to parse the intent
|
||||
* type (i.e. THREAD_STACK_REGION) and return the correct parameter set.
|
||||
*/
|
||||
static inline uint32_t get_region_attr_by_type(uint32_t type)
|
||||
static inline u32_t get_region_attr_by_type(u32_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case THREAD_STACK_USER_REGION:
|
||||
@@ -52,8 +52,8 @@ static inline uint32_t get_region_attr_by_type(uint32_t type)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_ARC_MPU_VER == 4
|
||||
#include "arc_mpu_v4_internal.h"
|
||||
#else
|
||||
#include "arc_mpu_common_internal.h"
|
||||
#if CONFIG_ARC_MPU_VER == 2
|
||||
#include "arc_mpu_v2_internal.h"
|
||||
#elif CONFIG_ARC_MPU_VER == 3
|
||||
#include "arc_mpu_v3_internal.h"
|
||||
#endif
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_COMMON_INTERNAL_H_
|
||||
#define ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_COMMON_INTERNAL_H_
|
||||
|
||||
#if CONFIG_ARC_MPU_VER == 2 || CONFIG_ARC_MPU_VER == 3
|
||||
#include "arc_mpu_v2_internal.h"
|
||||
#elif CONFIG_ARC_MPU_VER == 6
|
||||
#include "arc_mpu_v6_internal.h"
|
||||
#else
|
||||
#error "Unsupported MPU version"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief configure the base address and size for an MPU region
|
||||
*
|
||||
* @param type MPU region type
|
||||
* @param base base address in RAM
|
||||
* @param size size of the region
|
||||
*/
|
||||
static inline int _mpu_configure(uint8_t type, uint32_t base, uint32_t size)
|
||||
{
|
||||
int32_t region_index = get_region_index_by_type(type);
|
||||
uint32_t region_attr = get_region_attr_by_type(type);
|
||||
|
||||
LOG_DBG("Region info: 0x%x 0x%x", base, size);
|
||||
|
||||
if (region_attr == 0U || region_index < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* For ARC MPU, MPU regions can be overlapped, smaller
|
||||
* region index has higher priority.
|
||||
*/
|
||||
_region_init(region_index, base, size, region_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ARC Core MPU Driver API Implementation for ARC MP */
|
||||
|
||||
/**
|
||||
* @brief enable the MPU
|
||||
*/
|
||||
void arc_core_mpu_enable(void)
|
||||
{
|
||||
/* Enable MPU */
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN,
|
||||
z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) | AUX_MPU_EN_ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief disable the MPU
|
||||
*/
|
||||
void arc_core_mpu_disable(void)
|
||||
{
|
||||
/* Disable MPU */
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN,
|
||||
z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) & AUX_MPU_EN_DISABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the thread's MPU regions
|
||||
*
|
||||
* @param thread the target thread
|
||||
*/
|
||||
void arc_core_mpu_configure_thread(struct k_thread *thread)
|
||||
{
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/* configure stack region of user thread */
|
||||
if (thread->base.user_options & K_USER) {
|
||||
LOG_DBG("configure user thread %p's stack", thread);
|
||||
if (_mpu_configure(THREAD_STACK_USER_REGION,
|
||||
(uint32_t)thread->stack_info.start,
|
||||
thread->stack_info.size) < 0) {
|
||||
LOG_ERR("user thread %p's stack failed", thread);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DBG("configure thread %p's domain", thread);
|
||||
arc_core_mpu_configure_mem_domain(thread);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief configure the default region
|
||||
*
|
||||
* @param region_attr region attribute of default region
|
||||
*/
|
||||
void arc_core_mpu_default(uint32_t region_attr)
|
||||
{
|
||||
uint32_t val = z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) & (~AUX_MPU_RDP_ATTR_MASK);
|
||||
|
||||
region_attr &= AUX_MPU_RDP_ATTR_MASK;
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, region_attr | val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the MPU region
|
||||
*
|
||||
* @param index MPU region index
|
||||
* @param base base address
|
||||
* @param region_attr region attribute
|
||||
*/
|
||||
int arc_core_mpu_region(uint32_t index, uint32_t base, uint32_t size, uint32_t region_attr)
|
||||
{
|
||||
if (index >= get_num_regions()) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
region_attr &= AUX_MPU_RDP_ATTR_MASK;
|
||||
|
||||
_region_init(index, base, size, region_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
|
||||
/**
|
||||
* @brief configure MPU regions for the memory partitions of the memory domain
|
||||
*
|
||||
* @param thread the thread which has memory domain
|
||||
*/
|
||||
void arc_core_mpu_configure_mem_domain(struct k_thread *thread)
|
||||
{
|
||||
int region_index = get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);
|
||||
uint32_t num_partitions;
|
||||
struct k_mem_partition *pparts;
|
||||
struct k_mem_domain *mem_domain = NULL;
|
||||
|
||||
if (thread) {
|
||||
mem_domain = thread->mem_domain_info.mem_domain;
|
||||
}
|
||||
|
||||
if (mem_domain) {
|
||||
LOG_DBG("configure domain: %p", mem_domain);
|
||||
num_partitions = mem_domain->num_partitions;
|
||||
pparts = mem_domain->partitions;
|
||||
} else {
|
||||
LOG_DBG("disable domain partition regions");
|
||||
num_partitions = 0U;
|
||||
pparts = NULL;
|
||||
}
|
||||
|
||||
for (; region_index >= 0; region_index--) {
|
||||
if (num_partitions) {
|
||||
LOG_DBG("set region 0x%x 0x%lx 0x%x",
|
||||
region_index, pparts->start, pparts->size);
|
||||
_region_init(region_index, pparts->start, pparts->size, pparts->attr);
|
||||
num_partitions--;
|
||||
} else {
|
||||
/* clear the left mpu entries */
|
||||
_region_init(region_index, 0, 0, 0);
|
||||
}
|
||||
pparts++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief remove MPU regions for the memory partitions of the memory domain
|
||||
*
|
||||
* @param mem_domain the target memory domain
|
||||
*/
|
||||
void arc_core_mpu_remove_mem_domain(struct k_mem_domain *mem_domain)
|
||||
{
|
||||
ARG_UNUSED(mem_domain);
|
||||
|
||||
int region_index = get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);
|
||||
|
||||
for (; region_index >= 0; region_index--) {
|
||||
_region_init(region_index, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reset MPU region for a single memory partition
|
||||
*
|
||||
* @param domain the target memory domain
|
||||
* @param partition_id memory partition id
|
||||
*/
|
||||
void arc_core_mpu_remove_mem_partition(struct k_mem_domain *domain, uint32_t part_id)
|
||||
{
|
||||
ARG_UNUSED(domain);
|
||||
|
||||
int region_index = get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);
|
||||
|
||||
LOG_DBG("disable region 0x%x", region_index + part_id);
|
||||
/* Disable region */
|
||||
_region_init(region_index + part_id, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the maximum number of free regions for memory domain partitions
|
||||
*/
|
||||
int arc_core_mpu_get_max_domain_partition_regions(void)
|
||||
{
|
||||
return get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief validate the given buffer is user accessible or not
|
||||
*/
|
||||
int arc_core_mpu_buffer_validate(void *addr, size_t size, int write)
|
||||
{
|
||||
/*
|
||||
* For ARC MPU, smaller region number takes priority.
|
||||
* we can stop the iteration immediately once we find the
|
||||
* matched region that grants permission or denies access.
|
||||
*
|
||||
*/
|
||||
for (int r_index = 0; r_index < get_num_regions(); r_index++) {
|
||||
if (!_is_enabled_region(r_index) || !_is_in_region(r_index, (uint32_t)addr, size)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_is_user_accessible_region(r_index, write)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
return -EPERM;
|
||||
}
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
/* ARC MPU Driver Initial Setup */
|
||||
/*
|
||||
* @brief MPU default initialization and configuration
|
||||
*
|
||||
* This function provides the default configuration mechanism for the Memory
|
||||
* Protection Unit (MPU).
|
||||
*/
|
||||
static int arc_mpu_init(const struct device *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
uint32_t num_regions = get_num_regions();
|
||||
|
||||
if (mpu_config.num_regions > num_regions) {
|
||||
__ASSERT(0, "Request to configure: %u regions (supported: %u)\n",
|
||||
mpu_config.num_regions, num_regions);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Disable MPU */
|
||||
arc_core_mpu_disable();
|
||||
|
||||
/*
|
||||
* the MPU regions are filled in the reverse order.
|
||||
* According to ARCv2 ISA, the MPU region with smaller
|
||||
* index has higher priority. The static background MPU
|
||||
* regions in mpu_config will be in the bottom. Then
|
||||
* the special type regions will be above.
|
||||
*/
|
||||
int r_index = num_regions - mpu_config.num_regions;
|
||||
|
||||
/* clear all the regions first */
|
||||
for (uint32_t i = 0U; i < r_index; i++) {
|
||||
_region_init(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* configure the static regions */
|
||||
for (uint32_t i = 0U; i < mpu_config.num_regions; i++) {
|
||||
_region_init(r_index, mpu_config.mpu_regions[i].base,
|
||||
mpu_config.mpu_regions[i].size, mpu_config.mpu_regions[i].attr);
|
||||
r_index++;
|
||||
}
|
||||
|
||||
/* default region: no read, write and execute */
|
||||
arc_core_mpu_default(0);
|
||||
|
||||
/* Enable MPU */
|
||||
arc_core_mpu_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(arc_mpu_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_COMMON_INTERNAL_H_ */
|
||||
@@ -6,64 +6,42 @@
|
||||
#ifndef ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V2_INTERNAL_H_
|
||||
#define ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V2_INTERNAL_H_
|
||||
|
||||
#define AUX_MPU_EN_ENABLE BIT(30)
|
||||
#define AUX_MPU_EN_DISABLE ~BIT(30)
|
||||
#define AUX_MPU_RDB_VALID_MASK (0x1)
|
||||
#define AUX_MPU_EN_ENABLE (0x40000000)
|
||||
#define AUX_MPU_EN_DISABLE (0xBFFFFFFF)
|
||||
|
||||
/*
|
||||
* The size of the region is a 5-bit field, the three MSB bits are
|
||||
* represented in [11:9] and the two LSB bits are represented in [1:0].
|
||||
* Together these fields specify the size of the region in bytes:
|
||||
* 00000-00011 Reserved
|
||||
* 0x4 32 0x5 64 0x6 128 0x7 256
|
||||
* 0x8 512 0x9 1k 0xA 2K 0xB 4K
|
||||
* 0xC 8K 0xD 16K 0xE 32K 0xF 64K
|
||||
* 0x10 128K 0x11 256K 0x12 512K 0x13 1M
|
||||
* 0x14 2M 0x15 4M 0x16 8M 0x17 16M
|
||||
* 0x18 32M 0x19 64M 0x1A 128M 0x1B 256M
|
||||
* 0x1C 512M 0x1D 1G 0x1E 2G 0x1F 4G
|
||||
*
|
||||
* Bit ... 12 11 10 9 8 3 2 1 0
|
||||
* ------+------------+------+---+-----------+
|
||||
* ... | SIZE[11:9] | ATTR | R | SIZE[1:0] |
|
||||
* ------+------------+------+---+-----------+
|
||||
*/
|
||||
/* arrange size into proper bit field in RDP aux reg*/
|
||||
#define AUX_MPU_RDP_REGION_SIZE(size) (((size - 1) & BIT_MASK(2)) | \
|
||||
(((size - 1) & (BIT_MASK(3) << 2)) << 7))
|
||||
/* recover size from bit fields in RDP aux reg*/
|
||||
#define AUX_MPU_RDP_SIZE_SHIFT(rdp) ((rdp & BIT_MASK(2)) | (((rdp >> 9) & BIT_MASK(3)) << 2))
|
||||
#define AUX_MPU_RDP_REGION_SIZE(bits) \
|
||||
(((bits - 1) & 0x3) | (((bits - 1) & 0x1C) << 7))
|
||||
|
||||
#define AUX_MPU_RDB_VALID_MASK BIT(0)
|
||||
#define AUX_MPU_RDP_ATTR_MASK (BIT_MASK(6) << 3)
|
||||
#define AUX_MPU_RDP_SIZE_MASK ((BIT_MASK(3) << 9) | BIT_MASK(2))
|
||||
#define AUX_MPU_RDP_ATTR_MASK (0x1FC)
|
||||
#define AUX_MPU_RDP_SIZE_MASK (0xE03)
|
||||
|
||||
#define _ARC_V2_MPU_EN (0x409)
|
||||
#define _ARC_V2_MPU_RDB0 (0x422)
|
||||
#define _ARC_V2_MPU_RDP0 (0x423)
|
||||
|
||||
/* For MPU version 2, the minimum protection region size is 2048 bytes */
|
||||
#if CONFIG_ARC_MPU_VER == 2
|
||||
#define ARC_FEATURE_MPU_ALIGNMENT_BITS 11
|
||||
/* For MPU version 3, the minimum protection region size is 32 bytes */
|
||||
#else
|
||||
#define ARC_FEATURE_MPU_ALIGNMENT_BITS 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This internal function initializes a MPU region
|
||||
*/
|
||||
static inline void _region_init(uint32_t index, uint32_t region_addr, uint32_t size,
|
||||
uint32_t region_attr)
|
||||
static inline void _region_init(u32_t index, u32_t region_addr, u32_t size,
|
||||
u32_t region_attr)
|
||||
{
|
||||
u8_t bits = find_msb_set(size) - 1;
|
||||
|
||||
index = index * 2U;
|
||||
|
||||
if (bits < ARC_FEATURE_MPU_ALIGNMENT_BITS) {
|
||||
bits = ARC_FEATURE_MPU_ALIGNMENT_BITS;
|
||||
}
|
||||
|
||||
if ((1 << bits) < size) {
|
||||
bits++;
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
uint8_t bits = find_msb_set(size) - 1;
|
||||
|
||||
if (bits < ARC_FEATURE_MPU_ALIGNMENT_BITS) {
|
||||
bits = ARC_FEATURE_MPU_ALIGNMENT_BITS;
|
||||
}
|
||||
|
||||
if (BIT(bits) < size) {
|
||||
bits++;
|
||||
}
|
||||
|
||||
region_attr &= ~(AUX_MPU_RDP_SIZE_MASK);
|
||||
region_attr |= AUX_MPU_RDP_REGION_SIZE(bits);
|
||||
region_addr |= AUX_MPU_RDB_VALID_MASK;
|
||||
@@ -79,7 +57,7 @@ static inline void _region_init(uint32_t index, uint32_t region_addr, uint32_t s
|
||||
* This internal function is utilized by the MPU driver to parse the intent
|
||||
* type (i.e. THREAD_STACK_REGION) and return the correct region index.
|
||||
*/
|
||||
static inline int get_region_index_by_type(uint32_t type)
|
||||
static inline int get_region_index_by_type(u32_t type)
|
||||
{
|
||||
/*
|
||||
* The new MPU regions are allocated per type after the statically
|
||||
@@ -93,15 +71,22 @@ static inline int get_region_index_by_type(uint32_t type)
|
||||
*/
|
||||
switch (type) {
|
||||
case THREAD_STACK_USER_REGION:
|
||||
return get_num_regions() - mpu_config.num_regions - THREAD_STACK_REGION;
|
||||
return get_num_regions() - mpu_config.num_regions
|
||||
- THREAD_STACK_REGION;
|
||||
case THREAD_STACK_REGION:
|
||||
case THREAD_APP_DATA_REGION:
|
||||
case THREAD_STACK_GUARD_REGION:
|
||||
return get_num_regions() - mpu_config.num_regions - type;
|
||||
case THREAD_DOMAIN_PARTITION_REGION:
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
return get_num_regions() - mpu_config.num_regions - type;
|
||||
#else
|
||||
/*
|
||||
* Start domain partition region from stack guard region
|
||||
* since stack guard is not supported.
|
||||
* since stack guard is not enabled.
|
||||
*/
|
||||
return get_num_regions() - mpu_config.num_regions - type + 1;
|
||||
#endif
|
||||
default:
|
||||
__ASSERT(0, "Unsupported type");
|
||||
return -EINVAL;
|
||||
@@ -111,7 +96,7 @@ static inline int get_region_index_by_type(uint32_t type)
|
||||
/**
|
||||
* This internal function checks if region is enabled or not
|
||||
*/
|
||||
static inline bool _is_enabled_region(uint32_t r_index)
|
||||
static inline bool _is_enabled_region(u32_t r_index)
|
||||
{
|
||||
return ((z_arc_v2_aux_reg_read(_ARC_V2_MPU_RDB0 + r_index * 2U)
|
||||
& AUX_MPU_RDB_VALID_MASK) == AUX_MPU_RDB_VALID_MASK);
|
||||
@@ -120,32 +105,32 @@ static inline bool _is_enabled_region(uint32_t r_index)
|
||||
/**
|
||||
* This internal function check if the given buffer in in the region
|
||||
*/
|
||||
static inline bool _is_in_region(uint32_t r_index, uint32_t start, uint32_t size)
|
||||
static inline bool _is_in_region(u32_t r_index, u32_t start, u32_t size)
|
||||
{
|
||||
uint32_t r_addr_start;
|
||||
uint32_t r_addr_end;
|
||||
uint32_t r_size_lshift;
|
||||
u32_t r_addr_start;
|
||||
u32_t r_addr_end;
|
||||
u32_t r_size_lshift;
|
||||
|
||||
r_addr_start = z_arc_v2_aux_reg_read(_ARC_V2_MPU_RDB0 + r_index * 2U)
|
||||
& (~AUX_MPU_RDB_VALID_MASK);
|
||||
r_size_lshift = z_arc_v2_aux_reg_read(_ARC_V2_MPU_RDP0 + r_index * 2U)
|
||||
& AUX_MPU_RDP_SIZE_MASK;
|
||||
r_size_lshift = AUX_MPU_RDP_SIZE_SHIFT(r_size_lshift);
|
||||
r_size_lshift = (r_size_lshift & 0x3) | ((r_size_lshift >> 7) & 0x1C);
|
||||
r_addr_end = r_addr_start + (1 << (r_size_lshift + 1));
|
||||
|
||||
if (start >= r_addr_start && (start + size) <= r_addr_end) {
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
static inline bool _is_user_accessible_region(uint32_t r_index, int write)
|
||||
static inline bool _is_user_accessible_region(u32_t r_index, int write)
|
||||
{
|
||||
uint32_t r_ap;
|
||||
u32_t r_ap;
|
||||
|
||||
r_ap = z_arc_v2_aux_reg_read(_ARC_V2_MPU_RDP0 + r_index * 2U);
|
||||
|
||||
@@ -160,4 +145,335 @@ static inline bool _is_user_accessible_region(uint32_t r_index, int write)
|
||||
(AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the base address and size for an MPU region
|
||||
*
|
||||
* @param type MPU region type
|
||||
* @param base base address in RAM
|
||||
* @param size size of the region
|
||||
*/
|
||||
static inline int _mpu_configure(u8_t type, u32_t base, u32_t size)
|
||||
{
|
||||
s32_t region_index = get_region_index_by_type(type);
|
||||
u32_t region_attr = get_region_attr_by_type(type);
|
||||
|
||||
LOG_DBG("Region info: 0x%x 0x%x", base, size);
|
||||
|
||||
if (region_attr == 0U || region_index < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* For ARC MPU v2, MPU regions can be overlapped, smaller
|
||||
* region index has higher priority.
|
||||
*/
|
||||
_region_init(region_index, base, size, region_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ARC Core MPU Driver API Implementation for ARC MPUv2 */
|
||||
|
||||
/**
|
||||
* @brief enable the MPU
|
||||
*/
|
||||
void arc_core_mpu_enable(void)
|
||||
{
|
||||
/* Enable MPU */
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN,
|
||||
z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) | AUX_MPU_EN_ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief disable the MPU
|
||||
*/
|
||||
void arc_core_mpu_disable(void)
|
||||
{
|
||||
/* Disable MPU */
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN,
|
||||
z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) & AUX_MPU_EN_DISABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the thread's MPU regions
|
||||
*
|
||||
* @param thread the target thread
|
||||
*/
|
||||
void arc_core_mpu_configure_thread(struct k_thread *thread)
|
||||
{
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
if ((thread->base.user_options & K_USER) != 0) {
|
||||
/* the areas before and after the user stack of thread is
|
||||
* kernel only. These area can be used as stack guard.
|
||||
* -----------------------
|
||||
* | kernel only area |
|
||||
* |---------------------|
|
||||
* | user stack |
|
||||
* |---------------------|
|
||||
* |privilege stack guard|
|
||||
* |---------------------|
|
||||
* | privilege stack |
|
||||
* -----------------------
|
||||
*/
|
||||
if (_mpu_configure(THREAD_STACK_GUARD_REGION,
|
||||
thread->arch.priv_stack_start - STACK_GUARD_SIZE,
|
||||
STACK_GUARD_SIZE) < 0) {
|
||||
LOG_ERR("thread %p's stack guard failed", thread);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (_mpu_configure(THREAD_STACK_GUARD_REGION,
|
||||
thread->stack_info.start - STACK_GUARD_SIZE,
|
||||
STACK_GUARD_SIZE) < 0) {
|
||||
LOG_ERR("thread %p's stack guard failed", thread);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (_mpu_configure(THREAD_STACK_GUARD_REGION,
|
||||
thread->stack_info.start - STACK_GUARD_SIZE,
|
||||
STACK_GUARD_SIZE) < 0) {
|
||||
LOG_ERR("thread %p's stack guard failed", thread);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/* configure stack region of user thread */
|
||||
if (thread->base.user_options & K_USER) {
|
||||
LOG_DBG("configure user thread %p's stack", thread);
|
||||
if (_mpu_configure(THREAD_STACK_USER_REGION,
|
||||
(u32_t)thread->stack_obj, thread->stack_info.size) < 0) {
|
||||
LOG_ERR("user thread %p's stack failed", thread);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DBG("configure thread %p's domain", thread);
|
||||
arc_core_mpu_configure_mem_domain(thread);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief configure the default region
|
||||
*
|
||||
* @param region_attr region attribute of default region
|
||||
*/
|
||||
void arc_core_mpu_default(u32_t region_attr)
|
||||
{
|
||||
u32_t val = z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) &
|
||||
(~AUX_MPU_RDP_ATTR_MASK);
|
||||
|
||||
region_attr &= AUX_MPU_RDP_ATTR_MASK;
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, region_attr | val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the MPU region
|
||||
*
|
||||
* @param index MPU region index
|
||||
* @param base base address
|
||||
* @param region_attr region attribute
|
||||
*/
|
||||
int arc_core_mpu_region(u32_t index, u32_t base, u32_t size,
|
||||
u32_t region_attr)
|
||||
{
|
||||
if (index >= get_num_regions()) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
region_attr &= AUX_MPU_RDP_ATTR_MASK;
|
||||
|
||||
_region_init(index, base, size, region_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
|
||||
/**
|
||||
* @brief configure MPU regions for the memory partitions of the memory domain
|
||||
*
|
||||
* @param thread the thread which has memory domain
|
||||
*/
|
||||
void arc_core_mpu_configure_mem_domain(struct k_thread *thread)
|
||||
{
|
||||
int region_index =
|
||||
get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);
|
||||
u32_t num_partitions;
|
||||
struct k_mem_partition *pparts;
|
||||
struct k_mem_domain *mem_domain = NULL;
|
||||
|
||||
if (thread) {
|
||||
mem_domain = thread->mem_domain_info.mem_domain;
|
||||
}
|
||||
|
||||
if (mem_domain) {
|
||||
LOG_DBG("configure domain: %p", mem_domain);
|
||||
num_partitions = mem_domain->num_partitions;
|
||||
pparts = mem_domain->partitions;
|
||||
} else {
|
||||
LOG_DBG("disable domain partition regions");
|
||||
num_partitions = 0U;
|
||||
pparts = NULL;
|
||||
}
|
||||
|
||||
for (; region_index >= 0; region_index--) {
|
||||
if (num_partitions) {
|
||||
LOG_DBG("set region 0x%x 0x%lx 0x%x",
|
||||
region_index, pparts->start, pparts->size);
|
||||
_region_init(region_index, pparts->start,
|
||||
pparts->size, pparts->attr);
|
||||
num_partitions--;
|
||||
} else {
|
||||
/* clear the left mpu entries */
|
||||
_region_init(region_index, 0, 0, 0);
|
||||
}
|
||||
pparts++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief remove MPU regions for the memory partitions of the memory domain
|
||||
*
|
||||
* @param mem_domain the target memory domain
|
||||
*/
|
||||
void arc_core_mpu_remove_mem_domain(struct k_mem_domain *mem_domain)
|
||||
{
|
||||
ARG_UNUSED(mem_domain);
|
||||
|
||||
int region_index =
|
||||
get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);
|
||||
|
||||
for (; region_index >= 0; region_index--) {
|
||||
_region_init(region_index, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reset MPU region for a single memory partition
|
||||
*
|
||||
* @param domain the target memory domain
|
||||
* @param partition_id memory partition id
|
||||
*/
|
||||
void arc_core_mpu_remove_mem_partition(struct k_mem_domain *domain,
|
||||
u32_t part_id)
|
||||
{
|
||||
ARG_UNUSED(domain);
|
||||
|
||||
int region_index =
|
||||
get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);
|
||||
|
||||
LOG_DBG("disable region 0x%x", region_index + part_id);
|
||||
/* Disable region */
|
||||
_region_init(region_index + part_id, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the maximum number of free regions for memory domain partitions
|
||||
*/
|
||||
int arc_core_mpu_get_max_domain_partition_regions(void)
|
||||
{
|
||||
return get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief validate the given buffer is user accessible or not
|
||||
*/
|
||||
int arc_core_mpu_buffer_validate(void *addr, size_t size, int write)
|
||||
{
|
||||
int r_index;
|
||||
|
||||
/*
|
||||
* For ARC MPU v2, smaller region number takes priority.
|
||||
* we can stop the iteration immediately once we find the
|
||||
* matched region that grants permission or denies access.
|
||||
*
|
||||
*/
|
||||
for (r_index = 0; r_index < get_num_regions(); r_index++) {
|
||||
if (!_is_enabled_region(r_index) ||
|
||||
!_is_in_region(r_index, (u32_t)addr, size)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_is_user_accessible_region(r_index, write)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
return -EPERM;
|
||||
}
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
/* ARC MPU Driver Initial Setup */
|
||||
/*
|
||||
* @brief MPU default initialization and configuration
|
||||
*
|
||||
* This function provides the default configuration mechanism for the Memory
|
||||
* Protection Unit (MPU).
|
||||
*/
|
||||
static int arc_mpu_init(struct device *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
|
||||
u32_t num_regions;
|
||||
u32_t i;
|
||||
|
||||
num_regions = get_num_regions();
|
||||
|
||||
/* ARC MPU supports up to 16 Regions */
|
||||
if (mpu_config.num_regions > num_regions) {
|
||||
__ASSERT(0,
|
||||
"Request to configure: %u regions (supported: %u)\n",
|
||||
mpu_config.num_regions, num_regions);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Disable MPU */
|
||||
arc_core_mpu_disable();
|
||||
|
||||
int r_index;
|
||||
/*
|
||||
* the MPU regions are filled in the reverse order.
|
||||
* According to ARCv2 ISA, the MPU region with smaller
|
||||
* index has higher priority. The static background MPU
|
||||
* regions in mpu_config will be in the bottom. Then
|
||||
* the special type regions will be above.
|
||||
*
|
||||
*/
|
||||
r_index = num_regions - mpu_config.num_regions;
|
||||
|
||||
/* clear all the regions first */
|
||||
for (i = 0U; i < r_index; i++) {
|
||||
_region_init(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* configure the static regions */
|
||||
for (i = 0U; i < mpu_config.num_regions; i++) {
|
||||
_region_init(r_index,
|
||||
mpu_config.mpu_regions[i].base,
|
||||
mpu_config.mpu_regions[i].size,
|
||||
mpu_config.mpu_regions[i].attr);
|
||||
r_index++;
|
||||
}
|
||||
|
||||
/* default region: no read, write and execute */
|
||||
arc_core_mpu_default(0);
|
||||
|
||||
/* Enable MPU */
|
||||
arc_core_mpu_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(arc_mpu_init, PRE_KERNEL_1,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V2_INTERNAL_H_ */
|
||||
|
||||
752
arch/arc/core/mpu/arc_mpu_v3_internal.h
Normal file
752
arch/arc/core/mpu/arc_mpu_v3_internal.h
Normal file
@@ -0,0 +1,752 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V3_INTERNAL_H_
|
||||
#define ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V3_INTERNAL_H_
|
||||
|
||||
#define AUX_MPU_RPER_SID1 0x10000
|
||||
/* valid mask: SID1+secure+valid */
|
||||
#define AUX_MPU_RPER_VALID_MASK ((0x1) | AUX_MPU_RPER_SID1 | AUX_MPU_ATTR_S)
|
||||
|
||||
#define AUX_MPU_RPER_ATTR_MASK (0x1FF)
|
||||
|
||||
#define _ARC_V2_MPU_EN (0x409)
|
||||
|
||||
/* aux regs added in MPU version 3 */
|
||||
#define _ARC_V2_MPU_INDEX (0x448) /* MPU index */
|
||||
#define _ARC_V2_MPU_RSTART (0x449) /* MPU region start address */
|
||||
#define _ARC_V2_MPU_REND (0x44A) /* MPU region end address */
|
||||
#define _ARC_V2_MPU_RPER (0x44B) /* MPU region permission register */
|
||||
#define _ARC_V2_MPU_PROBE (0x44C) /* MPU probe register */
|
||||
|
||||
|
||||
/* For MPU version 3, the minimum protection region size is 32 bytes */
|
||||
#define ARC_FEATURE_MPU_ALIGNMENT_BITS 5
|
||||
|
||||
#define CALC_REGION_END_ADDR(start, size) \
|
||||
(start + size - (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS))
|
||||
|
||||
#if defined(CONFIG_USERSPACE) && defined(CONFIG_MPU_STACK_GUARD)
|
||||
/* 1 for stack guard , 1 for user thread, 1 for split */
|
||||
#define MPU_REGION_NUM_FOR_THREAD 3
|
||||
#elif defined(CONFIG_USERSPACE) || defined(CONFIG_MPU_STACK_GUARD)
|
||||
/* 1 for stack guard or user thread stack , 1 for split */
|
||||
#define MPU_REGION_NUM_FOR_THREAD 2
|
||||
#else
|
||||
#define MPU_REGION_NUM_FOR_THREAD 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief internal structure holding information of
|
||||
* memory areas where dynamic MPU programming is allowed.
|
||||
*/
|
||||
struct dynamic_region_info {
|
||||
u8_t index;
|
||||
u32_t base;
|
||||
u32_t size;
|
||||
u32_t attr;
|
||||
};
|
||||
|
||||
#define MPU_DYNAMIC_REGION_AREAS_NUM 2
|
||||
|
||||
static u8_t static_regions_num;
|
||||
static u8_t dynamic_regions_num;
|
||||
static u8_t dynamic_region_index;
|
||||
|
||||
/**
|
||||
* Global array, holding the MPU region index of
|
||||
* the memory region inside which dynamic memory
|
||||
* regions may be configured.
|
||||
*/
|
||||
static struct dynamic_region_info dyn_reg_info[MPU_DYNAMIC_REGION_AREAS_NUM];
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* \todo through secure service to access mpu */
|
||||
static inline void _region_init(u32_t index, u32_t region_addr, u32_t size,
|
||||
u32_t region_attr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void _region_set_attr(u32_t index, u32_t attr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_attr(u32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_start(u32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _region_set_start(u32_t index, u32_t start)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_end(u32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _region_set_end(u32_t index, u32_t end)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function probes the given addr's MPU index.if not
|
||||
* in MPU, returns error
|
||||
*/
|
||||
static inline int _mpu_probe(u32_t addr)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks if MPU region is enabled or not
|
||||
*/
|
||||
static inline bool _is_enabled_region(u32_t r_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
static inline bool _is_user_accessible_region(u32_t r_index, int write)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else /* CONFIG_ARC_NORMAL_FIRMWARE */
|
||||
/* the following functions are prepared for SECURE_FRIMWARE */
|
||||
static inline void _region_init(u32_t index, u32_t region_addr, u32_t size,
|
||||
u32_t region_attr)
|
||||
{
|
||||
if (size < (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS)) {
|
||||
size = (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS);
|
||||
}
|
||||
|
||||
if (region_attr) {
|
||||
region_attr &= AUX_MPU_RPER_ATTR_MASK;
|
||||
region_attr |= AUX_MPU_RPER_VALID_MASK;
|
||||
}
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RSTART, region_addr);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_REND,
|
||||
CALC_REGION_END_ADDR(region_addr, size));
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RPER, region_attr);
|
||||
}
|
||||
|
||||
static inline void _region_set_attr(u32_t index, u32_t attr)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RPER, attr |
|
||||
AUX_MPU_RPER_VALID_MASK);
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_attr(u32_t index)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
|
||||
return z_arc_v2_aux_reg_read(_ARC_V2_MPU_RPER);
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_start(u32_t index)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
|
||||
return z_arc_v2_aux_reg_read(_ARC_V2_MPU_RSTART);
|
||||
}
|
||||
|
||||
static inline void _region_set_start(u32_t index, u32_t start)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RSTART, start);
|
||||
}
|
||||
|
||||
static inline u32_t _region_get_end(u32_t index)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
|
||||
return z_arc_v2_aux_reg_read(_ARC_V2_MPU_REND) +
|
||||
(1 << ARC_FEATURE_MPU_ALIGNMENT_BITS);
|
||||
}
|
||||
|
||||
static inline void _region_set_end(u32_t index, u32_t end)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_REND, end -
|
||||
(1 << ARC_FEATURE_MPU_ALIGNMENT_BITS));
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function probes the given addr's MPU index.if not
|
||||
* in MPU, returns error
|
||||
*/
|
||||
static inline int _mpu_probe(u32_t addr)
|
||||
{
|
||||
u32_t val;
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_PROBE, addr);
|
||||
val = z_arc_v2_aux_reg_read(_ARC_V2_MPU_INDEX);
|
||||
|
||||
/* if no match or multiple regions match, return error */
|
||||
if (val & 0xC0000000) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks if MPU region is enabled or not
|
||||
*/
|
||||
static inline bool _is_enabled_region(u32_t r_index)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, r_index);
|
||||
return ((z_arc_v2_aux_reg_read(_ARC_V2_MPU_RPER) &
|
||||
AUX_MPU_RPER_VALID_MASK) == AUX_MPU_RPER_VALID_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
static inline bool _is_user_accessible_region(u32_t r_index, int write)
|
||||
{
|
||||
u32_t r_ap;
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, r_index);
|
||||
r_ap = z_arc_v2_aux_reg_read(_ARC_V2_MPU_RPER);
|
||||
r_ap &= AUX_MPU_RPER_ATTR_MASK;
|
||||
|
||||
if (write) {
|
||||
return ((r_ap & (AUX_MPU_ATTR_UW | AUX_MPU_ATTR_KW)) ==
|
||||
(AUX_MPU_ATTR_UW | AUX_MPU_ATTR_KW));
|
||||
}
|
||||
|
||||
return ((r_ap & (AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR)) ==
|
||||
(AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARC_NORMAL_FIRMWARE */
|
||||
|
||||
/**
|
||||
* This internal function allocates a dynamic MPU region and returns
|
||||
* the index or error
|
||||
*/
|
||||
static inline int _dynamic_region_allocate_index(void)
|
||||
{
|
||||
if (dynamic_region_index >= get_num_regions()) {
|
||||
LOG_ERR("no enough mpu entries %d", dynamic_region_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dynamic_region_index++;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks the area given by (start, size)
|
||||
* and returns the index if the area match one MPU entry
|
||||
*/
|
||||
static inline int _get_region_index(u32_t start, u32_t size)
|
||||
{
|
||||
int index = _mpu_probe(start);
|
||||
|
||||
if (index > 0 && index == _mpu_probe(start + size - 1)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* @brief allocate and init a dynamic MPU region
|
||||
*
|
||||
* This internal function performs the allocation and initialization of
|
||||
* a dynamic MPU region
|
||||
*
|
||||
* @param base region base
|
||||
* @param size region size
|
||||
* @param attr region attribute
|
||||
* @return <0 failure, >0 allocated dynamic region index
|
||||
*/
|
||||
static int _dynamic_region_allocate_and_init(u32_t base, u32_t size,
|
||||
u32_t attr)
|
||||
{
|
||||
int u_region_index = _get_region_index(base, size);
|
||||
int region_index;
|
||||
|
||||
LOG_DBG("Region info: base 0x%x size 0x%x attr 0x%x", base, size, attr);
|
||||
|
||||
if (u_region_index == -EINVAL) {
|
||||
/* no underlying region */
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
/* a new region */
|
||||
_region_init(region_index, base, size, attr);
|
||||
}
|
||||
|
||||
return region_index;
|
||||
}
|
||||
|
||||
/*
|
||||
* The new memory region is to be placed inside the underlying
|
||||
* region, possibly splitting the underlying region into two.
|
||||
*/
|
||||
|
||||
u32_t u_region_start = _region_get_start(u_region_index);
|
||||
u32_t u_region_end = _region_get_end(u_region_index);
|
||||
u32_t u_region_attr = _region_get_attr(u_region_index);
|
||||
u32_t end = base + size;
|
||||
|
||||
|
||||
if ((base == u_region_start) && (end == u_region_end)) {
|
||||
/* The new region overlaps entirely with the
|
||||
* underlying region. In this case we simply
|
||||
* update the partition attributes of the
|
||||
* underlying region with those of the new
|
||||
* region.
|
||||
*/
|
||||
_region_init(u_region_index, base, size, attr);
|
||||
region_index = u_region_index;
|
||||
} else if (base == u_region_start) {
|
||||
/* The new region starts exactly at the start of the
|
||||
* underlying region; the start of the underlying
|
||||
* region needs to be set to the end of the new region.
|
||||
*/
|
||||
_region_set_start(u_region_index, base + size);
|
||||
_region_set_attr(u_region_index, u_region_attr);
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
_region_init(region_index, base, size, attr);
|
||||
}
|
||||
|
||||
} else if (end == u_region_end) {
|
||||
/* The new region ends exactly at the end of the
|
||||
* underlying region; the end of the underlying
|
||||
* region needs to be set to the start of the
|
||||
* new region.
|
||||
*/
|
||||
_region_set_end(u_region_index, base);
|
||||
_region_set_attr(u_region_index, u_region_attr);
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
_region_init(region_index, base, size, attr);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* The new region lies strictly inside the
|
||||
* underlying region, which needs to split
|
||||
* into two regions.
|
||||
*/
|
||||
|
||||
_region_set_end(u_region_index, base);
|
||||
_region_set_attr(u_region_index, u_region_attr);
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
_region_init(region_index, base, size, attr);
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
_region_init(region_index, base + size,
|
||||
u_region_end - end, u_region_attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return region_index;
|
||||
}
|
||||
|
||||
/* @brief reset the dynamic MPU regions
|
||||
*
|
||||
* This internal function performs the reset of dynamic MPU regions
|
||||
*/
|
||||
static void _mpu_reset_dynamic_regions(void)
|
||||
{
|
||||
u32_t i;
|
||||
u32_t num_regions = get_num_regions();
|
||||
|
||||
for (i = static_regions_num; i < num_regions; i++) {
|
||||
_region_init(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
for (i = 0U; i < dynamic_regions_num; i++) {
|
||||
_region_init(
|
||||
dyn_reg_info[i].index,
|
||||
dyn_reg_info[i].base,
|
||||
dyn_reg_info[i].size,
|
||||
dyn_reg_info[i].attr);
|
||||
}
|
||||
|
||||
/* dynamic regions are after static regions */
|
||||
dynamic_region_index = static_regions_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the base address and size for an MPU region
|
||||
*
|
||||
* @param type MPU region type
|
||||
* @param base base address in RAM
|
||||
* @param size size of the region
|
||||
*/
|
||||
static inline int _mpu_configure(u8_t type, u32_t base, u32_t size)
|
||||
{
|
||||
u32_t region_attr = get_region_attr_by_type(type);
|
||||
|
||||
return _dynamic_region_allocate_and_init(base, size, region_attr);
|
||||
}
|
||||
|
||||
/* ARC Core MPU Driver API Implementation for ARC MPUv3 */
|
||||
|
||||
/**
|
||||
* @brief enable the MPU
|
||||
*/
|
||||
void arc_core_mpu_enable(void)
|
||||
{
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* the default region:
|
||||
* normal:0x000, SID:0x10000, KW:0x100 KR:0x80, KE:0x4 0
|
||||
*/
|
||||
#define MPU_ENABLE_ATTR 0x101c0
|
||||
#else
|
||||
#define MPU_ENABLE_ATTR 0
|
||||
#endif
|
||||
arc_core_mpu_default(MPU_ENABLE_ATTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief disable the MPU
|
||||
*/
|
||||
void arc_core_mpu_disable(void)
|
||||
{
|
||||
/* MPU is always enabled, use default region to
|
||||
* simulate MPU disable
|
||||
*/
|
||||
arc_core_mpu_default(REGION_ALL_ATTR | AUX_MPU_ATTR_S |
|
||||
AUX_MPU_RPER_SID1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the thread's mpu regions
|
||||
*
|
||||
* @param thread the target thread
|
||||
*/
|
||||
void arc_core_mpu_configure_thread(struct k_thread *thread)
|
||||
{
|
||||
/* the mpu entries of ARC MPUv3 are divided into 2 parts:
|
||||
* static entries: global mpu entries, not changed in context switch
|
||||
* dynamic entries: MPU entries changed in context switch and
|
||||
* memory domain configure, including:
|
||||
* MPU entries for user thread stack
|
||||
* MPU entries for stack guard
|
||||
* MPU entries for mem domain
|
||||
* MPU entries for other thread specific regions
|
||||
* before configuring thread specific mpu entries, need to reset dynamic
|
||||
* entries
|
||||
*/
|
||||
_mpu_reset_dynamic_regions();
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
if ((thread->base.user_options & K_USER) != 0U) {
|
||||
/* the areas before and after the user stack of thread is
|
||||
* kernel only. These area can be used as stack guard.
|
||||
* -----------------------
|
||||
* | kernel only area |
|
||||
* |---------------------|
|
||||
* | user stack |
|
||||
* |---------------------|
|
||||
* |privilege stack guard|
|
||||
* |---------------------|
|
||||
* | privilege stack |
|
||||
* -----------------------
|
||||
*/
|
||||
if (_mpu_configure(THREAD_STACK_GUARD_REGION,
|
||||
thread->arch.priv_stack_start - STACK_GUARD_SIZE,
|
||||
STACK_GUARD_SIZE) < 0) {
|
||||
LOG_ERR("thread %p's stack guard failed", thread);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (_mpu_configure(THREAD_STACK_GUARD_REGION,
|
||||
thread->stack_info.start - STACK_GUARD_SIZE,
|
||||
STACK_GUARD_SIZE) < 0) {
|
||||
LOG_ERR("thread %p's stack guard failed", thread);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (_mpu_configure(THREAD_STACK_GUARD_REGION,
|
||||
thread->stack_info.start - STACK_GUARD_SIZE,
|
||||
STACK_GUARD_SIZE) < 0) {
|
||||
LOG_ERR("thread %p's stack guard failed", thread);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
u32_t num_partitions;
|
||||
struct k_mem_partition *pparts;
|
||||
struct k_mem_domain *mem_domain = thread->mem_domain_info.mem_domain;
|
||||
|
||||
/* configure stack region of user thread */
|
||||
if (thread->base.user_options & K_USER) {
|
||||
LOG_DBG("configure user thread %p's stack", thread);
|
||||
if (_mpu_configure(THREAD_STACK_USER_REGION,
|
||||
(u32_t)thread->stack_obj, thread->stack_info.size) < 0) {
|
||||
LOG_ERR("thread %p's stack failed", thread);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* configure thread's memory domain */
|
||||
if (mem_domain) {
|
||||
LOG_DBG("configure thread %p's domain: %p",
|
||||
thread, mem_domain);
|
||||
num_partitions = mem_domain->num_partitions;
|
||||
pparts = mem_domain->partitions;
|
||||
} else {
|
||||
num_partitions = 0U;
|
||||
pparts = NULL;
|
||||
}
|
||||
|
||||
for (u32_t i = 0; i < num_partitions; i++) {
|
||||
if (pparts->size) {
|
||||
if (_dynamic_region_allocate_and_init(pparts->start,
|
||||
pparts->size, pparts->attr) < 0) {
|
||||
LOG_ERR(
|
||||
"thread %p's mem region: %p failed",
|
||||
thread, pparts);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pparts++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the default region
|
||||
*
|
||||
* @param region_attr region attribute of default region
|
||||
*/
|
||||
void arc_core_mpu_default(u32_t region_attr)
|
||||
{
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* \todo through secure service to access mpu */
|
||||
#else
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, region_attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the MPU region
|
||||
*
|
||||
* @param index MPU region index
|
||||
* @param base base address
|
||||
* @param size region size
|
||||
* @param region_attr region attribute
|
||||
*/
|
||||
int arc_core_mpu_region(u32_t index, u32_t base, u32_t size,
|
||||
u32_t region_attr)
|
||||
{
|
||||
if (index >= get_num_regions()) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
region_attr &= AUX_MPU_RPER_ATTR_MASK;
|
||||
|
||||
_region_init(index, base, size, region_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/**
|
||||
* @brief configure MPU regions for the memory partitions of the memory domain
|
||||
*
|
||||
* @param thread the thread which has memory domain
|
||||
*/
|
||||
void arc_core_mpu_configure_mem_domain(struct k_thread *thread)
|
||||
{
|
||||
arc_core_mpu_configure_thread(thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief remove MPU regions for the memory partitions of the memory domain
|
||||
*
|
||||
* @param mem_domain the target memory domain
|
||||
*/
|
||||
void arc_core_mpu_remove_mem_domain(struct k_mem_domain *mem_domain)
|
||||
{
|
||||
u32_t num_partitions;
|
||||
struct k_mem_partition *pparts;
|
||||
int index;
|
||||
|
||||
if (mem_domain) {
|
||||
LOG_DBG("configure domain: %p", mem_domain);
|
||||
num_partitions = mem_domain->num_partitions;
|
||||
pparts = mem_domain->partitions;
|
||||
} else {
|
||||
LOG_DBG("disable domain partition regions");
|
||||
num_partitions = 0U;
|
||||
pparts = NULL;
|
||||
}
|
||||
|
||||
for (u32_t i = 0; i < num_partitions; i++) {
|
||||
if (pparts->size) {
|
||||
index = _get_region_index(pparts->start,
|
||||
pparts->size);
|
||||
if (index > 0) {
|
||||
_region_set_attr(index,
|
||||
REGION_KERNEL_RAM_ATTR);
|
||||
}
|
||||
}
|
||||
pparts++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reset MPU region for a single memory partition
|
||||
*
|
||||
* @param partition_id memory partition id
|
||||
*/
|
||||
void arc_core_mpu_remove_mem_partition(struct k_mem_domain *domain,
|
||||
u32_t partition_id)
|
||||
{
|
||||
struct k_mem_partition *partition = &domain->partitions[partition_id];
|
||||
|
||||
int region_index = _get_region_index(partition->start,
|
||||
partition->size);
|
||||
|
||||
if (region_index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DBG("remove region 0x%x", region_index);
|
||||
_region_set_attr(region_index, REGION_KERNEL_RAM_ATTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the maximum number of free regions for memory domain partitions
|
||||
*/
|
||||
int arc_core_mpu_get_max_domain_partition_regions(void)
|
||||
{
|
||||
/* consider the worst case: each partition requires split */
|
||||
return (get_num_regions() - MPU_REGION_NUM_FOR_THREAD) / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief validate the given buffer is user accessible or not
|
||||
*/
|
||||
int arc_core_mpu_buffer_validate(void *addr, size_t size, int write)
|
||||
{
|
||||
int r_index;
|
||||
int key = arch_irq_lock();
|
||||
|
||||
/*
|
||||
* For ARC MPU v3, overlapping is not supported.
|
||||
* we can stop the iteration immediately once we find the
|
||||
* matched region that grants permission or denies access.
|
||||
*/
|
||||
r_index = _mpu_probe((u32_t)addr);
|
||||
/* match and the area is in one region */
|
||||
if (r_index >= 0 && r_index == _mpu_probe((u32_t)addr + (size - 1))) {
|
||||
if (_is_user_accessible_region(r_index, write)) {
|
||||
r_index = 0;
|
||||
} else {
|
||||
r_index = -EPERM;
|
||||
}
|
||||
} else {
|
||||
r_index = -EPERM;
|
||||
}
|
||||
|
||||
arch_irq_unlock(key);
|
||||
|
||||
return r_index;
|
||||
}
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
/* ARC MPU Driver Initial Setup */
|
||||
/*
|
||||
* @brief MPU default initialization and configuration
|
||||
*
|
||||
* This function provides the default configuration mechanism for the Memory
|
||||
* Protection Unit (MPU).
|
||||
*/
|
||||
static int arc_mpu_init(struct device *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
u32_t num_regions;
|
||||
u32_t i;
|
||||
|
||||
num_regions = get_num_regions();
|
||||
|
||||
/* ARC MPU supports up to 16 Regions */
|
||||
if (mpu_config.num_regions > num_regions) {
|
||||
__ASSERT(0,
|
||||
"Request to configure: %u regions (supported: %u)\n",
|
||||
mpu_config.num_regions, num_regions);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Disable MPU */
|
||||
arc_core_mpu_disable();
|
||||
|
||||
for (i = 0U; i < mpu_config.num_regions; i++) {
|
||||
_region_init(i,
|
||||
mpu_config.mpu_regions[i].base,
|
||||
mpu_config.mpu_regions[i].size,
|
||||
mpu_config.mpu_regions[i].attr);
|
||||
|
||||
/* record the static region which can be split */
|
||||
if (mpu_config.mpu_regions[i].attr & REGION_DYNAMIC) {
|
||||
if (dynamic_regions_num >=
|
||||
MPU_DYNAMIC_REGION_AREAS_NUM) {
|
||||
LOG_ERR("not enough dynamic regions %d",
|
||||
dynamic_regions_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dyn_reg_info[dynamic_regions_num].index = i;
|
||||
dyn_reg_info[dynamic_regions_num].base =
|
||||
mpu_config.mpu_regions[i].base;
|
||||
dyn_reg_info[dynamic_regions_num].size =
|
||||
mpu_config.mpu_regions[i].size;
|
||||
dyn_reg_info[dynamic_regions_num].attr =
|
||||
mpu_config.mpu_regions[i].attr;
|
||||
|
||||
dynamic_regions_num++;
|
||||
}
|
||||
}
|
||||
|
||||
static_regions_num = mpu_config.num_regions;
|
||||
|
||||
for (; i < num_regions; i++) {
|
||||
_region_init(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Enable MPU */
|
||||
arc_core_mpu_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(arc_mpu_init, PRE_KERNEL_1,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V3_INTERNAL_H_ */
|
||||
@@ -1,896 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V4_INTERNAL_H_
|
||||
#define ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V4_INTERNAL_H_
|
||||
|
||||
#define AUX_MPU_RPER_SID1 0x10000
|
||||
/* valid mask: SID1+secure+valid */
|
||||
#define AUX_MPU_RPER_VALID_MASK ((0x1) | AUX_MPU_RPER_SID1 | AUX_MPU_ATTR_S)
|
||||
|
||||
#define AUX_MPU_RPER_ATTR_MASK (0x1FF)
|
||||
|
||||
/* For MPU version 4, the minimum protection region size is 32 bytes */
|
||||
#define ARC_FEATURE_MPU_ALIGNMENT_BITS 5
|
||||
|
||||
#define CALC_REGION_END_ADDR(start, size) \
|
||||
(start + size - (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS))
|
||||
|
||||
/* ARC MPU version 4 does not support mpu region overlap in hardware
|
||||
* so if we want to allocate MPU region dynamically, e.g. thread stack,
|
||||
* memory domain from a background region, a dynamic region splitting
|
||||
* approach is designed. pls see comments in
|
||||
* _dynamic_region_allocate_and_init
|
||||
* But this approach has an impact on performance of thread switch.
|
||||
* As a trade off, we can use the default mpu region as the background region
|
||||
* to avoid the dynamic region splitting. This will give more privilege to
|
||||
* codes in kernel mode which can access the memory region not covered by
|
||||
* explicit mpu entry. Considering memory protection is mainly used to
|
||||
* isolate malicious codes in user mode, it makes sense to get better
|
||||
* thread switch performance through default mpu region.
|
||||
* CONFIG_MPU_GAP_FILLING is used to turn this on/off.
|
||||
*
|
||||
*/
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
|
||||
#if defined(CONFIG_USERSPACE) && defined(CONFIG_MPU_STACK_GUARD)
|
||||
/* 1 for stack guard , 1 for user thread, 1 for split */
|
||||
#define MPU_REGION_NUM_FOR_THREAD 3
|
||||
#elif defined(CONFIG_USERSPACE) || defined(CONFIG_MPU_STACK_GUARD)
|
||||
/* 1 for stack guard or user thread stack , 1 for split */
|
||||
#define MPU_REGION_NUM_FOR_THREAD 2
|
||||
#else
|
||||
#define MPU_REGION_NUM_FOR_THREAD 0
|
||||
#endif
|
||||
|
||||
#define MPU_DYNAMIC_REGION_AREAS_NUM 2
|
||||
|
||||
/**
|
||||
* @brief internal structure holding information of
|
||||
* memory areas where dynamic MPU programming is allowed.
|
||||
*/
|
||||
struct dynamic_region_info {
|
||||
uint8_t index;
|
||||
uint32_t base;
|
||||
uint32_t size;
|
||||
uint32_t attr;
|
||||
};
|
||||
|
||||
static uint8_t dynamic_regions_num;
|
||||
static uint8_t dynamic_region_index;
|
||||
|
||||
/**
|
||||
* Global array, holding the MPU region index of
|
||||
* the memory region inside which dynamic memory
|
||||
* regions may be configured.
|
||||
*/
|
||||
static struct dynamic_region_info dyn_reg_info[MPU_DYNAMIC_REGION_AREAS_NUM];
|
||||
#endif /* CONFIG_MPU_GAP_FILLING */
|
||||
|
||||
static uint8_t static_regions_num;
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* \todo through secure service to access mpu */
|
||||
static inline void _region_init(uint32_t index, uint32_t region_addr, uint32_t size,
|
||||
uint32_t region_attr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void _region_set_attr(uint32_t index, uint32_t attr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline uint32_t _region_get_attr(uint32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t _region_get_start(uint32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _region_set_start(uint32_t index, uint32_t start)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static inline uint32_t _region_get_end(uint32_t index)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void _region_set_end(uint32_t index, uint32_t end)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function probes the given addr's MPU index.if not
|
||||
* in MPU, returns error
|
||||
*/
|
||||
static inline int _mpu_probe(uint32_t addr)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks if MPU region is enabled or not
|
||||
*/
|
||||
static inline bool _is_enabled_region(uint32_t r_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
static inline bool _is_user_accessible_region(uint32_t r_index, int write)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else /* CONFIG_ARC_NORMAL_FIRMWARE */
|
||||
/* the following functions are prepared for SECURE_FRIMWARE */
|
||||
static inline void _region_init(uint32_t index, uint32_t region_addr, uint32_t size,
|
||||
uint32_t region_attr)
|
||||
{
|
||||
if (size < (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS)) {
|
||||
size = (1 << ARC_FEATURE_MPU_ALIGNMENT_BITS);
|
||||
}
|
||||
|
||||
if (region_attr) {
|
||||
region_attr &= AUX_MPU_RPER_ATTR_MASK;
|
||||
region_attr |= AUX_MPU_RPER_VALID_MASK;
|
||||
}
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RSTART, region_addr);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_REND,
|
||||
CALC_REGION_END_ADDR(region_addr, size));
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RPER, region_attr);
|
||||
}
|
||||
|
||||
static inline void _region_set_attr(uint32_t index, uint32_t attr)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RPER, attr |
|
||||
AUX_MPU_RPER_VALID_MASK);
|
||||
}
|
||||
|
||||
static inline uint32_t _region_get_attr(uint32_t index)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
|
||||
return z_arc_v2_aux_reg_read(_ARC_V2_MPU_RPER);
|
||||
}
|
||||
|
||||
static inline uint32_t _region_get_start(uint32_t index)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
|
||||
return z_arc_v2_aux_reg_read(_ARC_V2_MPU_RSTART);
|
||||
}
|
||||
|
||||
static inline void _region_set_start(uint32_t index, uint32_t start)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RSTART, start);
|
||||
}
|
||||
|
||||
static inline uint32_t _region_get_end(uint32_t index)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
|
||||
return z_arc_v2_aux_reg_read(_ARC_V2_MPU_REND) +
|
||||
(1 << ARC_FEATURE_MPU_ALIGNMENT_BITS);
|
||||
}
|
||||
|
||||
static inline void _region_set_end(uint32_t index, uint32_t end)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, index);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_REND, end -
|
||||
(1 << ARC_FEATURE_MPU_ALIGNMENT_BITS));
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function probes the given addr's MPU index.if not
|
||||
* in MPU, returns error
|
||||
*/
|
||||
static inline int _mpu_probe(uint32_t addr)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_PROBE, addr);
|
||||
val = z_arc_v2_aux_reg_read(_ARC_V2_MPU_INDEX);
|
||||
|
||||
/* if no match or multiple regions match, return error */
|
||||
if (val & 0xC0000000) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks if MPU region is enabled or not
|
||||
*/
|
||||
static inline bool _is_enabled_region(uint32_t r_index)
|
||||
{
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, r_index);
|
||||
return ((z_arc_v2_aux_reg_read(_ARC_V2_MPU_RPER) &
|
||||
AUX_MPU_RPER_VALID_MASK) == AUX_MPU_RPER_VALID_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
static inline bool _is_user_accessible_region(uint32_t r_index, int write)
|
||||
{
|
||||
uint32_t r_ap;
|
||||
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_INDEX, r_index);
|
||||
r_ap = z_arc_v2_aux_reg_read(_ARC_V2_MPU_RPER);
|
||||
r_ap &= AUX_MPU_RPER_ATTR_MASK;
|
||||
|
||||
if (write) {
|
||||
return ((r_ap & (AUX_MPU_ATTR_UW | AUX_MPU_ATTR_KW)) ==
|
||||
(AUX_MPU_ATTR_UW | AUX_MPU_ATTR_KW));
|
||||
}
|
||||
|
||||
return ((r_ap & (AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR)) ==
|
||||
(AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARC_NORMAL_FIRMWARE */
|
||||
|
||||
/**
|
||||
* This internal function checks the area given by (start, size)
|
||||
* and returns the index if the area match one MPU entry
|
||||
*/
|
||||
static inline int _get_region_index(uint32_t start, uint32_t size)
|
||||
{
|
||||
int index = _mpu_probe(start);
|
||||
|
||||
if (index > 0 && index == _mpu_probe(start + size - 1)) {
|
||||
return index;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
/**
|
||||
* This internal function allocates a dynamic MPU region and returns
|
||||
* the index or error
|
||||
*/
|
||||
static inline int _dynamic_region_allocate_index(void)
|
||||
{
|
||||
if (dynamic_region_index >= get_num_regions()) {
|
||||
LOG_ERR("no enough mpu entries %d", dynamic_region_index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return dynamic_region_index++;
|
||||
}
|
||||
|
||||
/* @brief allocate and init a dynamic MPU region
|
||||
*
|
||||
* This internal function performs the allocation and initialization of
|
||||
* a dynamic MPU region
|
||||
*
|
||||
* @param base region base
|
||||
* @param size region size
|
||||
* @param attr region attribute
|
||||
* @return <0 failure, >0 allocated dynamic region index
|
||||
*/
|
||||
static int _dynamic_region_allocate_and_init(uint32_t base, uint32_t size,
|
||||
uint32_t attr)
|
||||
{
|
||||
int u_region_index = _get_region_index(base, size);
|
||||
int region_index;
|
||||
|
||||
LOG_DBG("Region info: base 0x%x size 0x%x attr 0x%x", base, size, attr);
|
||||
|
||||
if (u_region_index == -EINVAL) {
|
||||
/* no underlying region */
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
/* a new region */
|
||||
_region_init(region_index, base, size, attr);
|
||||
}
|
||||
|
||||
return region_index;
|
||||
}
|
||||
|
||||
/*
|
||||
* The new memory region is to be placed inside the underlying
|
||||
* region, possibly splitting the underlying region into two.
|
||||
*/
|
||||
|
||||
uint32_t u_region_start = _region_get_start(u_region_index);
|
||||
uint32_t u_region_end = _region_get_end(u_region_index);
|
||||
uint32_t u_region_attr = _region_get_attr(u_region_index);
|
||||
uint32_t end = base + size;
|
||||
|
||||
|
||||
if ((base == u_region_start) && (end == u_region_end)) {
|
||||
/* The new region overlaps entirely with the
|
||||
* underlying region. In this case we simply
|
||||
* update the partition attributes of the
|
||||
* underlying region with those of the new
|
||||
* region.
|
||||
*/
|
||||
_region_init(u_region_index, base, size, attr);
|
||||
region_index = u_region_index;
|
||||
} else if (base == u_region_start) {
|
||||
/* The new region starts exactly at the start of the
|
||||
* underlying region; the start of the underlying
|
||||
* region needs to be set to the end of the new region.
|
||||
*/
|
||||
_region_set_start(u_region_index, base + size);
|
||||
_region_set_attr(u_region_index, u_region_attr);
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
_region_init(region_index, base, size, attr);
|
||||
}
|
||||
|
||||
} else if (end == u_region_end) {
|
||||
/* The new region ends exactly at the end of the
|
||||
* underlying region; the end of the underlying
|
||||
* region needs to be set to the start of the
|
||||
* new region.
|
||||
*/
|
||||
_region_set_end(u_region_index, base);
|
||||
_region_set_attr(u_region_index, u_region_attr);
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
_region_init(region_index, base, size, attr);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* The new region lies strictly inside the
|
||||
* underlying region, which needs to split
|
||||
* into two regions.
|
||||
*/
|
||||
|
||||
_region_set_end(u_region_index, base);
|
||||
_region_set_attr(u_region_index, u_region_attr);
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
_region_init(region_index, base, size, attr);
|
||||
|
||||
region_index = _dynamic_region_allocate_index();
|
||||
|
||||
if (region_index > 0) {
|
||||
_region_init(region_index, base + size,
|
||||
u_region_end - end, u_region_attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return region_index;
|
||||
}
|
||||
|
||||
/* @brief reset the dynamic MPU regions
|
||||
*
|
||||
* This internal function performs the reset of dynamic MPU regions
|
||||
*/
|
||||
static void _mpu_reset_dynamic_regions(void)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t num_regions = get_num_regions();
|
||||
|
||||
for (i = static_regions_num; i < num_regions; i++) {
|
||||
_region_init(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
for (i = 0U; i < dynamic_regions_num; i++) {
|
||||
_region_init(
|
||||
dyn_reg_info[i].index,
|
||||
dyn_reg_info[i].base,
|
||||
dyn_reg_info[i].size,
|
||||
dyn_reg_info[i].attr);
|
||||
}
|
||||
|
||||
/* dynamic regions are after static regions */
|
||||
dynamic_region_index = static_regions_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the base address and size for an MPU region
|
||||
*
|
||||
* @param type MPU region type
|
||||
* @param base base address in RAM
|
||||
* @param size size of the region
|
||||
*/
|
||||
static inline int _mpu_configure(uint8_t type, uint32_t base, uint32_t size)
|
||||
{
|
||||
uint32_t region_attr = get_region_attr_by_type(type);
|
||||
|
||||
return _dynamic_region_allocate_and_init(base, size, region_attr);
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* This internal function is utilized by the MPU driver to parse the intent
|
||||
* type (i.e. THREAD_STACK_REGION) and return the correct region index.
|
||||
*/
|
||||
static inline int get_region_index_by_type(uint32_t type)
|
||||
{
|
||||
/*
|
||||
* The new MPU regions are allocated per type after the statically
|
||||
* configured regions. The type is one-indexed rather than
|
||||
* zero-indexed.
|
||||
*
|
||||
* For ARC MPU v2, the smaller index has higher priority, so the
|
||||
* index is allocated in reverse order. Static regions start from
|
||||
* the biggest index, then thread related regions.
|
||||
*
|
||||
*/
|
||||
switch (type) {
|
||||
case THREAD_STACK_USER_REGION:
|
||||
return static_regions_num + THREAD_STACK_REGION;
|
||||
case THREAD_STACK_REGION:
|
||||
case THREAD_APP_DATA_REGION:
|
||||
case THREAD_STACK_GUARD_REGION:
|
||||
return static_regions_num + type;
|
||||
case THREAD_DOMAIN_PARTITION_REGION:
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
return static_regions_num + type;
|
||||
#else
|
||||
/*
|
||||
* Start domain partition region from stack guard region
|
||||
* since stack guard is not enabled.
|
||||
*/
|
||||
return static_regions_num + type - 1;
|
||||
#endif
|
||||
default:
|
||||
__ASSERT(0, "Unsupported type");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the base address and size for an MPU region
|
||||
*
|
||||
* @param type MPU region type
|
||||
* @param base base address in RAM
|
||||
* @param size size of the region
|
||||
*/
|
||||
static inline int _mpu_configure(uint8_t type, uint32_t base, uint32_t size)
|
||||
{
|
||||
int region_index = get_region_index_by_type(type);
|
||||
uint32_t region_attr = get_region_attr_by_type(type);
|
||||
|
||||
LOG_DBG("Region info: 0x%x 0x%x", base, size);
|
||||
|
||||
if (region_attr == 0U || region_index < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
_region_init(region_index, base, size, region_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ARC Core MPU Driver API Implementation for ARC MPUv3 */
|
||||
|
||||
/**
|
||||
* @brief enable the MPU
|
||||
*/
|
||||
void arc_core_mpu_enable(void)
|
||||
{
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* the default region:
|
||||
* secure:0x8000, SID:0x10000, KW:0x100 KR:0x80
|
||||
*/
|
||||
#define MPU_ENABLE_ATTR 0x18180
|
||||
#else
|
||||
#define MPU_ENABLE_ATTR 0
|
||||
#endif
|
||||
arc_core_mpu_default(MPU_ENABLE_ATTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief disable the MPU
|
||||
*/
|
||||
void arc_core_mpu_disable(void)
|
||||
{
|
||||
/* MPU is always enabled, use default region to
|
||||
* simulate MPU disable
|
||||
*/
|
||||
arc_core_mpu_default(REGION_ALL_ATTR | AUX_MPU_ATTR_S |
|
||||
AUX_MPU_RPER_SID1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the thread's mpu regions
|
||||
*
|
||||
* @param thread the target thread
|
||||
*/
|
||||
void arc_core_mpu_configure_thread(struct k_thread *thread)
|
||||
{
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
/* the mpu entries of ARC MPUv4 are divided into 2 parts:
|
||||
* static entries: global mpu entries, not changed in context switch
|
||||
* dynamic entries: MPU entries changed in context switch and
|
||||
* memory domain configure, including:
|
||||
* MPU entries for user thread stack
|
||||
* MPU entries for stack guard
|
||||
* MPU entries for mem domain
|
||||
* MPU entries for other thread specific regions
|
||||
* before configuring thread specific mpu entries, need to reset dynamic
|
||||
* entries
|
||||
*/
|
||||
_mpu_reset_dynamic_regions();
|
||||
#endif
|
||||
#if defined(CONFIG_MPU_STACK_GUARD)
|
||||
uint32_t guard_start;
|
||||
|
||||
/* Set location of guard area when the thread is running in
|
||||
* supervisor mode. For a supervisor thread, this is just low
|
||||
* memory in the stack buffer. For a user thread, it only runs
|
||||
* in supervisor mode when handling a system call on the privilege
|
||||
* elevation stack.
|
||||
*/
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
if ((thread->base.user_options & K_USER) != 0U) {
|
||||
guard_start = thread->arch.priv_stack_start;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
guard_start = thread->stack_info.start;
|
||||
}
|
||||
guard_start -= Z_ARC_STACK_GUARD_SIZE;
|
||||
|
||||
if (_mpu_configure(THREAD_STACK_GUARD_REGION, guard_start,
|
||||
Z_ARC_STACK_GUARD_SIZE) < 0) {
|
||||
LOG_ERR("thread %p's stack guard failed", thread);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_MPU_STACK_GUARD */
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/* configure stack region of user thread */
|
||||
if (thread->base.user_options & K_USER) {
|
||||
LOG_DBG("configure user thread %p's stack", thread);
|
||||
if (_mpu_configure(THREAD_STACK_USER_REGION,
|
||||
(uint32_t)thread->stack_info.start,
|
||||
thread->stack_info.size) < 0) {
|
||||
LOG_ERR("thread %p's stack failed", thread);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
uint32_t num_partitions;
|
||||
struct k_mem_partition *pparts;
|
||||
struct k_mem_domain *mem_domain = thread->mem_domain_info.mem_domain;
|
||||
|
||||
/* configure thread's memory domain */
|
||||
if (mem_domain) {
|
||||
LOG_DBG("configure thread %p's domain: %p",
|
||||
thread, mem_domain);
|
||||
num_partitions = mem_domain->num_partitions;
|
||||
pparts = mem_domain->partitions;
|
||||
} else {
|
||||
num_partitions = 0U;
|
||||
pparts = NULL;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < num_partitions; i++) {
|
||||
if (pparts->size) {
|
||||
if (_dynamic_region_allocate_and_init(pparts->start,
|
||||
pparts->size, pparts->attr) < 0) {
|
||||
LOG_ERR(
|
||||
"thread %p's mem region: %p failed",
|
||||
thread, pparts);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pparts++;
|
||||
}
|
||||
#else
|
||||
arc_core_mpu_configure_mem_domain(thread);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the default region
|
||||
*
|
||||
* @param region_attr region attribute of default region
|
||||
*/
|
||||
void arc_core_mpu_default(uint32_t region_attr)
|
||||
{
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* \todo through secure service to access mpu */
|
||||
#else
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, region_attr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief configure the MPU region
|
||||
*
|
||||
* @param index MPU region index
|
||||
* @param base base address
|
||||
* @param size region size
|
||||
* @param region_attr region attribute
|
||||
*/
|
||||
int arc_core_mpu_region(uint32_t index, uint32_t base, uint32_t size,
|
||||
uint32_t region_attr)
|
||||
{
|
||||
if (index >= get_num_regions()) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
region_attr &= AUX_MPU_RPER_ATTR_MASK;
|
||||
|
||||
_region_init(index, base, size, region_attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/**
|
||||
* @brief configure MPU regions for the memory partitions of the memory domain
|
||||
*
|
||||
* @param thread the thread which has memory domain
|
||||
*/
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
void arc_core_mpu_configure_mem_domain(struct k_thread *thread)
|
||||
{
|
||||
arc_core_mpu_configure_thread(thread);
|
||||
}
|
||||
#else
|
||||
void arc_core_mpu_configure_mem_domain(struct k_thread *thread)
|
||||
{
|
||||
uint32_t region_index;
|
||||
uint32_t num_partitions;
|
||||
uint32_t num_regions;
|
||||
struct k_mem_partition *pparts;
|
||||
struct k_mem_domain *mem_domain = NULL;
|
||||
|
||||
if (thread) {
|
||||
mem_domain = thread->mem_domain_info.mem_domain;
|
||||
}
|
||||
|
||||
if (mem_domain) {
|
||||
LOG_DBG("configure domain: %p", mem_domain);
|
||||
num_partitions = mem_domain->num_partitions;
|
||||
pparts = mem_domain->partitions;
|
||||
} else {
|
||||
LOG_DBG("disable domain partition regions");
|
||||
num_partitions = 0U;
|
||||
pparts = NULL;
|
||||
}
|
||||
|
||||
num_regions = get_num_regions();
|
||||
region_index = get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION);
|
||||
|
||||
while (num_partitions && region_index < num_regions) {
|
||||
if (pparts->size > 0) {
|
||||
LOG_DBG("set region 0x%x 0x%lx 0x%x",
|
||||
region_index, pparts->start, pparts->size);
|
||||
_region_init(region_index, pparts->start,
|
||||
pparts->size, pparts->attr);
|
||||
region_index++;
|
||||
}
|
||||
pparts++;
|
||||
num_partitions--;
|
||||
}
|
||||
|
||||
while (region_index < num_regions) {
|
||||
/* clear the left mpu entries */
|
||||
_region_init(region_index, 0, 0, 0);
|
||||
region_index++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief remove MPU regions for the memory partitions of the memory domain
|
||||
*
|
||||
* @param mem_domain the target memory domain
|
||||
*/
|
||||
void arc_core_mpu_remove_mem_domain(struct k_mem_domain *mem_domain)
|
||||
{
|
||||
uint32_t num_partitions;
|
||||
struct k_mem_partition *pparts;
|
||||
int index;
|
||||
|
||||
if (mem_domain) {
|
||||
LOG_DBG("configure domain: %p", mem_domain);
|
||||
num_partitions = mem_domain->num_partitions;
|
||||
pparts = mem_domain->partitions;
|
||||
} else {
|
||||
LOG_DBG("disable domain partition regions");
|
||||
num_partitions = 0U;
|
||||
pparts = NULL;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < num_partitions; i++) {
|
||||
if (pparts->size) {
|
||||
index = _get_region_index(pparts->start,
|
||||
pparts->size);
|
||||
if (index > 0) {
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
_region_set_attr(index,
|
||||
REGION_KERNEL_RAM_ATTR);
|
||||
#else
|
||||
_region_init(index, 0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
pparts++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief reset MPU region for a single memory partition
|
||||
*
|
||||
* @param partition_id memory partition id
|
||||
*/
|
||||
void arc_core_mpu_remove_mem_partition(struct k_mem_domain *domain,
|
||||
uint32_t partition_id)
|
||||
{
|
||||
struct k_mem_partition *partition = &domain->partitions[partition_id];
|
||||
|
||||
int region_index = _get_region_index(partition->start,
|
||||
partition->size);
|
||||
|
||||
if (region_index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DBG("remove region 0x%x", region_index);
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
_region_set_attr(region_index, REGION_KERNEL_RAM_ATTR);
|
||||
#else
|
||||
_region_init(region_index, 0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the maximum number of free regions for memory domain partitions
|
||||
*/
|
||||
int arc_core_mpu_get_max_domain_partition_regions(void)
|
||||
{
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
/* consider the worst case: each partition requires split */
|
||||
return (get_num_regions() - MPU_REGION_NUM_FOR_THREAD) / 2;
|
||||
#else
|
||||
return get_num_regions() -
|
||||
get_region_index_by_type(THREAD_DOMAIN_PARTITION_REGION) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief validate the given buffer is user accessible or not
|
||||
*/
|
||||
int arc_core_mpu_buffer_validate(void *addr, size_t size, int write)
|
||||
{
|
||||
int r_index;
|
||||
int key = arch_irq_lock();
|
||||
|
||||
/*
|
||||
* For ARC MPU v4, overlapping is not supported.
|
||||
* we can stop the iteration immediately once we find the
|
||||
* matched region that grants permission or denies access.
|
||||
*/
|
||||
r_index = _mpu_probe((uint32_t)addr);
|
||||
/* match and the area is in one region */
|
||||
if (r_index >= 0 && r_index == _mpu_probe((uint32_t)addr + (size - 1))) {
|
||||
if (_is_user_accessible_region(r_index, write)) {
|
||||
r_index = 0;
|
||||
} else {
|
||||
r_index = -EPERM;
|
||||
}
|
||||
} else {
|
||||
r_index = -EPERM;
|
||||
}
|
||||
|
||||
arch_irq_unlock(key);
|
||||
|
||||
return r_index;
|
||||
}
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
/* ARC MPU Driver Initial Setup */
|
||||
/*
|
||||
* @brief MPU default initialization and configuration
|
||||
*
|
||||
* This function provides the default configuration mechanism for the Memory
|
||||
* Protection Unit (MPU).
|
||||
*/
|
||||
static int arc_mpu_init(const struct device *arg)
|
||||
{
|
||||
ARG_UNUSED(arg);
|
||||
uint32_t num_regions;
|
||||
uint32_t i;
|
||||
|
||||
num_regions = get_num_regions();
|
||||
|
||||
/* ARC MPU supports up to 16 Regions */
|
||||
if (mpu_config.num_regions > num_regions) {
|
||||
__ASSERT(0,
|
||||
"Request to configure: %u regions (supported: %u)\n",
|
||||
mpu_config.num_regions, num_regions);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static_regions_num = 0U;
|
||||
|
||||
/* Disable MPU */
|
||||
arc_core_mpu_disable();
|
||||
|
||||
for (i = 0U; i < mpu_config.num_regions; i++) {
|
||||
/* skip empty region */
|
||||
if (mpu_config.mpu_regions[i].size == 0) {
|
||||
continue;
|
||||
}
|
||||
#if defined(CONFIG_MPU_GAP_FILLING)
|
||||
_region_init(static_regions_num,
|
||||
mpu_config.mpu_regions[i].base,
|
||||
mpu_config.mpu_regions[i].size,
|
||||
mpu_config.mpu_regions[i].attr);
|
||||
|
||||
/* record the static region which can be split */
|
||||
if (mpu_config.mpu_regions[i].attr & REGION_DYNAMIC) {
|
||||
if (dynamic_regions_num >=
|
||||
MPU_DYNAMIC_REGION_AREAS_NUM) {
|
||||
LOG_ERR("not enough dynamic regions %d",
|
||||
dynamic_regions_num);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dyn_reg_info[dynamic_regions_num].index = i;
|
||||
dyn_reg_info[dynamic_regions_num].base =
|
||||
mpu_config.mpu_regions[i].base;
|
||||
dyn_reg_info[dynamic_regions_num].size =
|
||||
mpu_config.mpu_regions[i].size;
|
||||
dyn_reg_info[dynamic_regions_num].attr =
|
||||
mpu_config.mpu_regions[i].attr;
|
||||
|
||||
dynamic_regions_num++;
|
||||
}
|
||||
static_regions_num++;
|
||||
#else
|
||||
/* dynamic region will be covered by default mpu setting
|
||||
* no need to configure
|
||||
*/
|
||||
if (!(mpu_config.mpu_regions[i].attr & REGION_DYNAMIC)) {
|
||||
_region_init(static_regions_num,
|
||||
mpu_config.mpu_regions[i].base,
|
||||
mpu_config.mpu_regions[i].size,
|
||||
mpu_config.mpu_regions[i].attr);
|
||||
static_regions_num++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = static_regions_num; i < num_regions; i++) {
|
||||
_region_init(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Enable MPU */
|
||||
arc_core_mpu_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(arc_mpu_init, PRE_KERNEL_1,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V4_INTERNAL_H_ */
|
||||
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Synopsys.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V6_INTERNAL_H_
|
||||
#define ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V6_INTERNAL_H_
|
||||
|
||||
#define AUX_MPU_EN_BANK_MASK BIT(0)
|
||||
#define AUX_MPU_EN_IC BIT(12)
|
||||
#define AUX_MPU_EN_DC BIT(13)
|
||||
#define AUX_MPU_EN_ENABLE BIT(30)
|
||||
#define AUX_MPU_EN_DISABLE ~BIT(30)
|
||||
|
||||
/*
|
||||
* The size of the region is a 5-bit field, the three MSB bits are
|
||||
* represented in [11:9] and the two LSB bits are represented in [1:0].
|
||||
* Together these fields specify the size of the region in bytes:
|
||||
* 00000-00011 Reserved
|
||||
* 0x4 32 0x5 64 0x6 128 0x7 256
|
||||
* 0x8 512 0x9 1k 0xA 2K 0xB 4K
|
||||
* 0xC 8K 0xD 16K 0xE 32K 0xF 64K
|
||||
* 0x10 128K 0x11 256K 0x12 512K 0x13 1M
|
||||
* 0x14 2M 0x15 4M 0x16 8M 0x17 16M
|
||||
* 0x18 32M 0x19 64M 0x1A 128M 0x1B 256M
|
||||
* 0x1C 512M 0x1D 1G 0x1E 2G 0x1F 4G
|
||||
*
|
||||
* Bit ... 12 11 10 9 8 3 2 1 0
|
||||
* ------+------------+------+---+-----------+
|
||||
* ... | SIZE[11:9] | ATTR | R | SIZE[1:0] |
|
||||
* ------+------------+------+---+-----------+
|
||||
*/
|
||||
/* arrange size into proper bit field in RDP aux reg*/
|
||||
#define AUX_MPU_RDP_REGION_SIZE(size) (((size - 1) & BIT_MASK(2)) | \
|
||||
(((size - 1) & (BIT_MASK(3) << 2)) << 7))
|
||||
/* recover size from bit fields in RDP aux reg*/
|
||||
#define AUX_MPU_RDP_SIZE_SHIFT(rdp) ((rdp & BIT_MASK(2)) | (((rdp >> 9) & BIT_MASK(3)) << 2))
|
||||
|
||||
#define AUX_MPU_RDB_VALID_MASK BIT(0)
|
||||
#define AUX_MPU_RDP_ATTR_MASK (BIT_MASK(6) << 3)
|
||||
#define AUX_MPU_RDP_SIZE_MASK ((BIT_MASK(3) << 9) | BIT_MASK(2))
|
||||
/* Global code cacheability that applies to a region
|
||||
* 0x0: (Default) Code is cacheable in all levels of the cache hierarchy
|
||||
* 0x1: Code is not cacheable in any level of the cache hierarchy
|
||||
*/
|
||||
#define AUX_MPU_RDB_IC BIT(12)
|
||||
/* Global data cacheability that applies to a region
|
||||
* 0x0: (Default) Data is cacheable in all levels of the cache hierarchy
|
||||
* 0x1: Data is not cacheable in any level of the cache hierarchy
|
||||
*/
|
||||
#define AUX_MPU_RDB_DC BIT(13)
|
||||
/* Define a MPU region as non-volatile
|
||||
* 0x0: (Default) The memory space for this MPU region is treated as a volatile uncached space.
|
||||
* 0x1: The memory space for this MPU region is non-volatile
|
||||
*/
|
||||
#define AUX_MPU_RDB_NV BIT(14)
|
||||
|
||||
/* For MPU version 6, the minimum protection region size is 32 bytes */
|
||||
#define ARC_FEATURE_MPU_ALIGNMENT_BITS 5
|
||||
#define ARC_FEATURE_MPU_BANK_SIZE 16
|
||||
|
||||
/**
|
||||
* This internal function select a MPU bank
|
||||
*/
|
||||
static inline void _bank_select(uint32_t bank)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = z_arc_v2_aux_reg_read(_ARC_V2_MPU_EN) & (~AUX_MPU_EN_BANK_MASK);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_EN, val | bank);
|
||||
}
|
||||
/**
|
||||
* This internal function initializes a MPU region
|
||||
*/
|
||||
static inline void _region_init(uint32_t index, uint32_t region_addr,
|
||||
uint32_t size, uint32_t region_attr)
|
||||
{
|
||||
uint32_t bank = index / ARC_FEATURE_MPU_BANK_SIZE;
|
||||
|
||||
index = (index % ARC_FEATURE_MPU_BANK_SIZE) * 2U;
|
||||
|
||||
if (size > 0) {
|
||||
uint8_t bits = find_msb_set(size) - 1;
|
||||
|
||||
if (bits < ARC_FEATURE_MPU_ALIGNMENT_BITS) {
|
||||
bits = ARC_FEATURE_MPU_ALIGNMENT_BITS;
|
||||
}
|
||||
|
||||
if (BIT(bits) < size) {
|
||||
bits++;
|
||||
}
|
||||
|
||||
/* Clear size bits and IC, DC bits, and set NV bit
|
||||
* The default value of NV bit is 0 which means the region is volatile and uncached.
|
||||
* Setting the NV bit here has no effect on mpu v6 but is for the
|
||||
* forward compatibility to mpu v7. Currently we do not allow to toggle these bits
|
||||
* until we implement the control of these region properties
|
||||
* TODO: support uncacheable regions and volatile uncached regions
|
||||
*/
|
||||
region_attr &= ~(AUX_MPU_RDP_SIZE_MASK | AUX_MPU_RDB_IC | AUX_MPU_RDB_DC);
|
||||
region_attr |= AUX_MPU_RDP_REGION_SIZE(bits) | AUX_MPU_RDB_NV;
|
||||
region_addr |= AUX_MPU_RDB_VALID_MASK;
|
||||
} else {
|
||||
region_addr = 0U;
|
||||
}
|
||||
|
||||
_bank_select(bank);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RDP0 + index, region_attr);
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_MPU_RDB0 + index, region_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function is utilized by the MPU driver to parse the intent
|
||||
* type (i.e. THREAD_STACK_REGION) and return the correct region index.
|
||||
*/
|
||||
static inline int get_region_index_by_type(uint32_t type)
|
||||
{
|
||||
/*
|
||||
* The new MPU regions are allocated per type after the statically
|
||||
* configured regions. The type is one-indexed rather than
|
||||
* zero-indexed.
|
||||
*
|
||||
* For ARC MPU v6, the smaller index has higher priority, so the
|
||||
* index is allocated in reverse order. Static regions start from
|
||||
* the biggest index, then thread related regions.
|
||||
*
|
||||
*/
|
||||
switch (type) {
|
||||
case THREAD_STACK_USER_REGION:
|
||||
return get_num_regions() - mpu_config.num_regions - THREAD_STACK_REGION;
|
||||
case THREAD_STACK_REGION:
|
||||
case THREAD_APP_DATA_REGION:
|
||||
case THREAD_DOMAIN_PARTITION_REGION:
|
||||
/*
|
||||
* Start domain partition region from stack guard region
|
||||
* since stack guard is not supported.
|
||||
*/
|
||||
return get_num_regions() - mpu_config.num_regions - type + 1;
|
||||
default:
|
||||
__ASSERT(0, "Unsupported type");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function checks if region is enabled or not
|
||||
*/
|
||||
static inline bool _is_enabled_region(uint32_t r_index)
|
||||
{
|
||||
uint32_t bank = r_index / ARC_FEATURE_MPU_BANK_SIZE;
|
||||
uint32_t index = (r_index % ARC_FEATURE_MPU_BANK_SIZE) * 2U;
|
||||
|
||||
_bank_select(bank);
|
||||
return ((z_arc_v2_aux_reg_read(_ARC_V2_MPU_RDB0 + index)
|
||||
& AUX_MPU_RDB_VALID_MASK) == AUX_MPU_RDB_VALID_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the given buffer in in the region
|
||||
*/
|
||||
static inline bool _is_in_region(uint32_t r_index, uint32_t start, uint32_t size)
|
||||
{
|
||||
uint32_t r_addr_start;
|
||||
uint32_t r_addr_end;
|
||||
uint32_t r_size_lshift;
|
||||
uint32_t bank = r_index / ARC_FEATURE_MPU_BANK_SIZE;
|
||||
uint32_t index = (r_index % ARC_FEATURE_MPU_BANK_SIZE) * 2U;
|
||||
|
||||
_bank_select(bank);
|
||||
r_addr_start = z_arc_v2_aux_reg_read(_ARC_V2_MPU_RDB0 + index) & (~AUX_MPU_RDB_VALID_MASK);
|
||||
r_size_lshift = z_arc_v2_aux_reg_read(_ARC_V2_MPU_RDP0 + index) & AUX_MPU_RDP_SIZE_MASK;
|
||||
r_size_lshift = AUX_MPU_RDP_SIZE_SHIFT(r_size_lshift);
|
||||
r_addr_end = r_addr_start + (1 << (r_size_lshift + 1));
|
||||
|
||||
if (start >= r_addr_start && (start + size) <= r_addr_end) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This internal function check if the region is user accessible or not
|
||||
*/
|
||||
static inline bool _is_user_accessible_region(uint32_t r_index, int write)
|
||||
{
|
||||
uint32_t r_ap;
|
||||
uint32_t bank = r_index / ARC_FEATURE_MPU_BANK_SIZE;
|
||||
uint32_t index = (r_index % ARC_FEATURE_MPU_BANK_SIZE) * 2U;
|
||||
|
||||
_bank_select(bank);
|
||||
r_ap = z_arc_v2_aux_reg_read(_ARC_V2_MPU_RDP0 + index);
|
||||
|
||||
r_ap &= AUX_MPU_RDP_ATTR_MASK;
|
||||
|
||||
if (write) {
|
||||
return ((r_ap & (AUX_MPU_ATTR_UW | AUX_MPU_ATTR_KW)) ==
|
||||
(AUX_MPU_ATTR_UW | AUX_MPU_ATTR_KW));
|
||||
}
|
||||
|
||||
return ((r_ap & (AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR)) ==
|
||||
(AUX_MPU_ATTR_UR | AUX_MPU_ATTR_KR));
|
||||
}
|
||||
|
||||
#endif /* ZEPHYR_ARCH_ARC_CORE_MPU_ARC_MPU_V6_INTERNAL_H_ */
|
||||
@@ -37,11 +37,6 @@ GEN_OFFSET_SYM(_thread_arch_t, u_stack_top);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
GEN_OFFSET_SYM(_thread_arch_t, priv_stack_start);
|
||||
#endif
|
||||
|
||||
|
||||
/* ARCv2-specific IRQ stack frame structure member offsets */
|
||||
GEN_OFFSET_SYM(_isf_t, r0);
|
||||
GEN_OFFSET_SYM(_isf_t, r1);
|
||||
@@ -58,11 +53,9 @@ GEN_OFFSET_SYM(_isf_t, r11);
|
||||
GEN_OFFSET_SYM(_isf_t, r12);
|
||||
GEN_OFFSET_SYM(_isf_t, r13);
|
||||
GEN_OFFSET_SYM(_isf_t, blink);
|
||||
#ifdef CONFIG_ARC_HAS_ZOL
|
||||
GEN_OFFSET_SYM(_isf_t, lp_end);
|
||||
GEN_OFFSET_SYM(_isf_t, lp_start);
|
||||
GEN_OFFSET_SYM(_isf_t, lp_count);
|
||||
#endif /* CONFIG_ARC_HAS_ZOL */
|
||||
#ifdef CONFIG_CODE_DENSITY
|
||||
GEN_OFFSET_SYM(_isf_t, ei_base);
|
||||
GEN_OFFSET_SYM(_isf_t, ldi_base);
|
||||
@@ -106,7 +99,7 @@ GEN_OFFSET_SYM(_callee_saved_stack_t, r30);
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, r58);
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, r59);
|
||||
#endif
|
||||
#ifdef CONFIG_FPU_SHARING
|
||||
#ifdef CONFIG_FP_SHARING
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, fpu_status);
|
||||
GEN_OFFSET_SYM(_callee_saved_stack_t, fpu_ctrl);
|
||||
#ifdef CONFIG_FP_FPU_DA
|
||||
|
||||
@@ -27,10 +27,13 @@
|
||||
/* XXX - keep for future use in full-featured cache APIs */
|
||||
#if 0
|
||||
/**
|
||||
*
|
||||
* @brief Disable the i-cache if present
|
||||
*
|
||||
* For those ARC CPUs that have a i-cache present,
|
||||
* invalidate the i-cache and then disable it.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
static void disable_icache(void)
|
||||
@@ -43,15 +46,18 @@ static void disable_icache(void)
|
||||
return; /* skip if i-cache is not present */
|
||||
}
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IC_IVIC, 0);
|
||||
__builtin_arc_nop();
|
||||
__asm__ __volatile__ ("nop");
|
||||
z_arc_v2_aux_reg_write(_ARC_V2_IC_CTRL, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Invalidate the data cache if present
|
||||
*
|
||||
* For those ARC CPUs that have a data cache present,
|
||||
* invalidate the data cache.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
static void invalidate_dcache(void)
|
||||
@@ -69,13 +75,17 @@ static void invalidate_dcache(void)
|
||||
|
||||
extern FUNC_NORETURN void z_cstart(void);
|
||||
/**
|
||||
*
|
||||
* @brief Prepare to and run C code
|
||||
*
|
||||
* This routine prepares for the execution of and runs C code.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
void _PrepC(void)
|
||||
{
|
||||
z_icache_setup();
|
||||
z_bss_zero();
|
||||
z_data_copy();
|
||||
z_cstart();
|
||||
|
||||
@@ -20,11 +20,21 @@
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <swap_macros.h>
|
||||
#include <arch/arc/asm-compat/assembler.h>
|
||||
|
||||
GTEXT(_rirq_enter)
|
||||
GTEXT(_rirq_exit)
|
||||
GTEXT(_rirq_newthread_switch)
|
||||
GTEXT(_rirq_common_interrupt_swap)
|
||||
|
||||
|
||||
#if 0 /* TODO: when FIRQ is not present, all would be regular */
|
||||
#define NUM_REGULAR_IRQ_PRIO_LEVELS CONFIG_NUM_IRQ_PRIO_LEVELS
|
||||
#else
|
||||
#define NUM_REGULAR_IRQ_PRIO_LEVELS (CONFIG_NUM_IRQ_PRIO_LEVELS-1)
|
||||
#endif
|
||||
/* note: the above define assumes that prio 0 IRQ is for FIRQ, and
|
||||
* that all others are regular interrupts.
|
||||
* TODO: Revist this if FIRQ becomes configurable.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -190,6 +200,7 @@ will be corrupted.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Work to be done before handing control to an IRQ ISR
|
||||
*
|
||||
* The processor pushes automatically all registers that need to be saved.
|
||||
@@ -197,57 +208,93 @@ will be corrupted.
|
||||
* automatic switch to the IRQ stack: this must be done in software.
|
||||
*
|
||||
* Assumption by _isr_demux: r3 is untouched by _rirq_enter.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _rirq_enter)
|
||||
|
||||
/* the ISR will be handled in separate interrupt stack,
|
||||
* so stack checking must be diabled, or exception will
|
||||
* be caused
|
||||
*/
|
||||
_disable_stack_checking r2
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r2, [_ARC_V2_SEC_STAT]
|
||||
bclr r2, r2, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r2
|
||||
|
||||
#else
|
||||
/* disable stack checking */
|
||||
lr r2, [_ARC_V2_STATUS32]
|
||||
bclr r2, r2, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag r2
|
||||
#endif
|
||||
#endif
|
||||
clri
|
||||
|
||||
/* check whether irq stack is used, if
|
||||
* not switch to isr stack
|
||||
*/
|
||||
/* check whether irq stack is used */
|
||||
_check_and_inc_int_nest_counter r0, r1
|
||||
|
||||
bne.d rirq_nest
|
||||
MOVR r0, sp
|
||||
mov_s r0, sp
|
||||
|
||||
_get_curr_cpu_irq_stack sp
|
||||
rirq_nest:
|
||||
PUSHR r0
|
||||
push_s r0
|
||||
|
||||
seti
|
||||
j _isr_demux
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Work to be done exiting an IRQ
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, _rirq_exit)
|
||||
clri
|
||||
|
||||
POPR sp
|
||||
pop sp
|
||||
|
||||
_dec_int_nest_counter r0, r1
|
||||
|
||||
_check_nest_int_by_irq_act r0, r1
|
||||
|
||||
jne _rirq_no_switch
|
||||
jne _rirq_no_reschedule
|
||||
|
||||
/* sp is struct k_thread **old of z_arc_switch_in_isr
|
||||
* which is a wrapper of z_get_next_switch_handle.
|
||||
* r0 contains the 1st thread in ready queue. if
|
||||
* it equals _current(r2) ,then do swap, or no swap.
|
||||
#ifdef CONFIG_STACK_SENTINEL
|
||||
bl z_check_stack_sentinel
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
bl z_arc_smp_switch_in_isr
|
||||
/* r0 points to new thread, r1 points to old thread */
|
||||
cmp_s r0, 0
|
||||
beq _rirq_no_reschedule
|
||||
mov_s r2, r1
|
||||
#else
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
/*
|
||||
* Both (a)reschedule and (b)non-reschedule cases need to load the
|
||||
* current thread's stack, but don't have to use it until the decision
|
||||
* is taken: load the delay slots with the 'load stack pointer'
|
||||
* instruction.
|
||||
*
|
||||
* a) needs to load it to save outgoing context.
|
||||
* b) needs to load it to restore the interrupted context.
|
||||
*/
|
||||
_get_next_switch_handle
|
||||
|
||||
CMPR r0, r2
|
||||
beq _rirq_no_switch
|
||||
/* check if the current thread needs to be rescheduled */
|
||||
ld_s r0, [r1, _kernel_offset_to_ready_q_cache]
|
||||
cmp_s r0, r2
|
||||
beq _rirq_no_reschedule
|
||||
|
||||
/* cached thread to run is in r0, fall through */
|
||||
#endif
|
||||
.balign 4
|
||||
_rirq_reschedule:
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* here need to remember SEC_STAT.IRM bit */
|
||||
@@ -255,35 +302,81 @@ SECTION_FUNC(TEXT, _rirq_exit)
|
||||
push_s r3
|
||||
#endif
|
||||
|
||||
/* r2 is old thread */
|
||||
_irq_store_old_thread_callee_regs
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* need to remember the user/kernel status of interrupted thread
|
||||
*/
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
and r3, r3, 0x80000000
|
||||
push_s r3
|
||||
#endif
|
||||
/* _save_callee_saved_regs expects outgoing thread in r2 */
|
||||
_save_callee_saved_regs
|
||||
|
||||
/* _thread_arch.relinquish_cause is 32 bit despite of platform bittnes */
|
||||
_st32_huge_offset _CAUSE_RIRQ, r2, _thread_offset_to_relinquish_cause, r2
|
||||
st _CAUSE_RIRQ, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
/* mov new thread (r0) to r2 */
|
||||
MOVR r2, r0
|
||||
#ifdef CONFIG_SMP
|
||||
mov_s r2, r0
|
||||
#else
|
||||
/* incoming thread is in r0: it becomes the new 'current' */
|
||||
mov_s r2, r0
|
||||
st_s r2, [r1, _kernel_offset_to_current]
|
||||
#endif
|
||||
|
||||
/* _rirq_newthread_switch required by exception handling */
|
||||
.align 4
|
||||
_rirq_newthread_switch:
|
||||
.balign 4
|
||||
_rirq_common_interrupt_swap:
|
||||
/* r2 contains pointer to new thread */
|
||||
|
||||
_load_new_thread_callee_regs
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
_load_stack_check_regs
|
||||
#endif
|
||||
/*
|
||||
* _load_callee_saved_regs expects incoming thread in r2.
|
||||
* _load_callee_saved_regs restores the stack pointer.
|
||||
*/
|
||||
_load_callee_saved_regs
|
||||
|
||||
breq r3, _CAUSE_RIRQ, _rirq_switch_from_rirq
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
push_s r2
|
||||
mov_s r0, r2
|
||||
bl configure_mpu_thread
|
||||
pop_s r2
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* when USERSPACE is enabled, according to ARCv2 ISA, SP will be switched
|
||||
* if interrupt comes out in user mode, and will be recorded in bit 31
|
||||
* (U bit) of IRQ_ACT. when interrupt exits, SP will be switched back
|
||||
* according to U bit.
|
||||
*
|
||||
* For the case that context switches in interrupt, the target sp must be
|
||||
* thread's kernel stack, no need to do hardware sp switch. so, U bit should
|
||||
* be cleared.
|
||||
*/
|
||||
lr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
bclr r0, r0, 31
|
||||
sr r0, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
|
||||
ld r3, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
breq r3, _CAUSE_RIRQ, _rirq_return_from_rirq
|
||||
nop_s
|
||||
breq r3, _CAUSE_FIRQ, _rirq_switch_from_firq
|
||||
breq r3, _CAUSE_FIRQ, _rirq_return_from_firq
|
||||
nop_s
|
||||
|
||||
/* fall through */
|
||||
|
||||
.align 4
|
||||
_rirq_switch_from_coop:
|
||||
.balign 4
|
||||
_rirq_return_from_coop:
|
||||
|
||||
/* for a cooperative switch, it's not in irq, so
|
||||
* need to set some regs for irq return
|
||||
*/
|
||||
_set_misc_regs_irq_switch_from_coop
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* must return to secure mode, so set IRM bit to 1 */
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
bset r0, r0, _ARC_V2_SEC_STAT_IRM_BIT
|
||||
sflag r0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* See verbose explanation of
|
||||
@@ -291,13 +384,11 @@ _rirq_switch_from_coop:
|
||||
*/
|
||||
|
||||
/* carve fake stack */
|
||||
SUBR sp, sp, ___isf_t_pc_OFFSET
|
||||
sub sp, sp, ___isf_t_pc_OFFSET
|
||||
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ZOL
|
||||
/* reset zero-overhead loops */
|
||||
STR 0, sp, ___isf_t_lp_end_OFFSET
|
||||
#endif /* CONFIG_ARC_HAS_ZOL */
|
||||
st 0, [sp, ___isf_t_lp_end_OFFSET]
|
||||
|
||||
/*
|
||||
* r13 is part of both the callee and caller-saved register sets because
|
||||
@@ -305,31 +396,29 @@ _rirq_switch_from_coop:
|
||||
* IRQ prologue. r13 thus has to be set to its correct value in the IRQ
|
||||
* stack frame.
|
||||
*/
|
||||
STR r13, sp, ___isf_t_r13_OFFSET
|
||||
st_s r13, [sp, ___isf_t_r13_OFFSET]
|
||||
|
||||
#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING
|
||||
PUSHR blink
|
||||
|
||||
bl z_thread_mark_switched_in
|
||||
|
||||
POPR blink
|
||||
#endif
|
||||
/* stack now has the IRQ stack frame layout, pointing to sp */
|
||||
/* rtie will pop the rest from the stack */
|
||||
rtie
|
||||
|
||||
.align 4
|
||||
_rirq_switch_from_firq:
|
||||
_rirq_switch_from_rirq:
|
||||
|
||||
_set_misc_regs_irq_switch_from_irq
|
||||
|
||||
#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING
|
||||
PUSHR blink
|
||||
|
||||
bl z_thread_mark_switched_in
|
||||
|
||||
POPR blink
|
||||
.balign 4
|
||||
_rirq_return_from_firq:
|
||||
_rirq_return_from_rirq:
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* need to recover the user/kernel status of interrupted thread
|
||||
*/
|
||||
pop_s r3
|
||||
lr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
or r2, r2, r3
|
||||
sr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
_rirq_no_switch:
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* here need to recover SEC_STAT.IRM bit */
|
||||
pop_s r3
|
||||
sflag r3
|
||||
#endif
|
||||
_rirq_no_reschedule:
|
||||
|
||||
rtie
|
||||
|
||||
@@ -15,22 +15,22 @@
|
||||
#include <linker/sections.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <swap_macros.h>
|
||||
#include <arch/arc/asm-compat/assembler.h>
|
||||
|
||||
GDATA(z_interrupt_stacks)
|
||||
GDATA(_interrupt_stack)
|
||||
GDATA(z_main_stack)
|
||||
GDATA(_VectorTable)
|
||||
|
||||
/* use one of the available interrupt stacks during init */
|
||||
|
||||
|
||||
#define INIT_STACK z_interrupt_stacks
|
||||
#define INIT_STACK _interrupt_stack
|
||||
#define INIT_STACK_SIZE CONFIG_ISR_STACK_SIZE
|
||||
|
||||
GTEXT(__reset)
|
||||
GTEXT(__start)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Reset vector
|
||||
*
|
||||
* Ran when the system comes out of reset. The processor is at supervisor level.
|
||||
@@ -39,10 +39,12 @@ GTEXT(__start)
|
||||
*
|
||||
* When these steps are completed, jump to _PrepC(), which will finish setting
|
||||
* up the system for running C code.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_SUBSEC_FUNC(TEXT,_reset_and__start,__reset)
|
||||
SECTION_SUBSEC_FUNC(TEXT,_reset_and__start,__start)
|
||||
SECTION_FUNC(TEXT,__reset)
|
||||
SECTION_FUNC(TEXT,__start)
|
||||
/* lock interrupts: will get unlocked when switch to main task
|
||||
* also make sure the processor in the correct status
|
||||
*/
|
||||
@@ -52,6 +54,17 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_and__start,__start)
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
sflag r0
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BOOT_TIME_MEASUREMENT) && defined(CONFIG_ARCV2_TIMER)
|
||||
/*
|
||||
* ARCV2 timer (timer0) is a free run timer, let it start to count
|
||||
* here.
|
||||
*/
|
||||
mov_s r0, 0xffffffff
|
||||
sr r0, [_ARC_V2_TMR0_LIMIT]
|
||||
mov_s r0, 0
|
||||
sr r0, [_ARC_V2_TMR0_COUNT]
|
||||
#endif
|
||||
/* interrupt related init */
|
||||
#ifndef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
/* IRQ_ACT and IRQ_CTRL should be initialized and set in secure mode */
|
||||
@@ -63,17 +76,13 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_and__start,__start)
|
||||
/* set the vector table base early,
|
||||
* so that exception vectors can be handled.
|
||||
*/
|
||||
MOVR r0, _VectorTable
|
||||
mov_s r0, _VectorTable
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
sr r0, [_ARC_V2_IRQ_VECT_BASE_S]
|
||||
#else
|
||||
SRR r0, [_ARC_V2_IRQ_VECT_BASE]
|
||||
sr r0, [_ARC_V2_IRQ_VECT_BASE]
|
||||
#endif
|
||||
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_DZ_BIT
|
||||
kflag r0
|
||||
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_US_BIT
|
||||
@@ -86,10 +95,13 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_and__start,__start)
|
||||
kflag r0
|
||||
#endif
|
||||
|
||||
/* Invalidate icache */
|
||||
mov_s r1, 1
|
||||
|
||||
invalidate_and_disable_icache:
|
||||
|
||||
lr r0, [_ARC_V2_I_CACHE_BUILD]
|
||||
and.f r0, r0, 0xff
|
||||
bz.nd done_icache_invalidate
|
||||
bz.nd invalidate_dcache
|
||||
|
||||
mov_s r2, 0
|
||||
sr r2, [_ARC_V2_IC_IVIC]
|
||||
@@ -97,52 +109,24 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_and__start,__start)
|
||||
nop_s
|
||||
nop_s
|
||||
nop_s
|
||||
done_icache_invalidate:
|
||||
sr r1, [_ARC_V2_IC_CTRL]
|
||||
|
||||
invalidate_dcache:
|
||||
|
||||
/* Invalidate dcache */
|
||||
lr r3, [_ARC_V2_D_CACHE_BUILD]
|
||||
and.f r3, r3, 0xff
|
||||
bz.nd done_dcache_invalidate
|
||||
bz.nd done_cache_invalidate
|
||||
|
||||
mov_s r1, 1
|
||||
sr r1, [_ARC_V2_DC_IVDC]
|
||||
|
||||
done_dcache_invalidate:
|
||||
done_cache_invalidate:
|
||||
|
||||
/*
|
||||
* Init ARC internal architecture state
|
||||
* Force to initialize internal architecture state to reset values
|
||||
* For scenarios where board hardware is not re-initialized between tests,
|
||||
* some settings need to be restored to its default initial states as a
|
||||
* substitution of normal hardware reset sequence.
|
||||
*/
|
||||
#ifdef CONFIG_INIT_ARCH_HW_AT_BOOT
|
||||
/* Set MPU (v4) registers to default */
|
||||
#if CONFIG_ARC_MPU_VER == 4
|
||||
/* Set default reset value to _ARC_V2_MPU_EN register */
|
||||
#define ARC_MPU_EN_RESET_VALUE 0x400181C0
|
||||
mov_s r1, ARC_MPU_EN_RESET_VALUE
|
||||
sr r1, [_ARC_V2_MPU_EN]
|
||||
/* Get MPU region numbers */
|
||||
lr r3, [_ARC_V2_MPU_BUILD]
|
||||
lsr_s r3, r3, 8
|
||||
and r3, r3, 0xff
|
||||
mov_s r1, 0
|
||||
mov_s r2, 0
|
||||
/* Set all MPU regions by iterating index */
|
||||
mpu_regions_reset:
|
||||
brge r2, r3, done_mpu_regions_reset
|
||||
sr r2, [_ARC_V2_MPU_INDEX]
|
||||
sr r1, [_ARC_V2_MPU_RSTART]
|
||||
sr r1, [_ARC_V2_MPU_REND]
|
||||
sr r1, [_ARC_V2_MPU_RPER]
|
||||
add_s r2, r2, 1
|
||||
b_s mpu_regions_reset
|
||||
done_mpu_regions_reset:
|
||||
#endif
|
||||
#if defined(CONFIG_SYS_POWER_DEEP_SLEEP_STATES) && \
|
||||
!defined(CONFIG_BOOTLOADER_CONTEXT_RESTORE)
|
||||
jl @_sys_resume_from_deep_sleep
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SMP) || CONFIG_MP_NUM_CPUS > 1
|
||||
#if CONFIG_MP_NUM_CPUS > 1
|
||||
_get_cpu_id r0
|
||||
breq r0, 0, _master_core_startup
|
||||
|
||||
@@ -150,20 +134,15 @@ done_mpu_regions_reset:
|
||||
* Non-masters wait for master core (core 0) to boot enough
|
||||
*/
|
||||
_slave_core_wait:
|
||||
#if CONFIG_MP_NUM_CPUS == 1
|
||||
kflag 1
|
||||
#endif
|
||||
ld r1, [arc_cpu_wake_flag]
|
||||
brne r0, r1, _slave_core_wait
|
||||
|
||||
LDR sp, arc_cpu_sp
|
||||
ld sp, [arc_cpu_sp]
|
||||
/* signal master core that slave core runs */
|
||||
st 0, [arc_cpu_wake_flag]
|
||||
|
||||
#if defined(CONFIG_ARC_FIRQ_STACK)
|
||||
push r0
|
||||
jl z_arc_firq_stack_set
|
||||
pop r0
|
||||
#endif
|
||||
j z_arc_slave_start
|
||||
|
||||
@@ -179,7 +158,7 @@ _master_core_startup:
|
||||
mov_s sp, z_main_stack
|
||||
add sp, sp, CONFIG_MAIN_STACK_SIZE
|
||||
|
||||
mov_s r0, z_interrupt_stacks
|
||||
mov_s r0, _interrupt_stack
|
||||
mov_s r1, 0xaa
|
||||
mov_s r2, CONFIG_ISR_STACK_SIZE
|
||||
jl memset
|
||||
@@ -193,4 +172,4 @@ _master_core_startup:
|
||||
jl z_arc_firq_stack_set
|
||||
#endif
|
||||
|
||||
j _PrepC
|
||||
j @_PrepC
|
||||
|
||||
@@ -19,9 +19,9 @@ static void _default_sjli_entry(void);
|
||||
* \todo: how to let user to install customized sjli entry easily, e.g.
|
||||
* through macros or with the help of compiler?
|
||||
*/
|
||||
const static uint32_t _sjli_vector_table[CONFIG_SJLI_TABLE_SIZE] = {
|
||||
[0] = (uint32_t)_arc_do_secure_call,
|
||||
[1 ... (CONFIG_SJLI_TABLE_SIZE - 1)] = (uint32_t)_default_sjli_entry,
|
||||
const static u32_t _sjli_vector_table[CONFIG_SJLI_TABLE_SIZE] = {
|
||||
[0] = (u32_t)_arc_do_secure_call,
|
||||
[1 ... (CONFIG_SJLI_TABLE_SIZE - 1)] = (u32_t)_default_sjli_entry,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -48,7 +48,7 @@ static void sjli_table_init(void)
|
||||
/*
|
||||
* @brief initializaiton of secureshield related functions.
|
||||
*/
|
||||
static int arc_secureshield_init(const struct device *arg)
|
||||
static int arc_secureshield_init(struct device *arg)
|
||||
{
|
||||
sjli_table_init();
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* an secure service to access secure aux regs. Check should be done
|
||||
* to decide whether the access is valid.
|
||||
*/
|
||||
static int32_t arc_s_aux_read(uint32_t aux_reg)
|
||||
static s32_t arc_s_aux_read(u32_t aux_reg)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -37,7 +37,7 @@ static int32_t arc_s_aux_read(uint32_t aux_reg)
|
||||
* an secure service to access secure aux regs. Check should be done
|
||||
* to decide whether the access is valid.
|
||||
*/
|
||||
static int32_t arc_s_aux_write(uint32_t aux_reg, uint32_t val)
|
||||
static s32_t arc_s_aux_write(u32_t aux_reg, u32_t val)
|
||||
{
|
||||
if (aux_reg == _ARC_V2_AUX_IRQ_ACT) {
|
||||
/* 0 -> CONFIG_NUM_IRQ_PRIO_LEVELS allocated to secure world
|
||||
@@ -64,7 +64,7 @@ static int32_t arc_s_aux_write(uint32_t aux_reg, uint32_t val)
|
||||
* apply one. Necessary check should be done to decide whether the apply is
|
||||
* valid
|
||||
*/
|
||||
static int32_t arc_s_irq_alloc(uint32_t intno)
|
||||
static s32_t arc_s_irq_alloc(u32_t intno)
|
||||
{
|
||||
z_arc_v2_irq_uinit_secure_set(intno, 0);
|
||||
return 0;
|
||||
|
||||
@@ -21,9 +21,8 @@
|
||||
#include <arch/cpu.h>
|
||||
#include <v2/irq.h>
|
||||
#include <swap_macros.h>
|
||||
#include <arch/arc/asm-compat/assembler.h>
|
||||
|
||||
GTEXT(z_arc_switch)
|
||||
GTEXT(arch_switch)
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -53,25 +52,39 @@ GTEXT(z_arc_switch)
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, z_arc_switch)
|
||||
SECTION_FUNC(TEXT, arch_switch)
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
push_s r0
|
||||
push_s r1
|
||||
push_s blink
|
||||
|
||||
bl read_timer_start_of_swap
|
||||
|
||||
pop_s blink
|
||||
pop_s r1
|
||||
pop_s r0
|
||||
#endif
|
||||
/*
|
||||
* r0 = new_thread->switch_handle = switch_to thread,
|
||||
* r1 = &old_thread->switch_handle
|
||||
* get old_thread from r1
|
||||
* r1 = &old_thread->switch_handle = &switch_from thread
|
||||
*/
|
||||
|
||||
SUBR r2, r1, ___thread_t_switch_handle_OFFSET
|
||||
ld_s r2, [r1]
|
||||
/*
|
||||
* r2 may be dummy_thread in z_cstart, dummy_thread->switch_handle
|
||||
* must be 0
|
||||
*/
|
||||
breq r2, 0, _switch_to_target_thread
|
||||
|
||||
/* _thread_arch.relinquish_cause is 32 bit despite of platform bittnes */
|
||||
_st32_huge_offset _CAUSE_COOP, r2, _thread_offset_to_relinquish_cause, r3
|
||||
st _CAUSE_COOP, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
/*
|
||||
* Save status32 and blink on the stack before the callee-saved registers.
|
||||
* This is the same layout as the start of an IRQ stack frame.
|
||||
*/
|
||||
LRR r3, [_ARC_V2_STATUS32]
|
||||
PUSHR r3
|
||||
lr r3, [_ARC_V2_STATUS32]
|
||||
push_s r3
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
@@ -82,18 +95,41 @@ SECTION_FUNC(TEXT, z_arc_switch)
|
||||
push_s r3
|
||||
#endif
|
||||
|
||||
PUSHR blink
|
||||
push_s blink
|
||||
|
||||
_store_old_thread_callee_regs
|
||||
_save_callee_saved_regs
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* disable stack checking here, as sp will be changed to target
|
||||
* thread'sp
|
||||
*/
|
||||
_disable_stack_checking r3
|
||||
#if defined(CONFIG_ARC_HAS_SECURE) && defined(CONFIG_ARC_SECURE_FIRMWARE)
|
||||
bclr r3, r3, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r3
|
||||
#else
|
||||
bclr r3, r3, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag r3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
MOVR r2, r0
|
||||
_switch_to_target_thread:
|
||||
|
||||
_load_new_thread_callee_regs
|
||||
mov_s r2, r0
|
||||
|
||||
/* entering here, r2 contains the new current thread */
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
_load_stack_check_regs
|
||||
#endif
|
||||
|
||||
_load_callee_saved_regs
|
||||
|
||||
#if defined(CONFIG_MPU_STACK_GUARD) || defined(CONFIG_USERSPACE)
|
||||
push_s r2
|
||||
bl configure_mpu_thread
|
||||
pop_s r2
|
||||
#endif
|
||||
|
||||
ld r3, [r2, _thread_offset_to_relinquish_cause]
|
||||
|
||||
breq r3, _CAUSE_RIRQ, _switch_return_from_rirq
|
||||
nop_s
|
||||
@@ -102,45 +138,52 @@ SECTION_FUNC(TEXT, z_arc_switch)
|
||||
|
||||
/* fall through to _switch_return_from_coop */
|
||||
|
||||
.align 4
|
||||
.balign 4
|
||||
_switch_return_from_coop:
|
||||
|
||||
POPR blink /* pc into blink */
|
||||
pop_s blink /* pc into blink */
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
pop_s r3 /* pop SEC_STAT */
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
sflag r3
|
||||
#endif
|
||||
#endif
|
||||
POPR r3 /* status32 into r3 */
|
||||
pop_s r3 /* status32 into r3 */
|
||||
kflag r3 /* write status32 */
|
||||
|
||||
#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING
|
||||
PUSHR blink
|
||||
|
||||
bl z_thread_mark_switched_in
|
||||
|
||||
POPR blink
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
b _capture_value_for_benchmarking
|
||||
#endif
|
||||
return_loc:
|
||||
j_s [blink]
|
||||
|
||||
|
||||
.align 4
|
||||
.balign 4
|
||||
_switch_return_from_rirq:
|
||||
_switch_return_from_firq:
|
||||
|
||||
_set_misc_regs_irq_switch_from_irq
|
||||
#if defined(CONFIG_USERSPACE)
|
||||
/*
|
||||
* need to recover the user/kernel status of interrupted thread
|
||||
*/
|
||||
pop_s r3
|
||||
lr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
or r2, r2, r3
|
||||
sr r2, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
|
||||
/* use lowest interrupt priority to simulate
|
||||
* a interrupt return to load left regs of new
|
||||
* thread
|
||||
*/
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
/* here need to recover SEC_STAT.IRM bit */
|
||||
pop_s r3
|
||||
sflag r3
|
||||
#endif
|
||||
|
||||
LRR r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
lr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
/* use lowest interrupt priority */
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
or r3, r3, (1 << (ARC_N_IRQ_START_LEVEL - 1))
|
||||
#else
|
||||
ORR r3, r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
or r3, r3, (1 << (CONFIG_NUM_IRQ_PRIO_LEVELS - 1))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_NORMAL_FIRMWARE
|
||||
@@ -149,13 +192,17 @@ _switch_return_from_firq:
|
||||
mov_s r6, ARC_S_CALL_AUX_WRITE
|
||||
sjli SJLI_CALL_ARC_SECURE
|
||||
#else
|
||||
SRR r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
#ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING
|
||||
PUSHR blink
|
||||
|
||||
bl z_thread_mark_switched_in
|
||||
|
||||
POPR blink
|
||||
sr r3, [_ARC_V2_AUX_IRQ_ACT]
|
||||
#endif
|
||||
rtie
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
.balign 4
|
||||
_capture_value_for_benchmarking:
|
||||
push_s blink
|
||||
|
||||
bl read_timer_end_of_swap
|
||||
|
||||
pop_s blink
|
||||
b return_loc
|
||||
#endif /* CONFIG_EXECUTION_BENCHMARKING */
|
||||
|
||||
@@ -22,204 +22,254 @@
|
||||
|
||||
/* initial stack frame */
|
||||
struct init_stack_frame {
|
||||
uintptr_t pc;
|
||||
u32_t pc;
|
||||
#ifdef CONFIG_ARC_HAS_SECURE
|
||||
uint32_t sec_stat;
|
||||
u32_t sec_stat;
|
||||
#endif
|
||||
uintptr_t status32;
|
||||
uintptr_t r3;
|
||||
uintptr_t r2;
|
||||
uintptr_t r1;
|
||||
uintptr_t r0;
|
||||
u32_t status32;
|
||||
u32_t r3;
|
||||
u32_t r2;
|
||||
u32_t r1;
|
||||
u32_t r0;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
struct user_init_stack_frame {
|
||||
struct init_stack_frame iframe;
|
||||
uint32_t user_sp;
|
||||
};
|
||||
|
||||
static bool is_user(struct k_thread *thread)
|
||||
{
|
||||
return (thread->base.user_options & K_USER) != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set all stack-related architecture variables for the provided thread */
|
||||
static void setup_stack_vars(struct k_thread *thread)
|
||||
{
|
||||
#ifdef CONFIG_USERSPACE
|
||||
if (is_user(thread)) {
|
||||
#ifdef CONFIG_GEN_PRIV_STACKS
|
||||
thread->arch.priv_stack_start =
|
||||
(uint32_t)z_priv_stack_find(thread->stack_obj);
|
||||
#else
|
||||
thread->arch.priv_stack_start = (uint32_t)(thread->stack_obj);
|
||||
#endif /* CONFIG_GEN_PRIV_STACKS */
|
||||
thread->arch.priv_stack_start += Z_ARC_STACK_GUARD_SIZE;
|
||||
} else {
|
||||
thread->arch.priv_stack_start = 0;
|
||||
}
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_USERSPACE
|
||||
if (is_user(thread)) {
|
||||
thread->arch.k_stack_top = thread->arch.priv_stack_start;
|
||||
thread->arch.k_stack_base = (thread->arch.priv_stack_start +
|
||||
CONFIG_PRIVILEGED_STACK_SIZE);
|
||||
thread->arch.u_stack_top = thread->stack_info.start;
|
||||
thread->arch.u_stack_base = (thread->stack_info.start +
|
||||
thread->stack_info.size);
|
||||
} else
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
{
|
||||
thread->arch.k_stack_top = (uint32_t)thread->stack_info.start;
|
||||
thread->arch.k_stack_base = (uint32_t)(thread->stack_info.start +
|
||||
thread->stack_info.size);
|
||||
#ifdef CONFIG_USERSPACE
|
||||
thread->arch.u_stack_top = 0;
|
||||
thread->arch.u_stack_base = 0;
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
}
|
||||
#endif /* CONFIG_ARC_STACK_CHECKING */
|
||||
}
|
||||
|
||||
/* Get the initial stack frame pointer from the thread's stack buffer. */
|
||||
static struct init_stack_frame *get_iframe(struct k_thread *thread,
|
||||
char *stack_ptr)
|
||||
{
|
||||
#ifdef CONFIG_USERSPACE
|
||||
if (is_user(thread)) {
|
||||
/* Initial stack frame for a user thread is slightly larger;
|
||||
* we land in z_user_thread_entry_wrapper on the privilege
|
||||
* stack, and pop off an additional value for the user
|
||||
* stack pointer.
|
||||
*/
|
||||
struct user_init_stack_frame *uframe;
|
||||
|
||||
uframe = Z_STACK_PTR_TO_FRAME(struct user_init_stack_frame,
|
||||
thread->arch.priv_stack_start +
|
||||
CONFIG_PRIVILEGED_STACK_SIZE);
|
||||
uframe->user_sp = (uint32_t)stack_ptr;
|
||||
return &uframe->iframe;
|
||||
}
|
||||
#endif
|
||||
return Z_STACK_PTR_TO_FRAME(struct init_stack_frame, stack_ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pre-populate values in the registers inside _callee_saved_stack struct
|
||||
* so these registers have pre-defined values when new thread begins
|
||||
* execution. For example, setting up the thread pointer for thread local
|
||||
* storage here so the thread starts with thread pointer already set up.
|
||||
*/
|
||||
static inline void arch_setup_callee_saved_regs(struct k_thread *thread,
|
||||
uintptr_t stack_ptr)
|
||||
{
|
||||
_callee_saved_stack_t *regs = UINT_TO_POINTER(stack_ptr);
|
||||
|
||||
ARG_UNUSED(regs);
|
||||
|
||||
#ifdef CONFIG_THREAD_LOCAL_STORAGE
|
||||
#ifdef CONFIG_ISA_ARCV2
|
||||
/* R26 is used for thread pointer for ARCv2 */
|
||||
regs->r26 = thread->tls;
|
||||
#else
|
||||
/* R30 is used for thread pointer for ARCv3 */
|
||||
regs->r30 = thread->tls;
|
||||
#endif /* CONFIG_ISA_ARCV2 */
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief Initialize a new thread from its stack space
|
||||
*
|
||||
* The thread control structure is put at the lower address of the stack. An
|
||||
* initial context, to be "restored" by __return_from_coop(), is put at
|
||||
* the other end of the stack, and thus reusable by the stack when not
|
||||
* needed anymore.
|
||||
*
|
||||
* The initial context is a basic stack frame that contains arguments for
|
||||
* z_thread_entry() return address, that points at z_thread_entry()
|
||||
* and status register.
|
||||
*
|
||||
* <options> is currently unused.
|
||||
*
|
||||
* @param pStackmem the pointer to aligned stack memory
|
||||
* @param stackSize the stack size in bytes
|
||||
* @param pEntry thread entry point routine
|
||||
* @param parameter1 first param to entry point
|
||||
* @param parameter2 second param to entry point
|
||||
* @param parameter3 third param to entry point
|
||||
* @param priority thread priority
|
||||
* @param options thread options: K_ESSENTIAL
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack,
|
||||
char *stack_ptr, k_thread_entry_t entry,
|
||||
void *p1, void *p2, void *p3)
|
||||
size_t stackSize, k_thread_entry_t pEntry,
|
||||
void *parameter1, void *parameter2, void *parameter3,
|
||||
int priority, unsigned int options)
|
||||
{
|
||||
struct init_stack_frame *iframe;
|
||||
char *pStackMem = Z_THREAD_STACK_BUFFER(stack);
|
||||
Z_ASSERT_VALID_PRIO(priority, pEntry);
|
||||
|
||||
setup_stack_vars(thread);
|
||||
|
||||
/* Set up initial stack frame */
|
||||
iframe = get_iframe(thread, stack_ptr);
|
||||
char *stackEnd;
|
||||
char *stackAdjEnd;
|
||||
struct init_stack_frame *pInitCtx;
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
/* enable US bit, US is read as zero in user mode. This will allow user
|
||||
|
||||
size_t stackAdjSize;
|
||||
size_t offset = 0;
|
||||
|
||||
/* adjust stack and stack size */
|
||||
#if CONFIG_ARC_MPU_VER == 2
|
||||
stackAdjSize = Z_ARC_MPUV2_SIZE_ALIGN(stackSize);
|
||||
#elif CONFIG_ARC_MPU_VER == 3
|
||||
stackAdjSize = STACK_SIZE_ALIGN(stackSize);
|
||||
#endif
|
||||
stackEnd = pStackMem + stackAdjSize;
|
||||
|
||||
#ifdef CONFIG_STACK_POINTER_RANDOM
|
||||
offset = stackAdjSize - stackSize;
|
||||
#endif
|
||||
|
||||
if (options & K_USER) {
|
||||
thread->arch.priv_stack_start =
|
||||
(u32_t)(stackEnd + STACK_GUARD_SIZE);
|
||||
|
||||
stackAdjEnd = (char *)STACK_ROUND_DOWN(stackEnd +
|
||||
ARCH_THREAD_STACK_RESERVED);
|
||||
|
||||
/* reserve 4 bytes for the start of user sp */
|
||||
stackAdjEnd -= 4;
|
||||
(*(u32_t *)stackAdjEnd) = STACK_ROUND_DOWN(
|
||||
(u32_t)stackEnd - offset);
|
||||
|
||||
#ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA
|
||||
/* reserve stack space for the userspace local data struct */
|
||||
thread->userspace_local_data =
|
||||
(struct _thread_userspace_local_data *)
|
||||
STACK_ROUND_DOWN(stackEnd -
|
||||
sizeof(*thread->userspace_local_data) - offset);
|
||||
/* update the start of user sp */
|
||||
(*(u32_t *)stackAdjEnd) = (u32_t) thread->userspace_local_data;
|
||||
#endif
|
||||
|
||||
} else {
|
||||
/* for kernel thread, the privilege stack is merged into thread stack */
|
||||
/* if MPU_STACK_GUARD is enabled, reserve the the stack area
|
||||
* |---------------------| |----------------|
|
||||
* | user stack | | stack guard |
|
||||
* |---------------------| to |----------------|
|
||||
* | stack guard | | kernel thread |
|
||||
* |---------------------| | stack |
|
||||
* | privilege stack | | |
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
pStackMem += STACK_GUARD_SIZE;
|
||||
stackAdjSize = stackAdjSize + CONFIG_PRIVILEGED_STACK_SIZE;
|
||||
stackEnd += ARCH_THREAD_STACK_RESERVED;
|
||||
|
||||
thread->arch.priv_stack_start = 0;
|
||||
|
||||
#ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA
|
||||
/* reserve stack space for the userspace local data struct */
|
||||
stackAdjEnd = (char *)STACK_ROUND_DOWN(stackEnd
|
||||
- sizeof(*thread->userspace_local_data) - offset);
|
||||
thread->userspace_local_data =
|
||||
(struct _thread_userspace_local_data *)stackAdjEnd;
|
||||
#else
|
||||
stackAdjEnd = (char *)STACK_ROUND_DOWN(stackEnd - offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
z_new_thread_init(thread, pStackMem, stackAdjSize, priority, options);
|
||||
|
||||
/* carve the thread entry struct from the "base" of
|
||||
the privileged stack */
|
||||
pInitCtx = (struct init_stack_frame *)(
|
||||
stackAdjEnd - sizeof(struct init_stack_frame));
|
||||
|
||||
/* fill init context */
|
||||
pInitCtx->status32 = 0U;
|
||||
if (options & K_USER) {
|
||||
pInitCtx->pc = ((u32_t)z_user_thread_entry_wrapper);
|
||||
} else {
|
||||
pInitCtx->pc = ((u32_t)z_thread_entry_wrapper);
|
||||
}
|
||||
|
||||
/*
|
||||
* enable US bit, US is read as zero in user mode. This will allow use
|
||||
* mode sleep instructions, and it enables a form of denial-of-service
|
||||
* attack by putting the processor in sleep mode, but since interrupt
|
||||
* level/mask can't be set from user space that's not worse than
|
||||
* executing a loop without yielding.
|
||||
*/
|
||||
iframe->status32 = _ARC_V2_STATUS32_US | _ARC_V2_STATUS32_DZ;
|
||||
if (is_user(thread)) {
|
||||
iframe->pc = (uint32_t)z_user_thread_entry_wrapper;
|
||||
} else {
|
||||
iframe->pc = (uint32_t)z_thread_entry_wrapper;
|
||||
}
|
||||
#else
|
||||
iframe->status32 = _ARC_V2_STATUS32_DZ;
|
||||
iframe->pc = ((uintptr_t)z_thread_entry_wrapper);
|
||||
#endif /* CONFIG_USERSPACE */
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
iframe->sec_stat = z_arc_v2_aux_reg_read(_ARC_V2_SEC_STAT);
|
||||
#endif
|
||||
iframe->r0 = (uintptr_t)entry;
|
||||
iframe->r1 = (uintptr_t)p1;
|
||||
iframe->r2 = (uintptr_t)p2;
|
||||
iframe->r3 = (uintptr_t)p3;
|
||||
pInitCtx->status32 |= _ARC_V2_STATUS32_US;
|
||||
#else /* For no USERSPACE feature */
|
||||
pStackMem += ARCH_THREAD_STACK_RESERVED;
|
||||
stackEnd = pStackMem + stackSize;
|
||||
|
||||
z_new_thread_init(thread, pStackMem, stackSize, priority, options);
|
||||
|
||||
stackAdjEnd = stackEnd;
|
||||
|
||||
pInitCtx = (struct init_stack_frame *)(
|
||||
STACK_ROUND_DOWN(stackAdjEnd) -
|
||||
sizeof(struct init_stack_frame));
|
||||
|
||||
pInitCtx->status32 = 0U;
|
||||
pInitCtx->pc = ((u32_t)z_thread_entry_wrapper);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
pInitCtx->sec_stat = z_arc_v2_aux_reg_read(_ARC_V2_SEC_STAT);
|
||||
#endif
|
||||
|
||||
pInitCtx->r0 = (u32_t)pEntry;
|
||||
pInitCtx->r1 = (u32_t)parameter1;
|
||||
pInitCtx->r2 = (u32_t)parameter2;
|
||||
pInitCtx->r3 = (u32_t)parameter3;
|
||||
|
||||
/* stack check configuration */
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
iframe->sec_stat |= _ARC_V2_SEC_STAT_SSC;
|
||||
pInitCtx->sec_stat |= _ARC_V2_SEC_STAT_SSC;
|
||||
#else
|
||||
iframe->status32 |= _ARC_V2_STATUS32_SC;
|
||||
#endif /* CONFIG_ARC_SECURE_FIRMWARE */
|
||||
#endif /* CONFIG_ARC_STACK_CHECKING */
|
||||
#ifdef CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS
|
||||
iframe->status32 |= _ARC_V2_STATUS32_AD;
|
||||
pInitCtx->status32 |= _ARC_V2_STATUS32_SC;
|
||||
#endif
|
||||
/* Set required thread members */
|
||||
#ifdef CONFIG_USERSPACE
|
||||
if (options & K_USER) {
|
||||
thread->arch.u_stack_top = (u32_t)pStackMem;
|
||||
thread->arch.u_stack_base = (u32_t)stackEnd;
|
||||
thread->arch.k_stack_top =
|
||||
(u32_t)(stackEnd + STACK_GUARD_SIZE);
|
||||
thread->arch.k_stack_base = (u32_t)
|
||||
(stackEnd + ARCH_THREAD_STACK_RESERVED);
|
||||
} else {
|
||||
thread->arch.k_stack_top = (u32_t)pStackMem;
|
||||
thread->arch.k_stack_base = (u32_t)stackEnd;
|
||||
thread->arch.u_stack_top = 0;
|
||||
thread->arch.u_stack_base = 0;
|
||||
}
|
||||
#else
|
||||
thread->arch.k_stack_top = (u32_t) pStackMem;
|
||||
thread->arch.k_stack_base = (u32_t) stackEnd;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS
|
||||
pInitCtx->status32 |= _ARC_V2_STATUS32_AD;
|
||||
#endif
|
||||
|
||||
thread->switch_handle = thread;
|
||||
thread->arch.relinquish_cause = _CAUSE_COOP;
|
||||
thread->callee_saved.sp =
|
||||
(uintptr_t)iframe - ___callee_saved_stack_t_SIZEOF;
|
||||
|
||||
arch_setup_callee_saved_regs(thread, thread->callee_saved.sp);
|
||||
(u32_t)pInitCtx - ___callee_saved_stack_t_SIZEOF;
|
||||
|
||||
/* initial values in all other regs/k_thread entries are irrelevant */
|
||||
}
|
||||
|
||||
void *z_arch_get_next_switch_handle(struct k_thread **old_thread)
|
||||
{
|
||||
*old_thread = _current;
|
||||
|
||||
return z_get_next_switch_handle(*old_thread);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
||||
FUNC_NORETURN void arch_user_mode_enter(k_thread_entry_t user_entry,
|
||||
void *p1, void *p2, void *p3)
|
||||
{
|
||||
setup_stack_vars(_current);
|
||||
|
||||
/*
|
||||
* adjust the thread stack layout
|
||||
* |----------------| |---------------------|
|
||||
* | stack guard | | user stack |
|
||||
* |----------------| to |---------------------|
|
||||
* | kernel thread | | stack guard |
|
||||
* | stack | |---------------------|
|
||||
* | | | privilege stack |
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
_current->stack_info.start = (u32_t)_current->stack_obj;
|
||||
_current->stack_info.size -= CONFIG_PRIVILEGED_STACK_SIZE;
|
||||
|
||||
_current->arch.priv_stack_start =
|
||||
(u32_t)(_current->stack_info.start +
|
||||
_current->stack_info.size + STACK_GUARD_SIZE);
|
||||
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
_current->arch.k_stack_top = _current->arch.priv_stack_start;
|
||||
_current->arch.k_stack_base = _current->arch.priv_stack_start +
|
||||
CONFIG_PRIVILEGED_STACK_SIZE;
|
||||
_current->arch.u_stack_top = _current->stack_info.start;
|
||||
_current->arch.u_stack_base = _current->stack_info.start +
|
||||
_current->stack_info.size;
|
||||
#endif
|
||||
|
||||
/* possible optimizaiton: no need to load mem domain anymore */
|
||||
/* need to lock cpu here ? */
|
||||
configure_mpu_thread(_current);
|
||||
|
||||
z_arc_userspace_enter(user_entry, p1, p2, p3,
|
||||
(uint32_t)_current->stack_info.start,
|
||||
(_current->stack_info.size -
|
||||
_current->stack_info.delta), _current);
|
||||
(u32_t)_current->stack_obj,
|
||||
_current->stack_info.size);
|
||||
CODE_UNREACHABLE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING)
|
||||
#if defined(CONFIG_FLOAT) && defined(CONFIG_FP_SHARING)
|
||||
int arch_float_disable(struct k_thread *thread)
|
||||
{
|
||||
unsigned int key;
|
||||
@@ -237,7 +287,7 @@ int arch_float_disable(struct k_thread *thread)
|
||||
}
|
||||
|
||||
|
||||
int arch_float_enable(struct k_thread *thread, unsigned int options)
|
||||
int arch_float_enable(struct k_thread *thread)
|
||||
{
|
||||
unsigned int key;
|
||||
|
||||
@@ -252,4 +302,4 @@ int arch_float_enable(struct k_thread *thread, unsigned int options)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_FPU && CONFIG_FPU_SHARING */
|
||||
#endif /* CONFIG_FLOAT && CONFIG_FP_SHARING */
|
||||
|
||||
@@ -14,24 +14,25 @@
|
||||
#include <toolchain.h>
|
||||
#include <linker/sections.h>
|
||||
#include <v2/irq.h>
|
||||
#include <arch/arc/asm-compat/assembler.h>
|
||||
|
||||
GTEXT(z_thread_entry_wrapper)
|
||||
GTEXT(z_thread_entry_wrapper1)
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Wrapper for z_thread_entry
|
||||
*
|
||||
* The routine pops parameters for the z_thread_entry from stack frame, prepared
|
||||
* by the arch_new_thread() routine.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
|
||||
SECTION_FUNC(TEXT, z_thread_entry_wrapper)
|
||||
seti _ARC_V2_INIT_IRQ_LOCK_KEY
|
||||
z_thread_entry_wrapper1:
|
||||
POPR r3
|
||||
POPR r2
|
||||
POPR r1
|
||||
POPR r0
|
||||
pop_s r3
|
||||
pop_s r2
|
||||
pop_s r1
|
||||
pop_s r0
|
||||
j z_thread_entry
|
||||
nop
|
||||
|
||||
@@ -23,17 +23,17 @@
|
||||
*
|
||||
* @return 64-bit time stamp value
|
||||
*/
|
||||
uint64_t z_tsc_read(void)
|
||||
u64_t z_tsc_read(void)
|
||||
{
|
||||
unsigned int key;
|
||||
uint64_t t;
|
||||
uint32_t count;
|
||||
u64_t t;
|
||||
u32_t count;
|
||||
|
||||
key = arch_irq_lock();
|
||||
t = (uint64_t)sys_clock_tick_get();
|
||||
key = irq_lock();
|
||||
t = (u64_t)z_tick_get();
|
||||
count = z_arc_v2_aux_reg_read(_ARC_V2_TMR0_COUNT);
|
||||
arch_irq_unlock(key);
|
||||
irq_unlock(key);
|
||||
t *= k_ticks_to_cyc_floor64(1);
|
||||
t += (uint64_t)count;
|
||||
t += (u64_t)count;
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <kernel_structs.h>
|
||||
#include <kernel_internal.h>
|
||||
#include <kernel_tls.h>
|
||||
#include <sys/util.h>
|
||||
|
||||
size_t arch_tls_stack_setup(struct k_thread *new_thread, char *stack_ptr)
|
||||
{
|
||||
/*
|
||||
* TLS area for ARC has some data fields following by
|
||||
* thread data and bss. These fields are supposed to be
|
||||
* used by toolchain and OS TLS code to aid in locating
|
||||
* the TLS data/bss. Zephyr currently has no use for
|
||||
* this so we can simply skip these. However, since GCC
|
||||
* is generating code assuming these fields are there,
|
||||
* we simply skip them when setting the TLS pointer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Since we are populating things backwards,
|
||||
* setup the TLS data/bss area first.
|
||||
*/
|
||||
stack_ptr -= z_tls_data_size();
|
||||
z_tls_copy(stack_ptr);
|
||||
|
||||
/* Skip two pointers due to toolchain */
|
||||
stack_ptr -= sizeof(uintptr_t) * 2;
|
||||
|
||||
/*
|
||||
* Set thread TLS pointer which is used in
|
||||
* context switch to point to TLS area.
|
||||
*/
|
||||
new_thread->tls = POINTER_TO_UINT(stack_ptr);
|
||||
|
||||
return (z_tls_data_size() + (sizeof(uintptr_t) * 2));
|
||||
}
|
||||
@@ -52,11 +52,11 @@ GTEXT(arch_user_string_nlen)
|
||||
GTEXT(z_arc_user_string_nlen_fault_start)
|
||||
GTEXT(z_arc_user_string_nlen_fault_end)
|
||||
GTEXT(z_arc_user_string_nlen_fixup)
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Wrapper for z_thread_entry in the case of user thread
|
||||
*
|
||||
* The init parameters are in privileged stack
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
SECTION_FUNC(TEXT, z_user_thread_entry_wrapper)
|
||||
seti _ARC_V2_INIT_IRQ_LOCK_KEY
|
||||
@@ -93,15 +93,22 @@ SECTION_FUNC(TEXT, z_arc_userspace_enter)
|
||||
/*
|
||||
* In ARCv2, the U bit can only be set through exception return
|
||||
*/
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* disable stack checking as the stack should be initialized */
|
||||
_disable_stack_checking blink
|
||||
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr blink, [_ARC_V2_SEC_STAT]
|
||||
bclr blink, blink, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag blink
|
||||
#else
|
||||
lr blink, [_ARC_V2_STATUS32]
|
||||
bclr blink, blink, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag blink
|
||||
#endif
|
||||
#endif
|
||||
/* the end of user stack in r5 */
|
||||
add r5, r4, r5
|
||||
/* get start of privilege stack, r6 points to current thread */
|
||||
ld blink, [r6, _thread_offset_to_priv_stack_start]
|
||||
add blink, blink, CONFIG_PRIVILEGED_STACK_SIZE
|
||||
|
||||
/* start of privilege stack */
|
||||
add blink, r5, CONFIG_PRIVILEGED_STACK_SIZE+STACK_GUARD_SIZE
|
||||
mov_s sp, r5
|
||||
|
||||
push_s r0
|
||||
@@ -111,9 +118,6 @@ SECTION_FUNC(TEXT, z_arc_userspace_enter)
|
||||
|
||||
mov r5, sp /* skip r0, r1, r2, r3 */
|
||||
|
||||
/* to avoid the leakage of kernel info, the thread stack needs to be
|
||||
* re-initialized
|
||||
*/
|
||||
#ifdef CONFIG_INIT_STACKS
|
||||
mov_s r0, 0xaaaaaaaa
|
||||
#else
|
||||
@@ -124,22 +128,23 @@ _clear_user_stack:
|
||||
cmp r4, r5
|
||||
jlt _clear_user_stack
|
||||
|
||||
/* reload the stack checking regs as the original kernel stack
|
||||
* becomes user stack
|
||||
*/
|
||||
#ifdef CONFIG_ARC_STACK_CHECKING
|
||||
/* current thread in r6, SMP case is also considered */
|
||||
mov r2, r6
|
||||
mov_s r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
|
||||
_load_stack_check_regs
|
||||
|
||||
_enable_stack_checking r0
|
||||
#ifdef CONFIG_ARC_SECURE_FIRMWARE
|
||||
lr r0, [_ARC_V2_SEC_STAT]
|
||||
bset r0, r0, _ARC_V2_SEC_STAT_SSC_BIT
|
||||
sflag r0
|
||||
#else
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_SC_BIT
|
||||
kflag r0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* the following codes are used to switch from kernel mode
|
||||
* to user mode by fake exception, because U bit can only be set
|
||||
* by exception
|
||||
*/
|
||||
_arc_go_to_user_space:
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_U_BIT
|
||||
@@ -151,7 +156,7 @@ _arc_go_to_user_space:
|
||||
|
||||
/* fake exception return */
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
bset r0, r0, _ARC_V2_STATUS32_AE_BIT
|
||||
bclr r0, r0, _ARC_V2_STATUS32_AE_BIT
|
||||
kflag r0
|
||||
|
||||
/* when exception returns from kernel to user, sp and _ARC_V2_USER_SP
|
||||
@@ -174,10 +179,15 @@ _arc_go_to_user_space:
|
||||
|
||||
clear_scratch_regs
|
||||
|
||||
mov fp, 0
|
||||
mov r29, 0
|
||||
mov r30, 0
|
||||
mov blink, 0
|
||||
mov_s fp, 0
|
||||
mov_s r29, 0
|
||||
mov_s r30, 0
|
||||
mov_s blink, 0
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
b _capture_value_for_benchmarking_userspace
|
||||
return_loc_userspace_enter:
|
||||
#endif /* CONFIG_EXECUTION_BENCHMARKING */
|
||||
|
||||
rtie
|
||||
|
||||
@@ -214,8 +224,8 @@ SECTION_FUNC(TEXT, _arc_do_syscall)
|
||||
/* save return value */
|
||||
st_s r0, [sp, ___isf_t_r0_OFFSET]
|
||||
|
||||
mov r29, 0
|
||||
mov r30, 0
|
||||
mov_s r29, 0
|
||||
mov_s r30, 0
|
||||
|
||||
/* through fake exception return, go back to the caller */
|
||||
lr r0, [_ARC_V2_STATUS32]
|
||||
@@ -288,3 +298,20 @@ inc_len:
|
||||
/* increment length measurement, loop again */
|
||||
add_s r0, r0, 1
|
||||
b_s strlen_loop
|
||||
|
||||
#ifdef CONFIG_EXECUTION_BENCHMARKING
|
||||
.balign 4
|
||||
_capture_value_for_benchmarking_userspace:
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
_save_callee_saved_regs
|
||||
push_s blink
|
||||
|
||||
bl read_timer_end_of_userspace_enter
|
||||
|
||||
pop_s blink
|
||||
mov r1, _kernel
|
||||
ld_s r2, [r1, _kernel_offset_to_current]
|
||||
_load_callee_saved_regs
|
||||
b return_loc_userspace_enter
|
||||
#endif
|
||||
|
||||
@@ -28,40 +28,39 @@
|
||||
#include "vector_table.h"
|
||||
|
||||
struct vector_table {
|
||||
uintptr_t reset;
|
||||
uintptr_t memory_error;
|
||||
uintptr_t instruction_error;
|
||||
uintptr_t ev_machine_check;
|
||||
uintptr_t ev_tlb_miss_i;
|
||||
uintptr_t ev_tlb_miss_d;
|
||||
uintptr_t ev_prot_v;
|
||||
uintptr_t ev_privilege_v;
|
||||
uintptr_t ev_swi;
|
||||
uintptr_t ev_trap;
|
||||
uintptr_t ev_extension;
|
||||
uintptr_t ev_div_zero;
|
||||
/* ev_dc_error is unused in ARCv3 and de-facto unused in ARCv2 as well */
|
||||
uintptr_t ev_dc_error;
|
||||
uintptr_t ev_maligned;
|
||||
uintptr_t unused_1;
|
||||
uintptr_t unused_2;
|
||||
u32_t reset;
|
||||
u32_t memory_error;
|
||||
u32_t instruction_error;
|
||||
u32_t ev_machine_check;
|
||||
u32_t ev_tlb_miss_i;
|
||||
u32_t ev_tlb_miss_d;
|
||||
u32_t ev_prot_v;
|
||||
u32_t ev_privilege_v;
|
||||
u32_t ev_swi;
|
||||
u32_t ev_trap;
|
||||
u32_t ev_extension;
|
||||
u32_t ev_div_zero;
|
||||
u32_t ev_dc_error;
|
||||
u32_t ev_maligned;
|
||||
u32_t unused_1;
|
||||
u32_t unused_2;
|
||||
};
|
||||
|
||||
struct vector_table _VectorTable Z_GENERIC_SECTION(.exc_vector_table) = {
|
||||
(uintptr_t)__reset,
|
||||
(uintptr_t)__memory_error,
|
||||
(uintptr_t)__instruction_error,
|
||||
(uintptr_t)__ev_machine_check,
|
||||
(uintptr_t)__ev_tlb_miss_i,
|
||||
(uintptr_t)__ev_tlb_miss_d,
|
||||
(uintptr_t)__ev_prot_v,
|
||||
(uintptr_t)__ev_privilege_v,
|
||||
(uintptr_t)__ev_swi,
|
||||
(uintptr_t)__ev_trap,
|
||||
(uintptr_t)__ev_extension,
|
||||
(uintptr_t)__ev_div_zero,
|
||||
(uintptr_t)__ev_dc_error,
|
||||
(uintptr_t)__ev_maligned,
|
||||
(u32_t)__reset,
|
||||
(u32_t)__memory_error,
|
||||
(u32_t)__instruction_error,
|
||||
(u32_t)__ev_machine_check,
|
||||
(u32_t)__ev_tlb_miss_i,
|
||||
(u32_t)__ev_tlb_miss_d,
|
||||
(u32_t)__ev_prot_v,
|
||||
(u32_t)__ev_privilege_v,
|
||||
(u32_t)__ev_swi,
|
||||
(u32_t)__ev_trap,
|
||||
(u32_t)__ev_extension,
|
||||
(u32_t)__ev_div_zero,
|
||||
(u32_t)__ev_dc_error,
|
||||
(u32_t)__ev_maligned,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
|
||||
KEEP(*(.exc_vector_table))
|
||||
KEEP(*(".exc_vector_table.*"))
|
||||
KEEP(*(_IRQ_VECTOR_TABLE_SECTION_SYMS))
|
||||
KEEP(*(IRQ_VECTOR_TABLE))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user