Merge 039aeb9deb
("Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm") into android-mainline
Baby steps on the way to 5.8-rc1. Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I5962e12546d3d215c73c3d74b00ad6263d96f64e
This commit is contained in:
commit
035f08016d
@ -80,6 +80,7 @@ ForEachMacros:
|
||||
- 'ax25_uid_for_each'
|
||||
- '__bio_for_each_bvec'
|
||||
- 'bio_for_each_bvec'
|
||||
- 'bio_for_each_bvec_all'
|
||||
- 'bio_for_each_integrity_vec'
|
||||
- '__bio_for_each_segment'
|
||||
- 'bio_for_each_segment'
|
||||
|
@ -1190,6 +1190,11 @@
|
||||
This is designed to be used in conjunction with
|
||||
the boot argument: earlyprintk=vga
|
||||
|
||||
This parameter works in place of the kgdboc parameter
|
||||
but can only be used if the backing tty is available
|
||||
very early in the boot process. For early debugging
|
||||
via a serial port see kgdboc_earlycon instead.
|
||||
|
||||
edd= [EDD]
|
||||
Format: {"off" | "on" | "skip[mbr]"}
|
||||
|
||||
@ -2112,6 +2117,21 @@
|
||||
kms, kbd format: kms,kbd
|
||||
kms, kbd and serial format: kms,kbd,<ser_dev>[,baud]
|
||||
|
||||
kgdboc_earlycon= [KGDB,HW]
|
||||
If the boot console provides the ability to read
|
||||
characters and can work in polling mode, you can use
|
||||
this parameter to tell kgdb to use it as a backend
|
||||
until the normal console is registered. Intended to
|
||||
be used together with the kgdboc parameter which
|
||||
specifies the normal console to transition to.
|
||||
|
||||
The name of the early console should be specified
|
||||
as the value of this parameter. Note that the name of
|
||||
the early console might be different than the tty
|
||||
name passed to kgdboc. It's OK to leave the value
|
||||
blank and the first boot console that implements
|
||||
read() will be picked.
|
||||
|
||||
kgdbwait [KGDB] Stop kernel execution and enter the
|
||||
kernel debugger at the earliest opportunity.
|
||||
|
||||
@ -5093,6 +5113,12 @@
|
||||
interruptions from clocksource watchdog are not
|
||||
acceptable).
|
||||
|
||||
tsc_early_khz= [X86] Skip early TSC calibration and use the given
|
||||
value instead. Useful when the early TSC frequency discovery
|
||||
procedure is not reliable, such as on overclocked systems
|
||||
with CPUID.16h support and partial CPUID.15h support.
|
||||
Format: <unsigned int>
|
||||
|
||||
tsx= [X86] Control Transactional Synchronization
|
||||
Extensions (TSX) feature in Intel processors that
|
||||
support TSX control.
|
||||
|
@ -129,6 +129,7 @@ Usage of helpers:
|
||||
::
|
||||
|
||||
bio_for_each_segment_all()
|
||||
bio_for_each_bvec_all()
|
||||
bio_first_bvec_all()
|
||||
bio_first_page_all()
|
||||
bio_last_bvec_all()
|
||||
@ -143,4 +144,5 @@ Usage of helpers:
|
||||
bio_vec' will contain a multi-page IO vector during the iteration::
|
||||
|
||||
bio_for_each_bvec()
|
||||
bio_for_each_bvec_all()
|
||||
rq_for_each_bvec()
|
||||
|
@ -274,6 +274,30 @@ don't like this are to hack gdb to send the :kbd:`SysRq-G` for you as well as
|
||||
on the initial connect, or to use a debugger proxy that allows an
|
||||
unmodified gdb to do the debugging.
|
||||
|
||||
Kernel parameter: ``kgdboc_earlycon``
|
||||
-------------------------------------
|
||||
|
||||
If you specify the kernel parameter ``kgdboc_earlycon`` and your serial
|
||||
driver registers a boot console that supports polling (doesn't need
|
||||
interrupts and implements a nonblocking read() function) kgdb will attempt
|
||||
to work using the boot console until it can transition to the regular
|
||||
tty driver specified by the ``kgdboc`` parameter.
|
||||
|
||||
Normally there is only one boot console (especially that implements the
|
||||
read() function) so just adding ``kgdboc_earlycon`` on its own is
|
||||
sufficient to make this work. If you have more than one boot console you
|
||||
can add the boot console's name to differentiate. Note that names that
|
||||
are registered through the boot console layer and the tty layer are not
|
||||
the same for the same port.
|
||||
|
||||
For instance, on one board to be explicit you might do::
|
||||
|
||||
kgdboc_earlycon=qcom_geni kgdboc=ttyMSM0
|
||||
|
||||
If the only boot console on the device was "qcom_geni", you could simplify::
|
||||
|
||||
kgdboc_earlycon kgdboc=ttyMSM0
|
||||
|
||||
Kernel parameter: ``kgdbwait``
|
||||
------------------------------
|
||||
|
||||
|
@ -0,0 +1,57 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/interrupt-controller/loongson,htvec.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Loongson-3 HyperTransport Interrupt Vector Controller
|
||||
|
||||
maintainers:
|
||||
- Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
|
||||
description:
|
||||
This interrupt controller is found in the Loongson-3 family of chips for
|
||||
receiving vectorized interrupts from PCH's interrupt controller.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: loongson,htvec-1.0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
description: Four parent interrupts that receive chained interrupts.
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
'#interrupt-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-controller
|
||||
- '#interrupt-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
htvec: interrupt-controller@fb000080 {
|
||||
compatible = "loongson,htvec-1.0";
|
||||
reg = <0xfb000080 0x40>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
interrupt-parent = <&liointc>;
|
||||
interrupts = <24 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<25 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<26 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<27 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
...
|
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/interrupt-controller/loongson,pch-msi.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Loongson PCH MSI Controller
|
||||
|
||||
maintainers:
|
||||
- Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
|
||||
description:
|
||||
This interrupt controller is found in the Loongson LS7A family of PCH for
|
||||
transforming interrupts from PCIe MSI into HyperTransport vectorized
|
||||
interrupts.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: loongson,pch-msi-1.0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
loongson,msi-base-vec:
|
||||
description:
|
||||
u32 value of the base of parent HyperTransport vector allocated
|
||||
to PCH MSI.
|
||||
allOf:
|
||||
- $ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
- minimum: 0
|
||||
maximum: 255
|
||||
|
||||
loongson,msi-num-vecs:
|
||||
description:
|
||||
u32 value of the number of parent HyperTransport vectors allocated
|
||||
to PCH MSI.
|
||||
allOf:
|
||||
- $ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
- minimum: 1
|
||||
maximum: 256
|
||||
|
||||
msi-controller: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- msi-controller
|
||||
- loongson,msi-base-vec
|
||||
- loongson,msi-num-vecs
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
msi: msi-controller@2ff00000 {
|
||||
compatible = "loongson,pch-msi-1.0";
|
||||
reg = <0x2ff00000 0x4>;
|
||||
msi-controller;
|
||||
loongson,msi-base-vec = <64>;
|
||||
loongson,msi-num-vecs = <64>;
|
||||
interrupt-parent = <&htvec>;
|
||||
};
|
||||
...
|
@ -0,0 +1,56 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/interrupt-controller/loongson,pch-pic.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Loongson PCH PIC Controller
|
||||
|
||||
maintainers:
|
||||
- Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
|
||||
description:
|
||||
This interrupt controller is found in the Loongson LS7A family of PCH for
|
||||
transforming interrupts from on-chip devices into HyperTransport vectorized
|
||||
interrupts.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: loongson,pch-pic-1.0
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
loongson,pic-base-vec:
|
||||
description:
|
||||
u32 value of the base of parent HyperTransport vector allocated
|
||||
to PCH PIC.
|
||||
allOf:
|
||||
- $ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
- minimum: 0
|
||||
maximum: 192
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
'#interrupt-cells':
|
||||
const: 2
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- loongson,pic-base-vec
|
||||
- interrupt-controller
|
||||
- '#interrupt-cells'
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
pic: interrupt-controller@10000000 {
|
||||
compatible = "loongson,pch-pic-1.0";
|
||||
reg = <0x10000000 0x400>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
loongson,pic-base-vec = <64>;
|
||||
interrupt-parent = <&htvec>;
|
||||
};
|
||||
...
|
@ -0,0 +1,40 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/mips/loongson/rs780e-acpi.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Loongson RS780E PCH ACPI Controller
|
||||
|
||||
maintainers:
|
||||
- Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
|
||||
description: |
|
||||
This controller can be found in Loongson-3 systems with RS780E PCH.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: loongson,rs780e-acpi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
isa@0 {
|
||||
compatible = "isa";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
ranges = <1 0 0 0x1000>;
|
||||
|
||||
acpi@800 {
|
||||
compatible = "loongson,rs780e-acpi";
|
||||
reg = <1 0x800 0x100>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
62
Documentation/devicetree/bindings/pci/loongson.yaml
Normal file
62
Documentation/devicetree/bindings/pci/loongson.yaml
Normal file
@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pci/loongson.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Loongson PCI Host Controller
|
||||
|
||||
maintainers:
|
||||
- Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
|
||||
description: |+
|
||||
PCI host controller found on Loongson PCHs and SoCs.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/pci/pci-bus.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: loongson,ls2k-pci
|
||||
- const: loongson,ls7a-pci
|
||||
- const: loongson,rs780e-pci
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
- description: CFG0 standard config space register
|
||||
- description: CFG1 extended config space register
|
||||
|
||||
ranges:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- ranges
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
bus {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
pcie@1a000000 {
|
||||
compatible = "loongson,rs780e-pci";
|
||||
device_type = "pci";
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
|
||||
// CPU_PHYSICAL(2) SIZE(2)
|
||||
reg = <0x0 0x1a000000 0x0 0x2000000>;
|
||||
|
||||
// BUS_ADDRESS(3) CPU_PHYSICAL(2) SIZE(2)
|
||||
ranges = <0x01000000 0x0 0x00004000 0x0 0x00004000 0x0 0x00004000>,
|
||||
<0x02000000 0x0 0x40000000 0x0 0x40000000 0x0 0x40000000>;
|
||||
};
|
||||
};
|
||||
...
|
@ -1,32 +0,0 @@
|
||||
* Designware APB timer
|
||||
|
||||
Required properties:
|
||||
- compatible: One of:
|
||||
"snps,dw-apb-timer"
|
||||
"snps,dw-apb-timer-sp" <DEPRECATED>
|
||||
"snps,dw-apb-timer-osc" <DEPRECATED>
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: IRQ line for the timer.
|
||||
- either clocks+clock-names or clock-frequency properties
|
||||
|
||||
Optional properties:
|
||||
- clocks : list of clock specifiers, corresponding to entries in
|
||||
the clock-names property;
|
||||
- clock-names : should contain "timer" and "pclk" entries, matching entries
|
||||
in the clocks property.
|
||||
- clock-frequency: The frequency in HZ of the timer.
|
||||
- clock-freq: For backwards compatibility with picoxcell
|
||||
|
||||
If using the clock specifiers, the pclk clock is optional, as not all
|
||||
systems may use one.
|
||||
|
||||
|
||||
Example:
|
||||
timer@ffe00000 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
interrupts = <0 170 4>;
|
||||
reg = <0xffe00000 0x1000>;
|
||||
clocks = <&timer_clk>, <&timer_pclk>;
|
||||
clock-names = "timer", "pclk";
|
||||
};
|
46
Documentation/devicetree/bindings/timer/renesas,em-sti.yaml
Normal file
46
Documentation/devicetree/bindings/timer/renesas,em-sti.yaml
Normal file
@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/timer/renesas,em-sti.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas EMMA Mobile System Timer
|
||||
|
||||
maintainers:
|
||||
- Magnus Damm <magnus.damm@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: renesas,em-sti
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: sclk
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
timer@e0180000 {
|
||||
compatible = "renesas,em-sti";
|
||||
reg = <0xe0180000 0x54>;
|
||||
interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&sti_sclk>;
|
||||
clock-names = "sclk";
|
||||
};
|
@ -0,0 +1,88 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/timer/snps,dw-apb-timer.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Synopsys DesignWare APB Timer
|
||||
|
||||
maintainers:
|
||||
- Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: snps,dw-apb-timer
|
||||
- enum:
|
||||
- snps,dw-apb-timer-sp
|
||||
- snps,dw-apb-timer-osc
|
||||
deprecated: true
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: Timer ticks reference clock source
|
||||
- description: APB interface clock source
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: timer
|
||||
- const: pclk
|
||||
|
||||
clock-frequency: true
|
||||
|
||||
clock-freq:
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
description: |
|
||||
Has the same meaning as the 'clock-frequency' property - timer clock
|
||||
frequency in HZ, but is defined only for the backwards compatibility
|
||||
with the picoxcell platform.
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
oneOf:
|
||||
- required:
|
||||
- clocks
|
||||
- clock-names
|
||||
- required:
|
||||
- clock-frequency
|
||||
- required:
|
||||
- clock-freq
|
||||
|
||||
examples:
|
||||
- |
|
||||
timer@ffe00000 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
interrupts = <0 170 4>;
|
||||
reg = <0xffe00000 0x1000>;
|
||||
clocks = <&timer_clk>, <&timer_pclk>;
|
||||
clock-names = "timer", "pclk";
|
||||
};
|
||||
- |
|
||||
timer@ffe00000 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
interrupts = <0 170 4>;
|
||||
reg = <0xffe00000 0x1000>;
|
||||
clocks = <&timer_clk>;
|
||||
clock-names = "timer";
|
||||
};
|
||||
- |
|
||||
timer@ffe00000 {
|
||||
compatible = "snps,dw-apb-timer";
|
||||
interrupts = <0 170 4>;
|
||||
reg = <0xffe00000 0x1000>;
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
...
|
@ -20,8 +20,144 @@ Usage
|
||||
If you have a block device which supports DAX, you can make a filesystem
|
||||
on it as usual. The DAX code currently only supports files with a block
|
||||
size equal to your kernel's PAGE_SIZE, so you may need to specify a block
|
||||
size when creating the filesystem. When mounting it, use the "-o dax"
|
||||
option on the command line or add 'dax' to the options in /etc/fstab.
|
||||
size when creating the filesystem.
|
||||
|
||||
Currently 3 filesystems support DAX: ext2, ext4 and xfs. Enabling DAX on them
|
||||
is different.
|
||||
|
||||
Enabling DAX on ext4 and ext2
|
||||
-----------------------------
|
||||
|
||||
When mounting the filesystem, use the "-o dax" option on the command line or
|
||||
add 'dax' to the options in /etc/fstab. This works to enable DAX on all files
|
||||
within the filesystem. It is equivalent to the '-o dax=always' behavior below.
|
||||
|
||||
|
||||
Enabling DAX on xfs
|
||||
-------------------
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
1. There exists an in-kernel file access mode flag S_DAX that corresponds to
|
||||
the statx flag STATX_ATTR_DAX. See the manpage for statx(2) for details
|
||||
about this access mode.
|
||||
|
||||
2. There exists a persistent flag FS_XFLAG_DAX that can be applied to regular
|
||||
files and directories. This advisory flag can be set or cleared at any
|
||||
time, but doing so does not immediately affect the S_DAX state.
|
||||
|
||||
3. If the persistent FS_XFLAG_DAX flag is set on a directory, this flag will
|
||||
be inherited by all regular files and subdirectories that are subsequently
|
||||
created in this directory. Files and subdirectories that exist at the time
|
||||
this flag is set or cleared on the parent directory are not modified by
|
||||
this modification of the parent directory.
|
||||
|
||||
4. There exist dax mount options which can override FS_XFLAG_DAX in the
|
||||
setting of the S_DAX flag. Given underlying storage which supports DAX the
|
||||
following hold:
|
||||
|
||||
"-o dax=inode" means "follow FS_XFLAG_DAX" and is the default.
|
||||
|
||||
"-o dax=never" means "never set S_DAX, ignore FS_XFLAG_DAX."
|
||||
|
||||
"-o dax=always" means "always set S_DAX ignore FS_XFLAG_DAX."
|
||||
|
||||
"-o dax" is a legacy option which is an alias for "dax=always".
|
||||
This may be removed in the future so "-o dax=always" is
|
||||
the preferred method for specifying this behavior.
|
||||
|
||||
NOTE: Modifications to and the inheritance behavior of FS_XFLAG_DAX remain
|
||||
the same even when the filesystem is mounted with a dax option. However,
|
||||
in-core inode state (S_DAX) will be overridden until the filesystem is
|
||||
remounted with dax=inode and the inode is evicted from kernel memory.
|
||||
|
||||
5. The S_DAX policy can be changed via:
|
||||
|
||||
a) Setting the parent directory FS_XFLAG_DAX as needed before files are
|
||||
created
|
||||
|
||||
b) Setting the appropriate dax="foo" mount option
|
||||
|
||||
c) Changing the FS_XFLAG_DAX flag on existing regular files and
|
||||
directories. This has runtime constraints and limitations that are
|
||||
described in 6) below.
|
||||
|
||||
6. When changing the S_DAX policy via toggling the persistent FS_XFLAG_DAX flag,
|
||||
the change in behaviour for existing regular files may not occur
|
||||
immediately. If the change must take effect immediately, the administrator
|
||||
needs to:
|
||||
|
||||
a) stop the application so there are no active references to the data set
|
||||
the policy change will affect
|
||||
|
||||
b) evict the data set from kernel caches so it will be re-instantiated when
|
||||
the application is restarted. This can be achieved by:
|
||||
|
||||
i. drop-caches
|
||||
ii. a filesystem unmount and mount cycle
|
||||
iii. a system reboot
|
||||
|
||||
|
||||
Details
|
||||
-------
|
||||
|
||||
There are 2 per-file dax flags. One is a persistent inode setting (FS_XFLAG_DAX)
|
||||
and the other is a volatile flag indicating the active state of the feature
|
||||
(S_DAX).
|
||||
|
||||
FS_XFLAG_DAX is preserved within the filesystem. This persistent config
|
||||
setting can be set, cleared and/or queried using the FS_IOC_FS[GS]ETXATTR ioctl
|
||||
(see ioctl_xfs_fsgetxattr(2)) or an utility such as 'xfs_io'.
|
||||
|
||||
New files and directories automatically inherit FS_XFLAG_DAX from
|
||||
their parent directory _when_ _created_. Therefore, setting FS_XFLAG_DAX at
|
||||
directory creation time can be used to set a default behavior for an entire
|
||||
sub-tree.
|
||||
|
||||
To clarify inheritance, here are 3 examples:
|
||||
|
||||
Example A:
|
||||
|
||||
mkdir -p a/b/c
|
||||
xfs_io -c 'chattr +x' a
|
||||
mkdir a/b/c/d
|
||||
mkdir a/e
|
||||
|
||||
dax: a,e
|
||||
no dax: b,c,d
|
||||
|
||||
Example B:
|
||||
|
||||
mkdir a
|
||||
xfs_io -c 'chattr +x' a
|
||||
mkdir -p a/b/c/d
|
||||
|
||||
dax: a,b,c,d
|
||||
no dax:
|
||||
|
||||
Example C:
|
||||
|
||||
mkdir -p a/b/c
|
||||
xfs_io -c 'chattr +x' c
|
||||
mkdir a/b/c/d
|
||||
|
||||
dax: c,d
|
||||
no dax: a,b
|
||||
|
||||
|
||||
The current enabled state (S_DAX) is set when a file inode is instantiated in
|
||||
memory by the kernel. It is set based on the underlying media support, the
|
||||
value of FS_XFLAG_DAX and the filesystem's dax mount option.
|
||||
|
||||
statx can be used to query S_DAX. NOTE that only regular files will ever have
|
||||
S_DAX set and therefore statx will never indicate that S_DAX is set on
|
||||
directories.
|
||||
|
||||
Setting the FS_XFLAG_DAX flag (specifically or through inheritance) occurs even
|
||||
if the underlying media does not support dax and/or the filesystem is
|
||||
overridden with a mount option.
|
||||
|
||||
|
||||
|
||||
Implementation Tips for Block Driver Writers
|
||||
@ -94,7 +230,7 @@ sysadmins have an option to restore the lost data from a prior backup/inbuilt
|
||||
redundancy in the following ways:
|
||||
|
||||
1. Delete the affected file, and restore from a backup (sysadmin route):
|
||||
This will free the file system blocks that were being used by the file,
|
||||
This will free the filesystem blocks that were being used by the file,
|
||||
and the next time they're allocated, they will be zeroed first, which
|
||||
happens through the driver, and will clear bad sectors.
|
||||
|
||||
|
@ -340,11 +340,11 @@ buffer.
|
||||
|
||||
The structure of the verifiers and the identifiers checks is very similar to the
|
||||
buffer code described above. The only difference is where they are called. For
|
||||
example, inode read verification is done in xfs_iread() when the inode is first
|
||||
read out of the buffer and the struct xfs_inode is instantiated. The inode is
|
||||
already extensively verified during writeback in xfs_iflush_int, so the only
|
||||
addition here is to add the LSN and CRC to the inode as it is copied back into
|
||||
the buffer.
|
||||
example, inode read verification is done in xfs_inode_from_disk() when the inode
|
||||
is first read out of the buffer and the struct xfs_inode is instantiated. The
|
||||
inode is already extensively verified during writeback in xfs_iflush_int, so the
|
||||
only addition here is to add the LSN and CRC to the inode as it is copied back
|
||||
into the buffer.
|
||||
|
||||
XXX: inode unlinked list modification doesn't recalculate the inode CRC! None of
|
||||
the unlinked list modifications check or update CRCs, neither during unlink nor
|
||||
|
@ -4336,9 +4336,13 @@ Errors:
|
||||
#define KVM_STATE_NESTED_VMX_SMM_GUEST_MODE 0x00000001
|
||||
#define KVM_STATE_NESTED_VMX_SMM_VMXON 0x00000002
|
||||
|
||||
#define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001
|
||||
|
||||
struct kvm_vmx_nested_state_hdr {
|
||||
__u32 flags;
|
||||
__u64 vmxon_pa;
|
||||
__u64 vmcs12_pa;
|
||||
__u64 preemption_timer_deadline;
|
||||
|
||||
struct {
|
||||
__u16 flags;
|
||||
@ -5068,10 +5072,13 @@ EOI was received.
|
||||
struct kvm_hyperv_exit {
|
||||
#define KVM_EXIT_HYPERV_SYNIC 1
|
||||
#define KVM_EXIT_HYPERV_HCALL 2
|
||||
#define KVM_EXIT_HYPERV_SYNDBG 3
|
||||
__u32 type;
|
||||
__u32 pad1;
|
||||
union {
|
||||
struct {
|
||||
__u32 msr;
|
||||
__u32 pad2;
|
||||
__u64 control;
|
||||
__u64 evt_page;
|
||||
__u64 msg_page;
|
||||
@ -5081,6 +5088,15 @@ EOI was received.
|
||||
__u64 result;
|
||||
__u64 params[2];
|
||||
} hcall;
|
||||
struct {
|
||||
__u32 msr;
|
||||
__u32 pad2;
|
||||
__u64 control;
|
||||
__u64 status;
|
||||
__u64 send_page;
|
||||
__u64 recv_page;
|
||||
__u64 pending_page;
|
||||
} syndbg;
|
||||
} u;
|
||||
};
|
||||
/* KVM_EXIT_HYPERV */
|
||||
@ -5097,6 +5113,12 @@ Hyper-V SynIC state change. Notification is used to remap SynIC
|
||||
event/message pages and to enable/disable SynIC messages/events processing
|
||||
in userspace.
|
||||
|
||||
- KVM_EXIT_HYPERV_SYNDBG -- synchronously notify user-space about
|
||||
|
||||
Hyper-V Synthetic debugger state change. Notification is used to either update
|
||||
the pending_page location or to send a control command (send the buffer located
|
||||
in send_page or recv a buffer to recv_page).
|
||||
|
||||
::
|
||||
|
||||
/* KVM_EXIT_ARM_NISV */
|
||||
@ -5779,7 +5801,7 @@ will be initialized to 1 when created. This also improves performance because
|
||||
dirty logging can be enabled gradually in small chunks on the first call
|
||||
to KVM_CLEAR_DIRTY_LOG. KVM_DIRTY_LOG_INITIALLY_SET depends on
|
||||
KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (it is also only available on
|
||||
x86 for now).
|
||||
x86 and arm64 for now).
|
||||
|
||||
KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 was previously available under the name
|
||||
KVM_CAP_MANUAL_DIRTY_LOG_PROTECT, but the implementation had bugs that make
|
||||
@ -5804,6 +5826,23 @@ If present, this capability can be enabled for a VM, meaning that KVM
|
||||
will allow the transition to secure guest mode. Otherwise KVM will
|
||||
veto the transition.
|
||||
|
||||
7.20 KVM_CAP_HALT_POLL
|
||||
----------------------
|
||||
|
||||
:Architectures: all
|
||||
:Target: VM
|
||||
:Parameters: args[0] is the maximum poll time in nanoseconds
|
||||
:Returns: 0 on success; -1 on error
|
||||
|
||||
This capability overrides the kvm module parameter halt_poll_ns for the
|
||||
target VM.
|
||||
|
||||
VCPU polling allows a VCPU to poll for wakeup events instead of immediately
|
||||
scheduling during guest halts. The maximum time a VCPU can spend polling is
|
||||
controlled by the kvm module parameter halt_poll_ns. This capability allows
|
||||
the maximum halt time to specified on a per-VM basis, effectively overriding
|
||||
the module parameter for the target VM.
|
||||
|
||||
8. Other capabilities.
|
||||
======================
|
||||
|
||||
|
@ -50,8 +50,8 @@ KVM_FEATURE_NOP_IO_DELAY 1 not necessary to perform delays
|
||||
KVM_FEATURE_MMU_OP 2 deprecated
|
||||
|
||||
KVM_FEATURE_CLOCKSOURCE2 3 kvmclock available at msrs
|
||||
|
||||
0x4b564d00 and 0x4b564d01
|
||||
|
||||
KVM_FEATURE_ASYNC_PF 4 async pf can be enabled by
|
||||
writing to msr 0x4b564d02
|
||||
|
||||
@ -86,6 +86,12 @@ KVM_FEATURE_PV_SCHED_YIELD 13 guest checks this feature bit
|
||||
before using paravirtualized
|
||||
sched yield.
|
||||
|
||||
KVM_FEATURE_ASYNC_PF_INT 14 guest checks this feature bit
|
||||
before using the second async
|
||||
pf control msr 0x4b564d06 and
|
||||
async pf acknowledgment msr
|
||||
0x4b564d07.
|
||||
|
||||
KVM_FEATURE_CLOCSOURCE_STABLE_BIT 24 host will warn if no guest-side
|
||||
per-cpu warps are expeced in
|
||||
kvmclock
|
||||
|
@ -190,41 +190,72 @@ MSR_KVM_ASYNC_PF_EN:
|
||||
0x4b564d02
|
||||
|
||||
data:
|
||||
Bits 63-6 hold 64-byte aligned physical address of a
|
||||
64 byte memory area which must be in guest RAM and must be
|
||||
zeroed. Bits 5-3 are reserved and should be zero. Bit 0 is 1
|
||||
when asynchronous page faults are enabled on the vcpu 0 when
|
||||
disabled. Bit 1 is 1 if asynchronous page faults can be injected
|
||||
when vcpu is in cpl == 0. Bit 2 is 1 if asynchronous page faults
|
||||
are delivered to L1 as #PF vmexits. Bit 2 can be set only if
|
||||
KVM_FEATURE_ASYNC_PF_VMEXIT is present in CPUID.
|
||||
Asynchronous page fault (APF) control MSR.
|
||||
|
||||
First 4 byte of 64 byte memory location will be written to by
|
||||
the hypervisor at the time of asynchronous page fault (APF)
|
||||
injection to indicate type of asynchronous page fault. Value
|
||||
of 1 means that the page referred to by the page fault is not
|
||||
present. Value 2 means that the page is now available. Disabling
|
||||
interrupt inhibits APFs. Guest must not enable interrupt
|
||||
before the reason is read, or it may be overwritten by another
|
||||
APF. Since APF uses the same exception vector as regular page
|
||||
fault guest must reset the reason to 0 before it does
|
||||
something that can generate normal page fault. If during page
|
||||
fault APF reason is 0 it means that this is regular page
|
||||
fault.
|
||||
Bits 63-6 hold 64-byte aligned physical address of a 64 byte memory area
|
||||
which must be in guest RAM and must be zeroed. This memory is expected
|
||||
to hold a copy of the following structure::
|
||||
|
||||
During delivery of type 1 APF cr2 contains a token that will
|
||||
be used to notify a guest when missing page becomes
|
||||
available. When page becomes available type 2 APF is sent with
|
||||
cr2 set to the token associated with the page. There is special
|
||||
kind of token 0xffffffff which tells vcpu that it should wake
|
||||
up all processes waiting for APFs and no individual type 2 APFs
|
||||
will be sent.
|
||||
struct kvm_vcpu_pv_apf_data {
|
||||
/* Used for 'page not present' events delivered via #PF */
|
||||
__u32 flags;
|
||||
|
||||
/* Used for 'page ready' events delivered via interrupt notification */
|
||||
__u32 token;
|
||||
|
||||
__u8 pad[56];
|
||||
__u32 enabled;
|
||||
};
|
||||
|
||||
Bits 5-4 of the MSR are reserved and should be zero. Bit 0 is set to 1
|
||||
when asynchronous page faults are enabled on the vcpu, 0 when disabled.
|
||||
Bit 1 is 1 if asynchronous page faults can be injected when vcpu is in
|
||||
cpl == 0. Bit 2 is 1 if asynchronous page faults are delivered to L1 as
|
||||
#PF vmexits. Bit 2 can be set only if KVM_FEATURE_ASYNC_PF_VMEXIT is
|
||||
present in CPUID. Bit 3 enables interrupt based delivery of 'page ready'
|
||||
events. Bit 3 can only be set if KVM_FEATURE_ASYNC_PF_INT is present in
|
||||
CPUID.
|
||||
|
||||
'Page not present' events are currently always delivered as synthetic
|
||||
#PF exception. During delivery of these events APF CR2 register contains
|
||||
a token that will be used to notify the guest when missing page becomes
|
||||
available. Also, to make it possible to distinguish between real #PF and
|
||||
APF, first 4 bytes of 64 byte memory location ('flags') will be written
|
||||
to by the hypervisor at the time of injection. Only first bit of 'flags'
|
||||
is currently supported, when set, it indicates that the guest is dealing
|
||||
with asynchronous 'page not present' event. If during a page fault APF
|
||||
'flags' is '0' it means that this is regular page fault. Guest is
|
||||
supposed to clear 'flags' when it is done handling #PF exception so the
|
||||
next event can be delivered.
|
||||
|
||||
Note, since APF 'page not present' events use the same exception vector
|
||||
as regular page fault, guest must reset 'flags' to '0' before it does
|
||||
something that can generate normal page fault.
|
||||
|
||||
Bytes 5-7 of 64 byte memory location ('token') will be written to by the
|
||||
hypervisor at the time of APF 'page ready' event injection. The content
|
||||
of these bytes is a token which was previously delivered as 'page not
|
||||
present' event. The event indicates the page in now available. Guest is
|
||||
supposed to write '0' to 'token' when it is done handling 'page ready'
|
||||
event and to write 1' to MSR_KVM_ASYNC_PF_ACK after clearing the location;
|
||||
writing to the MSR forces KVM to re-scan its queue and deliver the next
|
||||
pending notification.
|
||||
|
||||
Note, MSR_KVM_ASYNC_PF_INT MSR specifying the interrupt vector for 'page
|
||||
ready' APF delivery needs to be written to before enabling APF mechanism
|
||||
in MSR_KVM_ASYNC_PF_EN or interrupt #0 can get injected. The MSR is
|
||||
available if KVM_FEATURE_ASYNC_PF_INT is present in CPUID.
|
||||
|
||||
Note, previously, 'page ready' events were delivered via the same #PF
|
||||
exception as 'page not present' events but this is now deprecated. If
|
||||
bit 3 (interrupt based delivery) is not set APF events are not delivered.
|
||||
|
||||
If APF is disabled while there are outstanding APFs, they will
|
||||
not be delivered.
|
||||
|
||||
Currently type 2 APF will be always delivered on the same vcpu as
|
||||
type 1 was, but guest should not rely on that.
|
||||
Currently 'page ready' APF events will be always delivered on the
|
||||
same vcpu as 'page not present' event was, but guest should not rely on
|
||||
that.
|
||||
|
||||
MSR_KVM_STEAL_TIME:
|
||||
0x4b564d03
|
||||
@ -319,3 +350,29 @@ data:
|
||||
|
||||
KVM guests can request the host not to poll on HLT, for example if
|
||||
they are performing polling themselves.
|
||||
|
||||
MSR_KVM_ASYNC_PF_INT:
|
||||
0x4b564d06
|
||||
|
||||
data:
|
||||
Second asynchronous page fault (APF) control MSR.
|
||||
|
||||
Bits 0-7: APIC vector for delivery of 'page ready' APF events.
|
||||
Bits 8-63: Reserved
|
||||
|
||||
Interrupt vector for asynchnonous 'page ready' notifications delivery.
|
||||
The vector has to be set up before asynchronous page fault mechanism
|
||||
is enabled in MSR_KVM_ASYNC_PF_EN. The MSR is only available if
|
||||
KVM_FEATURE_ASYNC_PF_INT is present in CPUID.
|
||||
|
||||
MSR_KVM_ASYNC_PF_ACK:
|
||||
0x4b564d07
|
||||
|
||||
data:
|
||||
Asynchronous page fault (APF) acknowledgment.
|
||||
|
||||
When the guest is done processing 'page ready' APF event and 'token'
|
||||
field in 'struct kvm_vcpu_pv_apf_data' is cleared it is supposed to
|
||||
write '1' to bit 0 of the MSR, this causes the host to re-scan its queue
|
||||
and check if there are more notifications pending. The MSR is available
|
||||
if KVM_FEATURE_ASYNC_PF_INT is present in CPUID.
|
||||
|
@ -116,10 +116,7 @@ struct shadow_vmcs is ever changed.
|
||||
natural_width cr4_guest_host_mask;
|
||||
natural_width cr0_read_shadow;
|
||||
natural_width cr4_read_shadow;
|
||||
natural_width cr3_target_value0;
|
||||
natural_width cr3_target_value1;
|
||||
natural_width cr3_target_value2;
|
||||
natural_width cr3_target_value3;
|
||||
natural_width dead_space[4]; /* Last remnants of cr3_target_value[0-3]. */
|
||||
natural_width exit_qualification;
|
||||
natural_width guest_linear_address;
|
||||
natural_width guest_cr0;
|
||||
|
@ -7924,6 +7924,7 @@ F: drivers/pci/controller/pci-hyperv.c
|
||||
F: drivers/scsi/storvsc_drv.c
|
||||
F: drivers/uio/uio_hv_generic.c
|
||||
F: drivers/video/fbdev/hyperv_fb.c
|
||||
F: include/asm-generic/hyperv-tlfs.h
|
||||
F: include/asm-generic/mshyperv.h
|
||||
F: include/clocksource/hyperv_timer.h
|
||||
F: include/linux/hyperv.h
|
||||
@ -9367,7 +9368,6 @@ F: arch/arm64/include/asm/kvm*
|
||||
F: arch/arm64/include/uapi/asm/kvm*
|
||||
F: arch/arm64/kvm/
|
||||
F: include/kvm/arm_*
|
||||
F: virt/kvm/arm/
|
||||
|
||||
KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
|
||||
L: linux-mips@vger.kernel.org
|
||||
@ -12847,7 +12847,7 @@ M: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
|
||||
M: Helge Deller <deller@gmx.de>
|
||||
L: linux-parisc@vger.kernel.org
|
||||
S: Maintained
|
||||
W: http://www.parisc-linux.org/
|
||||
W: https://parisc.wiki.kernel.org
|
||||
Q: http://patchwork.kernel.org/project/linux-parisc/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git
|
||||
@ -14717,6 +14717,7 @@ S: Supported
|
||||
W: http://www.ibm.com/developerworks/linux/linux390/
|
||||
F: block/partitions/ibm.c
|
||||
F: drivers/s390/block/dasd*
|
||||
F: include/linux/dasd_mod.h
|
||||
|
||||
S390 IOMMU (PCI)
|
||||
M: Gerald Schaefer <gerald.schaefer@de.ibm.com>
|
||||
|
@ -11,8 +11,8 @@
|
||||
#define __ASM_ALPHA_FLOPPY_H
|
||||
|
||||
|
||||
#define fd_inb(port) inb_p(port)
|
||||
#define fd_outb(value,port) outb_p(value,port)
|
||||
#define fd_inb(base, reg) inb_p((base) + (reg))
|
||||
#define fd_outb(value, base, reg) outb_p(value, (base) + (reg))
|
||||
|
||||
#define fd_enable_dma() enable_dma(FLOPPY_DMA)
|
||||
#define fd_disable_dma() disable_dma(FLOPPY_DMA)
|
||||
|
@ -105,6 +105,7 @@ pwm7: dmtimer-pwm {
|
||||
ti,timers = <&timer7>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dmtimer7_pins>;
|
||||
ti,clock-source = <0x01>;
|
||||
};
|
||||
|
||||
vmmcsd_fixed: regulator-3v3 {
|
||||
|
@ -156,6 +156,7 @@ pwm11: dmtimer-pwm@11 {
|
||||
pinctrl-0 = <&pwm_pins>;
|
||||
ti,timers = <&timer11>;
|
||||
#pwm-cells = <3>;
|
||||
ti,clock-source = <0x01>;
|
||||
};
|
||||
|
||||
/* HS USB Host PHY on PORT 1 */
|
||||
|
@ -65,6 +65,7 @@ pwm10: dmtimer-pwm {
|
||||
pinctrl-0 = <&pwm_pins>;
|
||||
ti,timers = <&timer10>;
|
||||
#pwm-cells = <3>;
|
||||
ti,clock-source = <0x01>;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -150,6 +150,7 @@ pwm11: dmtimer-pwm {
|
||||
compatible = "ti,omap-dmtimer-pwm";
|
||||
ti,timers = <&timer11>;
|
||||
#pwm-cells = <3>;
|
||||
ti,clock-source = <0x01>;
|
||||
};
|
||||
|
||||
hsusb2_phy: hsusb2_phy {
|
||||
|
@ -9,20 +9,20 @@
|
||||
#ifndef __ASM_ARM_FLOPPY_H
|
||||
#define __ASM_ARM_FLOPPY_H
|
||||
|
||||
#define fd_outb(val,port) \
|
||||
#define fd_outb(val, base, reg) \
|
||||
do { \
|
||||
int new_val = (val); \
|
||||
if (((port) & 7) == FD_DOR) { \
|
||||
if ((reg) == FD_DOR) { \
|
||||
if (new_val & 0xf0) \
|
||||
new_val = (new_val & 0x0c) | \
|
||||
floppy_selects[new_val & 3]; \
|
||||
else \
|
||||
new_val &= 0x0c; \
|
||||
} \
|
||||
outb(new_val, (port)); \
|
||||
outb(new_val, (base) + (reg)); \
|
||||
} while(0)
|
||||
|
||||
#define fd_inb(port) inb((port))
|
||||
#define fd_inb(base, reg) inb((base) + (reg))
|
||||
#define fd_request_irq() request_irq(IRQ_FLOPPYDISK,floppy_interrupt,\
|
||||
0,"floppy",NULL)
|
||||
#define fd_free_irq() free_irq(IRQ_FLOPPYDISK,NULL)
|
||||
|
@ -64,12 +64,14 @@ extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
|
||||
extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
|
||||
extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
|
||||
|
||||
extern void __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high);
|
||||
extern void __kvm_timer_set_cntvoff(u64 cntvoff);
|
||||
|
||||
extern int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu);
|
||||
|
||||
extern int __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu);
|
||||
|
||||
extern void __kvm_enable_ssbs(void);
|
||||
|
||||
extern u64 __vgic_v3_get_ich_vtr_el2(void);
|
||||
extern u64 __vgic_v3_read_vmcr(void);
|
||||
extern void __vgic_v3_write_vmcr(u32 vmcr);
|
||||
|
@ -46,6 +46,9 @@
|
||||
#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(3)
|
||||
#define KVM_REQ_RELOAD_GICv4 KVM_ARCH_REQ(4)
|
||||
|
||||
#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
|
||||
KVM_DIRTY_LOG_INITIALLY_SET)
|
||||
|
||||
DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
|
||||
|
||||
extern unsigned int kvm_sve_max_vl;
|
||||
@ -112,12 +115,8 @@ struct kvm_vcpu_fault_info {
|
||||
u64 disr_el1; /* Deferred [SError] Status Register */
|
||||
};
|
||||
|
||||
/*
|
||||
* 0 is reserved as an invalid value.
|
||||
* Order should be kept in sync with the save/restore code.
|
||||
*/
|
||||
enum vcpu_sysreg {
|
||||
__INVALID_SYSREG__,
|
||||
__INVALID_SYSREG__, /* 0 is reserved as an invalid value */
|
||||
MPIDR_EL1, /* MultiProcessor Affinity Register */
|
||||
CSSELR_EL1, /* Cache Size Selection Register */
|
||||
SCTLR_EL1, /* System Control Register */
|
||||
@ -415,6 +414,8 @@ struct kvm_vm_stat {
|
||||
struct kvm_vcpu_stat {
|
||||
u64 halt_successful_poll;
|
||||
u64 halt_attempted_poll;
|
||||
u64 halt_poll_success_ns;
|
||||
u64 halt_poll_fail_ns;
|
||||
u64 halt_poll_invalid;
|
||||
u64 halt_wakeup;
|
||||
u64 hvc_exit_stat;
|
||||
@ -530,39 +531,6 @@ static inline void kvm_init_host_cpu_context(struct kvm_cpu_context *cpu_ctxt)
|
||||
cpu_ctxt->sys_regs[MPIDR_EL1] = read_cpuid_mpidr();
|
||||
}
|
||||
|
||||
void __kvm_enable_ssbs(void);
|
||||
|
||||
static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
|
||||
unsigned long hyp_stack_ptr,
|
||||
unsigned long vector_ptr)
|
||||
{
|
||||
/*
|
||||
* Calculate the raw per-cpu offset without a translation from the
|
||||
* kernel's mapping to the linear mapping, and store it in tpidr_el2
|
||||
* so that we can use adr_l to access per-cpu variables in EL2.
|
||||
*/
|
||||
u64 tpidr_el2 = ((u64)this_cpu_ptr(&kvm_host_data) -
|
||||
(u64)kvm_ksym_ref(kvm_host_data));
|
||||
|
||||
/*
|
||||
* Call initialization code, and switch to the full blown HYP code.
|
||||
* If the cpucaps haven't been finalized yet, something has gone very
|
||||
* wrong, and hyp will crash and burn when it uses any
|
||||
* cpus_have_const_cap() wrapper.
|
||||
*/
|
||||
BUG_ON(!system_capabilities_finalized());
|
||||
__kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr, tpidr_el2);
|
||||
|
||||
/*
|
||||
* Disabling SSBD on a non-VHE system requires us to enable SSBS
|
||||
* at EL2.
|
||||
*/
|
||||
if (!has_vhe() && this_cpu_has_cap(ARM64_SSBS) &&
|
||||
arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) {
|
||||
kvm_call_hyp(__kvm_enable_ssbs);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool kvm_arch_requires_vhe(void)
|
||||
{
|
||||
/*
|
||||
@ -594,8 +562,6 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
|
||||
int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
|
||||
struct kvm_device_attr *attr);
|
||||
|
||||
static inline void __cpu_init_stage2(void) {}
|
||||
|
||||
/* Guest/host FPSIMD coordination helpers */
|
||||
int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
|
||||
void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu);
|
||||
|
@ -55,12 +55,12 @@
|
||||
|
||||
int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
|
||||
|
||||
void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
|
||||
void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
|
||||
void __vgic_v3_activate_traps(struct kvm_vcpu *vcpu);
|
||||
void __vgic_v3_deactivate_traps(struct kvm_vcpu *vcpu);
|
||||
void __vgic_v3_save_aprs(struct kvm_vcpu *vcpu);
|
||||
void __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu);
|
||||
void __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if);
|
||||
void __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if);
|
||||
void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if);
|
||||
void __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if);
|
||||
void __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if);
|
||||
void __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if);
|
||||
int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
|
||||
|
||||
void __timer_enable_traps(struct kvm_vcpu *vcpu);
|
||||
|
@ -363,8 +363,6 @@ static inline void __kvm_flush_dcache_pud(pud_t pud)
|
||||
}
|
||||
}
|
||||
|
||||
#define kvm_virt_to_phys(x) __pa_symbol(x)
|
||||
|
||||
void kvm_set_way_flush(struct kvm_vcpu *vcpu);
|
||||
void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled);
|
||||
|
||||
@ -473,7 +471,7 @@ static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa,
|
||||
extern void *__kvm_bp_vect_base;
|
||||
extern int __kvm_harden_el2_vector_slot;
|
||||
|
||||
/* This is only called on a VHE system */
|
||||
/* This is called on both VHE and !VHE systems */
|
||||
static inline void *kvm_get_hyp_vector(void)
|
||||
{
|
||||
struct bp_hardening_data *data = arm64_get_bp_hardening_data();
|
||||
|
@ -35,7 +35,7 @@
|
||||
#define GIC_PRIO_PSR_I_SET (1 << 4)
|
||||
|
||||
/* Additional SPSR bits not exposed in the UABI */
|
||||
|
||||
#define PSR_MODE_THREAD_BIT (1 << 0)
|
||||
#define PSR_IL_BIT (1 << 20)
|
||||
|
||||
/* AArch32-specific ptrace requests */
|
||||
|
@ -85,7 +85,7 @@ static inline bool is_kernel_in_hyp_mode(void)
|
||||
|
||||
static __always_inline bool has_vhe(void)
|
||||
{
|
||||
if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
|
||||
if (cpus_have_final_cap(ARM64_HAS_VIRT_HOST_EXTN))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -97,7 +97,7 @@ int main(void)
|
||||
DEFINE(CPU_BOOT_STACK, offsetof(struct secondary_data, stack));
|
||||
DEFINE(CPU_BOOT_TASK, offsetof(struct secondary_data, task));
|
||||
BLANK();
|
||||
#ifdef CONFIG_KVM_ARM_HOST
|
||||
#ifdef CONFIG_KVM
|
||||
DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt));
|
||||
DEFINE(VCPU_FAULT_DISR, offsetof(struct kvm_vcpu, arch.fault.disr_el1));
|
||||
DEFINE(VCPU_WORKAROUND_FLAGS, offsetof(struct kvm_vcpu, arch.workaround_flags));
|
||||
|
@ -234,7 +234,7 @@ static int detect_harden_bp_fw(void)
|
||||
smccc_end = NULL;
|
||||
break;
|
||||
|
||||
#if IS_ENABLED(CONFIG_KVM_ARM_HOST)
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
case SMCCC_CONDUIT_SMC:
|
||||
cb = call_smc_arch_workaround_1;
|
||||
smccc_start = __smccc_workaround_1_smc;
|
||||
|
@ -422,7 +422,7 @@ static void __init hyp_mode_check(void)
|
||||
"CPU: CPUs started in inconsistent modes");
|
||||
else
|
||||
pr_info("CPU: All CPU(s) started at EL1\n");
|
||||
if (IS_ENABLED(CONFIG_KVM_ARM_HOST))
|
||||
if (IS_ENABLED(CONFIG_KVM))
|
||||
kvm_compute_layout();
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
# KVM configuration
|
||||
#
|
||||
|
||||
source "virt/kvm/Kconfig"
|
||||
source "virt/lib/Kconfig"
|
||||
|
||||
menuconfig VIRTUALIZATION
|
||||
@ -18,7 +17,7 @@ menuconfig VIRTUALIZATION
|
||||
|
||||
if VIRTUALIZATION
|
||||
|
||||
config KVM
|
||||
menuconfig KVM
|
||||
bool "Kernel-based Virtual Machine (KVM) support"
|
||||
depends on OF
|
||||
# for TASKSTATS/TASK_DELAY_ACCT:
|
||||
@ -28,13 +27,11 @@ config KVM
|
||||
select HAVE_KVM_CPU_RELAX_INTERCEPT
|
||||
select HAVE_KVM_ARCH_TLB_FLUSH_ALL
|
||||
select KVM_MMIO
|
||||
select KVM_ARM_HOST
|
||||
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
|
||||
select SRCU
|
||||
select KVM_VFIO
|
||||
select HAVE_KVM_EVENTFD
|
||||
select HAVE_KVM_IRQFD
|
||||
select KVM_ARM_PMU if HW_PERF_EVENTS
|
||||
select HAVE_KVM_MSI
|
||||
select HAVE_KVM_IRQCHIP
|
||||
select HAVE_KVM_IRQ_ROUTING
|
||||
@ -45,23 +42,24 @@ config KVM
|
||||
select TASK_DELAY_ACCT
|
||||
---help---
|
||||
Support hosting virtualized guest machines.
|
||||
We don't support KVM with 16K page tables yet, due to the multiple
|
||||
levels of fake page tables.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config KVM_ARM_HOST
|
||||
bool
|
||||
---help---
|
||||
Provides host support for ARM processors.
|
||||
if KVM
|
||||
|
||||
source "virt/kvm/Kconfig"
|
||||
|
||||
config KVM_ARM_PMU
|
||||
bool
|
||||
bool "Virtual Performance Monitoring Unit (PMU) support"
|
||||
depends on HW_PERF_EVENTS
|
||||
default y
|
||||
---help---
|
||||
Adds support for a virtual Performance Monitoring Unit (PMU) in
|
||||
virtual machines.
|
||||
|
||||
config KVM_INDIRECT_VECTORS
|
||||
def_bool KVM && (HARDEN_BRANCH_PREDICTOR || HARDEN_EL2_VECTORS)
|
||||
def_bool HARDEN_BRANCH_PREDICTOR || HARDEN_EL2_VECTORS
|
||||
|
||||
endif # KVM
|
||||
|
||||
endif # VIRTUALIZATION
|
||||
|
@ -3,38 +3,26 @@
|
||||
# Makefile for Kernel-based Virtual Machine module
|
||||
#
|
||||
|
||||
ccflags-y += -I $(srctree)/$(src) -I $(srctree)/virt/kvm/arm/vgic
|
||||
ccflags-y += -I $(srctree)/$(src)
|
||||
CFLAGS_REMOVE_debug.o += $(CC_FLAGS_CFI)
|
||||
|
||||
KVM=../../../virt/kvm
|
||||
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += kvm.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += hyp/
|
||||
obj-$(CONFIG_KVM) += kvm.o
|
||||
obj-$(CONFIG_KVM) += hyp/
|
||||
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hypercalls.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/pvtime.o
|
||||
kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \
|
||||
$(KVM)/vfio.o $(KVM)/irqchip.o \
|
||||
arm.o mmu.o mmio.o psci.o perf.o hypercalls.o pvtime.o \
|
||||
inject_fault.o regmap.o va_layout.o hyp.o hyp-init.o handle_exit.o \
|
||||
guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o \
|
||||
vgic-sys-reg-v3.o fpsimd.o pmu.o \
|
||||
aarch32.o arch_timer.o \
|
||||
vgic/vgic.o vgic/vgic-init.o \
|
||||
vgic/vgic-irqfd.o vgic/vgic-v2.o \
|
||||
vgic/vgic-v3.o vgic/vgic-v4.o \
|
||||
vgic/vgic-mmio.o vgic/vgic-mmio-v2.o \
|
||||
vgic/vgic-mmio-v3.o vgic/vgic-kvm-device.o \
|
||||
vgic/vgic-its.o vgic/vgic-debug.o
|
||||
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o pmu.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o
|
||||
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v4.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-debug.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
|
||||
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
|
||||
kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
|
||||
kvm-$(CONFIG_KVM_ARM_PMU) += pmu-emul.o
|
||||
|
@ -451,17 +451,7 @@ static void timer_restore_state(struct arch_timer_context *ctx)
|
||||
|
||||
static void set_cntvoff(u64 cntvoff)
|
||||
{
|
||||
u32 low = lower_32_bits(cntvoff);
|
||||
u32 high = upper_32_bits(cntvoff);
|
||||
|
||||
/*
|
||||
* Since kvm_call_hyp doesn't fully support the ARM PCS especially on
|
||||
* 32-bit systems, but rather passes register by register shifted one
|
||||
* place (we put the function address in r0/x0), we cannot simply pass
|
||||
* a 64-bit value as an argument, but have to split the value in two
|
||||
* 32-bit halves.
|
||||
*/
|
||||
kvm_call_hyp(__kvm_timer_set_cntvoff, low, high);
|
||||
kvm_call_hyp(__kvm_timer_set_cntvoff, cntvoff);
|
||||
}
|
||||
|
||||
static inline void set_timer_irq_phys_active(struct arch_timer_context *ctx, bool active)
|
||||
@ -571,6 +561,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct arch_timer_cpu *timer = vcpu_timer(vcpu);
|
||||
struct timer_map map;
|
||||
struct rcuwait *wait = kvm_arch_vcpu_get_wait(vcpu);
|
||||
|
||||
if (unlikely(!timer->enabled))
|
||||
return;
|
||||
@ -593,7 +584,7 @@ void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
if (map.emul_ptimer)
|
||||
soft_timer_cancel(&map.emul_ptimer->hrtimer);
|
||||
|
||||
if (swait_active(kvm_arch_vcpu_wq(vcpu)))
|
||||
if (rcuwait_active(wait))
|
||||
kvm_timer_blocking(vcpu);
|
||||
|
||||
/*
|
@ -22,7 +22,7 @@
|
||||
#include <trace/events/kvm.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "trace.h"
|
||||
#include "trace_arm.h"
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/ptrace.h>
|
||||
@ -95,6 +95,11 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
|
||||
return r;
|
||||
}
|
||||
|
||||
static int kvm_arm_default_max_vcpus(void)
|
||||
{
|
||||
return vgic_present ? kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_arch_init_vm - initializes a VM data structure
|
||||
* @kvm: pointer to the KVM struct
|
||||
@ -128,8 +133,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
kvm->arch.vmid.vmid_gen = 0;
|
||||
|
||||
/* The maximum number of VCPUs is limited by the host's GIC model */
|
||||
kvm->arch.max_vcpus = vgic_present ?
|
||||
kvm_vgic_get_max_vcpus() : KVM_MAX_VCPUS;
|
||||
kvm->arch.max_vcpus = kvm_arm_default_max_vcpus();
|
||||
|
||||
return ret;
|
||||
out_free_stage2_pgd:
|
||||
@ -204,10 +208,11 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
r = num_online_cpus();
|
||||
break;
|
||||
case KVM_CAP_MAX_VCPUS:
|
||||
r = KVM_MAX_VCPUS;
|
||||
break;
|
||||
case KVM_CAP_MAX_VCPU_ID:
|
||||
r = KVM_MAX_VCPU_ID;
|
||||
if (kvm)
|
||||
r = kvm->arch.max_vcpus;
|
||||
else
|
||||
r = kvm_arm_default_max_vcpus();
|
||||
break;
|
||||
case KVM_CAP_MSI_DEVID:
|
||||
if (!kvm)
|
||||
@ -455,9 +460,9 @@ void force_vm_exit(const cpumask_t *mask)
|
||||
*
|
||||
* The hardware supports a limited set of values with the value zero reserved
|
||||
* for the host, so we check if an assigned value belongs to a previous
|
||||
* generation, which which requires us to assign a new value. If we're the
|
||||
* first to use a VMID for the new generation, we must flush necessary caches
|
||||
* and TLBs on all CPUs.
|
||||
* generation, which requires us to assign a new value. If we're the first to
|
||||
* use a VMID for the new generation, we must flush necessary caches and TLBs
|
||||
* on all CPUs.
|
||||
*/
|
||||
static bool need_new_vmid_gen(struct kvm_vmid *vmid)
|
||||
{
|
||||
@ -579,16 +584,17 @@ void kvm_arm_resume_guest(struct kvm *kvm)
|
||||
|
||||
kvm_for_each_vcpu(i, vcpu, kvm) {
|
||||
vcpu->arch.pause = false;
|
||||
swake_up_one(kvm_arch_vcpu_wq(vcpu));
|
||||
rcuwait_wake_up(kvm_arch_vcpu_get_wait(vcpu));
|
||||
}
|
||||
}
|
||||
|
||||
static void vcpu_req_sleep(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct swait_queue_head *wq = kvm_arch_vcpu_wq(vcpu);
|
||||
struct rcuwait *wait = kvm_arch_vcpu_get_wait(vcpu);
|
||||
|
||||
swait_event_interruptible_exclusive(*wq, ((!vcpu->arch.power_off) &&
|
||||
(!vcpu->arch.pause)));
|
||||
rcuwait_wait_event(wait,
|
||||
(!vcpu->arch.power_off) &&(!vcpu->arch.pause),
|
||||
TASK_INTERRUPTIBLE);
|
||||
|
||||
if (vcpu->arch.power_off || vcpu->arch.pause) {
|
||||
/* Awaken to handle a signal, request we sleep again later. */
|
||||
@ -639,7 +645,6 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
|
||||
/**
|
||||
* kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
|
||||
* @vcpu: The VCPU pointer
|
||||
* @run: The kvm_run structure pointer used for userspace state exchange
|
||||
*
|
||||
* This function is called through the VCPU_RUN ioctl called from user space. It
|
||||
* will execute VM code in a loop until the time slice for the process is used
|
||||
@ -647,8 +652,9 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
|
||||
* return with return value 0 and with the kvm_run structure filled in with the
|
||||
* required data for the requested emulation.
|
||||
*/
|
||||
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_run *run = vcpu->run;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!kvm_vcpu_initialized(vcpu)))
|
||||
@ -659,7 +665,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
||||
return ret;
|
||||
|
||||
if (run->exit_reason == KVM_EXIT_MMIO) {
|
||||
ret = kvm_handle_mmio_return(vcpu, vcpu->run);
|
||||
ret = kvm_handle_mmio_return(vcpu, run);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -983,8 +989,11 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
|
||||
/*
|
||||
* Ensure a rebooted VM will fault in RAM pages and detect if the
|
||||
* guest MMU is turned off and flush the caches as needed.
|
||||
*
|
||||
* S2FWB enforces all memory accesses to RAM being cacheable, we
|
||||
* ensure that the cache is always coherent.
|
||||
*/
|
||||
if (vcpu->arch.has_run_once)
|
||||
if (vcpu->arch.has_run_once && !cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
|
||||
stage2_unmap_vm(vcpu->kvm);
|
||||
|
||||
vcpu_reset_hcr(vcpu);
|
||||
@ -1265,19 +1274,41 @@ static void cpu_init_hyp_mode(void)
|
||||
{
|
||||
phys_addr_t pgd_ptr;
|
||||
unsigned long hyp_stack_ptr;
|
||||
unsigned long stack_page;
|
||||
unsigned long vector_ptr;
|
||||
unsigned long tpidr_el2;
|
||||
|
||||
/* Switch from the HYP stub to our own HYP init vector */
|
||||
__hyp_set_vectors(kvm_get_idmap_vector());
|
||||
|
||||
/*
|
||||
* Calculate the raw per-cpu offset without a translation from the
|
||||
* kernel's mapping to the linear mapping, and store it in tpidr_el2
|
||||
* so that we can use adr_l to access per-cpu variables in EL2.
|
||||
*/
|
||||
tpidr_el2 = ((unsigned long)this_cpu_ptr(&kvm_host_data) -
|
||||
(unsigned long)kvm_ksym_ref(kvm_host_data));
|
||||
|
||||
pgd_ptr = kvm_mmu_get_httbr();
|
||||
stack_page = __this_cpu_read(kvm_arm_hyp_stack_page);
|
||||
hyp_stack_ptr = stack_page + PAGE_SIZE;
|
||||
hyp_stack_ptr = __this_cpu_read(kvm_arm_hyp_stack_page) + PAGE_SIZE;
|
||||
vector_ptr = (unsigned long)kvm_get_hyp_vector();
|
||||
|
||||
__cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
|
||||
__cpu_init_stage2();
|
||||
/*
|
||||
* Call initialization code, and switch to the full blown HYP code.
|
||||
* If the cpucaps haven't been finalized yet, something has gone very
|
||||
* wrong, and hyp will crash and burn when it uses any
|
||||
* cpus_have_const_cap() wrapper.
|
||||
*/
|
||||
BUG_ON(!system_capabilities_finalized());
|
||||
__kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr, tpidr_el2);
|
||||
|
||||
/*
|
||||
* Disabling SSBD on a non-VHE system requires us to enable SSBS
|
||||
* at EL2.
|
||||
*/
|
||||
if (this_cpu_has_cap(ARM64_SSBS) &&
|
||||
arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) {
|
||||
kvm_call_hyp(__kvm_enable_ssbs);
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_hyp_reset(void)
|
@ -29,20 +29,19 @@
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
#define VM_STAT(x) { #x, offsetof(struct kvm, stat.x), KVM_STAT_VM }
|
||||
#define VCPU_STAT(x) { #x, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU }
|
||||
|
||||
struct kvm_stats_debugfs_item debugfs_entries[] = {
|
||||
VCPU_STAT(halt_successful_poll),
|
||||
VCPU_STAT(halt_attempted_poll),
|
||||
VCPU_STAT(halt_poll_invalid),
|
||||
VCPU_STAT(halt_wakeup),
|
||||
VCPU_STAT(hvc_exit_stat),
|
||||
VCPU_STAT(wfe_exit_stat),
|
||||
VCPU_STAT(wfi_exit_stat),
|
||||
VCPU_STAT(mmio_exit_user),
|
||||
VCPU_STAT(mmio_exit_kernel),
|
||||
VCPU_STAT(exits),
|
||||
VCPU_STAT("halt_successful_poll", halt_successful_poll),
|
||||
VCPU_STAT("halt_attempted_poll", halt_attempted_poll),
|
||||
VCPU_STAT("halt_poll_invalid", halt_poll_invalid),
|
||||
VCPU_STAT("halt_wakeup", halt_wakeup),
|
||||
VCPU_STAT("hvc_exit_stat", hvc_exit_stat),
|
||||
VCPU_STAT("wfe_exit_stat", wfe_exit_stat),
|
||||
VCPU_STAT("wfi_exit_stat", wfi_exit_stat),
|
||||
VCPU_STAT("mmio_exit_user", mmio_exit_user),
|
||||
VCPU_STAT("mmio_exit_kernel", mmio_exit_kernel),
|
||||
VCPU_STAT("exits", exits),
|
||||
VCPU_STAT("halt_poll_success_ns", halt_poll_success_ns),
|
||||
VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns),
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -267,7 +266,7 @@ static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||
/*
|
||||
* Vector lengths supported by the host can't currently be
|
||||
* hidden from the guest individually: instead we can only set a
|
||||
* maxmium via ZCR_EL2.LEN. So, make sure the available vector
|
||||
* maximum via ZCR_EL2.LEN. So, make sure the available vector
|
||||
* lengths match the set requested exactly up to the requested
|
||||
* maximum:
|
||||
*/
|
||||
@ -337,7 +336,7 @@ static int sve_reg_to_region(struct sve_state_reg_region *region,
|
||||
unsigned int reg_num;
|
||||
|
||||
unsigned int reqoffset, reqlen; /* User-requested offset and length */
|
||||
unsigned int maxlen; /* Maxmimum permitted length */
|
||||
unsigned int maxlen; /* Maximum permitted length */
|
||||
|
||||
size_t sve_state_size;
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <kvm/arm_hypercalls.h>
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "trace.h"
|
||||
#include "trace_handle_exit.h"
|
||||
|
||||
typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
|
||||
|
||||
|
@ -6,20 +6,10 @@
|
||||
ccflags-y += -fno-stack-protector -DDISABLE_BRANCH_PROFILING \
|
||||
$(DISABLE_STACKLEAK_PLUGIN)
|
||||
|
||||
KVM=../../../../virt/kvm
|
||||
obj-$(CONFIG_KVM) += hyp.o
|
||||
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v3-sr.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/timer-sr.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/aarch32.o
|
||||
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += vgic-v2-cpuif-proxy.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += sysreg-sr.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += debug-sr.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += entry.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += switch.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += fpsimd.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += tlb.o
|
||||
obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o
|
||||
hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \
|
||||
debug-sr.o entry.o switch.o fpsimd.o tlb.o hyp-entry.o
|
||||
|
||||
# KVM code is run at a different exception code with a different map, so
|
||||
# compiler instrumentation that inserts callbacks or checks into the code may
|
||||
|
@ -270,8 +270,8 @@ static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu)
|
||||
static void __hyp_text __hyp_vgic_save_state(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) {
|
||||
__vgic_v3_save_state(vcpu);
|
||||
__vgic_v3_deactivate_traps(vcpu);
|
||||
__vgic_v3_save_state(&vcpu->arch.vgic_cpu.vgic_v3);
|
||||
__vgic_v3_deactivate_traps(&vcpu->arch.vgic_cpu.vgic_v3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,8 +279,8 @@ static void __hyp_text __hyp_vgic_save_state(struct kvm_vcpu *vcpu)
|
||||
static void __hyp_text __hyp_vgic_restore_state(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif)) {
|
||||
__vgic_v3_activate_traps(vcpu);
|
||||
__vgic_v3_restore_state(vcpu);
|
||||
__vgic_v3_activate_traps(&vcpu->arch.vgic_cpu.vgic_v3);
|
||||
__vgic_v3_restore_state(&vcpu->arch.vgic_cpu.vgic_v3);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,9 +10,8 @@
|
||||
|
||||
#include <asm/kvm_hyp.h>
|
||||
|
||||
void __hyp_text __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high)
|
||||
void __hyp_text __kvm_timer_set_cntvoff(u64 cntvoff)
|
||||
{
|
||||
u64 cntvoff = (u64)cntvoff_high << 32 | cntvoff_low;
|
||||
write_sysreg(cntvoff, cntvoff_el2);
|
||||
}
|
||||
|
@ -194,10 +194,9 @@ static u32 __hyp_text __vgic_v3_read_ap1rn(int n)
|
||||
return val;
|
||||
}
|
||||
|
||||
void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
|
||||
void __hyp_text __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if)
|
||||
{
|
||||
struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
|
||||
u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
|
||||
u64 used_lrs = cpu_if->used_lrs;
|
||||
|
||||
/*
|
||||
* Make sure stores to the GIC via the memory mapped interface
|
||||
@ -230,10 +229,9 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
|
||||
void __hyp_text __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if)
|
||||
{
|
||||
struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
|
||||
u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
|
||||
u64 used_lrs = cpu_if->used_lrs;
|
||||
int i;
|
||||
|
||||
if (used_lrs || cpu_if->its_vpe.its_vm) {
|
||||
@ -257,10 +255,8 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
void __hyp_text __vgic_v3_activate_traps(struct kvm_vcpu *vcpu)
|
||||
void __hyp_text __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if)
|
||||
{
|
||||
struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
|
||||
|
||||
/*
|
||||
* VFIQEn is RES1 if ICC_SRE_EL1.SRE is 1. This causes a
|
||||
* Group0 interrupt (as generated in GICv2 mode) to be
|
||||
@ -306,9 +302,8 @@ void __hyp_text __vgic_v3_activate_traps(struct kvm_vcpu *vcpu)
|
||||
write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
|
||||
}
|
||||
|
||||
void __hyp_text __vgic_v3_deactivate_traps(struct kvm_vcpu *vcpu)
|
||||
void __hyp_text __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if)
|
||||
{
|
||||
struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
|
||||
u64 val;
|
||||
|
||||
if (!cpu_if->vgic_sre) {
|
||||
@ -333,15 +328,11 @@ void __hyp_text __vgic_v3_deactivate_traps(struct kvm_vcpu *vcpu)
|
||||
write_gicreg(0, ICH_HCR_EL2);
|
||||
}
|
||||
|
||||
void __hyp_text __vgic_v3_save_aprs(struct kvm_vcpu *vcpu)
|
||||
void __hyp_text __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if)
|
||||
{
|
||||
struct vgic_v3_cpu_if *cpu_if;
|
||||
u64 val;
|
||||
u32 nr_pre_bits;
|
||||
|
||||
vcpu = kern_hyp_va(vcpu);
|
||||
cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
|
||||
|
||||
val = read_gicreg(ICH_VTR_EL2);
|
||||
nr_pre_bits = vtr_to_nr_pre_bits(val);
|
||||
|
||||
@ -370,15 +361,11 @@ void __hyp_text __vgic_v3_save_aprs(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
void __hyp_text __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu)
|
||||
void __hyp_text __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if)
|
||||
{
|
||||
struct vgic_v3_cpu_if *cpu_if;
|
||||
u64 val;
|
||||
u32 nr_pre_bits;
|
||||
|
||||
vcpu = kern_hyp_va(vcpu);
|
||||
cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
|
||||
|
||||
val = read_gicreg(ICH_VTR_EL2);
|
||||
nr_pre_bits = vtr_to_nr_pre_bits(val);
|
||||
|
||||
@ -431,8 +418,6 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
|
||||
write_gicreg(vmcr, ICH_VMCR_EL2);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
|
||||
static int __hyp_text __vgic_v3_bpr_min(void)
|
||||
{
|
||||
/* See Pseudocode for VPriorityGroup */
|
||||
@ -453,7 +438,7 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
|
||||
u32 vmcr,
|
||||
u64 *lr_val)
|
||||
{
|
||||
unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
|
||||
unsigned int used_lrs = vcpu->arch.vgic_cpu.vgic_v3.used_lrs;
|
||||
u8 priority = GICv3_IDLE_PRIORITY;
|
||||
int i, lr = -1;
|
||||
|
||||
@ -492,7 +477,7 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
|
||||
static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
|
||||
int intid, u64 *lr_val)
|
||||
{
|
||||
unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
|
||||
unsigned int used_lrs = vcpu->arch.vgic_cpu.vgic_v3.used_lrs;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < used_lrs; i++) {
|
||||
@ -579,7 +564,7 @@ static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
|
||||
|
||||
/*
|
||||
* The priority value is independent of any of the BPR values, so we
|
||||
* normalize it using the minumal BPR value. This guarantees that no
|
||||
* normalize it using the minimal BPR value. This guarantees that no
|
||||
* matter what the guest does with its BPR, we can always set/get the
|
||||
* same value of a priority.
|
||||
*/
|
||||
@ -1126,5 +1111,3 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
@ -26,28 +26,12 @@ enum exception_type {
|
||||
except_type_serror = 0x180,
|
||||
};
|
||||
|
||||
static u64 get_except_vector(struct kvm_vcpu *vcpu, enum exception_type type)
|
||||
{
|
||||
u64 exc_offset;
|
||||
|
||||
switch (*vcpu_cpsr(vcpu) & (PSR_MODE_MASK | PSR_MODE32_BIT)) {
|
||||
case PSR_MODE_EL1t:
|
||||
exc_offset = CURRENT_EL_SP_EL0_VECTOR;
|
||||
break;
|
||||
case PSR_MODE_EL1h:
|
||||
exc_offset = CURRENT_EL_SP_ELx_VECTOR;
|
||||
break;
|
||||
case PSR_MODE_EL0t:
|
||||
exc_offset = LOWER_EL_AArch64_VECTOR;
|
||||
break;
|
||||
default:
|
||||
exc_offset = LOWER_EL_AArch32_VECTOR;
|
||||
}
|
||||
|
||||
return vcpu_read_sys_reg(vcpu, VBAR_EL1) + exc_offset + type;
|
||||
}
|
||||
|
||||
/*
|
||||
* This performs the exception entry at a given EL (@target_mode), stashing PC
|
||||
* and PSTATE into ELR and SPSR respectively, and compute the new PC/PSTATE.
|
||||
* The EL passed to this function *must* be a non-secure, privileged mode with
|
||||
* bit 0 being set (PSTATE.SP == 1).
|
||||
*
|
||||
* When an exception is taken, most PSTATE fields are left unchanged in the
|
||||
* handler. However, some are explicitly overridden (e.g. M[4:0]). Luckily all
|
||||
* of the inherited bits have the same position in the AArch64/AArch32 SPSR_ELx
|
||||
@ -59,10 +43,35 @@ static u64 get_except_vector(struct kvm_vcpu *vcpu, enum exception_type type)
|
||||
* Here we manipulate the fields in order of the AArch64 SPSR_ELx layout, from
|
||||
* MSB to LSB.
|
||||
*/
|
||||
static unsigned long get_except64_pstate(struct kvm_vcpu *vcpu)
|
||||
static void enter_exception64(struct kvm_vcpu *vcpu, unsigned long target_mode,
|
||||
enum exception_type type)
|
||||
{
|
||||
unsigned long sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
|
||||
unsigned long old, new;
|
||||
unsigned long sctlr, vbar, old, new, mode;
|
||||
u64 exc_offset;
|
||||
|
||||
mode = *vcpu_cpsr(vcpu) & (PSR_MODE_MASK | PSR_MODE32_BIT);
|
||||
|
||||
if (mode == target_mode)
|
||||
exc_offset = CURRENT_EL_SP_ELx_VECTOR;
|
||||
else if ((mode | PSR_MODE_THREAD_BIT) == target_mode)
|
||||
exc_offset = CURRENT_EL_SP_EL0_VECTOR;
|
||||
else if (!(mode & PSR_MODE32_BIT))
|
||||
exc_offset = LOWER_EL_AArch64_VECTOR;
|
||||
else
|
||||
exc_offset = LOWER_EL_AArch32_VECTOR;
|
||||
|
||||
switch (target_mode) {
|
||||
case PSR_MODE_EL1h:
|
||||
vbar = vcpu_read_sys_reg(vcpu, VBAR_EL1);
|
||||
sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
|
||||
vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu));
|
||||
break;
|
||||
default:
|
||||
/* Don't do that */
|
||||
BUG();
|
||||
}
|
||||
|
||||
*vcpu_pc(vcpu) = vbar + exc_offset + type;
|
||||
|
||||
old = *vcpu_cpsr(vcpu);
|
||||
new = 0;
|
||||
@ -105,9 +114,10 @@ static unsigned long get_except64_pstate(struct kvm_vcpu *vcpu)
|
||||
new |= PSR_I_BIT;
|
||||
new |= PSR_F_BIT;
|
||||
|
||||
new |= PSR_MODE_EL1h;
|
||||
new |= target_mode;
|
||||
|
||||
return new;
|
||||
*vcpu_cpsr(vcpu) = new;
|
||||
vcpu_write_spsr(vcpu, old);
|
||||
}
|
||||
|
||||
static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
|
||||
@ -116,11 +126,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
|
||||
bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
|
||||
u32 esr = 0;
|
||||
|
||||
vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu));
|
||||
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
|
||||
|
||||
*vcpu_cpsr(vcpu) = get_except64_pstate(vcpu);
|
||||
vcpu_write_spsr(vcpu, cpsr);
|
||||
enter_exception64(vcpu, PSR_MODE_EL1h, except_type_sync);
|
||||
|
||||
vcpu_write_sys_reg(vcpu, addr, FAR_EL1);
|
||||
|
||||
@ -148,14 +154,9 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
|
||||
|
||||
static void inject_undef64(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
unsigned long cpsr = *vcpu_cpsr(vcpu);
|
||||
u32 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
|
||||
|
||||
vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu));
|
||||
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
|
||||
|
||||
*vcpu_cpsr(vcpu) = get_except64_pstate(vcpu);
|
||||
vcpu_write_spsr(vcpu, cpsr);
|
||||
enter_exception64(vcpu, PSR_MODE_EL1h, except_type_sync);
|
||||
|
||||
/*
|
||||
* Build an unknown exception, depending on the instruction
|
||||
|
@ -131,7 +131,7 @@ int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
|
||||
/*
|
||||
* No valid syndrome? Ask userspace for help if it has
|
||||
* voluntered to do so, and bail out otherwise.
|
||||
* volunteered to do so, and bail out otherwise.
|
||||
*/
|
||||
if (!kvm_vcpu_dabt_isvalid(vcpu)) {
|
||||
if (vcpu->kvm->arch.return_nisv_io_abort_to_user) {
|
@ -422,6 +422,9 @@ static void stage2_flush_memslot(struct kvm *kvm,
|
||||
next = stage2_pgd_addr_end(kvm, addr, end);
|
||||
if (!stage2_pgd_none(kvm, *pgd))
|
||||
stage2_flush_puds(kvm, pgd, addr, next);
|
||||
|
||||
if (next != end)
|
||||
cond_resched_lock(&kvm->mmu_lock);
|
||||
} while (pgd++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
@ -784,7 +787,7 @@ static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size,
|
||||
mutex_lock(&kvm_hyp_pgd_mutex);
|
||||
|
||||
/*
|
||||
* This assumes that we we have enough space below the idmap
|
||||
* This assumes that we have enough space below the idmap
|
||||
* page to allocate our VAs. If not, the check below will
|
||||
* kick. A potential alternative would be to detect that
|
||||
* overflow and switch to an allocation above the idmap.
|
||||
@ -964,7 +967,7 @@ static void stage2_unmap_memslot(struct kvm *kvm,
|
||||
* stage2_unmap_vm - Unmap Stage-2 RAM mappings
|
||||
* @kvm: The struct kvm pointer
|
||||
*
|
||||
* Go through the memregions and unmap any reguler RAM
|
||||
* Go through the memregions and unmap any regular RAM
|
||||
* backing memory already mapped to the VM.
|
||||
*/
|
||||
void stage2_unmap_vm(struct kvm *kvm)
|
||||
@ -1372,47 +1375,6 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap)
|
||||
{
|
||||
kvm_pfn_t pfn = *pfnp;
|
||||
gfn_t gfn = *ipap >> PAGE_SHIFT;
|
||||
|
||||
if (kvm_is_transparent_hugepage(pfn)) {
|
||||
unsigned long mask;
|
||||
/*
|
||||
* The address we faulted on is backed by a transparent huge
|
||||
* page. However, because we map the compound huge page and
|
||||
* not the individual tail page, we need to transfer the
|
||||
* refcount to the head page. We have to be careful that the
|
||||
* THP doesn't start to split while we are adjusting the
|
||||
* refcounts.
|
||||
*
|
||||
* We are sure this doesn't happen, because mmu_notifier_retry
|
||||
* was successful and we are holding the mmu_lock, so if this
|
||||
* THP is trying to split, it will be blocked in the mmu
|
||||
* notifier before touching any of the pages, specifically
|
||||
* before being able to call __split_huge_page_refcount().
|
||||
*
|
||||
* We can therefore safely transfer the refcount from PG_tail
|
||||
* to PG_head and switch the pfn from a tail page to the head
|
||||
* page accordingly.
|
||||
*/
|
||||
mask = PTRS_PER_PMD - 1;
|
||||
VM_BUG_ON((gfn & mask) != (pfn & mask));
|
||||
if (pfn & mask) {
|
||||
*ipap &= PMD_MASK;
|
||||
kvm_release_pfn_clean(pfn);
|
||||
pfn &= ~mask;
|
||||
kvm_get_pfn(pfn);
|
||||
*pfnp = pfn;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* stage2_wp_ptes - write protect PMD range
|
||||
* @pmd: pointer to pmd entry
|
||||
@ -1607,6 +1569,10 @@ static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot,
|
||||
hva_t uaddr_start, uaddr_end;
|
||||
size_t size;
|
||||
|
||||
/* The memslot and the VMA are guaranteed to be aligned to PAGE_SIZE */
|
||||
if (map_size == PAGE_SIZE)
|
||||
return true;
|
||||
|
||||
size = memslot->npages * PAGE_SIZE;
|
||||
|
||||
gpa_start = memslot->base_gfn << PAGE_SHIFT;
|
||||
@ -1626,7 +1592,7 @@ static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot,
|
||||
* |abcde|fgh Stage-1 block | Stage-1 block tv|xyz|
|
||||
* +-----+--------------------+--------------------+---+
|
||||
*
|
||||
* memslot->base_gfn << PAGE_SIZE:
|
||||
* memslot->base_gfn << PAGE_SHIFT:
|
||||
* +---+--------------------+--------------------+-----+
|
||||
* |abc|def Stage-2 block | Stage-2 block |tvxyz|
|
||||
* +---+--------------------+--------------------+-----+
|
||||
@ -1656,6 +1622,59 @@ static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot,
|
||||
(hva & ~(map_size - 1)) + map_size <= uaddr_end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the given hva is backed by a transparent huge page (THP) and
|
||||
* whether it can be mapped using block mapping in stage2. If so, adjust
|
||||
* the stage2 PFN and IPA accordingly. Only PMD_SIZE THPs are currently
|
||||
* supported. This will need to be updated to support other THP sizes.
|
||||
*
|
||||
* Returns the size of the mapping.
|
||||
*/
|
||||
static unsigned long
|
||||
transparent_hugepage_adjust(struct kvm_memory_slot *memslot,
|
||||
unsigned long hva, kvm_pfn_t *pfnp,
|
||||
phys_addr_t *ipap)
|
||||
{
|
||||
kvm_pfn_t pfn = *pfnp;
|
||||
|
||||
/*
|
||||
* Make sure the adjustment is done only for THP pages. Also make
|
||||
* sure that the HVA and IPA are sufficiently aligned and that the
|
||||
* block map is contained within the memslot.
|
||||
*/
|
||||
if (kvm_is_transparent_hugepage(pfn) &&
|
||||
fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) {
|
||||
/*
|
||||
* The address we faulted on is backed by a transparent huge
|
||||
* page. However, because we map the compound huge page and
|
||||
* not the individual tail page, we need to transfer the
|
||||
* refcount to the head page. We have to be careful that the
|
||||
* THP doesn't start to split while we are adjusting the
|
||||
* refcounts.
|
||||
*
|
||||
* We are sure this doesn't happen, because mmu_notifier_retry
|
||||
* was successful and we are holding the mmu_lock, so if this
|
||||
* THP is trying to split, it will be blocked in the mmu
|
||||
* notifier before touching any of the pages, specifically
|
||||
* before being able to call __split_huge_page_refcount().
|
||||
*
|
||||
* We can therefore safely transfer the refcount from PG_tail
|
||||
* to PG_head and switch the pfn from a tail page to the head
|
||||
* page accordingly.
|
||||
*/
|
||||
*ipap &= PMD_MASK;
|
||||
kvm_release_pfn_clean(pfn);
|
||||
pfn &= ~(PTRS_PER_PMD - 1);
|
||||
kvm_get_pfn(pfn);
|
||||
*pfnp = pfn;
|
||||
|
||||
return PMD_SIZE;
|
||||
}
|
||||
|
||||
/* Use page mapping if we cannot use block mapping. */
|
||||
return PAGE_SIZE;
|
||||
}
|
||||
|
||||
static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||
struct kvm_memory_slot *memslot, unsigned long hva,
|
||||
unsigned long fault_status)
|
||||
@ -1769,20 +1788,13 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||
if (mmu_notifier_retry(kvm, mmu_seq))
|
||||
goto out_unlock;
|
||||
|
||||
if (vma_pagesize == PAGE_SIZE && !force_pte) {
|
||||
/*
|
||||
* Only PMD_SIZE transparent hugepages(THP) are
|
||||
* currently supported. This code will need to be
|
||||
* updated to support other THP sizes.
|
||||
*
|
||||
* Make sure the host VA and the guest IPA are sufficiently
|
||||
* aligned and that the block is contained within the memslot.
|
||||
*/
|
||||
if (fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE) &&
|
||||
transparent_hugepage_adjust(&pfn, &fault_ipa))
|
||||
vma_pagesize = PMD_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are not forced to use page mapping, check if we are
|
||||
* backed by a THP and thus use block mapping if possible.
|
||||
*/
|
||||
if (vma_pagesize == PAGE_SIZE && !force_pte)
|
||||
vma_pagesize = transparent_hugepage_adjust(memslot, hva,
|
||||
&pfn, &fault_ipa);
|
||||
if (writable)
|
||||
kvm_set_pfn_dirty(pfn);
|
||||
|
||||
@ -2185,11 +2197,11 @@ int kvm_mmu_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
hyp_idmap_start = kvm_virt_to_phys(__hyp_idmap_text_start);
|
||||
hyp_idmap_start = __pa_symbol(__hyp_idmap_text_start);
|
||||
hyp_idmap_start = ALIGN_DOWN(hyp_idmap_start, PAGE_SIZE);
|
||||
hyp_idmap_end = kvm_virt_to_phys(__hyp_idmap_text_end);
|
||||
hyp_idmap_end = __pa_symbol(__hyp_idmap_text_end);
|
||||
hyp_idmap_end = ALIGN(hyp_idmap_end, PAGE_SIZE);
|
||||
hyp_idmap_vector = kvm_virt_to_phys(__kvm_hyp_init);
|
||||
hyp_idmap_vector = __pa_symbol(__kvm_hyp_init);
|
||||
|
||||
/*
|
||||
* We rely on the linker script to ensure at build time that the HYP
|
||||
@ -2262,11 +2274,19 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
|
||||
{
|
||||
/*
|
||||
* At this point memslot has been committed and there is an
|
||||
* allocated dirty_bitmap[], dirty pages will be be tracked while the
|
||||
* allocated dirty_bitmap[], dirty pages will be tracked while the
|
||||
* memory slot is write protected.
|
||||
*/
|
||||
if (change != KVM_MR_DELETE && mem->flags & KVM_MEM_LOG_DIRTY_PAGES)
|
||||
kvm_mmu_wp_memory_region(kvm, mem->slot);
|
||||
if (change != KVM_MR_DELETE && mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
|
||||
/*
|
||||
* If we're with initial-all-set, we don't need to write
|
||||
* protect any pages because they're all reported as dirty.
|
||||
* Huge pages and normal pages will be write protect gradually.
|
||||
*/
|
||||
if (!kvm_dirty_log_manual_protect_and_init_set(kvm)) {
|
||||
kvm_mmu_wp_memory_region(kvm, mem->slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
@ -94,7 +94,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
|
||||
|
||||
/*
|
||||
* NOTE: We always update r0 (or x0) because for PSCI v0.1
|
||||
* the general puspose registers are undefined upon CPU_ON.
|
||||
* the general purpose registers are undefined upon CPU_ON.
|
||||
*/
|
||||
reset_state->r0 = smccc_get_arg3(source_vcpu);
|
||||
|
||||
@ -265,10 +265,10 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
|
||||
case PSCI_0_2_FN_SYSTEM_OFF:
|
||||
kvm_psci_system_off(vcpu);
|
||||
/*
|
||||
* We should'nt be going back to guest VCPU after
|
||||
* We shouldn't be going back to guest VCPU after
|
||||
* receiving SYSTEM_OFF request.
|
||||
*
|
||||
* If user space accidently/deliberately resumes
|
||||
* If user space accidentally/deliberately resumes
|
||||
* guest VCPU after SYSTEM_OFF request then guest
|
||||
* VCPU should see internal failure from PSCI return
|
||||
* value. To achieve this, we preload r0 (or x0) with
|
@ -36,15 +36,11 @@ static u32 kvm_ipa_limit;
|
||||
/*
|
||||
* ARMv8 Reset Values
|
||||
*/
|
||||
static const struct kvm_regs default_regs_reset = {
|
||||
.regs.pstate = (PSR_MODE_EL1h | PSR_A_BIT | PSR_I_BIT |
|
||||
PSR_F_BIT | PSR_D_BIT),
|
||||
};
|
||||
#define VCPU_RESET_PSTATE_EL1 (PSR_MODE_EL1h | PSR_A_BIT | PSR_I_BIT | \
|
||||
PSR_F_BIT | PSR_D_BIT)
|
||||
|
||||
static const struct kvm_regs default_regs_reset32 = {
|
||||
.regs.pstate = (PSR_AA32_MODE_SVC | PSR_AA32_A_BIT |
|
||||
PSR_AA32_I_BIT | PSR_AA32_F_BIT),
|
||||
};
|
||||
#define VCPU_RESET_PSTATE_SVC (PSR_AA32_MODE_SVC | PSR_AA32_A_BIT | \
|
||||
PSR_AA32_I_BIT | PSR_AA32_F_BIT)
|
||||
|
||||
/**
|
||||
* kvm_arch_vm_ioctl_check_extension
|
||||
@ -155,7 +151,7 @@ static int kvm_vcpu_finalize_sve(struct kvm_vcpu *vcpu)
|
||||
vl = vcpu->arch.sve_max_vl;
|
||||
|
||||
/*
|
||||
* Resposibility for these properties is shared between
|
||||
* Responsibility for these properties is shared between
|
||||
* kvm_arm_init_arch_resources(), kvm_vcpu_enable_sve() and
|
||||
* set_sve_vls(). Double-check here just to be sure:
|
||||
*/
|
||||
@ -241,7 +237,7 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
|
||||
* ioctl or as part of handling a request issued by another VCPU in the PSCI
|
||||
* handling code. In the first case, the VCPU will not be loaded, and in the
|
||||
* second case the VCPU will be loaded. Because this function operates purely
|
||||
* on the memory-backed valus of system registers, we want to do a full put if
|
||||
* on the memory-backed values of system registers, we want to do a full put if
|
||||
* we were loaded (handling a request) and load the values back at the end of
|
||||
* the function. Otherwise we leave the state alone. In both cases, we
|
||||
* disable preemption around the vcpu reset as we would otherwise race with
|
||||
@ -249,9 +245,9 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
|
||||
*/
|
||||
int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
const struct kvm_regs *cpu_reset;
|
||||
int ret = -EINVAL;
|
||||
bool loaded;
|
||||
u32 pstate;
|
||||
|
||||
/* Reset PMU outside of the non-preemptible section */
|
||||
kvm_pmu_vcpu_reset(vcpu);
|
||||
@ -282,16 +278,17 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
|
||||
if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
|
||||
if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1))
|
||||
goto out;
|
||||
cpu_reset = &default_regs_reset32;
|
||||
pstate = VCPU_RESET_PSTATE_SVC;
|
||||
} else {
|
||||
cpu_reset = &default_regs_reset;
|
||||
pstate = VCPU_RESET_PSTATE_EL1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reset core registers */
|
||||
memcpy(vcpu_gp_regs(vcpu), cpu_reset, sizeof(*cpu_reset));
|
||||
memset(vcpu_gp_regs(vcpu), 0, sizeof(*vcpu_gp_regs(vcpu)));
|
||||
vcpu_gp_regs(vcpu)->regs.pstate = pstate;
|
||||
|
||||
/* Reset system registers */
|
||||
kvm_reset_sys_regs(vcpu);
|
||||
@ -388,7 +385,7 @@ int kvm_set_ipa_limit(void)
|
||||
*
|
||||
* So clamp the ipa limit further down to limit the number of levels.
|
||||
* Since we can concatenate upto 16 tables at entry level, we could
|
||||
* go upto 4bits above the maximum VA addressible with the current
|
||||
* go upto 4bits above the maximum VA addressable with the current
|
||||
* number of levels.
|
||||
*/
|
||||
va_max = PGDIR_SHIFT + PAGE_SHIFT - 3;
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "trace.h"
|
||||
|
||||
/*
|
||||
* All of this file is extremly similar to the ARM coproc.c, but the
|
||||
* All of this file is extremely similar to the ARM coproc.c, but the
|
||||
* types are different. My gut feeling is that it should be pretty
|
||||
* easy to merge, but that would be an ABI breakage -- again. VFP
|
||||
* would also need to be abstracted.
|
||||
@ -64,11 +64,8 @@ static bool write_to_read_only(struct kvm_vcpu *vcpu,
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
|
||||
static bool __vcpu_read_sys_reg_from_cpu(int reg, u64 *val)
|
||||
{
|
||||
if (!vcpu->arch.sysregs_loaded_on_cpu)
|
||||
goto immediate_read;
|
||||
|
||||
/*
|
||||
* System registers listed in the switch are not saved on every
|
||||
* exit from the guest but are only saved on vcpu_put.
|
||||
@ -79,75 +76,92 @@ u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
|
||||
* thread when emulating cross-VCPU communication.
|
||||
*/
|
||||
switch (reg) {
|
||||
case CSSELR_EL1: return read_sysreg_s(SYS_CSSELR_EL1);
|
||||
case SCTLR_EL1: return read_sysreg_s(SYS_SCTLR_EL12);
|
||||
case ACTLR_EL1: return read_sysreg_s(SYS_ACTLR_EL1);
|
||||
case CPACR_EL1: return read_sysreg_s(SYS_CPACR_EL12);
|
||||
case TTBR0_EL1: return read_sysreg_s(SYS_TTBR0_EL12);
|
||||
case TTBR1_EL1: return read_sysreg_s(SYS_TTBR1_EL12);
|
||||
case TCR_EL1: return read_sysreg_s(SYS_TCR_EL12);
|
||||
case ESR_EL1: return read_sysreg_s(SYS_ESR_EL12);
|
||||
case AFSR0_EL1: return read_sysreg_s(SYS_AFSR0_EL12);
|
||||
case AFSR1_EL1: return read_sysreg_s(SYS_AFSR1_EL12);
|
||||
case FAR_EL1: return read_sysreg_s(SYS_FAR_EL12);
|
||||
case MAIR_EL1: return read_sysreg_s(SYS_MAIR_EL12);
|
||||
case VBAR_EL1: return read_sysreg_s(SYS_VBAR_EL12);
|
||||
case CONTEXTIDR_EL1: return read_sysreg_s(SYS_CONTEXTIDR_EL12);
|
||||
case TPIDR_EL0: return read_sysreg_s(SYS_TPIDR_EL0);
|
||||
case TPIDRRO_EL0: return read_sysreg_s(SYS_TPIDRRO_EL0);
|
||||
case TPIDR_EL1: return read_sysreg_s(SYS_TPIDR_EL1);
|
||||
case AMAIR_EL1: return read_sysreg_s(SYS_AMAIR_EL12);
|
||||
case CNTKCTL_EL1: return read_sysreg_s(SYS_CNTKCTL_EL12);
|
||||
case PAR_EL1: return read_sysreg_s(SYS_PAR_EL1);
|
||||
case DACR32_EL2: return read_sysreg_s(SYS_DACR32_EL2);
|
||||
case IFSR32_EL2: return read_sysreg_s(SYS_IFSR32_EL2);
|
||||
case DBGVCR32_EL2: return read_sysreg_s(SYS_DBGVCR32_EL2);
|
||||
case CSSELR_EL1: *val = read_sysreg_s(SYS_CSSELR_EL1); break;
|
||||
case SCTLR_EL1: *val = read_sysreg_s(SYS_SCTLR_EL12); break;
|
||||
case ACTLR_EL1: *val = read_sysreg_s(SYS_ACTLR_EL1); break;
|
||||
case CPACR_EL1: *val = read_sysreg_s(SYS_CPACR_EL12); break;
|
||||
case TTBR0_EL1: *val = read_sysreg_s(SYS_TTBR0_EL12); break;
|
||||
case TTBR1_EL1: *val = read_sysreg_s(SYS_TTBR1_EL12); break;
|
||||
case TCR_EL1: *val = read_sysreg_s(SYS_TCR_EL12); break;
|
||||
case ESR_EL1: *val = read_sysreg_s(SYS_ESR_EL12); break;
|
||||
case AFSR0_EL1: *val = read_sysreg_s(SYS_AFSR0_EL12); break;
|
||||
case AFSR1_EL1: *val = read_sysreg_s(SYS_AFSR1_EL12); break;
|
||||
case FAR_EL1: *val = read_sysreg_s(SYS_FAR_EL12); break;
|
||||
case MAIR_EL1: *val = read_sysreg_s(SYS_MAIR_EL12); break;
|
||||
case VBAR_EL1: *val = read_sysreg_s(SYS_VBAR_EL12); break;
|
||||
case CONTEXTIDR_EL1: *val = read_sysreg_s(SYS_CONTEXTIDR_EL12);break;
|
||||
case TPIDR_EL0: *val = read_sysreg_s(SYS_TPIDR_EL0); break;
|
||||
case TPIDRRO_EL0: *val = read_sysreg_s(SYS_TPIDRRO_EL0); break;
|
||||
case TPIDR_EL1: *val = read_sysreg_s(SYS_TPIDR_EL1); break;
|
||||
case AMAIR_EL1: *val = read_sysreg_s(SYS_AMAIR_EL12); break;
|
||||
case CNTKCTL_EL1: *val = read_sysreg_s(SYS_CNTKCTL_EL12); break;
|
||||
case PAR_EL1: *val = read_sysreg_s(SYS_PAR_EL1); break;
|
||||
case DACR32_EL2: *val = read_sysreg_s(SYS_DACR32_EL2); break;
|
||||
case IFSR32_EL2: *val = read_sysreg_s(SYS_IFSR32_EL2); break;
|
||||
case DBGVCR32_EL2: *val = read_sysreg_s(SYS_DBGVCR32_EL2); break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
immediate_read:
|
||||
return __vcpu_sys_reg(vcpu, reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
|
||||
static bool __vcpu_write_sys_reg_to_cpu(u64 val, int reg)
|
||||
{
|
||||
if (!vcpu->arch.sysregs_loaded_on_cpu)
|
||||
goto immediate_write;
|
||||
|
||||
/*
|
||||
* System registers listed in the switch are not restored on every
|
||||
* entry to the guest but are only restored on vcpu_load.
|
||||
*
|
||||
* Note that MPIDR_EL1 for the guest is set by KVM via VMPIDR_EL2 but
|
||||
* should never be listed below, because the the MPIDR should only be
|
||||
* set once, before running the VCPU, and never changed later.
|
||||
* should never be listed below, because the MPIDR should only be set
|
||||
* once, before running the VCPU, and never changed later.
|
||||
*/
|
||||
switch (reg) {
|
||||
case CSSELR_EL1: write_sysreg_s(val, SYS_CSSELR_EL1); return;
|
||||
case SCTLR_EL1: write_sysreg_s(val, SYS_SCTLR_EL12); return;
|
||||
case ACTLR_EL1: write_sysreg_s(val, SYS_ACTLR_EL1); return;
|
||||
case CPACR_EL1: write_sysreg_s(val, SYS_CPACR_EL12); return;
|
||||
case TTBR0_EL1: write_sysreg_s(val, SYS_TTBR0_EL12); return;
|
||||
case TTBR1_EL1: write_sysreg_s(val, SYS_TTBR1_EL12); return;
|
||||
case TCR_EL1: write_sysreg_s(val, SYS_TCR_EL12); return;
|
||||
case ESR_EL1: write_sysreg_s(val, SYS_ESR_EL12); return;
|
||||
case AFSR0_EL1: write_sysreg_s(val, SYS_AFSR0_EL12); return;
|
||||
case AFSR1_EL1: write_sysreg_s(val, SYS_AFSR1_EL12); return;
|
||||
case FAR_EL1: write_sysreg_s(val, SYS_FAR_EL12); return;
|
||||
case MAIR_EL1: write_sysreg_s(val, SYS_MAIR_EL12); return;
|
||||
case VBAR_EL1: write_sysreg_s(val, SYS_VBAR_EL12); return;
|
||||
case CONTEXTIDR_EL1: write_sysreg_s(val, SYS_CONTEXTIDR_EL12); return;
|
||||
case TPIDR_EL0: write_sysreg_s(val, SYS_TPIDR_EL0); return;
|
||||
case TPIDRRO_EL0: write_sysreg_s(val, SYS_TPIDRRO_EL0); return;
|
||||
case TPIDR_EL1: write_sysreg_s(val, SYS_TPIDR_EL1); return;
|
||||
case AMAIR_EL1: write_sysreg_s(val, SYS_AMAIR_EL12); return;
|
||||
case CNTKCTL_EL1: write_sysreg_s(val, SYS_CNTKCTL_EL12); return;
|
||||
case PAR_EL1: write_sysreg_s(val, SYS_PAR_EL1); return;
|
||||
case DACR32_EL2: write_sysreg_s(val, SYS_DACR32_EL2); return;
|
||||
case IFSR32_EL2: write_sysreg_s(val, SYS_IFSR32_EL2); return;
|
||||
case DBGVCR32_EL2: write_sysreg_s(val, SYS_DBGVCR32_EL2); return;
|
||||
case CSSELR_EL1: write_sysreg_s(val, SYS_CSSELR_EL1); break;
|
||||
case SCTLR_EL1: write_sysreg_s(val, SYS_SCTLR_EL12); break;
|
||||
case ACTLR_EL1: write_sysreg_s(val, SYS_ACTLR_EL1); break;
|
||||
case CPACR_EL1: write_sysreg_s(val, SYS_CPACR_EL12); break;
|
||||
case TTBR0_EL1: write_sysreg_s(val, SYS_TTBR0_EL12); break;
|
||||
case TTBR1_EL1: write_sysreg_s(val, SYS_TTBR1_EL12); break;
|
||||
case TCR_EL1: write_sysreg_s(val, SYS_TCR_EL12); break;
|
||||
case ESR_EL1: write_sysreg_s(val, SYS_ESR_EL12); break;
|
||||
case AFSR0_EL1: write_sysreg_s(val, SYS_AFSR0_EL12); break;
|
||||
case AFSR1_EL1: write_sysreg_s(val, SYS_AFSR1_EL12); break;
|
||||
case FAR_EL1: write_sysreg_s(val, SYS_FAR_EL12); break;
|
||||
case MAIR_EL1: write_sysreg_s(val, SYS_MAIR_EL12); break;
|
||||
case VBAR_EL1: write_sysreg_s(val, SYS_VBAR_EL12); break;
|
||||
case CONTEXTIDR_EL1: write_sysreg_s(val, SYS_CONTEXTIDR_EL12);break;
|
||||
case TPIDR_EL0: write_sysreg_s(val, SYS_TPIDR_EL0); break;
|
||||
case TPIDRRO_EL0: write_sysreg_s(val, SYS_TPIDRRO_EL0); break;
|
||||
case TPIDR_EL1: write_sysreg_s(val, SYS_TPIDR_EL1); break;
|
||||
case AMAIR_EL1: write_sysreg_s(val, SYS_AMAIR_EL12); break;
|
||||
case CNTKCTL_EL1: write_sysreg_s(val, SYS_CNTKCTL_EL12); break;
|
||||
case PAR_EL1: write_sysreg_s(val, SYS_PAR_EL1); break;
|
||||
case DACR32_EL2: write_sysreg_s(val, SYS_DACR32_EL2); break;
|
||||
case IFSR32_EL2: write_sysreg_s(val, SYS_IFSR32_EL2); break;
|
||||
case DBGVCR32_EL2: write_sysreg_s(val, SYS_DBGVCR32_EL2); break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
immediate_write:
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
|
||||
{
|
||||
u64 val = 0x8badf00d8badf00d;
|
||||
|
||||
if (vcpu->arch.sysregs_loaded_on_cpu &&
|
||||
__vcpu_read_sys_reg_from_cpu(reg, &val))
|
||||
return val;
|
||||
|
||||
return __vcpu_sys_reg(vcpu, reg);
|
||||
}
|
||||
|
||||
void vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
|
||||
{
|
||||
if (vcpu->arch.sysregs_loaded_on_cpu &&
|
||||
__vcpu_write_sys_reg_to_cpu(val, reg))
|
||||
return;
|
||||
|
||||
__vcpu_sys_reg(vcpu, reg) = val;
|
||||
}
|
||||
|
||||
@ -1532,7 +1546,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
||||
{ SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 },
|
||||
|
||||
{ SYS_DESC(SYS_PMINTENSET_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 },
|
||||
{ SYS_DESC(SYS_PMINTENCLR_EL1), access_pminten, NULL, PMINTENSET_EL1 },
|
||||
{ SYS_DESC(SYS_PMINTENCLR_EL1), access_pminten, reset_unknown, PMINTENSET_EL1 },
|
||||
|
||||
{ SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 },
|
||||
{ SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 },
|
||||
@ -1571,8 +1585,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
||||
|
||||
{ SYS_DESC(SYS_PMCR_EL0), access_pmcr, reset_pmcr, PMCR_EL0 },
|
||||
{ SYS_DESC(SYS_PMCNTENSET_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
|
||||
{ SYS_DESC(SYS_PMCNTENCLR_EL0), access_pmcnten, NULL, PMCNTENSET_EL0 },
|
||||
{ SYS_DESC(SYS_PMOVSCLR_EL0), access_pmovs, NULL, PMOVSSET_EL0 },
|
||||
{ SYS_DESC(SYS_PMCNTENCLR_EL0), access_pmcnten, reset_unknown, PMCNTENSET_EL0 },
|
||||
{ SYS_DESC(SYS_PMOVSCLR_EL0), access_pmovs, reset_unknown, PMOVSSET_EL0 },
|
||||
{ SYS_DESC(SYS_PMSWINC_EL0), access_pmswinc, reset_unknown, PMSWINC_EL0 },
|
||||
{ SYS_DESC(SYS_PMSELR_EL0), access_pmselr, reset_unknown, PMSELR_EL0 },
|
||||
{ SYS_DESC(SYS_PMCEID0_EL0), access_pmceid },
|
||||
@ -2073,12 +2087,37 @@ static const struct sys_reg_desc cp15_64_regs[] = {
|
||||
{ SYS_DESC(SYS_AARCH32_CNTP_CVAL), access_arch_timer },
|
||||
};
|
||||
|
||||
static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n,
|
||||
bool is_32)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (!is_32 && table[i].reg && !table[i].reset) {
|
||||
kvm_err("sys_reg table %p entry %d has lacks reset\n",
|
||||
table, i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (i && cmp_sys_reg(&table[i-1], &table[i]) >= 0) {
|
||||
kvm_err("sys_reg table %p out of order (%d)\n", table, i - 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Target specific emulation tables */
|
||||
static struct kvm_sys_reg_target_table *target_tables[KVM_ARM_NUM_TARGETS];
|
||||
|
||||
void kvm_register_target_sys_reg_table(unsigned int target,
|
||||
struct kvm_sys_reg_target_table *table)
|
||||
{
|
||||
if (check_sysreg_table(table->table64.table, table->table64.num, false) ||
|
||||
check_sysreg_table(table->table32.table, table->table32.num, true))
|
||||
return;
|
||||
|
||||
target_tables[target] = table;
|
||||
}
|
||||
|
||||
@ -2364,19 +2403,13 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
|
||||
}
|
||||
|
||||
static void reset_sys_reg_descs(struct kvm_vcpu *vcpu,
|
||||
const struct sys_reg_desc *table, size_t num,
|
||||
unsigned long *bmap)
|
||||
const struct sys_reg_desc *table, size_t num)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
if (table[i].reset) {
|
||||
int reg = table[i].reg;
|
||||
|
||||
if (table[i].reset)
|
||||
table[i].reset(vcpu, &table[i]);
|
||||
if (reg > 0 && reg < NR_SYS_REGS)
|
||||
set_bit(reg, bmap);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2832,32 +2865,18 @@ int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
|
||||
return write_demux_regids(uindices);
|
||||
}
|
||||
|
||||
static int check_sysreg_table(const struct sys_reg_desc *table, unsigned int n)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (cmp_sys_reg(&table[i-1], &table[i]) >= 0) {
|
||||
kvm_err("sys_reg table %p out of order (%d)\n", table, i - 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_sys_reg_table_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
struct sys_reg_desc clidr;
|
||||
|
||||
/* Make sure tables are unique and in order. */
|
||||
BUG_ON(check_sysreg_table(sys_reg_descs, ARRAY_SIZE(sys_reg_descs)));
|
||||
BUG_ON(check_sysreg_table(cp14_regs, ARRAY_SIZE(cp14_regs)));
|
||||
BUG_ON(check_sysreg_table(cp14_64_regs, ARRAY_SIZE(cp14_64_regs)));
|
||||
BUG_ON(check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs)));
|
||||
BUG_ON(check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs)));
|
||||
BUG_ON(check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs)));
|
||||
BUG_ON(check_sysreg_table(sys_reg_descs, ARRAY_SIZE(sys_reg_descs), false));
|
||||
BUG_ON(check_sysreg_table(cp14_regs, ARRAY_SIZE(cp14_regs), true));
|
||||
BUG_ON(check_sysreg_table(cp14_64_regs, ARRAY_SIZE(cp14_64_regs), true));
|
||||
BUG_ON(check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs), true));
|
||||
BUG_ON(check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs), true));
|
||||
BUG_ON(check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs), false));
|
||||
|
||||
/* We abuse the reset function to overwrite the table itself. */
|
||||
for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++)
|
||||
@ -2893,17 +2912,10 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
size_t num;
|
||||
const struct sys_reg_desc *table;
|
||||
DECLARE_BITMAP(bmap, NR_SYS_REGS) = { 0, };
|
||||
|
||||
/* Generic chip reset first (so target could override). */
|
||||
reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs), bmap);
|
||||
reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
|
||||
|
||||
table = get_target_table(vcpu->arch.target, true, &num);
|
||||
reset_sys_reg_descs(vcpu, table, num, bmap);
|
||||
|
||||
for (num = 1; num < NR_SYS_REGS; num++) {
|
||||
if (WARN(!test_bit(num, bmap),
|
||||
"Didn't reset __vcpu_sys_reg(%zi)\n", num))
|
||||
break;
|
||||
}
|
||||
reset_sys_reg_descs(vcpu, table, num);
|
||||
}
|
||||
|
@ -1,216 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#if !defined(_TRACE_ARM64_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#ifndef _TRACE_ARM64_KVM_H
|
||||
#define _TRACE_ARM64_KVM_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
#include "sys_regs.h"
|
||||
#include "trace_arm.h"
|
||||
#include "trace_handle_exit.h"
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM kvm
|
||||
|
||||
TRACE_EVENT(kvm_wfx_arm64,
|
||||
TP_PROTO(unsigned long vcpu_pc, bool is_wfe),
|
||||
TP_ARGS(vcpu_pc, is_wfe),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned long, vcpu_pc)
|
||||
__field(bool, is_wfe)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu_pc = vcpu_pc;
|
||||
__entry->is_wfe = is_wfe;
|
||||
),
|
||||
|
||||
TP_printk("guest executed wf%c at: 0x%08lx",
|
||||
__entry->is_wfe ? 'e' : 'i', __entry->vcpu_pc)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_hvc_arm64,
|
||||
TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm),
|
||||
TP_ARGS(vcpu_pc, r0, imm),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned long, vcpu_pc)
|
||||
__field(unsigned long, r0)
|
||||
__field(unsigned long, imm)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu_pc = vcpu_pc;
|
||||
__entry->r0 = r0;
|
||||
__entry->imm = imm;
|
||||
),
|
||||
|
||||
TP_printk("HVC at 0x%08lx (r0: 0x%08lx, imm: 0x%lx)",
|
||||
__entry->vcpu_pc, __entry->r0, __entry->imm)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_arm_setup_debug,
|
||||
TP_PROTO(struct kvm_vcpu *vcpu, __u32 guest_debug),
|
||||
TP_ARGS(vcpu, guest_debug),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(struct kvm_vcpu *, vcpu)
|
||||
__field(__u32, guest_debug)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu = vcpu;
|
||||
__entry->guest_debug = guest_debug;
|
||||
),
|
||||
|
||||
TP_printk("vcpu: %p, flags: 0x%08x", __entry->vcpu, __entry->guest_debug)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_arm_clear_debug,
|
||||
TP_PROTO(__u32 guest_debug),
|
||||
TP_ARGS(guest_debug),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(__u32, guest_debug)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->guest_debug = guest_debug;
|
||||
),
|
||||
|
||||
TP_printk("flags: 0x%08x", __entry->guest_debug)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_arm_set_dreg32,
|
||||
TP_PROTO(const char *name, __u32 value),
|
||||
TP_ARGS(name, value),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__field(__u32, value)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->name = name;
|
||||
__entry->value = value;
|
||||
),
|
||||
|
||||
TP_printk("%s: 0x%08x", __entry->name, __entry->value)
|
||||
);
|
||||
|
||||
TRACE_DEFINE_SIZEOF(__u64);
|
||||
|
||||
TRACE_EVENT(kvm_arm_set_regset,
|
||||
TP_PROTO(const char *type, int len, __u64 *control, __u64 *value),
|
||||
TP_ARGS(type, len, control, value),
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__field(int, len)
|
||||
__array(u64, ctrls, 16)
|
||||
__array(u64, values, 16)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->name = type;
|
||||
__entry->len = len;
|
||||
memcpy(__entry->ctrls, control, len << 3);
|
||||
memcpy(__entry->values, value, len << 3);
|
||||
),
|
||||
TP_printk("%d %s CTRL:%s VALUE:%s", __entry->len, __entry->name,
|
||||
__print_array(__entry->ctrls, __entry->len, sizeof(__u64)),
|
||||
__print_array(__entry->values, __entry->len, sizeof(__u64)))
|
||||
);
|
||||
|
||||
TRACE_EVENT(trap_reg,
|
||||
TP_PROTO(const char *fn, int reg, bool is_write, u64 write_value),
|
||||
TP_ARGS(fn, reg, is_write, write_value),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, fn)
|
||||
__field(int, reg)
|
||||
__field(bool, is_write)
|
||||
__field(u64, write_value)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->fn = fn;
|
||||
__entry->reg = reg;
|
||||
__entry->is_write = is_write;
|
||||
__entry->write_value = write_value;
|
||||
),
|
||||
|
||||
TP_printk("%s %s reg %d (0x%08llx)", __entry->fn, __entry->is_write?"write to":"read from", __entry->reg, __entry->write_value)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_handle_sys_reg,
|
||||
TP_PROTO(unsigned long hsr),
|
||||
TP_ARGS(hsr),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned long, hsr)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->hsr = hsr;
|
||||
),
|
||||
|
||||
TP_printk("HSR 0x%08lx", __entry->hsr)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_sys_access,
|
||||
TP_PROTO(unsigned long vcpu_pc, struct sys_reg_params *params, const struct sys_reg_desc *reg),
|
||||
TP_ARGS(vcpu_pc, params, reg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned long, vcpu_pc)
|
||||
__field(bool, is_write)
|
||||
__field(const char *, name)
|
||||
__field(u8, Op0)
|
||||
__field(u8, Op1)
|
||||
__field(u8, CRn)
|
||||
__field(u8, CRm)
|
||||
__field(u8, Op2)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu_pc = vcpu_pc;
|
||||
__entry->is_write = params->is_write;
|
||||
__entry->name = reg->name;
|
||||
__entry->Op0 = reg->Op0;
|
||||
__entry->Op0 = reg->Op0;
|
||||
__entry->Op1 = reg->Op1;
|
||||
__entry->CRn = reg->CRn;
|
||||
__entry->CRm = reg->CRm;
|
||||
__entry->Op2 = reg->Op2;
|
||||
),
|
||||
|
||||
TP_printk("PC: %lx %s (%d,%d,%d,%d,%d) %s",
|
||||
__entry->vcpu_pc, __entry->name ?: "UNKN",
|
||||
__entry->Op0, __entry->Op1, __entry->CRn,
|
||||
__entry->CRm, __entry->Op2,
|
||||
__entry->is_write ? "write" : "read")
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_set_guest_debug,
|
||||
TP_PROTO(struct kvm_vcpu *vcpu, __u32 guest_debug),
|
||||
TP_ARGS(vcpu, guest_debug),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(struct kvm_vcpu *, vcpu)
|
||||
__field(__u32, guest_debug)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu = vcpu;
|
||||
__entry->guest_debug = guest_debug;
|
||||
),
|
||||
|
||||
TP_printk("vcpu: %p, flags: 0x%08x", __entry->vcpu, __entry->guest_debug)
|
||||
);
|
||||
|
||||
|
||||
#endif /* _TRACE_ARM64_KVM_H */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE trace
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
||||
#endif /* _TRACE_ARM64_KVM_H */
|
||||
|
@ -1,10 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_KVM_H
|
||||
#if !defined(_TRACE_ARM_ARM64_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_ARM_ARM64_KVM_H
|
||||
|
||||
#include <kvm/arm_arch_timer.h>
|
||||
#include <linux/tracepoint.h>
|
||||
#include <asm/kvm_arm.h>
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM kvm
|
||||
@ -368,12 +367,12 @@ TRACE_EVENT(kvm_timer_emulate,
|
||||
__entry->timer_idx, __entry->should_fire)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_KVM_H */
|
||||
#endif /* _TRACE_ARM_ARM64_KVM_H */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH ../../virt/kvm/arm
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE trace
|
||||
#define TRACE_INCLUDE_FILE trace_arm
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
215
arch/arm64/kvm/trace_handle_exit.h
Normal file
215
arch/arm64/kvm/trace_handle_exit.h
Normal file
@ -0,0 +1,215 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#if !defined(_TRACE_HANDLE_EXIT_ARM64_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_HANDLE_EXIT_ARM64_KVM_H
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
#include "sys_regs.h"
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM kvm
|
||||
|
||||
TRACE_EVENT(kvm_wfx_arm64,
|
||||
TP_PROTO(unsigned long vcpu_pc, bool is_wfe),
|
||||
TP_ARGS(vcpu_pc, is_wfe),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned long, vcpu_pc)
|
||||
__field(bool, is_wfe)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu_pc = vcpu_pc;
|
||||
__entry->is_wfe = is_wfe;
|
||||
),
|
||||
|
||||
TP_printk("guest executed wf%c at: 0x%08lx",
|
||||
__entry->is_wfe ? 'e' : 'i', __entry->vcpu_pc)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_hvc_arm64,
|
||||
TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm),
|
||||
TP_ARGS(vcpu_pc, r0, imm),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned long, vcpu_pc)
|
||||
__field(unsigned long, r0)
|
||||
__field(unsigned long, imm)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu_pc = vcpu_pc;
|
||||
__entry->r0 = r0;
|
||||
__entry->imm = imm;
|
||||
),
|
||||
|
||||
TP_printk("HVC at 0x%08lx (r0: 0x%08lx, imm: 0x%lx)",
|
||||
__entry->vcpu_pc, __entry->r0, __entry->imm)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_arm_setup_debug,
|
||||
TP_PROTO(struct kvm_vcpu *vcpu, __u32 guest_debug),
|
||||
TP_ARGS(vcpu, guest_debug),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(struct kvm_vcpu *, vcpu)
|
||||
__field(__u32, guest_debug)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu = vcpu;
|
||||
__entry->guest_debug = guest_debug;
|
||||
),
|
||||
|
||||
TP_printk("vcpu: %p, flags: 0x%08x", __entry->vcpu, __entry->guest_debug)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_arm_clear_debug,
|
||||
TP_PROTO(__u32 guest_debug),
|
||||
TP_ARGS(guest_debug),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(__u32, guest_debug)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->guest_debug = guest_debug;
|
||||
),
|
||||
|
||||
TP_printk("flags: 0x%08x", __entry->guest_debug)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_arm_set_dreg32,
|
||||
TP_PROTO(const char *name, __u32 value),
|
||||
TP_ARGS(name, value),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__field(__u32, value)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->name = name;
|
||||
__entry->value = value;
|
||||
),
|
||||
|
||||
TP_printk("%s: 0x%08x", __entry->name, __entry->value)
|
||||
);
|
||||
|
||||
TRACE_DEFINE_SIZEOF(__u64);
|
||||
|
||||
TRACE_EVENT(kvm_arm_set_regset,
|
||||
TP_PROTO(const char *type, int len, __u64 *control, __u64 *value),
|
||||
TP_ARGS(type, len, control, value),
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__field(int, len)
|
||||
__array(u64, ctrls, 16)
|
||||
__array(u64, values, 16)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->name = type;
|
||||
__entry->len = len;
|
||||
memcpy(__entry->ctrls, control, len << 3);
|
||||
memcpy(__entry->values, value, len << 3);
|
||||
),
|
||||
TP_printk("%d %s CTRL:%s VALUE:%s", __entry->len, __entry->name,
|
||||
__print_array(__entry->ctrls, __entry->len, sizeof(__u64)),
|
||||
__print_array(__entry->values, __entry->len, sizeof(__u64)))
|
||||
);
|
||||
|
||||
TRACE_EVENT(trap_reg,
|
||||
TP_PROTO(const char *fn, int reg, bool is_write, u64 write_value),
|
||||
TP_ARGS(fn, reg, is_write, write_value),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, fn)
|
||||
__field(int, reg)
|
||||
__field(bool, is_write)
|
||||
__field(u64, write_value)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->fn = fn;
|
||||
__entry->reg = reg;
|
||||
__entry->is_write = is_write;
|
||||
__entry->write_value = write_value;
|
||||
),
|
||||
|
||||
TP_printk("%s %s reg %d (0x%08llx)", __entry->fn, __entry->is_write?"write to":"read from", __entry->reg, __entry->write_value)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_handle_sys_reg,
|
||||
TP_PROTO(unsigned long hsr),
|
||||
TP_ARGS(hsr),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned long, hsr)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->hsr = hsr;
|
||||
),
|
||||
|
||||
TP_printk("HSR 0x%08lx", __entry->hsr)
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_sys_access,
|
||||
TP_PROTO(unsigned long vcpu_pc, struct sys_reg_params *params, const struct sys_reg_desc *reg),
|
||||
TP_ARGS(vcpu_pc, params, reg),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned long, vcpu_pc)
|
||||
__field(bool, is_write)
|
||||
__field(const char *, name)
|
||||
__field(u8, Op0)
|
||||
__field(u8, Op1)
|
||||
__field(u8, CRn)
|
||||
__field(u8, CRm)
|
||||
__field(u8, Op2)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu_pc = vcpu_pc;
|
||||
__entry->is_write = params->is_write;
|
||||
__entry->name = reg->name;
|
||||
__entry->Op0 = reg->Op0;
|
||||
__entry->Op0 = reg->Op0;
|
||||
__entry->Op1 = reg->Op1;
|
||||
__entry->CRn = reg->CRn;
|
||||
__entry->CRm = reg->CRm;
|
||||
__entry->Op2 = reg->Op2;
|
||||
),
|
||||
|
||||
TP_printk("PC: %lx %s (%d,%d,%d,%d,%d) %s",
|
||||
__entry->vcpu_pc, __entry->name ?: "UNKN",
|
||||
__entry->Op0, __entry->Op1, __entry->CRn,
|
||||
__entry->CRm, __entry->Op2,
|
||||
__entry->is_write ? "write" : "read")
|
||||
);
|
||||
|
||||
TRACE_EVENT(kvm_set_guest_debug,
|
||||
TP_PROTO(struct kvm_vcpu *vcpu, __u32 guest_debug),
|
||||
TP_ARGS(vcpu, guest_debug),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(struct kvm_vcpu *, vcpu)
|
||||
__field(__u32, guest_debug)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->vcpu = vcpu;
|
||||
__entry->guest_debug = guest_debug;
|
||||
),
|
||||
|
||||
TP_printk("vcpu: %p, flags: 0x%08x", __entry->vcpu, __entry->guest_debug)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_HANDLE_EXIT_ARM64_KVM_H */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE trace_handle_exit
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
@ -7,7 +7,7 @@
|
||||
#include <linux/kvm.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <asm/kvm_emulate.h>
|
||||
#include "vgic.h"
|
||||
#include "vgic/vgic.h"
|
||||
#include "sys_regs.h"
|
||||
|
||||
static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
|
||||
|
@ -30,7 +30,7 @@ TRACE_EVENT(vgic_update_irq_pending,
|
||||
#endif /* _TRACE_VGIC_H */
|
||||
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH ../../virt/kvm/arm/vgic
|
||||
#define TRACE_INCLUDE_PATH ../../arch/arm64/kvm/vgic
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE trace
|
||||
|
@ -56,7 +56,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
|
||||
|
||||
cpuif->vgic_hcr &= ~GICH_HCR_UIE;
|
||||
|
||||
for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
|
||||
for (lr = 0; lr < vgic_cpu->vgic_v2.used_lrs; lr++) {
|
||||
u32 val = cpuif->vgic_lr[lr];
|
||||
u32 cpuid, intid = val & GICH_LR_VIRTUALID;
|
||||
struct vgic_irq *irq;
|
||||
@ -120,7 +120,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
|
||||
vgic_put_irq(vcpu->kvm, irq);
|
||||
}
|
||||
|
||||
vgic_cpu->used_lrs = 0;
|
||||
cpuif->used_lrs = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -427,7 +427,7 @@ int vgic_v2_probe(const struct gic_kvm_info *info)
|
||||
static void save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
|
||||
{
|
||||
struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
|
||||
u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
|
||||
u64 used_lrs = cpu_if->used_lrs;
|
||||
u64 elrsr;
|
||||
int i;
|
||||
|
||||
@ -448,7 +448,7 @@ static void save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
|
||||
void vgic_v2_save_state(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
void __iomem *base = kvm_vgic_global_state.vctrl_base;
|
||||
u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
|
||||
u64 used_lrs = vcpu->arch.vgic_cpu.vgic_v2.used_lrs;
|
||||
|
||||
if (!base)
|
||||
return;
|
||||
@ -463,7 +463,7 @@ void vgic_v2_restore_state(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
|
||||
void __iomem *base = kvm_vgic_global_state.vctrl_base;
|
||||
u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
|
||||
u64 used_lrs = cpu_if->used_lrs;
|
||||
int i;
|
||||
|
||||
if (!base)
|
@ -39,7 +39,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
|
||||
|
||||
cpuif->vgic_hcr &= ~ICH_HCR_UIE;
|
||||
|
||||
for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
|
||||
for (lr = 0; lr < cpuif->used_lrs; lr++) {
|
||||
u64 val = cpuif->vgic_lr[lr];
|
||||
u32 intid, cpuid;
|
||||
struct vgic_irq *irq;
|
||||
@ -111,7 +111,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
|
||||
vgic_put_irq(vcpu->kvm, irq);
|
||||
}
|
||||
|
||||
vgic_cpu->used_lrs = 0;
|
||||
cpuif->used_lrs = 0;
|
||||
}
|
||||
|
||||
/* Requires the irq to be locked already */
|
||||
@ -587,7 +587,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The ListRegs field is 5 bits, but there is a architectural
|
||||
* The ListRegs field is 5 bits, but there is an architectural
|
||||
* maximum of 16 list registers. Just ignore bit 4...
|
||||
*/
|
||||
kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
|
||||
@ -630,12 +630,10 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
|
||||
if (kvm_vgic_global_state.vcpu_base == 0)
|
||||
kvm_info("disabling GICv2 emulation\n");
|
||||
|
||||
#ifdef CONFIG_ARM64
|
||||
if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_30115)) {
|
||||
group0_trap = true;
|
||||
group1_trap = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (group0_trap || group1_trap || common_trap) {
|
||||
kvm_info("GICv3 sysreg trapping enabled ([%s%s%s], reduced performance)\n",
|
||||
@ -664,10 +662,10 @@ void vgic_v3_load(struct kvm_vcpu *vcpu)
|
||||
if (likely(cpu_if->vgic_sre))
|
||||
kvm_call_hyp(__vgic_v3_write_vmcr, cpu_if->vgic_vmcr);
|
||||
|
||||
kvm_call_hyp(__vgic_v3_restore_aprs, vcpu);
|
||||
kvm_call_hyp(__vgic_v3_restore_aprs, kern_hyp_va(cpu_if));
|
||||
|
||||
if (has_vhe())
|
||||
__vgic_v3_activate_traps(vcpu);
|
||||
__vgic_v3_activate_traps(cpu_if);
|
||||
|
||||
WARN_ON(vgic_v4_load(vcpu));
|
||||
}
|
||||
@ -682,12 +680,14 @@ void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu)
|
||||
|
||||
void vgic_v3_put(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
|
||||
|
||||
WARN_ON(vgic_v4_put(vcpu, false));
|
||||
|
||||
vgic_v3_vmcr_sync(vcpu);
|
||||
|
||||
kvm_call_hyp(__vgic_v3_save_aprs, vcpu);
|
||||
kvm_call_hyp(__vgic_v3_save_aprs, kern_hyp_va(cpu_if));
|
||||
|
||||
if (has_vhe())
|
||||
__vgic_v3_deactivate_traps(vcpu);
|
||||
__vgic_v3_deactivate_traps(cpu_if);
|
||||
}
|
@ -786,6 +786,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
|
||||
int count;
|
||||
bool multi_sgi;
|
||||
u8 prio = 0xff;
|
||||
int i = 0;
|
||||
|
||||
lockdep_assert_held(&vgic_cpu->ap_list_lock);
|
||||
|
||||
@ -827,11 +828,14 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
vcpu->arch.vgic_cpu.used_lrs = count;
|
||||
|
||||
/* Nuke remaining LRs */
|
||||
for ( ; count < kvm_vgic_global_state.nr_lr; count++)
|
||||
vgic_clear_lr(vcpu, count);
|
||||
for (i = count ; i < kvm_vgic_global_state.nr_lr; i++)
|
||||
vgic_clear_lr(vcpu, i);
|
||||
|
||||
if (!static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
|
||||
vcpu->arch.vgic_cpu.vgic_v2.used_lrs = count;
|
||||
else
|
||||
vcpu->arch.vgic_cpu.vgic_v3.used_lrs = count;
|
||||
}
|
||||
|
||||
static inline bool can_access_vgic_from_kernel(void)
|
||||
@ -849,13 +853,13 @@ static inline void vgic_save_state(struct kvm_vcpu *vcpu)
|
||||
if (!static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
|
||||
vgic_v2_save_state(vcpu);
|
||||
else
|
||||
__vgic_v3_save_state(vcpu);
|
||||
__vgic_v3_save_state(&vcpu->arch.vgic_cpu.vgic_v3);
|
||||
}
|
||||
|
||||
/* Sync back the hardware VGIC state into our emulation after a guest's run. */
|
||||
void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
||||
int used_lrs;
|
||||
|
||||
/* An empty ap_list_head implies used_lrs == 0 */
|
||||
if (list_empty(&vcpu->arch.vgic_cpu.ap_list_head))
|
||||
@ -864,7 +868,12 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
|
||||
if (can_access_vgic_from_kernel())
|
||||
vgic_save_state(vcpu);
|
||||
|
||||
if (vgic_cpu->used_lrs)
|
||||
if (!static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
|
||||
used_lrs = vcpu->arch.vgic_cpu.vgic_v2.used_lrs;
|
||||
else
|
||||
used_lrs = vcpu->arch.vgic_cpu.vgic_v3.used_lrs;
|
||||
|
||||
if (used_lrs)
|
||||
vgic_fold_lr_state(vcpu);
|
||||
vgic_prune_ap_list(vcpu);
|
||||
}
|
||||
@ -874,7 +883,7 @@ static inline void vgic_restore_state(struct kvm_vcpu *vcpu)
|
||||
if (!static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
|
||||
vgic_v2_restore_state(vcpu);
|
||||
else
|
||||
__vgic_v3_restore_state(vcpu);
|
||||
__vgic_v3_restore_state(&vcpu->arch.vgic_cpu.vgic_v3);
|
||||
}
|
||||
|
||||
/* Flush our emulation state into the GIC hardware before entering the guest. */
|
@ -12,7 +12,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <net/checksum.h>
|
||||
|
||||
/*
|
||||
* XXX Fixme: those 2 inlines are meant for debugging and will go away
|
||||
|
@ -63,21 +63,21 @@ static __inline__ void release_dma_lock(unsigned long flags)
|
||||
}
|
||||
|
||||
|
||||
static __inline__ unsigned char fd_inb(int port)
|
||||
static __inline__ unsigned char fd_inb(int base, int reg)
|
||||
{
|
||||
if(MACH_IS_Q40)
|
||||
return inb_p(port);
|
||||
return inb_p(base + reg);
|
||||
else if(MACH_IS_SUN3X)
|
||||
return sun3x_82072_fd_inb(port);
|
||||
return sun3x_82072_fd_inb(base + reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ void fd_outb(unsigned char value, int port)
|
||||
static __inline__ void fd_outb(unsigned char value, int base, int reg)
|
||||
{
|
||||
if(MACH_IS_Q40)
|
||||
outb_p(value, port);
|
||||
outb_p(value, base + reg);
|
||||
else if(MACH_IS_SUN3X)
|
||||
sun3x_82072_fd_outb(value, port);
|
||||
sun3x_82072_fd_outb(value, base + reg);
|
||||
}
|
||||
|
||||
|
||||
@ -211,26 +211,27 @@ asmlinkage irqreturn_t floppy_hardint(int irq, void *dev_id)
|
||||
st=1;
|
||||
for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
|
||||
lcount; lcount--, lptr++) {
|
||||
st=inb(virtual_dma_port+4) & 0xa0 ;
|
||||
if(st != 0xa0)
|
||||
st = inb(virtual_dma_port + FD_STATUS);
|
||||
st &= STATUS_DMA | STATUS_READY;
|
||||
if (st != (STATUS_DMA | STATUS_READY))
|
||||
break;
|
||||
if(virtual_dma_mode)
|
||||
outb_p(*lptr, virtual_dma_port+5);
|
||||
outb_p(*lptr, virtual_dma_port + FD_DATA);
|
||||
else
|
||||
*lptr = inb_p(virtual_dma_port+5);
|
||||
*lptr = inb_p(virtual_dma_port + FD_DATA);
|
||||
}
|
||||
|
||||
virtual_dma_count = lcount;
|
||||
virtual_dma_addr = lptr;
|
||||
st = inb(virtual_dma_port+4);
|
||||
st = inb(virtual_dma_port + FD_STATUS);
|
||||
}
|
||||
|
||||
#ifdef TRACE_FLPY_INT
|
||||
calls++;
|
||||
#endif
|
||||
if(st == 0x20)
|
||||
if (st == STATUS_DMA)
|
||||
return IRQ_HANDLED;
|
||||
if(!(st & 0x20)) {
|
||||
if (!(st & STATUS_DMA)) {
|
||||
virtual_dma_residue += virtual_dma_count;
|
||||
virtual_dma_count=0;
|
||||
#ifdef TRACE_FLPY_INT
|
||||
|
@ -12,7 +12,7 @@ obj-y := $(platform-y)
|
||||
|
||||
# make clean traverses $(obj-) without having included .config, so
|
||||
# everything ends up here
|
||||
obj- := $(platform-)
|
||||
obj- := $(platform-y)
|
||||
|
||||
# mips object files
|
||||
# The object files are linked as core-y files would be linked
|
||||
|
@ -1,42 +1,44 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# All platforms listed in alphabetic order
|
||||
|
||||
platforms += alchemy
|
||||
platforms += ar7
|
||||
platforms += ath25
|
||||
platforms += ath79
|
||||
platforms += bcm47xx
|
||||
platforms += bcm63xx
|
||||
platforms += bmips
|
||||
platforms += cavium-octeon
|
||||
platforms += cobalt
|
||||
platforms += dec
|
||||
platforms += emma
|
||||
platforms += generic
|
||||
platforms += jazz
|
||||
platforms += jz4740
|
||||
platforms += lantiq
|
||||
platforms += lasat
|
||||
platforms += loongson2ef
|
||||
platforms += loongson32
|
||||
platforms += loongson64
|
||||
platforms += mti-malta
|
||||
platforms += netlogic
|
||||
platforms += paravirt
|
||||
platforms += pic32
|
||||
platforms += pistachio
|
||||
platforms += pmcs-msp71xx
|
||||
platforms += pnx833x
|
||||
platforms += ralink
|
||||
platforms += rb532
|
||||
platforms += sgi-ip22
|
||||
platforms += sgi-ip27
|
||||
platforms += sgi-ip30
|
||||
platforms += sgi-ip32
|
||||
platforms += sibyte
|
||||
platforms += sni
|
||||
platforms += txx9
|
||||
platforms += vr41xx
|
||||
platform-$(CONFIG_MIPS_ALCHEMY) += alchemy/
|
||||
platform-$(CONFIG_AR7) += ar7/
|
||||
platform-$(CONFIG_ATH25) += ath25/
|
||||
platform-$(CONFIG_ATH79) += ath79/
|
||||
platform-$(CONFIG_BCM47XX) += bcm47xx/
|
||||
platform-$(CONFIG_BCM63XX) += bcm63xx/
|
||||
platform-$(CONFIG_BMIPS_GENERIC) += bmips/
|
||||
platform-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon/
|
||||
platform-$(CONFIG_MIPS_COBALT) += cobalt/
|
||||
platform-$(CONFIG_MACH_DECSTATION) += dec/
|
||||
platform-$(CONFIG_MIPS_GENERIC) += generic/
|
||||
platform-$(CONFIG_MACH_JAZZ) += jazz/
|
||||
platform-$(CONFIG_MACH_INGENIC) += jz4740/
|
||||
platform-$(CONFIG_LANTIQ) += lantiq/
|
||||
platform-$(CONFIG_MACH_LOONGSON2EF) += loongson2ef/
|
||||
platform-$(CONFIG_MACH_LOONGSON32) += loongson32/
|
||||
platform-$(CONFIG_MACH_LOONGSON64) += loongson64/
|
||||
platform-$(CONFIG_MIPS_MALTA) += mti-malta/
|
||||
platform-$(CONFIG_NLM_COMMON) += netlogic/
|
||||
platform-$(CONFIG_MIPS_PARAVIRT) += paravirt/
|
||||
platform-$(CONFIG_PIC32MZDA) += pic32/
|
||||
platform-$(CONFIG_MACH_PISTACHIO) += pistachio/
|
||||
platform-$(CONFIG_SOC_PNX833X) += pnx833x/
|
||||
platform-$(CONFIG_RALINK) += ralink/
|
||||
platform-$(CONFIG_MIKROTIK_RB532) += rb532/
|
||||
platform-$(CONFIG_SGI_IP22) += sgi-ip22/
|
||||
platform-$(CONFIG_SGI_IP27) += sgi-ip27/
|
||||
platform-$(CONFIG_SGI_IP28) += sgi-ip22/
|
||||
platform-$(CONFIG_SGI_IP30) += sgi-ip30/
|
||||
platform-$(CONFIG_SGI_IP32) += sgi-ip32/
|
||||
platform-$(CONFIG_SIBYTE_BCM112X) += sibyte/
|
||||
platform-$(CONFIG_SIBYTE_SB1250) += sibyte/
|
||||
platform-$(CONFIG_SIBYTE_BCM1x55) += sibyte/
|
||||
platform-$(CONFIG_SIBYTE_BCM1x80) += sibyte/
|
||||
platform-$(CONFIG_SNI_RM) += sni/
|
||||
platform-$(CONFIG_MACH_TX39XX) += txx9/
|
||||
platform-$(CONFIG_MACH_TX49XX) += txx9/
|
||||
platform-$(CONFIG_MACH_VR41XX) += vr41xx/
|
||||
|
||||
# include the platform specific files
|
||||
include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platforms))
|
||||
include $(patsubst %, $(srctree)/arch/mips/%/Platform, $(platform-y))
|
||||
|
@ -92,6 +92,9 @@ config MIPS
|
||||
select SYSCTL_EXCEPTION_TRACE
|
||||
select VIRT_TO_BUS
|
||||
|
||||
config MIPS_FIXUP_BIGPHYS_ADDR
|
||||
bool
|
||||
|
||||
menu "Machine selection"
|
||||
|
||||
choice
|
||||
@ -157,6 +160,7 @@ config MIPS_ALCHEMY
|
||||
select CSRC_R4K
|
||||
select IRQ_MIPS_CPU
|
||||
select DMA_MAYBE_COHERENT # Au1000,1500,1100 aren't, rest is
|
||||
select MIPS_FIXUP_BIGPHYS_ADDR if PCI
|
||||
select SYS_HAS_CPU_MIPS32_R1
|
||||
select SYS_SUPPORTS_32BIT_KERNEL
|
||||
select SYS_SUPPORTS_APM_EMULATION
|
||||
@ -427,23 +431,6 @@ config LANTIQ
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
||||
select RESET_CONTROLLER
|
||||
|
||||
config LASAT
|
||||
bool "LASAT Networks platforms"
|
||||
select CEVT_R4K
|
||||
select CRC32
|
||||
select CSRC_R4K
|
||||
select DMA_NONCOHERENT
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
select HAVE_PCI
|
||||
select IRQ_MIPS_CPU
|
||||
select PCI_GT64XXX_PCI0
|
||||
select MIPS_NILE4
|
||||
select R5000_CPU_SCACHE
|
||||
select SYS_HAS_CPU_R5000
|
||||
select SYS_SUPPORTS_32BIT_KERNEL
|
||||
select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
|
||||
select SYS_SUPPORTS_LITTLE_ENDIAN
|
||||
|
||||
config MACH_LOONGSON32
|
||||
bool "Loongson 32-bit family of machines"
|
||||
select SYS_SUPPORTS_ZBOOT
|
||||
@ -475,8 +462,10 @@ config MACH_LOONGSON64
|
||||
select ISA
|
||||
select I8259
|
||||
select IRQ_MIPS_CPU
|
||||
select NR_CPUS_DEFAULT_4
|
||||
select NO_EXCEPT_FILL
|
||||
select NR_CPUS_DEFAULT_64
|
||||
select USE_GENERIC_EARLY_PRINTK_8250
|
||||
select PCI_DRIVERS_GENERIC
|
||||
select SYS_HAS_CPU_LOONGSON64
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
select SYS_SUPPORTS_SMP
|
||||
@ -593,13 +582,6 @@ config MACH_PIC32
|
||||
Microchip PIC32 is a family of general-purpose 32 bit MIPS core
|
||||
microcontrollers.
|
||||
|
||||
config NEC_MARKEINS
|
||||
bool "NEC EMMA2RH Mark-eins board"
|
||||
select SOC_EMMA2RH
|
||||
select HAVE_PCI
|
||||
help
|
||||
This enables support for the NEC Electronics Mark-eins boards.
|
||||
|
||||
config MACH_VR41XX
|
||||
bool "NEC VR4100 series based machines"
|
||||
select CEVT_R4K
|
||||
@ -621,30 +603,6 @@ config NXP_STB225
|
||||
help
|
||||
Support for NXP Semiconductors STB225 Development Board.
|
||||
|
||||
config PMC_MSP
|
||||
bool "PMC-Sierra MSP chipsets"
|
||||
select CEVT_R4K
|
||||
select CSRC_R4K
|
||||
select DMA_NONCOHERENT
|
||||
select SWAP_IO_SPACE
|
||||
select NO_EXCEPT_FILL
|
||||
select BOOT_RAW
|
||||
select SYS_HAS_CPU_MIPS32_R1
|
||||
select SYS_HAS_CPU_MIPS32_R2
|
||||
select SYS_SUPPORTS_32BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
select SYS_SUPPORTS_MIPS16
|
||||
select IRQ_MIPS_CPU
|
||||
select SERIAL_8250
|
||||
select SERIAL_8250_CONSOLE
|
||||
select USB_EHCI_BIG_ENDIAN_MMIO
|
||||
select USB_EHCI_BIG_ENDIAN_DESC
|
||||
help
|
||||
This adds support for the PMC-Sierra family of Multi-Service
|
||||
Processor System-On-A-Chips. These parts include a number
|
||||
of integrated peripherals, interfaces and DSPs in addition to
|
||||
a variety of MIPS cores.
|
||||
|
||||
config RALINK
|
||||
bool "Ralink based machines"
|
||||
select CEVT_R4K
|
||||
@ -1087,10 +1045,8 @@ source "arch/mips/generic/Kconfig"
|
||||
source "arch/mips/jazz/Kconfig"
|
||||
source "arch/mips/jz4740/Kconfig"
|
||||
source "arch/mips/lantiq/Kconfig"
|
||||
source "arch/mips/lasat/Kconfig"
|
||||
source "arch/mips/pic32/Kconfig"
|
||||
source "arch/mips/pistachio/Kconfig"
|
||||
source "arch/mips/pmcs-msp71xx/Kconfig"
|
||||
source "arch/mips/ralink/Kconfig"
|
||||
source "arch/mips/sgi-ip27/Kconfig"
|
||||
source "arch/mips/sibyte/Kconfig"
|
||||
@ -1154,6 +1110,7 @@ config CSRC_IOASIC
|
||||
bool
|
||||
|
||||
config CSRC_R4K
|
||||
select CLOCKSOURCE_WATCHDOG if CPU_FREQ
|
||||
bool
|
||||
|
||||
config CSRC_SB1250
|
||||
@ -1211,9 +1168,6 @@ config MIPS_BONITO64
|
||||
config MIPS_MSC
|
||||
bool
|
||||
|
||||
config MIPS_NILE4
|
||||
bool
|
||||
|
||||
config SYNC_R4K
|
||||
bool
|
||||
|
||||
@ -1334,18 +1288,6 @@ config PCI_XTALK_BRIDGE
|
||||
config NO_EXCEPT_FILL
|
||||
bool
|
||||
|
||||
config SOC_EMMA2RH
|
||||
bool
|
||||
select CEVT_R4K
|
||||
select CSRC_R4K
|
||||
select DMA_NONCOHERENT
|
||||
select IRQ_MIPS_CPU
|
||||
select SWAP_IO_SPACE
|
||||
select SYS_HAS_CPU_R5500
|
||||
select SYS_SUPPORTS_32BIT_KERNEL
|
||||
select SYS_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
|
||||
config SOC_PNX833X
|
||||
bool
|
||||
select CEVT_R4K
|
||||
@ -1419,9 +1361,6 @@ config MIPS_L1_CACHE_SHIFT
|
||||
default "4" if MIPS_L1_CACHE_SHIFT_4
|
||||
default "5"
|
||||
|
||||
config HAVE_STD_PC_SERIAL_PORT
|
||||
bool
|
||||
|
||||
config ARC_CMDLINE_ONLY
|
||||
bool
|
||||
|
||||
@ -1504,6 +1443,18 @@ config CPU_LOONGSON3_WORKAROUNDS
|
||||
|
||||
If unsure, please say Y.
|
||||
|
||||
config CPU_LOONGSON3_CPUCFG_EMULATION
|
||||
bool "Emulate the CPUCFG instruction on older Loongson cores"
|
||||
default y
|
||||
depends on CPU_LOONGSON64
|
||||
help
|
||||
Loongson-3A R4 and newer have the CPUCFG instruction available for
|
||||
userland to query CPU capabilities, much like CPUID on x86. This
|
||||
option provides emulation of the instruction on older Loongson
|
||||
cores, back to Loongson-3A1000.
|
||||
|
||||
If unsure, please say Y.
|
||||
|
||||
config CPU_LOONGSON2E
|
||||
bool "Loongson 2E"
|
||||
depends on SYS_HAS_CPU_LOONGSON2E
|
||||
@ -1580,6 +1531,21 @@ config CPU_MIPS32_R2
|
||||
specific type of processor in your system, choose those that one
|
||||
otherwise CPU_MIPS32_R1 is a safe bet for any MIPS32 system.
|
||||
|
||||
config CPU_MIPS32_R5
|
||||
bool "MIPS32 Release 5"
|
||||
depends on SYS_HAS_CPU_MIPS32_R5
|
||||
select CPU_HAS_PREFETCH
|
||||
select CPU_SUPPORTS_32BIT_KERNEL
|
||||
select CPU_SUPPORTS_HIGHMEM
|
||||
select CPU_SUPPORTS_MSA
|
||||
select HAVE_KVM
|
||||
select MIPS_O32_FP64_SUPPORT
|
||||
help
|
||||
Choose this option to build a kernel for release 5 or later of the
|
||||
MIPS32 architecture. New MIPS processors, starting with the Warrior
|
||||
family, are based on a MIPS32r5 processor. If you own an older
|
||||
processor, you probably need to select MIPS32r1 or MIPS32r2 instead.
|
||||
|
||||
config CPU_MIPS32_R6
|
||||
bool "MIPS32 Release 6"
|
||||
depends on SYS_HAS_CPU_MIPS32_R6
|
||||
@ -1632,6 +1598,23 @@ config CPU_MIPS64_R2
|
||||
specific type of processor in your system, choose those that one
|
||||
otherwise CPU_MIPS64_R1 is a safe bet for any MIPS64 system.
|
||||
|
||||
config CPU_MIPS64_R5
|
||||
bool "MIPS64 Release 5"
|
||||
depends on SYS_HAS_CPU_MIPS64_R5
|
||||
select CPU_HAS_PREFETCH
|
||||
select CPU_SUPPORTS_32BIT_KERNEL
|
||||
select CPU_SUPPORTS_64BIT_KERNEL
|
||||
select CPU_SUPPORTS_HIGHMEM
|
||||
select CPU_SUPPORTS_HUGEPAGES
|
||||
select CPU_SUPPORTS_MSA
|
||||
select MIPS_O32_FP64_SUPPORT if 32BIT || MIPS32_O32
|
||||
select HAVE_KVM
|
||||
help
|
||||
Choose this option to build a kernel for release 5 or later of the
|
||||
MIPS64 architecture. This is a intermediate MIPS architecture
|
||||
release partly implementing release 6 features. Though there is no
|
||||
any hardware known to be based on this release.
|
||||
|
||||
config CPU_MIPS64_R6
|
||||
bool "MIPS64 Release 6"
|
||||
depends on SYS_HAS_CPU_MIPS64_R6
|
||||
@ -1650,6 +1633,28 @@ config CPU_MIPS64_R6
|
||||
family, are based on a MIPS64r6 processor. If you own an older
|
||||
processor, you probably need to select MIPS64r1 or MIPS64r2 instead.
|
||||
|
||||
config CPU_P5600
|
||||
bool "MIPS Warrior P5600"
|
||||
depends on SYS_HAS_CPU_P5600
|
||||
select CPU_HAS_PREFETCH
|
||||
select CPU_SUPPORTS_32BIT_KERNEL
|
||||
select CPU_SUPPORTS_HIGHMEM
|
||||
select CPU_SUPPORTS_MSA
|
||||
select CPU_SUPPORTS_UNCACHED_ACCELERATED
|
||||
select CPU_SUPPORTS_CPUFREQ
|
||||
select CPU_MIPSR2_IRQ_VI
|
||||
select CPU_MIPSR2_IRQ_EI
|
||||
select HAVE_KVM
|
||||
select MIPS_O32_FP64_SUPPORT
|
||||
help
|
||||
Choose this option to build a kernel for MIPS Warrior P5600 CPU.
|
||||
It's based on MIPS32r5 ISA with XPA, EVA, dual/quad issue exec pipes,
|
||||
MMU with two-levels TLB, UCA, MSA, MDU core level features and system
|
||||
level features like up to six P5600 calculation cores, CM2 with L2
|
||||
cache, IOCU/IOMMU (though might be unused depending on the system-
|
||||
specific IP core configuration), GIC, CPC, virtualisation module,
|
||||
eJTAG and PDtrace.
|
||||
|
||||
config CPU_R3000
|
||||
bool "R3000"
|
||||
depends on SYS_HAS_CPU_R3000
|
||||
@ -1826,7 +1831,8 @@ endchoice
|
||||
config CPU_MIPS32_3_5_FEATURES
|
||||
bool "MIPS32 Release 3.5 Features"
|
||||
depends on SYS_HAS_CPU_MIPS32_R3_5
|
||||
depends on CPU_MIPS32_R2 || CPU_MIPS32_R6
|
||||
depends on CPU_MIPS32_R2 || CPU_MIPS32_R5 || CPU_MIPS32_R6 || \
|
||||
CPU_P5600
|
||||
help
|
||||
Choose this option to build a kernel for release 2 or later of the
|
||||
MIPS32 architecture including features from the 3.5 release such as
|
||||
@ -1846,7 +1852,7 @@ config CPU_MIPS32_3_5_EVA
|
||||
config CPU_MIPS32_R5_FEATURES
|
||||
bool "MIPS32 Release 5 Features"
|
||||
depends on SYS_HAS_CPU_MIPS32_R5
|
||||
depends on CPU_MIPS32_R2
|
||||
depends on CPU_MIPS32_R2 || CPU_MIPS32_R5 || CPU_P5600
|
||||
help
|
||||
Choose this option to build a kernel for release 2 or later of the
|
||||
MIPS32 architecture including features from release 5 such as
|
||||
@ -2001,6 +2007,10 @@ config SYS_HAS_CPU_MIPS64_R6
|
||||
bool
|
||||
select ARCH_HAS_SYNC_DMA_FOR_CPU if DMA_NONCOHERENT
|
||||
|
||||
config SYS_HAS_CPU_P5600
|
||||
bool
|
||||
select ARCH_HAS_SYNC_DMA_FOR_CPU if DMA_NONCOHERENT
|
||||
|
||||
config SYS_HAS_CPU_R3000
|
||||
bool
|
||||
|
||||
@ -2084,11 +2094,13 @@ endmenu
|
||||
#
|
||||
config CPU_MIPS32
|
||||
bool
|
||||
default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 || CPU_MIPS32_R6
|
||||
default y if CPU_MIPS32_R1 || CPU_MIPS32_R2 || CPU_MIPS32_R5 || \
|
||||
CPU_MIPS32_R6 || CPU_P5600
|
||||
|
||||
config CPU_MIPS64
|
||||
bool
|
||||
default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 || CPU_MIPS64_R6
|
||||
default y if CPU_MIPS64_R1 || CPU_MIPS64_R2 || CPU_MIPS64_R5 || \
|
||||
CPU_MIPS64_R6
|
||||
|
||||
#
|
||||
# These indicate the revision of the architecture
|
||||
@ -2104,6 +2116,13 @@ config CPU_MIPSR2
|
||||
select CPU_HAS_DIEI if !CPU_DIEI_BROKEN
|
||||
select MIPS_SPRAM
|
||||
|
||||
config CPU_MIPSR5
|
||||
bool
|
||||
default y if CPU_MIPS32_R5 || CPU_MIPS64_R5 || CPU_P5600
|
||||
select CPU_HAS_RIXI
|
||||
select CPU_HAS_DIEI if !CPU_DIEI_BROKEN
|
||||
select MIPS_SPRAM
|
||||
|
||||
config CPU_MIPSR6
|
||||
bool
|
||||
default y if CPU_MIPS32_R6 || CPU_MIPS64_R6
|
||||
@ -2118,6 +2137,7 @@ config TARGET_ISA_REV
|
||||
int
|
||||
default 1 if CPU_MIPSR1
|
||||
default 2 if CPU_MIPSR2
|
||||
default 5 if CPU_MIPSR5
|
||||
default 6 if CPU_MIPSR6
|
||||
default 0
|
||||
help
|
||||
@ -2707,7 +2727,11 @@ config NEED_PER_CPU_EMBED_FIRST_CHUNK
|
||||
|
||||
config RELOCATABLE
|
||||
bool "Relocatable kernel"
|
||||
depends on SYS_SUPPORTS_RELOCATABLE && (CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_MIPS32_R6 || CPU_MIPS64_R6 || CAVIUM_OCTEON_SOC)
|
||||
depends on SYS_SUPPORTS_RELOCATABLE
|
||||
depends on CPU_MIPS32_R2 || CPU_MIPS64_R2 || \
|
||||
CPU_MIPS32_R5 || CPU_MIPS64_R5 || \
|
||||
CPU_MIPS32_R6 || CPU_MIPS64_R6 || \
|
||||
CPU_P5600 || CAVIUM_OCTEON_SOC
|
||||
help
|
||||
This builds a kernel image that retains relocation information
|
||||
so it can be loaded someplace besides the default 1MB.
|
||||
@ -3275,3 +3299,5 @@ endmenu
|
||||
source "drivers/firmware/Kconfig"
|
||||
|
||||
source "arch/mips/kvm/Kconfig"
|
||||
|
||||
source "arch/mips/vdso/Kconfig"
|
||||
|
@ -148,4 +148,14 @@ config MIPS_CPS_NS16550_SHIFT
|
||||
form their addresses. That is, log base 2 of the span between
|
||||
adjacent ns16550 registers in the system.
|
||||
|
||||
config MIPS_CPS_NS16550_WIDTH
|
||||
int "UART Register Width"
|
||||
default 1
|
||||
help
|
||||
ns16550 registers width. UART registers IO access methods will be
|
||||
selected in accordance with this parameter. By setting it to 1, 2 or
|
||||
4 UART registers will be accessed by means of lb/sb, lh/sh or lw/sw
|
||||
instructions respectively. Any value not from that set activates
|
||||
lb/sb instructions.
|
||||
|
||||
endif # MIPS_CPS_NS16550_BOOL
|
||||
|
@ -116,33 +116,8 @@ endif
|
||||
|
||||
cflags-y += -ffreestanding
|
||||
|
||||
#
|
||||
# We explicitly add the endianness specifier if needed, this allows
|
||||
# to compile kernels with a toolchain for the other endianness. We
|
||||
# carefully avoid to add it redundantly because gcc 3.3/3.4 complains
|
||||
# when fed the toolchain default!
|
||||
#
|
||||
# Certain gcc versions up to gcc 4.1.1 (probably 4.2-subversion as of
|
||||
# 2006-10-10 don't properly change the predefined symbols if -EB / -EL
|
||||
# are used, so we kludge that here. A bug has been filed at
|
||||
# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413.
|
||||
#
|
||||
# clang doesn't suffer from these issues and our checks against -dumpmachine
|
||||
# don't work so well when cross compiling, since without providing --target
|
||||
# clang's output will be based upon the build machine. So for clang we simply
|
||||
# unconditionally specify -EB or -EL as appropriate.
|
||||
#
|
||||
ifdef CONFIG_CC_IS_CLANG
|
||||
cflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB
|
||||
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -EL
|
||||
else
|
||||
undef-all += -UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__
|
||||
undef-all += -UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__
|
||||
predef-be += -DMIPSEB -D_MIPSEB -D__MIPSEB -D__MIPSEB__
|
||||
predef-le += -DMIPSEL -D_MIPSEL -D__MIPSEL -D__MIPSEL__
|
||||
cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB $(undef-all) $(predef-be))
|
||||
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL $(undef-all) $(predef-le))
|
||||
endif
|
||||
|
||||
cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \
|
||||
-fno-omit-frame-pointer
|
||||
@ -171,10 +146,13 @@ cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_MIPS32_R1) += -march=mips32 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_MIPS32_R5) += -march=mips32r5 -Wa,--trap -modd-spreg
|
||||
cflags-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6 -Wa,--trap -modd-spreg
|
||||
cflags-$(CONFIG_CPU_MIPS64_R1) += -march=mips64 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_MIPS64_R5) += -march=mips64r5 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_MIPS64_R6) += -march=mips64r6 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_P5600) += -march=p5600 -Wa,--trap -modd-spreg
|
||||
cflags-$(CONFIG_CPU_R5000) += -march=r5000 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_R5500) += $(call cc-option,-march=r5500,-march=r5000) \
|
||||
-Wa,--trap
|
||||
@ -288,12 +266,23 @@ ifdef CONFIG_64BIT
|
||||
endif
|
||||
endif
|
||||
|
||||
# When linking a 32-bit executable the LLVM linker cannot cope with a
|
||||
# 32-bit load address that has been sign-extended to 64 bits. Simply
|
||||
# remove the upper 32 bits then, as it is safe to do so with other
|
||||
# linkers.
|
||||
ifdef CONFIG_64BIT
|
||||
load-ld = $(load-y)
|
||||
else
|
||||
load-ld = $(subst 0xffffffff,0x,$(load-y))
|
||||
endif
|
||||
|
||||
KBUILD_AFLAGS += $(cflags-y)
|
||||
KBUILD_CFLAGS += $(cflags-y)
|
||||
KBUILD_CPPFLAGS += -DVMLINUX_LOAD_ADDRESS=$(load-y)
|
||||
KBUILD_CPPFLAGS += -DVMLINUX_LOAD_ADDRESS=$(load-y) -DLINKER_LOAD_ADDRESS=$(load-ld)
|
||||
KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)
|
||||
|
||||
bootvars-y = VMLINUX_LOAD_ADDRESS=$(load-y) \
|
||||
LINKER_LOAD_ADDRESS=$(load-ld) \
|
||||
VMLINUX_ENTRY_ADDRESS=$(entry-y) \
|
||||
PLATFORM="$(platform-y)" \
|
||||
ITS_INPUTS="$(its-y)"
|
||||
@ -359,12 +348,6 @@ ifeq ($(shell expr $(zload-y) \< 0xffffffff80000000 2> /dev/null), 0)
|
||||
bootz-y += uzImage.bin
|
||||
endif
|
||||
|
||||
ifdef CONFIG_LASAT
|
||||
rom.bin rom.sw: vmlinux
|
||||
$(Q)$(MAKE) $(build)=arch/mips/lasat/image \
|
||||
$(bootvars-y) $@
|
||||
endif
|
||||
|
||||
#
|
||||
# Some machines like the Indy need 32-bit ELF binaries for booting purposes.
|
||||
# Other need ECOFF, so we build a 32-bit ELF binary for them which we then
|
||||
@ -430,7 +413,6 @@ archclean:
|
||||
$(Q)$(MAKE) $(clean)=arch/mips/boot
|
||||
$(Q)$(MAKE) $(clean)=arch/mips/boot/compressed
|
||||
$(Q)$(MAKE) $(clean)=arch/mips/boot/tools
|
||||
$(Q)$(MAKE) $(clean)=arch/mips/lasat
|
||||
|
||||
archheaders:
|
||||
$(Q)$(MAKE) $(build)=arch/mips/kernel/syscalls all
|
||||
|
@ -15,19 +15,16 @@ load-$(CONFIG_MIPS_DB1XXX) += 0xffffffff80100000
|
||||
#
|
||||
# 4G-Systems MTX-1 "MeshCube" wireless router
|
||||
#
|
||||
platform-$(CONFIG_MIPS_MTX1) += alchemy/
|
||||
load-$(CONFIG_MIPS_MTX1) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# MyCable eval board
|
||||
#
|
||||
platform-$(CONFIG_MIPS_XXS1500) += alchemy/
|
||||
load-$(CONFIG_MIPS_XXS1500) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# Trapeze ITS GRP board
|
||||
#
|
||||
platform-$(CONFIG_MIPS_GPR) += alchemy/
|
||||
load-$(CONFIG_MIPS_GPR) += 0xffffffff80100000
|
||||
|
||||
# boards can specify their own <gpio.h> in one of their include dirs.
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/dma-coherence.h>
|
||||
#include <asm/mipsregs.h>
|
||||
@ -72,9 +73,9 @@ void __init plat_mem_setup(void)
|
||||
iomem_resource.end = IOMEM_RESOURCE_END;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_PCI)
|
||||
#ifdef CONFIG_MIPS_FIXUP_BIGPHYS_ADDR
|
||||
/* This routine should be valid for all Au1x based boards */
|
||||
phys_addr_t __fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size)
|
||||
phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size)
|
||||
{
|
||||
unsigned long start = ALCHEMY_PCI_MEMWIN_START;
|
||||
unsigned long end = ALCHEMY_PCI_MEMWIN_END;
|
||||
@ -90,5 +91,13 @@ phys_addr_t __fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size)
|
||||
/* default nop */
|
||||
return phys_addr;
|
||||
}
|
||||
EXPORT_SYMBOL(__fixup_bigphys_addr);
|
||||
#endif
|
||||
|
||||
int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long vaddr,
|
||||
unsigned long pfn, unsigned long size, pgprot_t prot)
|
||||
{
|
||||
phys_addr_t phys_addr = fixup_bigphys_addr(pfn << PAGE_SHIFT, size);
|
||||
|
||||
return remap_pfn_range(vma, vaddr, phys_addr >> PAGE_SHIFT, size, prot);
|
||||
}
|
||||
EXPORT_SYMBOL(io_remap_pfn_range);
|
||||
#endif /* CONFIG_MIPS_FIXUP_BIGPHYS_ADDR */
|
||||
|
@ -225,7 +225,7 @@ static void __init pb1550_nand_setup(void)
|
||||
case 0: case 2: case 8: case 0xC: case 0xD:
|
||||
/* x16 NAND Flash */
|
||||
pb1550_nand_pd.devwidth = 1;
|
||||
/* fallthrough */
|
||||
fallthrough;
|
||||
case 1: case 3: case 9: case 0xE: case 0xF:
|
||||
/* x8 NAND, already set up */
|
||||
platform_device_register(&pb1550_nand_dev);
|
||||
|
@ -1,6 +1,5 @@
|
||||
#
|
||||
# Texas Instruments AR7
|
||||
#
|
||||
platform-$(CONFIG_AR7) += ar7/
|
||||
cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7
|
||||
load-$(CONFIG_AR7) += 0xffffffff94100000
|
||||
|
@ -57,7 +57,7 @@ const char *get_system_type(void)
|
||||
case TITAN_CHIP_1060:
|
||||
return "TI AR7 (TNETV1060)";
|
||||
}
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
default:
|
||||
return "TI AR7 (unknown)";
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
#
|
||||
# Atheros AR531X/AR231X WiSoC
|
||||
#
|
||||
platform-$(CONFIG_ATH25) += ath25/
|
||||
cflags-$(CONFIG_ATH25) += -I$(srctree)/arch/mips/include/asm/mach-ath25
|
||||
load-$(CONFIG_ATH25) += 0xffffffff80041000
|
||||
|
@ -2,6 +2,5 @@
|
||||
# Atheros AR71xx/AR724x/AR913x
|
||||
#
|
||||
|
||||
platform-$(CONFIG_ATH79) += ath79/
|
||||
cflags-$(CONFIG_ATH79) += -I$(srctree)/arch/mips/include/asm/mach-ath79
|
||||
load-$(CONFIG_ATH79) = 0xffffffff80060000
|
||||
|
@ -153,8 +153,7 @@ static void __init ath79_detect_sys_type(void)
|
||||
case REV_ID_MAJOR_QCA9533_V2:
|
||||
ver = 2;
|
||||
ath79_soc_rev = 2;
|
||||
/* fall through */
|
||||
|
||||
fallthrough;
|
||||
case REV_ID_MAJOR_QCA9533:
|
||||
ath79_soc = ATH79_SOC_QCA9533;
|
||||
chip = "9533";
|
||||
|
@ -1,7 +1,6 @@
|
||||
#
|
||||
# Broadcom BCM47XX boards
|
||||
#
|
||||
platform-$(CONFIG_BCM47XX) += bcm47xx/
|
||||
cflags-$(CONFIG_BCM47XX) += \
|
||||
-I$(srctree)/arch/mips/include/asm/mach-bcm47xx
|
||||
load-$(CONFIG_BCM47XX) := 0xffffffff80001000
|
||||
|
@ -1,7 +1,6 @@
|
||||
#
|
||||
# Broadcom BCM63XX boards
|
||||
#
|
||||
platform-$(CONFIG_BCM63XX) += bcm63xx/
|
||||
cflags-$(CONFIG_BCM63XX) += \
|
||||
-I$(srctree)/arch/mips/include/asm/mach-bcm63xx/
|
||||
load-$(CONFIG_BCM63XX) := 0xffffffff80010000
|
||||
|
@ -304,7 +304,7 @@ void __init bcm63xx_cpu_init(void)
|
||||
case CPU_BMIPS3300:
|
||||
if ((read_c0_prid() & PRID_IMP_MASK) != PRID_IMP_BMIPS3300_ALT)
|
||||
__cpu_name[cpu] = "Broadcom BCM6338";
|
||||
/* fall-through */
|
||||
fallthrough;
|
||||
case CPU_BMIPS32:
|
||||
chipid_reg = BCM_6345_PERF_BASE;
|
||||
break;
|
||||
|
@ -94,7 +94,7 @@ static int __init bcm63xx_detect_flash_type(void)
|
||||
case STRAPBUS_6368_BOOT_SEL_PARALLEL:
|
||||
return BCM63XX_FLASH_TYPE_PARALLEL;
|
||||
}
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#
|
||||
# Broadcom Generic BMIPS kernel
|
||||
#
|
||||
platform-$(CONFIG_BMIPS_GENERIC) += bmips/
|
||||
cflags-$(CONFIG_BMIPS_GENERIC) += \
|
||||
-I$(srctree)/arch/mips/include/asm/mach-bmips/
|
||||
load-$(CONFIG_BMIPS_GENERIC) := 0xffffffff80010000
|
||||
|
@ -90,7 +90,7 @@ ifneq ($(zload-y),)
|
||||
VMLINUZ_LOAD_ADDRESS := $(zload-y)
|
||||
else
|
||||
VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \
|
||||
$(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS))
|
||||
$(obj)/vmlinux.bin $(LINKER_LOAD_ADDRESS))
|
||||
endif
|
||||
UIMAGE_LOADADDR = $(VMLINUZ_LOAD_ADDRESS)
|
||||
|
||||
|
@ -1,17 +1,19 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
subdir-y += brcm
|
||||
subdir-y += cavium-octeon
|
||||
subdir-y += img
|
||||
subdir-y += ingenic
|
||||
subdir-y += lantiq
|
||||
subdir-y += loongson
|
||||
subdir-y += mscc
|
||||
subdir-y += mti
|
||||
subdir-y += netlogic
|
||||
subdir-y += ni
|
||||
subdir-y += pic32
|
||||
subdir-y += qca
|
||||
subdir-y += ralink
|
||||
subdir-y += xilfpga
|
||||
subdir-$(CONFIG_BMIPS_GENERIC) += brcm
|
||||
subdir-$(CONFIG_CAVIUM_OCTEON_SOC) += cavium-octeon
|
||||
subdir-$(CONFIG_MACH_PISTACHIO) += img
|
||||
subdir-$(CONFIG_FIT_IMAGE_FDT_BOSTON) += img
|
||||
subdir-$(CONFIG_MACH_INGENIC) += ingenic
|
||||
subdir-$(CONFIG_LANTIQ) += lantiq
|
||||
subdir-$(CONFIG_MACH_LOONGSON64) += loongson
|
||||
subdir-$(CONFIG_MSCC_OCELOT) += mscc
|
||||
subdir-$(CONFIG_MIPS_MALTA) += mti
|
||||
subdir-$(CONFIG_LEGACY_BOARD_SEAD3) += mti
|
||||
subdir-$(CONFIG_NLM_XLP_BOARD) += netlogic
|
||||
subdir-$(CONFIG_FIT_IMAGE_FDT_NI169445) += ni
|
||||
subdir-$(CONFIG_MACH_PIC32) += pic32
|
||||
subdir-$(CONFIG_ATH79) += qca
|
||||
subdir-$(CONFIG_RALINK) += ralink
|
||||
subdir-$(CONFIG_FIT_IMAGE_FDT_XILFPGA) += xilfpga
|
||||
|
||||
obj-$(CONFIG_BUILTIN_DTB) := $(addsuffix /, $(subdir-y))
|
||||
|
@ -386,6 +386,9 @@ dm9000@6 {
|
||||
|
||||
interrupt-parent = <&gpe>;
|
||||
interrupts = <19 4>;
|
||||
|
||||
nvmem-cells = <ð0_addr>;
|
||||
nvmem-cell-names = "mac-address";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,10 @@
|
||||
#include "jz4770.dtsi"
|
||||
#include <dt-bindings/clock/ingenic,tcu.h>
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/iio/adc/ingenic,adc.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
/ {
|
||||
compatible = "gcw,zero", "ingenic,jz4770";
|
||||
model = "GCW Zero";
|
||||
@ -15,20 +19,370 @@ aliases {
|
||||
serial3 = &uart3;
|
||||
};
|
||||
|
||||
memory: memory {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x10000000>,
|
||||
<0x30000000 0x10000000>;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial2:57600n8";
|
||||
};
|
||||
|
||||
board {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
vcc: regulator@0 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc";
|
||||
|
||||
otg_phy: otg-phy {
|
||||
compatible = "usb-nop-xceiv";
|
||||
clocks = <&cgu JZ4770_CLK_OTG_PHY>;
|
||||
clock-names = "main_clk";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
mmc1_power: regulator@1 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "mmc1_vcc";
|
||||
gpio = <&gpe 9 0>;
|
||||
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
vin-supply = <&vcc>;
|
||||
};
|
||||
|
||||
headphones_amp: analog-amplifier@0 {
|
||||
compatible = "simple-audio-amplifier";
|
||||
enable-gpios = <&gpf 3 GPIO_ACTIVE_LOW>;
|
||||
enable-delay-ms = <50>;
|
||||
|
||||
VCC-supply = <&ldo5>;
|
||||
sound-name-prefix = "Headphones Amp";
|
||||
};
|
||||
|
||||
speaker_amp: analog-amplifier@1 {
|
||||
compatible = "simple-audio-amplifier";
|
||||
enable-gpios = <&gpf 20 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
VCC-supply = <&ldo5>;
|
||||
sound-name-prefix = "Speaker Amp";
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "simple-audio-card";
|
||||
|
||||
simple-audio-card,name = "gcw0-audio";
|
||||
simple-audio-card,format = "i2s";
|
||||
|
||||
simple-audio-card,widgets =
|
||||
"Speaker", "Speaker",
|
||||
"Headphone", "Headphones",
|
||||
"Line", "FM Radio",
|
||||
"Microphone", "Built-in Mic";
|
||||
simple-audio-card,routing =
|
||||
"Headphones Amp INL", "LHPOUT",
|
||||
"Headphones Amp INR", "RHPOUT",
|
||||
"Headphones", "Headphones Amp OUTL",
|
||||
"Headphones", "Headphones Amp OUTR",
|
||||
"Speaker Amp INL", "LOUT",
|
||||
"Speaker Amp INR", "ROUT",
|
||||
"Speaker", "Speaker Amp OUTL",
|
||||
"Speaker", "Speaker Amp OUTR",
|
||||
"LLINEIN", "FM Radio",
|
||||
"RLINEIN", "FM Radio",
|
||||
"Built-in Mic", "MICBIAS",
|
||||
"MIC1P", "Built-in Mic",
|
||||
"MIC1N", "Built-in Mic";
|
||||
simple-audio-card,pin-switches = "Speaker", "Headphones";
|
||||
|
||||
simple-audio-card,hp-det-gpio = <&gpf 21 GPIO_ACTIVE_HIGH>;
|
||||
simple-audio-card,aux-devs = <&speaker_amp>, <&headphones_amp>;
|
||||
|
||||
simple-audio-card,bitclock-master = <&dai_codec>;
|
||||
simple-audio-card,frame-master = <&dai_codec>;
|
||||
|
||||
dai_cpu: simple-audio-card,cpu {
|
||||
sound-dai = <&aic>;
|
||||
};
|
||||
|
||||
dai_codec: simple-audio-card,codec {
|
||||
sound-dai = <&codec>;
|
||||
};
|
||||
};
|
||||
|
||||
rumble {
|
||||
compatible = "pwm-vibrator";
|
||||
pwms = <&pwm 4 2000000 0>;
|
||||
pwm-names = "enable";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_pwm4>;
|
||||
};
|
||||
|
||||
backlight: backlight {
|
||||
compatible = "pwm-backlight";
|
||||
pwms = <&pwm 1 40000 0>;
|
||||
power-supply = <&vcc>;
|
||||
|
||||
brightness-levels = <0 16 32 48 64 80 96 112 128
|
||||
144 160 176 192 208 224 240 255>;
|
||||
default-brightness-level = <12>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_pwm1>;
|
||||
};
|
||||
|
||||
gpio-keys {
|
||||
compatible = "gpio-keys";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
autorepeat;
|
||||
|
||||
button@0 {
|
||||
label = "D-pad up";
|
||||
linux,code = <KEY_UP>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpe 21 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@1 {
|
||||
label = "D-pad down";
|
||||
linux,code = <KEY_DOWN>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpe 25 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@2 {
|
||||
label = "D-pad left";
|
||||
linux,code = <KEY_LEFT>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpe 23 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@3 {
|
||||
label = "D-pad right";
|
||||
linux,code = <KEY_RIGHT>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpe 24 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@4 {
|
||||
label = "Button A";
|
||||
linux,code = <KEY_LEFTCTRL>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpe 29 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@5 {
|
||||
label = "Button B";
|
||||
linux,code = <KEY_LEFTALT>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpe 20 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@6 {
|
||||
label = "Button Y";
|
||||
linux,code = <KEY_SPACE>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpe 27 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@7 {
|
||||
label = "Button X";
|
||||
linux,code = <KEY_LEFTSHIFT>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpe 28 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@8 {
|
||||
label = "Left shoulder button";
|
||||
linux,code = <KEY_TAB>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpb 20 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@9 {
|
||||
label = "Right shoulder button";
|
||||
linux,code = <KEY_BACKSPACE>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpe 26 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@10 {
|
||||
label = "Start button";
|
||||
linux,code = <KEY_ENTER>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpb 21 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
button@11 {
|
||||
label = "Select button";
|
||||
linux,code = <KEY_ESC>;
|
||||
linux,can-disable;
|
||||
/*
|
||||
* This is the only button that is active high,
|
||||
* since it doubles as BOOT_SEL1.
|
||||
*/
|
||||
gpios = <&gpd 18 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
button@12 {
|
||||
label = "Power slider";
|
||||
linux,code = <KEY_POWER>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpa 30 GPIO_ACTIVE_LOW>;
|
||||
wakeup-source;
|
||||
};
|
||||
|
||||
button@13 {
|
||||
label = "Power hold";
|
||||
linux,code = <KEY_PAUSE>;
|
||||
linux,can-disable;
|
||||
gpios = <&gpf 11 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c3: i2c-controller@3 {
|
||||
compatible = "i2c-gpio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sda-gpios = <&gpd 5 GPIO_ACTIVE_HIGH>;
|
||||
scl-gpios = <&gpd 4 GPIO_ACTIVE_HIGH>;
|
||||
i2c-gpio,delay-us = <2>; /* 250 kHz */
|
||||
|
||||
act8600: pmic@5a {
|
||||
compatible = "active-semi,act8600";
|
||||
reg = <0x5a>;
|
||||
|
||||
regulators {
|
||||
/* USB OTG */
|
||||
otg_vbus: SUDCDC_REG4 {
|
||||
/*
|
||||
* 5.3V instead of 5.0V to compensate
|
||||
* for the voltage drop of a diode
|
||||
* between the regulator and the
|
||||
* connector.
|
||||
*/
|
||||
regulator-min-microvolt = <5300000>;
|
||||
regulator-max-microvolt = <5300000>;
|
||||
inl-supply = <&vcc>;
|
||||
};
|
||||
|
||||
/*
|
||||
* When this is off, there is no sound, but also
|
||||
* no USB networking.
|
||||
*/
|
||||
ldo5: LDO5 {
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
inl-supply = <&vcc>;
|
||||
};
|
||||
|
||||
/* LCD panel and FM radio */
|
||||
ldo6: LDO6 {
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
inl-supply = <&vcc>;
|
||||
};
|
||||
|
||||
/* ??? */
|
||||
LDO7 {
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
/*regulator-always-on;*/
|
||||
inl-supply = <&vcc>;
|
||||
};
|
||||
|
||||
/*
|
||||
* The colors on the LCD are wrong when this is
|
||||
* off. Which is strange, since the LCD panel
|
||||
* data sheet only mentions a 3.3V input.
|
||||
*/
|
||||
LDO8 {
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-always-on;
|
||||
inl-supply = <&vcc>;
|
||||
};
|
||||
|
||||
/* RTC fixed 3.3V */
|
||||
LDO_REG9 {
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
inl-supply = <&vcc>;
|
||||
};
|
||||
|
||||
/* Unused fixed 1.2V */
|
||||
LDO_REG10 {
|
||||
inl-supply = <&vcc>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led {
|
||||
gpios = <&gpb 30 GPIO_ACTIVE_LOW>;
|
||||
default-state = "on";
|
||||
};
|
||||
};
|
||||
|
||||
spi {
|
||||
compatible = "spi-gpio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sck-gpios = <&gpe 15 GPIO_ACTIVE_HIGH>;
|
||||
mosi-gpios = <&gpe 17 GPIO_ACTIVE_HIGH>;
|
||||
cs-gpios = <&gpe 16 GPIO_ACTIVE_HIGH>;
|
||||
num-chipselects = <1>;
|
||||
|
||||
nt39016@0 {
|
||||
compatible = "kingdisplay,kd035g6-54nt";
|
||||
reg = <0>;
|
||||
|
||||
spi-max-frequency = <3125000>;
|
||||
spi-3wire;
|
||||
spi-cs-high;
|
||||
|
||||
reset-gpios = <&gpe 2 GPIO_ACTIVE_LOW>;
|
||||
|
||||
backlight = <&backlight>;
|
||||
power-supply = <&ldo6>;
|
||||
|
||||
port {
|
||||
panel_input: endpoint {
|
||||
remote-endpoint = <&panel_output>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
connector {
|
||||
compatible = "gpio-usb-b-connector", "usb-b-connector";
|
||||
label = "mini-USB";
|
||||
type = "mini";
|
||||
|
||||
/*
|
||||
* USB OTG is not yet working reliably, the ID detection
|
||||
* mechanism tends to fry easily for unknown reasons.
|
||||
* Until this is fixed, disable OTG by not providing the
|
||||
* ID GPIO to the driver.
|
||||
*/
|
||||
//id-gpios = <&gpf 18 GPIO_ACTIVE_LOW>;
|
||||
|
||||
vbus-gpios = <&gpb 5 GPIO_ACTIVE_HIGH>;
|
||||
vbus-supply = <&otg_vbus>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_otg>;
|
||||
|
||||
port {
|
||||
usb_ep: endpoint {
|
||||
remote-endpoint = <&usb_otg_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -37,24 +391,86 @@ &ext {
|
||||
clock-frequency = <12000000>;
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
pins_lcd: lcd {
|
||||
function = "lcd";
|
||||
groups = "lcd-24bit";
|
||||
};
|
||||
|
||||
pins_uart2: uart2 {
|
||||
function = "uart2";
|
||||
groups = "uart2-data";
|
||||
};
|
||||
|
||||
pins_mmc0: mmc0 {
|
||||
function = "mmc0";
|
||||
groups = "mmc0-1bit-a", "mmc0-4bit-a";
|
||||
};
|
||||
|
||||
pins_mmc1: mmc1 {
|
||||
function = "mmc1";
|
||||
groups = "mmc1-1bit-d", "mmc1-4bit-d";
|
||||
};
|
||||
|
||||
pins_otg: otg {
|
||||
otg-vbus-pin {
|
||||
function = "otg";
|
||||
groups = "otg-vbus";
|
||||
};
|
||||
|
||||
vbus-pin {
|
||||
pins = "PB5";
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
pins_pwm1: pwm1 {
|
||||
function = "pwm1";
|
||||
groups = "pwm1";
|
||||
};
|
||||
|
||||
pins_pwm4: pwm4 {
|
||||
function = "pwm4";
|
||||
groups = "pwm4";
|
||||
};
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_uart2>;
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&cgu {
|
||||
/* Put high-speed peripherals under PLL1, such that we can change the
|
||||
/*
|
||||
* Put high-speed peripherals under PLL1, such that we can change the
|
||||
* PLL0 frequency on demand without having to suspend peripherals.
|
||||
* We use a rate of 432 MHz, which is the least common multiple of
|
||||
* 27 MHz (required by TV encoder) and 48 MHz (required by USB host).
|
||||
* Put the GPU under PLL0 since we want a higher frequency.
|
||||
* Use the 32 kHz oscillator as the parent of the RTC for a higher
|
||||
* precision.
|
||||
*/
|
||||
assigned-clocks =
|
||||
<&cgu JZ4770_CLK_PLL1>,
|
||||
<&cgu JZ4770_CLK_UHC>;
|
||||
<&cgu JZ4770_CLK_GPU>,
|
||||
<&cgu JZ4770_CLK_RTC>,
|
||||
<&cgu JZ4770_CLK_UHC>,
|
||||
<&cgu JZ4770_CLK_LPCLK_MUX>,
|
||||
<&cgu JZ4770_CLK_MMC0_MUX>,
|
||||
<&cgu JZ4770_CLK_MMC1_MUX>;
|
||||
assigned-clock-parents =
|
||||
<0>,
|
||||
<&cgu JZ4770_CLK_PLL0>,
|
||||
<&cgu JZ4770_CLK_OSC32K>,
|
||||
<&cgu JZ4770_CLK_PLL1>,
|
||||
<&cgu JZ4770_CLK_PLL1>,
|
||||
<&cgu JZ4770_CLK_PLL1>,
|
||||
<&cgu JZ4770_CLK_PLL1>;
|
||||
assigned-clock-rates =
|
||||
<432000000>;
|
||||
<432000000>,
|
||||
<600000000>;
|
||||
};
|
||||
|
||||
&uhc {
|
||||
@ -63,10 +479,69 @@ &uhc {
|
||||
};
|
||||
|
||||
&tcu {
|
||||
/* 750 kHz for the system timer and clocksource */
|
||||
assigned-clocks = <&tcu TCU_CLK_TIMER0>, <&tcu TCU_CLK_TIMER2>;
|
||||
assigned-clock-rates = <750000>, <750000>;
|
||||
/*
|
||||
* 750 kHz for the system timer and clocksource, 12 MHz for the OST,
|
||||
* and use RTC as the parent for the watchdog clock
|
||||
*/
|
||||
assigned-clocks = <&tcu TCU_CLK_TIMER0>, <&tcu TCU_CLK_TIMER2>,
|
||||
<&tcu TCU_CLK_OST>, <&tcu TCU_CLK_WDT>;
|
||||
assigned-clock-parents = <0>, <0>, <0>, <&cgu JZ4770_CLK_RTC>;
|
||||
assigned-clock-rates = <750000>, <750000>, <12000000>;
|
||||
|
||||
/* PWM1 is in use, so reserve channel #2 for the clocksource */
|
||||
/* PWM1 is in use, so use channel #2 for the clocksource */
|
||||
ingenic,pwm-channels-mask = <0xfa>;
|
||||
};
|
||||
|
||||
&usb_otg {
|
||||
port {
|
||||
usb_otg_ep: endpoint {
|
||||
remote-endpoint = <&usb_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&otg_phy {
|
||||
vcc-supply = <&ldo5>;
|
||||
};
|
||||
|
||||
&rtc {
|
||||
clocks = <&cgu JZ4770_CLK_RTC>;
|
||||
clock-names = "rtc";
|
||||
|
||||
system-power-controller;
|
||||
};
|
||||
|
||||
&mmc0 {
|
||||
status = "okay";
|
||||
|
||||
bus-width = <4>;
|
||||
max-frequency = <48000000>;
|
||||
vmmc-supply = <&vcc>;
|
||||
non-removable;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_mmc0>;
|
||||
};
|
||||
|
||||
&mmc1 {
|
||||
status = "okay";
|
||||
|
||||
bus-width = <4>;
|
||||
max-frequency = <48000000>;
|
||||
cd-gpios = <&gpb 2 GPIO_ACTIVE_LOW>;
|
||||
vmmc-supply = <&mmc1_power>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_mmc1>;
|
||||
};
|
||||
|
||||
&lcd {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_lcd>;
|
||||
|
||||
port {
|
||||
panel_output: endpoint {
|
||||
remote-endpoint = <&panel_input>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
13
arch/mips/boot/dts/ingenic/gcw0_proto.dts
Normal file
13
arch/mips/boot/dts/ingenic/gcw0_proto.dts
Normal file
@ -0,0 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/dts-v1/;
|
||||
|
||||
#include "gcw0.dts"
|
||||
|
||||
/ {
|
||||
model = "GCW Zero Prototype";
|
||||
};
|
||||
|
||||
&memory {
|
||||
/* Prototype has only 256 MiB of RAM */
|
||||
reg = <0x0 0x10000000>;
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user