Merge 4.1-rc7 into staging-testing
We want the staging tree fixes in here too to help with testing and merge issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
commit
6394d6d01b
|
@ -162,7 +162,7 @@ Description: Discover CPUs in the same CPU frequency coordination domain
|
||||||
What: /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1}
|
What: /sys/devices/system/cpu/cpu*/cache/index3/cache_disable_{0,1}
|
||||||
Date: August 2008
|
Date: August 2008
|
||||||
KernelVersion: 2.6.27
|
KernelVersion: 2.6.27
|
||||||
Contact: discuss@x86-64.org
|
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
|
||||||
Description: Disable L3 cache indices
|
Description: Disable L3 cache indices
|
||||||
|
|
||||||
These files exist in every CPU's cache/index3 directory. Each
|
These files exist in every CPU's cache/index3 directory. Each
|
||||||
|
|
|
@ -17,7 +17,8 @@ Required properties:
|
||||||
- #clock-cells: from common clock binding; shall be set to 1.
|
- #clock-cells: from common clock binding; shall be set to 1.
|
||||||
- clocks: from common clock binding; list of parent clock
|
- clocks: from common clock binding; list of parent clock
|
||||||
handles, shall be xtal reference clock or xtal and clkin for
|
handles, shall be xtal reference clock or xtal and clkin for
|
||||||
si5351c only.
|
si5351c only. Corresponding clock input names are "xtal" and
|
||||||
|
"clkin" respectively.
|
||||||
- #address-cells: shall be set to 1.
|
- #address-cells: shall be set to 1.
|
||||||
- #size-cells: shall be set to 0.
|
- #size-cells: shall be set to 0.
|
||||||
|
|
||||||
|
@ -71,6 +72,7 @@ i2c-master-node {
|
||||||
|
|
||||||
/* connect xtal input to 25MHz reference */
|
/* connect xtal input to 25MHz reference */
|
||||||
clocks = <&ref25>;
|
clocks = <&ref25>;
|
||||||
|
clock-names = "xtal";
|
||||||
|
|
||||||
/* connect xtal input as source of pll0 and pll1 */
|
/* connect xtal input as source of pll0 and pll1 */
|
||||||
silabs,pll-source = <0 0>, <1 0>;
|
silabs,pll-source = <0 0>, <1 0>;
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: Should be "cdns,[<chip>-]{emac}"
|
- compatible: Should be "cdns,[<chip>-]{emac}"
|
||||||
Use "cdns,at91rm9200-emac" Atmel at91rm9200 SoC.
|
Use "cdns,at91rm9200-emac" Atmel at91rm9200 SoC.
|
||||||
or the generic form: "cdns,emac".
|
Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
|
||||||
|
Or the generic form: "cdns,emac".
|
||||||
- reg: Address and length of the register set for the device
|
- reg: Address and length of the register set for the device
|
||||||
- interrupts: Should contain macb interrupt
|
- interrupts: Should contain macb interrupt
|
||||||
- phy-mode: see ethernet.txt file in the same directory.
|
- phy-mode: see ethernet.txt file in the same directory.
|
||||||
|
|
|
@ -15,10 +15,8 @@ Optional properties:
|
||||||
- phys: phandle + phy specifier pair
|
- phys: phandle + phy specifier pair
|
||||||
- phy-names: must be "usb"
|
- phy-names: must be "usb"
|
||||||
- dmas: Must contain a list of references to DMA specifiers.
|
- dmas: Must contain a list of references to DMA specifiers.
|
||||||
- dma-names : Must contain a list of DMA names:
|
- dma-names : named "ch%d", where %d is the channel number ranging from zero
|
||||||
- tx0 ... tx<n>
|
to the number of channels (DnFIFOs) minus one.
|
||||||
- rx0 ... rx<n>
|
|
||||||
- This <n> means DnFIFO in USBHS module.
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
usbhs: usb@e6590000 {
|
usbhs: usb@e6590000 {
|
||||||
|
|
|
@ -20,7 +20,7 @@ Supported chips:
|
||||||
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp432.html
|
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp432.html
|
||||||
* Texas Instruments TMP435
|
* Texas Instruments TMP435
|
||||||
Prefix: 'tmp435'
|
Prefix: 'tmp435'
|
||||||
Addresses scanned: I2C 0x37, 0x48 - 0x4f
|
Addresses scanned: I2C 0x48 - 0x4f
|
||||||
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp435.html
|
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp435.html
|
||||||
|
|
||||||
Authors:
|
Authors:
|
||||||
|
|
|
@ -15,8 +15,7 @@ Contents:
|
||||||
a) Discovering and configuring TCMU uio devices
|
a) Discovering and configuring TCMU uio devices
|
||||||
b) Waiting for events on the device(s)
|
b) Waiting for events on the device(s)
|
||||||
c) Managing the command ring
|
c) Managing the command ring
|
||||||
3) Command filtering and pass_level
|
3) A final note
|
||||||
4) A final note
|
|
||||||
|
|
||||||
|
|
||||||
TCM Userspace Design
|
TCM Userspace Design
|
||||||
|
@ -324,7 +323,7 @@ int handle_device_events(int fd, void *map)
|
||||||
/* Process events from cmd ring until we catch up with cmd_head */
|
/* Process events from cmd ring until we catch up with cmd_head */
|
||||||
while (ent != (void *)mb + mb->cmdr_off + mb->cmd_head) {
|
while (ent != (void *)mb + mb->cmdr_off + mb->cmd_head) {
|
||||||
|
|
||||||
if (tcmu_hdr_get_op(&ent->hdr) == TCMU_OP_CMD) {
|
if (tcmu_hdr_get_op(ent->hdr.len_op) == TCMU_OP_CMD) {
|
||||||
uint8_t *cdb = (void *)mb + ent->req.cdb_off;
|
uint8_t *cdb = (void *)mb + ent->req.cdb_off;
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
|
@ -339,8 +338,12 @@ int handle_device_events(int fd, void *map)
|
||||||
ent->rsp.scsi_status = SCSI_CHECK_CONDITION;
|
ent->rsp.scsi_status = SCSI_CHECK_CONDITION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (tcmu_hdr_get_op(ent->hdr.len_op) != TCMU_OP_PAD) {
|
||||||
|
/* Tell the kernel we didn't handle unknown opcodes */
|
||||||
|
ent->hdr.uflags |= TCMU_UFLAG_UNKNOWN_OP;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
/* Do nothing for PAD entries */
|
/* Do nothing for PAD entries except update cmd_tail */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update cmd_tail */
|
/* update cmd_tail */
|
||||||
|
@ -360,28 +363,6 @@ int handle_device_events(int fd, void *map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Command filtering and pass_level
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
TCMU supports a "pass_level" option with valid values of 0 or 1. When
|
|
||||||
the value is 0 (the default), nearly all SCSI commands received for
|
|
||||||
the device are passed through to the handler. This allows maximum
|
|
||||||
flexibility but increases the amount of code required by the handler,
|
|
||||||
to support all mandatory SCSI commands. If pass_level is set to 1,
|
|
||||||
then only IO-related commands are presented, and the rest are handled
|
|
||||||
by LIO's in-kernel command emulation. The commands presented at level
|
|
||||||
1 include all versions of:
|
|
||||||
|
|
||||||
READ
|
|
||||||
WRITE
|
|
||||||
WRITE_VERIFY
|
|
||||||
XDWRITEREAD
|
|
||||||
WRITE_SAME
|
|
||||||
COMPARE_AND_WRITE
|
|
||||||
SYNCHRONIZE_CACHE
|
|
||||||
UNMAP
|
|
||||||
|
|
||||||
|
|
||||||
A final note
|
A final note
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,10 @@ Shadow pages contain the following information:
|
||||||
Contains the value of cr4.smep && !cr0.wp for which the page is valid
|
Contains the value of cr4.smep && !cr0.wp for which the page is valid
|
||||||
(pages for which this is true are different from other pages; see the
|
(pages for which this is true are different from other pages; see the
|
||||||
treatment of cr0.wp=0 below).
|
treatment of cr0.wp=0 below).
|
||||||
|
role.smap_andnot_wp:
|
||||||
|
Contains the value of cr4.smap && !cr0.wp for which the page is valid
|
||||||
|
(pages for which this is true are different from other pages; see the
|
||||||
|
treatment of cr0.wp=0 below).
|
||||||
gfn:
|
gfn:
|
||||||
Either the guest page table containing the translations shadowed by this
|
Either the guest page table containing the translations shadowed by this
|
||||||
page, or the base page frame for linear translations. See role.direct.
|
page, or the base page frame for linear translations. See role.direct.
|
||||||
|
@ -344,10 +348,16 @@ on fault type:
|
||||||
|
|
||||||
(user write faults generate a #PF)
|
(user write faults generate a #PF)
|
||||||
|
|
||||||
In the first case there is an additional complication if CR4.SMEP is
|
In the first case there are two additional complications:
|
||||||
enabled: since we've turned the page into a kernel page, the kernel may now
|
- if CR4.SMEP is enabled: since we've turned the page into a kernel page,
|
||||||
execute it. We handle this by also setting spte.nx. If we get a user
|
the kernel may now execute it. We handle this by also setting spte.nx.
|
||||||
fetch or read fault, we'll change spte.u=1 and spte.nx=gpte.nx back.
|
If we get a user fetch or read fault, we'll change spte.u=1 and
|
||||||
|
spte.nx=gpte.nx back.
|
||||||
|
- if CR4.SMAP is disabled: since the page has been changed to a kernel
|
||||||
|
page, it can not be reused when CR4.SMAP is enabled. We set
|
||||||
|
CR4.SMAP && !CR0.WP into shadow page's role to avoid this case. Note,
|
||||||
|
here we do not care the case that CR4.SMAP is enabled since KVM will
|
||||||
|
directly inject #PF to guest due to failed permission check.
|
||||||
|
|
||||||
To prevent an spte that was converted into a kernel page with cr0.wp=0
|
To prevent an spte that was converted into a kernel page with cr0.wp=0
|
||||||
from being written by the kernel after cr0.wp has changed to 1, we make
|
from being written by the kernel after cr0.wp has changed to 1, we make
|
||||||
|
|
29
MAINTAINERS
29
MAINTAINERS
|
@ -51,9 +51,9 @@ trivial patch so apply some common sense.
|
||||||
or does something very odd once a month document it.
|
or does something very odd once a month document it.
|
||||||
|
|
||||||
PLEASE remember that submissions must be made under the terms
|
PLEASE remember that submissions must be made under the terms
|
||||||
of the OSDL certificate of contribution and should include a
|
of the Linux Foundation certificate of contribution and should
|
||||||
Signed-off-by: line. The current version of this "Developer's
|
include a Signed-off-by: line. The current version of this
|
||||||
Certificate of Origin" (DCO) is listed in the file
|
"Developer's Certificate of Origin" (DCO) is listed in the file
|
||||||
Documentation/SubmittingPatches.
|
Documentation/SubmittingPatches.
|
||||||
|
|
||||||
6. Make sure you have the right to send any changes you make. If you
|
6. Make sure you have the right to send any changes you make. If you
|
||||||
|
@ -2427,7 +2427,6 @@ L: linux-security-module@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: include/linux/capability.h
|
F: include/linux/capability.h
|
||||||
F: include/uapi/linux/capability.h
|
F: include/uapi/linux/capability.h
|
||||||
F: security/capability.c
|
|
||||||
F: security/commoncap.c
|
F: security/commoncap.c
|
||||||
F: kernel/capability.c
|
F: kernel/capability.c
|
||||||
|
|
||||||
|
@ -3825,10 +3824,11 @@ M: David Woodhouse <dwmw2@infradead.org>
|
||||||
L: linux-embedded@vger.kernel.org
|
L: linux-embedded@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
EMULEX LPFC FC SCSI DRIVER
|
EMULEX/AVAGO LPFC FC/FCOE SCSI DRIVER
|
||||||
M: James Smart <james.smart@emulex.com>
|
M: James Smart <james.smart@avagotech.com>
|
||||||
|
M: Dick Kennedy <dick.kennedy@avagotech.com>
|
||||||
L: linux-scsi@vger.kernel.org
|
L: linux-scsi@vger.kernel.org
|
||||||
W: http://sourceforge.net/projects/lpfcxxxx
|
W: http://www.avagotech.com
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/scsi/lpfc/
|
F: drivers/scsi/lpfc/
|
||||||
|
|
||||||
|
@ -4536,7 +4536,7 @@ M: Jean Delvare <jdelvare@suse.de>
|
||||||
M: Guenter Roeck <linux@roeck-us.net>
|
M: Guenter Roeck <linux@roeck-us.net>
|
||||||
L: lm-sensors@lm-sensors.org
|
L: lm-sensors@lm-sensors.org
|
||||||
W: http://www.lm-sensors.org/
|
W: http://www.lm-sensors.org/
|
||||||
T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-hwmon/
|
T: quilt http://jdelvare.nerim.net/devel/linux/jdelvare-hwmon/
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/hwmon/
|
F: Documentation/hwmon/
|
||||||
|
@ -7575,6 +7575,7 @@ F: drivers/pci/host/pci-exynos.c
|
||||||
|
|
||||||
PCI DRIVER FOR SYNOPSIS DESIGNWARE
|
PCI DRIVER FOR SYNOPSIS DESIGNWARE
|
||||||
M: Jingoo Han <jingoohan1@gmail.com>
|
M: Jingoo Han <jingoohan1@gmail.com>
|
||||||
|
M: Pratyush Anand <pratyush.anand@gmail.com>
|
||||||
L: linux-pci@vger.kernel.org
|
L: linux-pci@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/pci/host/*designware*
|
F: drivers/pci/host/*designware*
|
||||||
|
@ -7588,8 +7589,9 @@ F: Documentation/devicetree/bindings/pci/host-generic-pci.txt
|
||||||
F: drivers/pci/host/pci-host-generic.c
|
F: drivers/pci/host/pci-host-generic.c
|
||||||
|
|
||||||
PCIE DRIVER FOR ST SPEAR13XX
|
PCIE DRIVER FOR ST SPEAR13XX
|
||||||
|
M: Pratyush Anand <pratyush.anand@gmail.com>
|
||||||
L: linux-pci@vger.kernel.org
|
L: linux-pci@vger.kernel.org
|
||||||
S: Orphan
|
S: Maintained
|
||||||
F: drivers/pci/host/*spear*
|
F: drivers/pci/host/*spear*
|
||||||
|
|
||||||
PCMCIA SUBSYSTEM
|
PCMCIA SUBSYSTEM
|
||||||
|
@ -8829,9 +8831,11 @@ F: drivers/misc/phantom.c
|
||||||
F: include/uapi/linux/phantom.h
|
F: include/uapi/linux/phantom.h
|
||||||
|
|
||||||
SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
|
SERVER ENGINES 10Gbps iSCSI - BladeEngine 2 DRIVER
|
||||||
M: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
|
M: Jayamohan Kallickal <jayamohan.kallickal@avagotech.com>
|
||||||
|
M: Minh Tran <minh.tran@avagotech.com>
|
||||||
|
M: John Soni Jose <sony.john-n@avagotech.com>
|
||||||
L: linux-scsi@vger.kernel.org
|
L: linux-scsi@vger.kernel.org
|
||||||
W: http://www.emulex.com
|
W: http://www.avagotech.com
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/scsi/be2iscsi/
|
F: drivers/scsi/be2iscsi/
|
||||||
|
|
||||||
|
@ -10594,8 +10598,7 @@ F: drivers/virtio/virtio_input.c
|
||||||
F: include/uapi/linux/virtio_input.h
|
F: include/uapi/linux/virtio_input.h
|
||||||
|
|
||||||
VIA RHINE NETWORK DRIVER
|
VIA RHINE NETWORK DRIVER
|
||||||
M: Roger Luethi <rl@hellgate.ch>
|
S: Orphan
|
||||||
S: Maintained
|
|
||||||
F: drivers/net/ethernet/via/via-rhine.c
|
F: drivers/net/ethernet/via/via-rhine.c
|
||||||
|
|
||||||
VIA SD/MMC CARD CONTROLLER DRIVER
|
VIA SD/MMC CARD CONTROLLER DRIVER
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
||||||
VERSION = 4
|
VERSION = 4
|
||||||
PATCHLEVEL = 1
|
PATCHLEVEL = 1
|
||||||
SUBLEVEL = 0
|
SUBLEVEL = 0
|
||||||
EXTRAVERSION = -rc4
|
EXTRAVERSION = -rc7
|
||||||
NAME = Hurr durr I'ma sheep
|
NAME = Hurr durr I'ma sheep
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
|
|
@ -14,6 +14,9 @@ targets := vmlinux.gz vmlinux \
|
||||||
tools/bootpzh bootloader bootpheader bootpzheader
|
tools/bootpzh bootloader bootpheader bootpzheader
|
||||||
OBJSTRIP := $(obj)/tools/objstrip
|
OBJSTRIP := $(obj)/tools/objstrip
|
||||||
|
|
||||||
|
HOSTCFLAGS := -Wall -I$(objtree)/usr/include
|
||||||
|
BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj)
|
||||||
|
|
||||||
# SRM bootable image. Copy to offset 512 of a partition.
|
# SRM bootable image. Copy to offset 512 of a partition.
|
||||||
$(obj)/bootimage: $(addprefix $(obj)/tools/,mkbb lxboot bootlx) $(obj)/vmlinux.nh
|
$(obj)/bootimage: $(addprefix $(obj)/tools/,mkbb lxboot bootlx) $(obj)/vmlinux.nh
|
||||||
( cat $(obj)/tools/lxboot $(obj)/tools/bootlx $(obj)/vmlinux.nh ) > $@
|
( cat $(obj)/tools/lxboot $(obj)/tools/bootlx $(obj)/vmlinux.nh ) > $@
|
||||||
|
@ -96,13 +99,14 @@ $(obj)/tools/bootph: $(obj)/bootpheader $(OBJSTRIP) FORCE
|
||||||
$(obj)/tools/bootpzh: $(obj)/bootpzheader $(OBJSTRIP) FORCE
|
$(obj)/tools/bootpzh: $(obj)/bootpzheader $(OBJSTRIP) FORCE
|
||||||
$(call if_changed,objstrip)
|
$(call if_changed,objstrip)
|
||||||
|
|
||||||
LDFLAGS_bootloader := -static -uvsprintf -T #-N -relax
|
LDFLAGS_bootloader := -static -T # -N -relax
|
||||||
LDFLAGS_bootpheader := -static -uvsprintf -T #-N -relax
|
LDFLAGS_bootloader := -static -T # -N -relax
|
||||||
LDFLAGS_bootpzheader := -static -uvsprintf -T #-N -relax
|
LDFLAGS_bootpheader := -static -T # -N -relax
|
||||||
|
LDFLAGS_bootpzheader := -static -T # -N -relax
|
||||||
|
|
||||||
OBJ_bootlx := $(obj)/head.o $(obj)/main.o
|
OBJ_bootlx := $(obj)/head.o $(obj)/stdio.o $(obj)/main.o
|
||||||
OBJ_bootph := $(obj)/head.o $(obj)/bootp.o
|
OBJ_bootph := $(obj)/head.o $(obj)/stdio.o $(obj)/bootp.o
|
||||||
OBJ_bootpzh := $(obj)/head.o $(obj)/bootpz.o $(obj)/misc.o
|
OBJ_bootpzh := $(obj)/head.o $(obj)/stdio.o $(obj)/bootpz.o $(obj)/misc.o
|
||||||
|
|
||||||
$(obj)/bootloader: $(obj)/bootloader.lds $(OBJ_bootlx) $(LIBS_Y) FORCE
|
$(obj)/bootloader: $(obj)/bootloader.lds $(OBJ_bootlx) $(LIBS_Y) FORCE
|
||||||
$(call if_changed,ld)
|
$(call if_changed,ld)
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
#include "ksize.h"
|
#include "ksize.h"
|
||||||
|
|
||||||
extern int vsprintf(char *, const char *, va_list);
|
|
||||||
extern unsigned long switch_to_osf_pal(unsigned long nr,
|
extern unsigned long switch_to_osf_pal(unsigned long nr,
|
||||||
struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
|
struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
|
||||||
unsigned long *vptb);
|
unsigned long *vptb);
|
||||||
|
|
|
@ -0,0 +1,306 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) Paul Mackerras 1997.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version
|
||||||
|
* 2 of the License, or (at your option) any later version.
|
||||||
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
size_t strnlen(const char * s, size_t count)
|
||||||
|
{
|
||||||
|
const char *sc;
|
||||||
|
|
||||||
|
for (sc = s; count-- && *sc != '\0'; ++sc)
|
||||||
|
/* nothing */;
|
||||||
|
return sc - s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# define do_div(n, base) ({ \
|
||||||
|
unsigned int __base = (base); \
|
||||||
|
unsigned int __rem; \
|
||||||
|
__rem = ((unsigned long long)(n)) % __base; \
|
||||||
|
(n) = ((unsigned long long)(n)) / __base; \
|
||||||
|
__rem; \
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
static int skip_atoi(const char **s)
|
||||||
|
{
|
||||||
|
int i, c;
|
||||||
|
|
||||||
|
for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
|
||||||
|
i = i*10 + c - '0';
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ZEROPAD 1 /* pad with zero */
|
||||||
|
#define SIGN 2 /* unsigned/signed long */
|
||||||
|
#define PLUS 4 /* show plus */
|
||||||
|
#define SPACE 8 /* space if plus */
|
||||||
|
#define LEFT 16 /* left justified */
|
||||||
|
#define SPECIAL 32 /* 0x */
|
||||||
|
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
|
||||||
|
|
||||||
|
static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
|
||||||
|
{
|
||||||
|
char c,sign,tmp[66];
|
||||||
|
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (type & LARGE)
|
||||||
|
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
if (type & LEFT)
|
||||||
|
type &= ~ZEROPAD;
|
||||||
|
if (base < 2 || base > 36)
|
||||||
|
return 0;
|
||||||
|
c = (type & ZEROPAD) ? '0' : ' ';
|
||||||
|
sign = 0;
|
||||||
|
if (type & SIGN) {
|
||||||
|
if ((signed long long)num < 0) {
|
||||||
|
sign = '-';
|
||||||
|
num = - (signed long long)num;
|
||||||
|
size--;
|
||||||
|
} else if (type & PLUS) {
|
||||||
|
sign = '+';
|
||||||
|
size--;
|
||||||
|
} else if (type & SPACE) {
|
||||||
|
sign = ' ';
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type & SPECIAL) {
|
||||||
|
if (base == 16)
|
||||||
|
size -= 2;
|
||||||
|
else if (base == 8)
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
if (num == 0)
|
||||||
|
tmp[i++]='0';
|
||||||
|
else while (num != 0) {
|
||||||
|
tmp[i++] = digits[do_div(num, base)];
|
||||||
|
}
|
||||||
|
if (i > precision)
|
||||||
|
precision = i;
|
||||||
|
size -= precision;
|
||||||
|
if (!(type&(ZEROPAD+LEFT)))
|
||||||
|
while(size-->0)
|
||||||
|
*str++ = ' ';
|
||||||
|
if (sign)
|
||||||
|
*str++ = sign;
|
||||||
|
if (type & SPECIAL) {
|
||||||
|
if (base==8)
|
||||||
|
*str++ = '0';
|
||||||
|
else if (base==16) {
|
||||||
|
*str++ = '0';
|
||||||
|
*str++ = digits[33];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(type & LEFT))
|
||||||
|
while (size-- > 0)
|
||||||
|
*str++ = c;
|
||||||
|
while (i < precision--)
|
||||||
|
*str++ = '0';
|
||||||
|
while (i-- > 0)
|
||||||
|
*str++ = tmp[i];
|
||||||
|
while (size-- > 0)
|
||||||
|
*str++ = ' ';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vsprintf(char *buf, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
unsigned long long num;
|
||||||
|
int i, base;
|
||||||
|
char * str;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
int flags; /* flags to number() */
|
||||||
|
|
||||||
|
int field_width; /* width of output field */
|
||||||
|
int precision; /* min. # of digits for integers; max
|
||||||
|
number of chars for from string */
|
||||||
|
int qualifier; /* 'h', 'l', or 'L' for integer fields */
|
||||||
|
/* 'z' support added 23/7/1999 S.H. */
|
||||||
|
/* 'z' changed to 'Z' --davidm 1/25/99 */
|
||||||
|
|
||||||
|
|
||||||
|
for (str=buf ; *fmt ; ++fmt) {
|
||||||
|
if (*fmt != '%') {
|
||||||
|
*str++ = *fmt;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process flags */
|
||||||
|
flags = 0;
|
||||||
|
repeat:
|
||||||
|
++fmt; /* this also skips first '%' */
|
||||||
|
switch (*fmt) {
|
||||||
|
case '-': flags |= LEFT; goto repeat;
|
||||||
|
case '+': flags |= PLUS; goto repeat;
|
||||||
|
case ' ': flags |= SPACE; goto repeat;
|
||||||
|
case '#': flags |= SPECIAL; goto repeat;
|
||||||
|
case '0': flags |= ZEROPAD; goto repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get field width */
|
||||||
|
field_width = -1;
|
||||||
|
if ('0' <= *fmt && *fmt <= '9')
|
||||||
|
field_width = skip_atoi(&fmt);
|
||||||
|
else if (*fmt == '*') {
|
||||||
|
++fmt;
|
||||||
|
/* it's the next argument */
|
||||||
|
field_width = va_arg(args, int);
|
||||||
|
if (field_width < 0) {
|
||||||
|
field_width = -field_width;
|
||||||
|
flags |= LEFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the precision */
|
||||||
|
precision = -1;
|
||||||
|
if (*fmt == '.') {
|
||||||
|
++fmt;
|
||||||
|
if ('0' <= *fmt && *fmt <= '9')
|
||||||
|
precision = skip_atoi(&fmt);
|
||||||
|
else if (*fmt == '*') {
|
||||||
|
++fmt;
|
||||||
|
/* it's the next argument */
|
||||||
|
precision = va_arg(args, int);
|
||||||
|
}
|
||||||
|
if (precision < 0)
|
||||||
|
precision = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the conversion qualifier */
|
||||||
|
qualifier = -1;
|
||||||
|
if (*fmt == 'l' && *(fmt + 1) == 'l') {
|
||||||
|
qualifier = 'q';
|
||||||
|
fmt += 2;
|
||||||
|
} else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L'
|
||||||
|
|| *fmt == 'Z') {
|
||||||
|
qualifier = *fmt;
|
||||||
|
++fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default base */
|
||||||
|
base = 10;
|
||||||
|
|
||||||
|
switch (*fmt) {
|
||||||
|
case 'c':
|
||||||
|
if (!(flags & LEFT))
|
||||||
|
while (--field_width > 0)
|
||||||
|
*str++ = ' ';
|
||||||
|
*str++ = (unsigned char) va_arg(args, int);
|
||||||
|
while (--field_width > 0)
|
||||||
|
*str++ = ' ';
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
s = va_arg(args, char *);
|
||||||
|
if (!s)
|
||||||
|
s = "<NULL>";
|
||||||
|
|
||||||
|
len = strnlen(s, precision);
|
||||||
|
|
||||||
|
if (!(flags & LEFT))
|
||||||
|
while (len < field_width--)
|
||||||
|
*str++ = ' ';
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
*str++ = *s++;
|
||||||
|
while (len < field_width--)
|
||||||
|
*str++ = ' ';
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
if (field_width == -1) {
|
||||||
|
field_width = 2*sizeof(void *);
|
||||||
|
flags |= ZEROPAD;
|
||||||
|
}
|
||||||
|
str = number(str,
|
||||||
|
(unsigned long) va_arg(args, void *), 16,
|
||||||
|
field_width, precision, flags);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
if (qualifier == 'l') {
|
||||||
|
long * ip = va_arg(args, long *);
|
||||||
|
*ip = (str - buf);
|
||||||
|
} else if (qualifier == 'Z') {
|
||||||
|
size_t * ip = va_arg(args, size_t *);
|
||||||
|
*ip = (str - buf);
|
||||||
|
} else {
|
||||||
|
int * ip = va_arg(args, int *);
|
||||||
|
*ip = (str - buf);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
*str++ = '%';
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* integer number formats - set up the flags and "break" */
|
||||||
|
case 'o':
|
||||||
|
base = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
flags |= LARGE;
|
||||||
|
case 'x':
|
||||||
|
base = 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
case 'i':
|
||||||
|
flags |= SIGN;
|
||||||
|
case 'u':
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*str++ = '%';
|
||||||
|
if (*fmt)
|
||||||
|
*str++ = *fmt;
|
||||||
|
else
|
||||||
|
--fmt;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (qualifier == 'l') {
|
||||||
|
num = va_arg(args, unsigned long);
|
||||||
|
if (flags & SIGN)
|
||||||
|
num = (signed long) num;
|
||||||
|
} else if (qualifier == 'q') {
|
||||||
|
num = va_arg(args, unsigned long long);
|
||||||
|
if (flags & SIGN)
|
||||||
|
num = (signed long long) num;
|
||||||
|
} else if (qualifier == 'Z') {
|
||||||
|
num = va_arg(args, size_t);
|
||||||
|
} else if (qualifier == 'h') {
|
||||||
|
num = (unsigned short) va_arg(args, int);
|
||||||
|
if (flags & SIGN)
|
||||||
|
num = (signed short) num;
|
||||||
|
} else {
|
||||||
|
num = va_arg(args, unsigned int);
|
||||||
|
if (flags & SIGN)
|
||||||
|
num = (signed int) num;
|
||||||
|
}
|
||||||
|
str = number(str, num, base, field_width, precision, flags);
|
||||||
|
}
|
||||||
|
*str = '\0';
|
||||||
|
return str-buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sprintf(char * buf, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
i=vsprintf(buf,fmt,args);
|
||||||
|
va_end(args);
|
||||||
|
return i;
|
||||||
|
}
|
|
@ -27,6 +27,9 @@
|
||||||
#include <linux/param.h>
|
#include <linux/param.h>
|
||||||
#ifdef __ELF__
|
#ifdef __ELF__
|
||||||
# include <linux/elf.h>
|
# include <linux/elf.h>
|
||||||
|
# define elfhdr elf64_hdr
|
||||||
|
# define elf_phdr elf64_phdr
|
||||||
|
# define elf_check_arch(x) ((x)->e_machine == EM_ALPHA)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* bootfile size must be multiple of BLOCK_SIZE: */
|
/* bootfile size must be multiple of BLOCK_SIZE: */
|
||||||
|
|
|
@ -2,6 +2,5 @@
|
||||||
#define _ALPHA_TYPES_H
|
#define _ALPHA_TYPES_H
|
||||||
|
|
||||||
#include <asm-generic/int-ll64.h>
|
#include <asm-generic/int-ll64.h>
|
||||||
#include <uapi/asm/types.h>
|
|
||||||
|
|
||||||
#endif /* _ALPHA_TYPES_H */
|
#endif /* _ALPHA_TYPES_H */
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <uapi/asm/unistd.h>
|
#include <uapi/asm/unistd.h>
|
||||||
|
|
||||||
#define NR_SYSCALLS 511
|
#define NR_SYSCALLS 514
|
||||||
|
|
||||||
#define __ARCH_WANT_OLD_READDIR
|
#define __ARCH_WANT_OLD_READDIR
|
||||||
#define __ARCH_WANT_STAT64
|
#define __ARCH_WANT_STAT64
|
||||||
|
|
|
@ -472,5 +472,8 @@
|
||||||
#define __NR_sched_setattr 508
|
#define __NR_sched_setattr 508
|
||||||
#define __NR_sched_getattr 509
|
#define __NR_sched_getattr 509
|
||||||
#define __NR_renameat2 510
|
#define __NR_renameat2 510
|
||||||
|
#define __NR_getrandom 511
|
||||||
|
#define __NR_memfd_create 512
|
||||||
|
#define __NR_execveat 513
|
||||||
|
|
||||||
#endif /* _UAPI_ALPHA_UNISTD_H */
|
#endif /* _UAPI_ALPHA_UNISTD_H */
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
* Error handling code supporting Alpha systems
|
* Error handling code supporting Alpha systems
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
|
|
|
@ -1019,14 +1019,13 @@ SYSCALL_DEFINE2(osf_settimeofday, struct timeval32 __user *, tv,
|
||||||
if (tv) {
|
if (tv) {
|
||||||
if (get_tv32((struct timeval *)&kts, tv))
|
if (get_tv32((struct timeval *)&kts, tv))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
kts.tv_nsec *= 1000;
|
||||||
}
|
}
|
||||||
if (tz) {
|
if (tz) {
|
||||||
if (copy_from_user(&ktz, tz, sizeof(*tz)))
|
if (copy_from_user(&ktz, tz, sizeof(*tz)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
kts.tv_nsec *= 1000;
|
|
||||||
|
|
||||||
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
|
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -236,12 +236,11 @@ release_thread(struct task_struct *dead_task)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy an alpha thread..
|
* Copy architecture-specific thread state
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
copy_thread(unsigned long clone_flags, unsigned long usp,
|
copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||||
unsigned long arg,
|
unsigned long kthread_arg,
|
||||||
struct task_struct *p)
|
struct task_struct *p)
|
||||||
{
|
{
|
||||||
extern void ret_from_fork(void);
|
extern void ret_from_fork(void);
|
||||||
|
@ -262,7 +261,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||||
sizeof(struct switch_stack) + sizeof(struct pt_regs));
|
sizeof(struct switch_stack) + sizeof(struct pt_regs));
|
||||||
childstack->r26 = (unsigned long) ret_from_kernel_thread;
|
childstack->r26 = (unsigned long) ret_from_kernel_thread;
|
||||||
childstack->r9 = usp; /* function */
|
childstack->r9 = usp; /* function */
|
||||||
childstack->r10 = arg;
|
childstack->r10 = kthread_arg;
|
||||||
childregs->hae = alpha_mv.hae_cache,
|
childregs->hae = alpha_mv.hae_cache,
|
||||||
childti->pcb.usp = 0;
|
childti->pcb.usp = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -63,7 +63,6 @@ static struct {
|
||||||
enum ipi_message_type {
|
enum ipi_message_type {
|
||||||
IPI_RESCHEDULE,
|
IPI_RESCHEDULE,
|
||||||
IPI_CALL_FUNC,
|
IPI_CALL_FUNC,
|
||||||
IPI_CALL_FUNC_SINGLE,
|
|
||||||
IPI_CPU_STOP,
|
IPI_CPU_STOP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -506,7 +505,6 @@ setup_profiling_timer(unsigned int multiplier)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
|
send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
|
||||||
{
|
{
|
||||||
|
@ -552,10 +550,6 @@ handle_ipi(struct pt_regs *regs)
|
||||||
generic_smp_call_function_interrupt();
|
generic_smp_call_function_interrupt();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IPI_CALL_FUNC_SINGLE:
|
|
||||||
generic_smp_call_function_single_interrupt();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IPI_CPU_STOP:
|
case IPI_CPU_STOP:
|
||||||
halt();
|
halt();
|
||||||
|
|
||||||
|
@ -606,7 +600,7 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask)
|
||||||
|
|
||||||
void arch_send_call_function_single_ipi(int cpu)
|
void arch_send_call_function_single_ipi(int cpu)
|
||||||
{
|
{
|
||||||
send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
|
send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -237,8 +237,7 @@ srmcons_init(void)
|
||||||
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
device_initcall(srmcons_init);
|
||||||
module_init(srmcons_init);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -331,7 +331,7 @@ marvel_map_irq(const struct pci_dev *cdev, u8 slot, u8 pin)
|
||||||
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
|
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
|
||||||
irq = intline;
|
irq = intline;
|
||||||
|
|
||||||
msi_loc = pci_find_capability(dev, PCI_CAP_ID_MSI);
|
msi_loc = dev->msi_cap;
|
||||||
msg_ctl = 0;
|
msg_ctl = 0;
|
||||||
if (msi_loc)
|
if (msi_loc)
|
||||||
pci_read_config_word(dev, msi_loc + PCI_MSI_FLAGS, &msg_ctl);
|
pci_read_config_word(dev, msi_loc + PCI_MSI_FLAGS, &msg_ctl);
|
||||||
|
|
|
@ -529,6 +529,9 @@ sys_call_table:
|
||||||
.quad sys_sched_setattr
|
.quad sys_sched_setattr
|
||||||
.quad sys_sched_getattr
|
.quad sys_sched_getattr
|
||||||
.quad sys_renameat2 /* 510 */
|
.quad sys_renameat2 /* 510 */
|
||||||
|
.quad sys_getrandom
|
||||||
|
.quad sys_memfd_create
|
||||||
|
.quad sys_execveat
|
||||||
|
|
||||||
.size sys_call_table, . - sys_call_table
|
.size sys_call_table, . - sys_call_table
|
||||||
.type sys_call_table, @object
|
.type sys_call_table, @object
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/kallsyms.h>
|
#include <linux/kallsyms.h>
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/oprofile.h>
|
#include <linux/oprofile.h>
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/oprofile.h>
|
#include <linux/oprofile.h>
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/oprofile.h>
|
#include <linux/oprofile.h>
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/oprofile.h>
|
#include <linux/oprofile.h>
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,7 @@ dtb-$(CONFIG_SOC_IMX25) += \
|
||||||
imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dtb \
|
imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dtb \
|
||||||
imx25-karo-tx25.dtb \
|
imx25-karo-tx25.dtb \
|
||||||
imx25-pdk.dtb
|
imx25-pdk.dtb
|
||||||
dtb-$(CONFIG_SOC_IMX31) += \
|
dtb-$(CONFIG_SOC_IMX27) += \
|
||||||
imx27-apf27.dtb \
|
imx27-apf27.dtb \
|
||||||
imx27-apf27dev.dtb \
|
imx27-apf27dev.dtb \
|
||||||
imx27-eukrea-mbimxsd27-baseboard.dtb \
|
imx27-eukrea-mbimxsd27-baseboard.dtb \
|
||||||
|
|
|
@ -80,7 +80,3 @@
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
&rtc {
|
|
||||||
system-power-controller;
|
|
||||||
};
|
|
||||||
|
|
|
@ -654,7 +654,7 @@
|
||||||
wlcore: wlcore@2 {
|
wlcore: wlcore@2 {
|
||||||
compatible = "ti,wl1271";
|
compatible = "ti,wl1271";
|
||||||
reg = <2>;
|
reg = <2>;
|
||||||
interrupt-parent = <&gpio1>;
|
interrupt-parent = <&gpio0>;
|
||||||
interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; /* gpio 31 */
|
interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; /* gpio 31 */
|
||||||
ref-clock-frequency = <38400000>;
|
ref-clock-frequency = <38400000>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -736,7 +736,7 @@
|
||||||
|
|
||||||
display-timings {
|
display-timings {
|
||||||
timing-0 {
|
timing-0 {
|
||||||
clock-frequency = <0>;
|
clock-frequency = <57153600>;
|
||||||
hactive = <720>;
|
hactive = <720>;
|
||||||
vactive = <1280>;
|
vactive = <1280>;
|
||||||
hfront-porch = <5>;
|
hfront-porch = <5>;
|
||||||
|
|
|
@ -533,7 +533,7 @@
|
||||||
|
|
||||||
fec: ethernet@1002b000 {
|
fec: ethernet@1002b000 {
|
||||||
compatible = "fsl,imx27-fec";
|
compatible = "fsl,imx27-fec";
|
||||||
reg = <0x1002b000 0x4000>;
|
reg = <0x1002b000 0x1000>;
|
||||||
interrupts = <50>;
|
interrupts = <50>;
|
||||||
clocks = <&clks IMX27_CLK_FEC_IPG_GATE>,
|
clocks = <&clks IMX27_CLK_FEC_IPG_GATE>,
|
||||||
<&clks IMX27_CLK_FEC_AHB_GATE>;
|
<&clks IMX27_CLK_FEC_AHB_GATE>;
|
||||||
|
|
|
@ -110,6 +110,8 @@
|
||||||
nand@0,0 {
|
nand@0,0 {
|
||||||
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
|
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
|
||||||
nand-bus-width = <16>;
|
nand-bus-width = <16>;
|
||||||
|
gpmc,device-width = <2>;
|
||||||
|
ti,nand-ecc-opt = "sw";
|
||||||
|
|
||||||
gpmc,sync-clk-ps = <0>;
|
gpmc,sync-clk-ps = <0>;
|
||||||
gpmc,cs-on-ns = <0>;
|
gpmc,cs-on-ns = <0>;
|
||||||
|
|
|
@ -193,7 +193,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
gem0: ethernet@e000b000 {
|
gem0: ethernet@e000b000 {
|
||||||
compatible = "cdns,gem";
|
compatible = "cdns,zynq-gem";
|
||||||
reg = <0xe000b000 0x1000>;
|
reg = <0xe000b000 0x1000>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
interrupts = <0 22 4>;
|
interrupts = <0 22 4>;
|
||||||
|
@ -204,7 +204,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
gem1: ethernet@e000c000 {
|
gem1: ethernet@e000c000 {
|
||||||
compatible = "cdns,gem";
|
compatible = "cdns,zynq-gem";
|
||||||
reg = <0xe000c000 0x1000>;
|
reg = <0xe000c000 0x1000>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
interrupts = <0 45 4>;
|
interrupts = <0 45 4>;
|
||||||
|
|
|
@ -429,7 +429,7 @@ CONFIG_USB_EHCI_EXYNOS=y
|
||||||
CONFIG_USB_EHCI_TEGRA=y
|
CONFIG_USB_EHCI_TEGRA=y
|
||||||
CONFIG_USB_EHCI_HCD_STI=y
|
CONFIG_USB_EHCI_HCD_STI=y
|
||||||
CONFIG_USB_EHCI_HCD_PLATFORM=y
|
CONFIG_USB_EHCI_HCD_PLATFORM=y
|
||||||
CONFIG_USB_ISP1760_HCD=y
|
CONFIG_USB_ISP1760=y
|
||||||
CONFIG_USB_OHCI_HCD=y
|
CONFIG_USB_OHCI_HCD=y
|
||||||
CONFIG_USB_OHCI_HCD_STI=y
|
CONFIG_USB_OHCI_HCD_STI=y
|
||||||
CONFIG_USB_OHCI_HCD_PLATFORM=y
|
CONFIG_USB_OHCI_HCD_PLATFORM=y
|
||||||
|
|
|
@ -33,7 +33,9 @@ ret_fast_syscall:
|
||||||
UNWIND(.fnstart )
|
UNWIND(.fnstart )
|
||||||
UNWIND(.cantunwind )
|
UNWIND(.cantunwind )
|
||||||
disable_irq @ disable interrupts
|
disable_irq @ disable interrupts
|
||||||
ldr r1, [tsk, #TI_FLAGS]
|
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
|
||||||
|
tst r1, #_TIF_SYSCALL_WORK
|
||||||
|
bne __sys_trace_return
|
||||||
tst r1, #_TIF_WORK_MASK
|
tst r1, #_TIF_WORK_MASK
|
||||||
bne fast_work_pending
|
bne fast_work_pending
|
||||||
asm_trace_hardirqs_on
|
asm_trace_hardirqs_on
|
||||||
|
|
|
@ -304,16 +304,17 @@ static int probe_current_pmu(struct arm_pmu *pmu)
|
||||||
static int of_pmu_irq_cfg(struct platform_device *pdev)
|
static int of_pmu_irq_cfg(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int i, irq;
|
int i, irq;
|
||||||
int *irqs = kcalloc(pdev->num_resources, sizeof(*irqs), GFP_KERNEL);
|
int *irqs;
|
||||||
|
|
||||||
if (!irqs)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* Don't bother with PPIs; they're already affine */
|
/* Don't bother with PPIs; they're already affine */
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq >= 0 && irq_is_percpu(irq))
|
if (irq >= 0 && irq_is_percpu(irq))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
irqs = kcalloc(pdev->num_resources, sizeof(*irqs), GFP_KERNEL);
|
||||||
|
if (!irqs)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < pdev->num_resources; ++i) {
|
for (i = 0; i < pdev->num_resources; ++i) {
|
||||||
struct device_node *dn;
|
struct device_node *dn;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
|
@ -280,9 +280,15 @@ void __init imx_gpc_check_dt(void)
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
|
||||||
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
|
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
|
||||||
if (WARN_ON(!np ||
|
if (WARN_ON(!np))
|
||||||
!of_find_property(np, "interrupt-controller", NULL)))
|
return;
|
||||||
pr_warn("Outdated DT detected, system is about to crash!!!\n");
|
|
||||||
|
if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {
|
||||||
|
pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
|
||||||
|
|
||||||
|
/* map GPC, so that at least CPUidle and WARs keep working */
|
||||||
|
gpc_base = of_iomap(np, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_GENERIC_DOMAINS
|
#ifdef CONFIG_PM_GENERIC_DOMAINS
|
||||||
|
@ -443,6 +449,10 @@ static int imx_gpc_probe(struct platform_device *pdev)
|
||||||
struct regulator *pu_reg;
|
struct regulator *pu_reg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* bail out if DT too old and doesn't provide the necessary info */
|
||||||
|
if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
pu_reg = devm_regulator_get_optional(&pdev->dev, "pu");
|
pu_reg = devm_regulator_get_optional(&pdev->dev, "pu");
|
||||||
if (PTR_ERR(pu_reg) == -ENODEV)
|
if (PTR_ERR(pu_reg) == -ENODEV)
|
||||||
pu_reg = NULL;
|
pu_reg = NULL;
|
||||||
|
|
|
@ -107,7 +107,7 @@ static int cplds_probe(struct platform_device *pdev)
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
struct cplds *fpga;
|
struct cplds *fpga;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int base_irq = 0;
|
int base_irq;
|
||||||
unsigned long irqflags = 0;
|
unsigned long irqflags = 0;
|
||||||
|
|
||||||
fpga = devm_kzalloc(&pdev->dev, sizeof(*fpga), GFP_KERNEL);
|
fpga = devm_kzalloc(&pdev->dev, sizeof(*fpga), GFP_KERNEL);
|
||||||
|
|
|
@ -1112,22 +1112,22 @@ void __init sanity_check_meminfo(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the first non-section-aligned page, and point
|
* Find the first non-pmd-aligned page, and point
|
||||||
* memblock_limit at it. This relies on rounding the
|
* memblock_limit at it. This relies on rounding the
|
||||||
* limit down to be section-aligned, which happens at
|
* limit down to be pmd-aligned, which happens at the
|
||||||
* the end of this function.
|
* end of this function.
|
||||||
*
|
*
|
||||||
* With this algorithm, the start or end of almost any
|
* With this algorithm, the start or end of almost any
|
||||||
* bank can be non-section-aligned. The only exception
|
* bank can be non-pmd-aligned. The only exception is
|
||||||
* is that the start of the bank 0 must be section-
|
* that the start of the bank 0 must be section-
|
||||||
* aligned, since otherwise memory would need to be
|
* aligned, since otherwise memory would need to be
|
||||||
* allocated when mapping the start of bank 0, which
|
* allocated when mapping the start of bank 0, which
|
||||||
* occurs before any free memory is mapped.
|
* occurs before any free memory is mapped.
|
||||||
*/
|
*/
|
||||||
if (!memblock_limit) {
|
if (!memblock_limit) {
|
||||||
if (!IS_ALIGNED(block_start, SECTION_SIZE))
|
if (!IS_ALIGNED(block_start, PMD_SIZE))
|
||||||
memblock_limit = block_start;
|
memblock_limit = block_start;
|
||||||
else if (!IS_ALIGNED(block_end, SECTION_SIZE))
|
else if (!IS_ALIGNED(block_end, PMD_SIZE))
|
||||||
memblock_limit = arm_lowmem_limit;
|
memblock_limit = arm_lowmem_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1137,12 +1137,12 @@ void __init sanity_check_meminfo(void)
|
||||||
high_memory = __va(arm_lowmem_limit - 1) + 1;
|
high_memory = __va(arm_lowmem_limit - 1) + 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Round the memblock limit down to a section size. This
|
* Round the memblock limit down to a pmd size. This
|
||||||
* helps to ensure that we will allocate memory from the
|
* helps to ensure that we will allocate memory from the
|
||||||
* last full section, which should be mapped.
|
* last full pmd, which should be mapped.
|
||||||
*/
|
*/
|
||||||
if (memblock_limit)
|
if (memblock_limit)
|
||||||
memblock_limit = round_down(memblock_limit, SECTION_SIZE);
|
memblock_limit = round_down(memblock_limit, PMD_SIZE);
|
||||||
if (!memblock_limit)
|
if (!memblock_limit)
|
||||||
memblock_limit = arm_lowmem_limit;
|
memblock_limit = arm_lowmem_limit;
|
||||||
|
|
||||||
|
|
|
@ -272,6 +272,7 @@ void xen_arch_pre_suspend(void) { }
|
||||||
void xen_arch_post_suspend(int suspend_cancelled) { }
|
void xen_arch_post_suspend(int suspend_cancelled) { }
|
||||||
void xen_timer_resume(void) { }
|
void xen_timer_resume(void) { }
|
||||||
void xen_arch_resume(void) { }
|
void xen_arch_resume(void) { }
|
||||||
|
void xen_arch_suspend(void) { }
|
||||||
|
|
||||||
|
|
||||||
/* In the hypervisor.S file. */
|
/* In the hypervisor.S file. */
|
||||||
|
|
|
@ -127,7 +127,7 @@ int smp_num_siblings = 1;
|
||||||
volatile int ia64_cpu_to_sapicid[NR_CPUS];
|
volatile int ia64_cpu_to_sapicid[NR_CPUS];
|
||||||
EXPORT_SYMBOL(ia64_cpu_to_sapicid);
|
EXPORT_SYMBOL(ia64_cpu_to_sapicid);
|
||||||
|
|
||||||
static volatile cpumask_t cpu_callin_map;
|
static cpumask_t cpu_callin_map;
|
||||||
|
|
||||||
struct smp_boot_data smp_boot_data __initdata;
|
struct smp_boot_data smp_boot_data __initdata;
|
||||||
|
|
||||||
|
@ -477,6 +477,7 @@ do_boot_cpu (int sapicid, int cpu, struct task_struct *idle)
|
||||||
for (timeout = 0; timeout < 100000; timeout++) {
|
for (timeout = 0; timeout < 100000; timeout++) {
|
||||||
if (cpumask_test_cpu(cpu, &cpu_callin_map))
|
if (cpumask_test_cpu(cpu, &cpu_callin_map))
|
||||||
break; /* It has booted */
|
break; /* It has booted */
|
||||||
|
barrier(); /* Make sure we re-read cpu_callin_map */
|
||||||
udelay(100);
|
udelay(100);
|
||||||
}
|
}
|
||||||
Dprintk("\n");
|
Dprintk("\n");
|
||||||
|
|
|
@ -478,9 +478,16 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||||
|
|
||||||
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
|
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
|
||||||
{
|
{
|
||||||
struct pci_controller *controller = bridge->bus->sysdata;
|
/*
|
||||||
|
* We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
|
||||||
ACPI_COMPANION_SET(&bridge->dev, controller->companion);
|
* here, pci_create_root_bus() has been called by someone else and
|
||||||
|
* sysdata is likely to be different from what we expect. Let it go in
|
||||||
|
* that case.
|
||||||
|
*/
|
||||||
|
if (!bridge->dev.parent) {
|
||||||
|
struct pci_controller *controller = bridge->bus->sysdata;
|
||||||
|
ACPI_COMPANION_SET(&bridge->dev, controller->companion);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Atheros AR71XX/AR724X/AR913X specific prom routines
|
* Atheros AR71XX/AR724X/AR913X specific prom routines
|
||||||
*
|
*
|
||||||
|
* Copyright (C) 2015 Laurent Fasnacht <l@libres.ch>
|
||||||
* Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
|
* Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
|
||||||
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
|
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
|
||||||
*
|
*
|
||||||
|
@ -25,12 +26,14 @@ void __init prom_init(void)
|
||||||
{
|
{
|
||||||
fw_init_cmdline();
|
fw_init_cmdline();
|
||||||
|
|
||||||
|
#ifdef CONFIG_BLK_DEV_INITRD
|
||||||
/* Read the initrd address from the firmware environment */
|
/* Read the initrd address from the firmware environment */
|
||||||
initrd_start = fw_getenvl("initrd_start");
|
initrd_start = fw_getenvl("initrd_start");
|
||||||
if (initrd_start) {
|
if (initrd_start) {
|
||||||
initrd_start = KSEG0ADDR(initrd_start);
|
initrd_start = KSEG0ADDR(initrd_start);
|
||||||
initrd_end = initrd_start + fw_getenvl("initrd_size");
|
initrd_end = initrd_start + fw_getenvl("initrd_size");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init prom_free_prom_memory(void)
|
void __init prom_free_prom_memory(void)
|
||||||
|
|
|
@ -225,7 +225,7 @@ void __init plat_time_init(void)
|
||||||
ddr_clk_rate = ath79_get_sys_clk_rate("ddr");
|
ddr_clk_rate = ath79_get_sys_clk_rate("ddr");
|
||||||
ref_clk_rate = ath79_get_sys_clk_rate("ref");
|
ref_clk_rate = ath79_get_sys_clk_rate("ref");
|
||||||
|
|
||||||
pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, Ref:%lu.%03luMHz",
|
pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, Ref:%lu.%03luMHz\n",
|
||||||
cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000,
|
cpu_clk_rate / 1000000, (cpu_clk_rate / 1000) % 1000,
|
||||||
ddr_clk_rate / 1000000, (ddr_clk_rate / 1000) % 1000,
|
ddr_clk_rate / 1000000, (ddr_clk_rate / 1000) % 1000,
|
||||||
ahb_clk_rate / 1000000, (ahb_clk_rate / 1000) % 1000,
|
ahb_clk_rate / 1000000, (ahb_clk_rate / 1000) % 1000,
|
||||||
|
|
|
@ -194,7 +194,7 @@ CONFIG_USB_WUSB_CBAF=m
|
||||||
CONFIG_USB_C67X00_HCD=m
|
CONFIG_USB_C67X00_HCD=m
|
||||||
CONFIG_USB_EHCI_HCD=y
|
CONFIG_USB_EHCI_HCD=y
|
||||||
CONFIG_USB_EHCI_ROOT_HUB_TT=y
|
CONFIG_USB_EHCI_ROOT_HUB_TT=y
|
||||||
CONFIG_USB_ISP1760_HCD=m
|
CONFIG_USB_ISP1760=m
|
||||||
CONFIG_USB_OHCI_HCD=y
|
CONFIG_USB_OHCI_HCD=y
|
||||||
CONFIG_USB_UHCI_HCD=m
|
CONFIG_USB_UHCI_HCD=m
|
||||||
CONFIG_USB_R8A66597_HCD=m
|
CONFIG_USB_R8A66597_HCD=m
|
||||||
|
|
|
@ -74,13 +74,12 @@ static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c)
|
||||||
{
|
{
|
||||||
unsigned long sr, mask, fcsr, fcsr0, fcsr1;
|
unsigned long sr, mask, fcsr, fcsr0, fcsr1;
|
||||||
|
|
||||||
|
fcsr = c->fpu_csr31;
|
||||||
mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM;
|
mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM;
|
||||||
|
|
||||||
sr = read_c0_status();
|
sr = read_c0_status();
|
||||||
__enable_fpu(FPU_AS_IS);
|
__enable_fpu(FPU_AS_IS);
|
||||||
|
|
||||||
fcsr = read_32bit_cp1_register(CP1_STATUS);
|
|
||||||
|
|
||||||
fcsr0 = fcsr & mask;
|
fcsr0 = fcsr & mask;
|
||||||
write_32bit_cp1_register(CP1_STATUS, fcsr0);
|
write_32bit_cp1_register(CP1_STATUS, fcsr0);
|
||||||
fcsr0 = read_32bit_cp1_register(CP1_STATUS);
|
fcsr0 = read_32bit_cp1_register(CP1_STATUS);
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
int kgdb_early_setup;
|
int kgdb_early_setup;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static unsigned long irq_map[NR_IRQS / BITS_PER_LONG];
|
static DECLARE_BITMAP(irq_map, NR_IRQS);
|
||||||
|
|
||||||
int allocate_irqno(void)
|
int allocate_irqno(void)
|
||||||
{
|
{
|
||||||
|
@ -109,7 +109,7 @@ void __init init_IRQ(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_STACKOVERFLOW
|
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||||
static inline void check_stack_overflow(void)
|
static inline void check_stack_overflow(void)
|
||||||
{
|
{
|
||||||
unsigned long sp;
|
unsigned long sp;
|
||||||
|
|
|
@ -444,7 +444,7 @@ struct plat_smp_ops bmips5000_smp_ops = {
|
||||||
static void bmips_wr_vec(unsigned long dst, char *start, char *end)
|
static void bmips_wr_vec(unsigned long dst, char *start, char *end)
|
||||||
{
|
{
|
||||||
memcpy((void *)dst, start, end - start);
|
memcpy((void *)dst, start, end - start);
|
||||||
dma_cache_wback((unsigned long)start, end - start);
|
dma_cache_wback(dst, end - start);
|
||||||
local_flush_icache_range(dst, dst + (end - start));
|
local_flush_icache_range(dst, dst + (end - start));
|
||||||
instruction_hazard();
|
instruction_hazard();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2409,7 +2409,7 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
|
||||||
if (vcpu->mmio_needed == 2)
|
if (vcpu->mmio_needed == 2)
|
||||||
*gpr = *(int16_t *) run->mmio.data;
|
*gpr = *(int16_t *) run->mmio.data;
|
||||||
else
|
else
|
||||||
*gpr = *(int16_t *) run->mmio.data;
|
*gpr = *(uint16_t *)run->mmio.data;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
@ -34,7 +34,12 @@ LEAF(__strnlen_\func\()_asm)
|
||||||
FEXPORT(__strnlen_\func\()_nocheck_asm)
|
FEXPORT(__strnlen_\func\()_nocheck_asm)
|
||||||
move v0, a0
|
move v0, a0
|
||||||
PTR_ADDU a1, a0 # stop pointer
|
PTR_ADDU a1, a0 # stop pointer
|
||||||
1: beq v0, a1, 1f # limit reached?
|
1:
|
||||||
|
#ifdef CONFIG_CPU_DADDI_WORKAROUNDS
|
||||||
|
.set noat
|
||||||
|
li AT, 1
|
||||||
|
#endif
|
||||||
|
beq v0, a1, 1f # limit reached?
|
||||||
.ifeqs "\func", "kernel"
|
.ifeqs "\func", "kernel"
|
||||||
EX(lb, t0, (v0), .Lfault\@)
|
EX(lb, t0, (v0), .Lfault\@)
|
||||||
.else
|
.else
|
||||||
|
@ -42,7 +47,13 @@ FEXPORT(__strnlen_\func\()_nocheck_asm)
|
||||||
.endif
|
.endif
|
||||||
.set noreorder
|
.set noreorder
|
||||||
bnez t0, 1b
|
bnez t0, 1b
|
||||||
1: PTR_ADDIU v0, 1
|
1:
|
||||||
|
#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
|
||||||
|
PTR_ADDIU v0, 1
|
||||||
|
#else
|
||||||
|
PTR_ADDU v0, AT
|
||||||
|
.set at
|
||||||
|
#endif
|
||||||
.set reorder
|
.set reorder
|
||||||
PTR_SUBU v0, a0
|
PTR_SUBU v0, a0
|
||||||
jr ra
|
jr ra
|
||||||
|
|
|
@ -272,7 +272,7 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
|
||||||
if (action & SMP_ASK_C0COUNT) {
|
if (action & SMP_ASK_C0COUNT) {
|
||||||
BUG_ON(cpu != 0);
|
BUG_ON(cpu != 0);
|
||||||
c0count = read_c0_count();
|
c0count = read_c0_count();
|
||||||
for (i = 1; i < loongson_sysconf.nr_cpus; i++)
|
for (i = 1; i < num_possible_cpus(); i++)
|
||||||
per_cpu(core0_c0count, i) = c0count;
|
per_cpu(core0_c0count, i) = c0count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1372,7 +1372,7 @@ static int probe_scache(void)
|
||||||
scache_size = addr;
|
scache_size = addr;
|
||||||
c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22);
|
c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22);
|
||||||
c->scache.ways = 1;
|
c->scache.ways = 1;
|
||||||
c->dcache.waybit = 0; /* does not matter */
|
c->scache.waybit = 0; /* does not matter */
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -681,11 +681,7 @@ static unsigned int get_stack_depth(struct jit_ctx *ctx)
|
||||||
sp_off += config_enabled(CONFIG_64BIT) ?
|
sp_off += config_enabled(CONFIG_64BIT) ?
|
||||||
(ARGS_USED_BY_JIT + 1) * RSIZE : RSIZE;
|
(ARGS_USED_BY_JIT + 1) * RSIZE : RSIZE;
|
||||||
|
|
||||||
/*
|
return sp_off;
|
||||||
* Subtract the bytes for the last registers since we only care about
|
|
||||||
* the location on the stack pointer.
|
|
||||||
*/
|
|
||||||
return sp_off - RSIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void build_prologue(struct jit_ctx *ctx)
|
static void build_prologue(struct jit_ctx *ctx)
|
||||||
|
|
|
@ -41,7 +41,7 @@ static irqreturn_t ill_acc_irq_handler(int irq, void *_priv)
|
||||||
addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M,
|
addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M,
|
||||||
type & ILL_ACC_LEN_M);
|
type & ILL_ACC_LEN_M);
|
||||||
|
|
||||||
rt_memc_w32(REG_ILL_ACC_TYPE, REG_ILL_ACC_TYPE);
|
rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE);
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ void save_mce_event(struct pt_regs *regs, long handled,
|
||||||
uint64_t nip, uint64_t addr)
|
uint64_t nip, uint64_t addr)
|
||||||
{
|
{
|
||||||
uint64_t srr1;
|
uint64_t srr1;
|
||||||
int index = __this_cpu_inc_return(mce_nest_count);
|
int index = __this_cpu_inc_return(mce_nest_count) - 1;
|
||||||
struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]);
|
struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -184,7 +184,7 @@ void machine_check_queue_event(void)
|
||||||
if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
|
if (!get_mce_event(&evt, MCE_EVENT_RELEASE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
index = __this_cpu_inc_return(mce_queue_count);
|
index = __this_cpu_inc_return(mce_queue_count) - 1;
|
||||||
/* If queue is full, just return for now. */
|
/* If queue is full, just return for now. */
|
||||||
if (index >= MAX_MC_EVT) {
|
if (index >= MAX_MC_EVT) {
|
||||||
__this_cpu_dec(mce_queue_count);
|
__this_cpu_dec(mce_queue_count);
|
||||||
|
|
|
@ -213,6 +213,7 @@ SECTIONS
|
||||||
*(.opd)
|
*(.opd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
. = ALIGN(256);
|
||||||
.got : AT(ADDR(.got) - LOAD_OFFSET) {
|
.got : AT(ADDR(.got) - LOAD_OFFSET) {
|
||||||
__toc_start = .;
|
__toc_start = .;
|
||||||
#ifndef CONFIG_RELOCATABLE
|
#ifndef CONFIG_RELOCATABLE
|
||||||
|
|
|
@ -1952,7 +1952,7 @@ static void post_guest_process(struct kvmppc_vcore *vc)
|
||||||
*/
|
*/
|
||||||
static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
|
static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
|
||||||
{
|
{
|
||||||
struct kvm_vcpu *vcpu;
|
struct kvm_vcpu *vcpu, *vnext;
|
||||||
int i;
|
int i;
|
||||||
int srcu_idx;
|
int srcu_idx;
|
||||||
|
|
||||||
|
@ -1982,7 +1982,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
|
||||||
*/
|
*/
|
||||||
if ((threads_per_core > 1) &&
|
if ((threads_per_core > 1) &&
|
||||||
((vc->num_threads > threads_per_subcore) || !on_primary_thread())) {
|
((vc->num_threads > threads_per_subcore) || !on_primary_thread())) {
|
||||||
list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
|
list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
|
||||||
|
arch.run_list) {
|
||||||
vcpu->arch.ret = -EBUSY;
|
vcpu->arch.ret = -EBUSY;
|
||||||
kvmppc_remove_runnable(vc, vcpu);
|
kvmppc_remove_runnable(vc, vcpu);
|
||||||
wake_up(&vcpu->arch.cpu_run);
|
wake_up(&vcpu->arch.cpu_run);
|
||||||
|
|
|
@ -689,27 +689,34 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb,
|
||||||
struct page *
|
struct page *
|
||||||
follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
|
follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
|
||||||
{
|
{
|
||||||
pte_t *ptep;
|
pte_t *ptep, pte;
|
||||||
struct page *page;
|
|
||||||
unsigned shift;
|
unsigned shift;
|
||||||
unsigned long mask, flags;
|
unsigned long mask, flags;
|
||||||
|
struct page *page = ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift);
|
||||||
|
if (!ptep)
|
||||||
|
goto no_page;
|
||||||
|
pte = READ_ONCE(*ptep);
|
||||||
/*
|
/*
|
||||||
|
* Verify it is a huge page else bail.
|
||||||
* Transparent hugepages are handled by generic code. We can skip them
|
* Transparent hugepages are handled by generic code. We can skip them
|
||||||
* here.
|
* here.
|
||||||
*/
|
*/
|
||||||
local_irq_save(flags);
|
if (!shift || pmd_trans_huge(__pmd(pte_val(pte))))
|
||||||
ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift);
|
goto no_page;
|
||||||
|
|
||||||
/* Verify it is a huge page else bail. */
|
if (!pte_present(pte)) {
|
||||||
if (!ptep || !shift || pmd_trans_huge(*(pmd_t *)ptep)) {
|
page = NULL;
|
||||||
local_irq_restore(flags);
|
goto no_page;
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
}
|
}
|
||||||
mask = (1UL << shift) - 1;
|
mask = (1UL << shift) - 1;
|
||||||
page = pte_page(*ptep);
|
page = pte_page(pte);
|
||||||
if (page)
|
if (page)
|
||||||
page += (address & mask) / PAGE_SIZE;
|
page += (address & mask) / PAGE_SIZE;
|
||||||
|
|
||||||
|
no_page:
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
|
@ -839,6 +839,17 @@ pmd_t pmdp_get_and_clear(struct mm_struct *mm,
|
||||||
* hash fault look at them.
|
* hash fault look at them.
|
||||||
*/
|
*/
|
||||||
memset(pgtable, 0, PTE_FRAG_SIZE);
|
memset(pgtable, 0, PTE_FRAG_SIZE);
|
||||||
|
/*
|
||||||
|
* Serialize against find_linux_pte_or_hugepte which does lock-less
|
||||||
|
* lookup in page tables with local interrupts disabled. For huge pages
|
||||||
|
* it casts pmd_t to pte_t. Since format of pte_t is different from
|
||||||
|
* pmd_t we want to prevent transit from pmd pointing to page table
|
||||||
|
* to pmd pointing to huge page (and back) while interrupts are disabled.
|
||||||
|
* We clear pmd to possibly replace it with page table pointer in
|
||||||
|
* different code paths. So make sure we wait for the parallel
|
||||||
|
* find_linux_pte_or_hugepage to finish.
|
||||||
|
*/
|
||||||
|
kick_all_cpus_sync();
|
||||||
return old_pmd;
|
return old_pmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,12 @@
|
||||||
#define GHASH_DIGEST_SIZE 16
|
#define GHASH_DIGEST_SIZE 16
|
||||||
|
|
||||||
struct ghash_ctx {
|
struct ghash_ctx {
|
||||||
u8 icv[16];
|
u8 key[GHASH_BLOCK_SIZE];
|
||||||
u8 key[16];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ghash_desc_ctx {
|
struct ghash_desc_ctx {
|
||||||
|
u8 icv[GHASH_BLOCK_SIZE];
|
||||||
|
u8 key[GHASH_BLOCK_SIZE];
|
||||||
u8 buffer[GHASH_BLOCK_SIZE];
|
u8 buffer[GHASH_BLOCK_SIZE];
|
||||||
u32 bytes;
|
u32 bytes;
|
||||||
};
|
};
|
||||||
|
@ -28,8 +29,10 @@ struct ghash_desc_ctx {
|
||||||
static int ghash_init(struct shash_desc *desc)
|
static int ghash_init(struct shash_desc *desc)
|
||||||
{
|
{
|
||||||
struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||||
|
struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
|
||||||
|
|
||||||
memset(dctx, 0, sizeof(*dctx));
|
memset(dctx, 0, sizeof(*dctx));
|
||||||
|
memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +48,6 @@ static int ghash_setkey(struct crypto_shash *tfm,
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(ctx->key, key, GHASH_BLOCK_SIZE);
|
memcpy(ctx->key, key, GHASH_BLOCK_SIZE);
|
||||||
memset(ctx->icv, 0, GHASH_BLOCK_SIZE);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +56,6 @@ static int ghash_update(struct shash_desc *desc,
|
||||||
const u8 *src, unsigned int srclen)
|
const u8 *src, unsigned int srclen)
|
||||||
{
|
{
|
||||||
struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||||
struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
|
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
u8 *buf = dctx->buffer;
|
u8 *buf = dctx->buffer;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -70,7 +71,7 @@ static int ghash_update(struct shash_desc *desc,
|
||||||
src += n;
|
src += n;
|
||||||
|
|
||||||
if (!dctx->bytes) {
|
if (!dctx->bytes) {
|
||||||
ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf,
|
ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf,
|
||||||
GHASH_BLOCK_SIZE);
|
GHASH_BLOCK_SIZE);
|
||||||
if (ret != GHASH_BLOCK_SIZE)
|
if (ret != GHASH_BLOCK_SIZE)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
@ -79,7 +80,7 @@ static int ghash_update(struct shash_desc *desc,
|
||||||
|
|
||||||
n = srclen & ~(GHASH_BLOCK_SIZE - 1);
|
n = srclen & ~(GHASH_BLOCK_SIZE - 1);
|
||||||
if (n) {
|
if (n) {
|
||||||
ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n);
|
ret = crypt_s390_kimd(KIMD_GHASH, dctx, src, n);
|
||||||
if (ret != n)
|
if (ret != n)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
src += n;
|
src += n;
|
||||||
|
@ -94,7 +95,7 @@ static int ghash_update(struct shash_desc *desc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
|
static int ghash_flush(struct ghash_desc_ctx *dctx)
|
||||||
{
|
{
|
||||||
u8 *buf = dctx->buffer;
|
u8 *buf = dctx->buffer;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -104,24 +105,24 @@ static int ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
|
||||||
|
|
||||||
memset(pos, 0, dctx->bytes);
|
memset(pos, 0, dctx->bytes);
|
||||||
|
|
||||||
ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE);
|
ret = crypt_s390_kimd(KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE);
|
||||||
if (ret != GHASH_BLOCK_SIZE)
|
if (ret != GHASH_BLOCK_SIZE)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
dctx->bytes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dctx->bytes = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ghash_final(struct shash_desc *desc, u8 *dst)
|
static int ghash_final(struct shash_desc *desc, u8 *dst)
|
||||||
{
|
{
|
||||||
struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
|
||||||
struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ghash_flush(ctx, dctx);
|
ret = ghash_flush(dctx);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE);
|
memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ static int generate_entropy(u8 *ebuf, size_t nbytes)
|
||||||
/* fill page with urandom bytes */
|
/* fill page with urandom bytes */
|
||||||
get_random_bytes(pg, PAGE_SIZE);
|
get_random_bytes(pg, PAGE_SIZE);
|
||||||
/* exor page with stckf values */
|
/* exor page with stckf values */
|
||||||
for (n = 0; n < sizeof(PAGE_SIZE/sizeof(u64)); n++) {
|
for (n = 0; n < PAGE_SIZE / sizeof(u64); n++) {
|
||||||
u64 *p = ((u64 *)pg) + n;
|
u64 *p = ((u64 *)pg) + n;
|
||||||
*p ^= get_tod_clock_fast();
|
*p ^= get_tod_clock_fast();
|
||||||
}
|
}
|
||||||
|
|
|
@ -494,7 +494,7 @@ static inline int pmd_large(pmd_t pmd)
|
||||||
return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
|
return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int pmd_pfn(pmd_t pmd)
|
static inline unsigned long pmd_pfn(pmd_t pmd)
|
||||||
{
|
{
|
||||||
unsigned long origin_mask;
|
unsigned long origin_mask;
|
||||||
|
|
||||||
|
|
|
@ -443,8 +443,11 @@ static void bpf_jit_epilogue(struct bpf_jit *jit)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compile one eBPF instruction into s390x code
|
* Compile one eBPF instruction into s390x code
|
||||||
|
*
|
||||||
|
* NOTE: Use noinline because for gcov (-fprofile-arcs) gcc allocates a lot of
|
||||||
|
* stack space for the large switch statement.
|
||||||
*/
|
*/
|
||||||
static int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i)
|
static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i)
|
||||||
{
|
{
|
||||||
struct bpf_insn *insn = &fp->insnsi[i];
|
struct bpf_insn *insn = &fp->insnsi[i];
|
||||||
int jmp_off, last, insn_count = 1;
|
int jmp_off, last, insn_count = 1;
|
||||||
|
@ -588,8 +591,8 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i)
|
||||||
EMIT4(0xb9160000, dst_reg, rc_reg);
|
EMIT4(0xb9160000, dst_reg, rc_reg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BPF_ALU64 | BPF_DIV | BPF_X: /* dst = dst / (u32) src */
|
case BPF_ALU64 | BPF_DIV | BPF_X: /* dst = dst / src */
|
||||||
case BPF_ALU64 | BPF_MOD | BPF_X: /* dst = dst % (u32) src */
|
case BPF_ALU64 | BPF_MOD | BPF_X: /* dst = dst % src */
|
||||||
{
|
{
|
||||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||||
|
|
||||||
|
@ -602,10 +605,8 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i)
|
||||||
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
EMIT4_IMM(0xa7090000, REG_W0, 0);
|
||||||
/* lgr %w1,%dst */
|
/* lgr %w1,%dst */
|
||||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||||
/* llgfr %dst,%src (u32 cast) */
|
|
||||||
EMIT4(0xb9160000, dst_reg, src_reg);
|
|
||||||
/* dlgr %w0,%dst */
|
/* dlgr %w0,%dst */
|
||||||
EMIT4(0xb9870000, REG_W0, dst_reg);
|
EMIT4(0xb9870000, REG_W0, src_reg);
|
||||||
/* lgr %dst,%rc */
|
/* lgr %dst,%rc */
|
||||||
EMIT4(0xb9040000, dst_reg, rc_reg);
|
EMIT4(0xb9040000, dst_reg, rc_reg);
|
||||||
break;
|
break;
|
||||||
|
@ -632,8 +633,8 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i)
|
||||||
EMIT4(0xb9160000, dst_reg, rc_reg);
|
EMIT4(0xb9160000, dst_reg, rc_reg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BPF_ALU64 | BPF_DIV | BPF_K: /* dst = dst / (u32) imm */
|
case BPF_ALU64 | BPF_DIV | BPF_K: /* dst = dst / imm */
|
||||||
case BPF_ALU64 | BPF_MOD | BPF_K: /* dst = dst % (u32) imm */
|
case BPF_ALU64 | BPF_MOD | BPF_K: /* dst = dst % imm */
|
||||||
{
|
{
|
||||||
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
int rc_reg = BPF_OP(insn->code) == BPF_DIV ? REG_W1 : REG_W0;
|
||||||
|
|
||||||
|
@ -649,7 +650,7 @@ static int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i)
|
||||||
EMIT4(0xb9040000, REG_W1, dst_reg);
|
EMIT4(0xb9040000, REG_W1, dst_reg);
|
||||||
/* dlg %w0,<d(imm)>(%l) */
|
/* dlg %w0,<d(imm)>(%l) */
|
||||||
EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0, REG_L,
|
EMIT6_DISP_LH(0xe3000000, 0x0087, REG_W0, REG_0, REG_L,
|
||||||
EMIT_CONST_U64((u32) imm));
|
EMIT_CONST_U64(imm));
|
||||||
/* lgr %dst,%rc */
|
/* lgr %dst,%rc */
|
||||||
EMIT4(0xb9040000, dst_reg, rc_reg);
|
EMIT4(0xb9040000, dst_reg, rc_reg);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -24,7 +24,8 @@ typedef struct {
|
||||||
unsigned int icache_line_size;
|
unsigned int icache_line_size;
|
||||||
unsigned int ecache_size;
|
unsigned int ecache_size;
|
||||||
unsigned int ecache_line_size;
|
unsigned int ecache_line_size;
|
||||||
int core_id;
|
unsigned short sock_id;
|
||||||
|
unsigned short core_id;
|
||||||
int proc_id;
|
int proc_id;
|
||||||
} cpuinfo_sparc;
|
} cpuinfo_sparc;
|
||||||
|
|
||||||
|
|
|
@ -308,12 +308,26 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
|
||||||
" sllx %1, 32, %1\n"
|
" sllx %1, 32, %1\n"
|
||||||
" or %0, %1, %0\n"
|
" or %0, %1, %0\n"
|
||||||
" .previous\n"
|
" .previous\n"
|
||||||
|
" .section .sun_m7_2insn_patch, \"ax\"\n"
|
||||||
|
" .word 661b\n"
|
||||||
|
" sethi %%uhi(%4), %1\n"
|
||||||
|
" sethi %%hi(%4), %0\n"
|
||||||
|
" .word 662b\n"
|
||||||
|
" or %1, %%ulo(%4), %1\n"
|
||||||
|
" or %0, %%lo(%4), %0\n"
|
||||||
|
" .word 663b\n"
|
||||||
|
" sllx %1, 32, %1\n"
|
||||||
|
" or %0, %1, %0\n"
|
||||||
|
" .previous\n"
|
||||||
: "=r" (mask), "=r" (tmp)
|
: "=r" (mask), "=r" (tmp)
|
||||||
: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
|
: "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
|
||||||
_PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U |
|
_PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U |
|
||||||
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U),
|
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U),
|
||||||
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
|
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
|
||||||
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V |
|
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V |
|
||||||
|
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V),
|
||||||
|
"i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
|
||||||
|
_PAGE_CP_4V | _PAGE_E_4V |
|
||||||
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V));
|
_PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V));
|
||||||
|
|
||||||
return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
|
return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
|
||||||
|
@ -342,9 +356,15 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot)
|
||||||
" andn %0, %4, %0\n"
|
" andn %0, %4, %0\n"
|
||||||
" or %0, %5, %0\n"
|
" or %0, %5, %0\n"
|
||||||
" .previous\n"
|
" .previous\n"
|
||||||
|
" .section .sun_m7_2insn_patch, \"ax\"\n"
|
||||||
|
" .word 661b\n"
|
||||||
|
" andn %0, %6, %0\n"
|
||||||
|
" or %0, %5, %0\n"
|
||||||
|
" .previous\n"
|
||||||
: "=r" (val)
|
: "=r" (val)
|
||||||
: "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
|
: "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
|
||||||
"i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V));
|
"i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V),
|
||||||
|
"i" (_PAGE_CP_4V));
|
||||||
|
|
||||||
return __pgprot(val);
|
return __pgprot(val);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,11 +40,12 @@ static inline int pcibus_to_node(struct pci_bus *pbus)
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
#define topology_physical_package_id(cpu) (cpu_data(cpu).proc_id)
|
#define topology_physical_package_id(cpu) (cpu_data(cpu).proc_id)
|
||||||
#define topology_core_id(cpu) (cpu_data(cpu).core_id)
|
#define topology_core_id(cpu) (cpu_data(cpu).core_id)
|
||||||
#define topology_core_cpumask(cpu) (&cpu_core_map[cpu])
|
#define topology_core_cpumask(cpu) (&cpu_core_sib_map[cpu])
|
||||||
#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
|
#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
extern cpumask_t cpu_core_map[NR_CPUS];
|
extern cpumask_t cpu_core_map[NR_CPUS];
|
||||||
|
extern cpumask_t cpu_core_sib_map[NR_CPUS];
|
||||||
static inline const struct cpumask *cpu_coregroup_mask(int cpu)
|
static inline const struct cpumask *cpu_coregroup_mask(int cpu)
|
||||||
{
|
{
|
||||||
return &cpu_core_map[cpu];
|
return &cpu_core_map[cpu];
|
||||||
|
|
|
@ -79,6 +79,8 @@ struct sun4v_2insn_patch_entry {
|
||||||
};
|
};
|
||||||
extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
|
extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
|
||||||
__sun4v_2insn_patch_end;
|
__sun4v_2insn_patch_end;
|
||||||
|
extern struct sun4v_2insn_patch_entry __sun_m7_2insn_patch,
|
||||||
|
__sun_m7_2insn_patch_end;
|
||||||
|
|
||||||
|
|
||||||
#endif /* !(__ASSEMBLY__) */
|
#endif /* !(__ASSEMBLY__) */
|
||||||
|
|
|
@ -69,6 +69,8 @@ void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
|
||||||
struct sun4v_1insn_patch_entry *);
|
struct sun4v_1insn_patch_entry *);
|
||||||
void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
|
void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
|
||||||
struct sun4v_2insn_patch_entry *);
|
struct sun4v_2insn_patch_entry *);
|
||||||
|
void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *,
|
||||||
|
struct sun4v_2insn_patch_entry *);
|
||||||
extern unsigned int dcache_parity_tl1_occurred;
|
extern unsigned int dcache_parity_tl1_occurred;
|
||||||
extern unsigned int icache_parity_tl1_occurred;
|
extern unsigned int icache_parity_tl1_occurred;
|
||||||
|
|
||||||
|
|
|
@ -723,7 +723,6 @@ static int grpci2_of_probe(struct platform_device *ofdev)
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
memset(grpci2priv, 0, sizeof(*grpci2priv));
|
|
||||||
priv->regs = regs;
|
priv->regs = regs;
|
||||||
priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */
|
priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */
|
||||||
priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT;
|
priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT;
|
||||||
|
|
|
@ -614,45 +614,68 @@ static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id)
|
static void find_back_node_value(struct mdesc_handle *hp, u64 node,
|
||||||
|
char *srch_val,
|
||||||
|
void (*func)(struct mdesc_handle *, u64, int),
|
||||||
|
u64 val, int depth)
|
||||||
{
|
{
|
||||||
u64 a;
|
u64 arc;
|
||||||
|
|
||||||
mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
|
/* Since we have an estimate of recursion depth, do a sanity check. */
|
||||||
u64 t = mdesc_arc_target(hp, a);
|
if (depth == 0)
|
||||||
const char *name;
|
return;
|
||||||
const u64 *id;
|
|
||||||
|
|
||||||
name = mdesc_node_name(hp, t);
|
mdesc_for_each_arc(arc, hp, node, MDESC_ARC_TYPE_BACK) {
|
||||||
if (!strcmp(name, "cpu")) {
|
u64 n = mdesc_arc_target(hp, arc);
|
||||||
id = mdesc_get_property(hp, t, "id", NULL);
|
const char *name = mdesc_node_name(hp, n);
|
||||||
if (*id < NR_CPUS)
|
|
||||||
cpu_data(*id).core_id = core_id;
|
|
||||||
} else {
|
|
||||||
u64 j;
|
|
||||||
|
|
||||||
mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {
|
if (!strcmp(srch_val, name))
|
||||||
u64 n = mdesc_arc_target(hp, j);
|
(*func)(hp, n, val);
|
||||||
const char *n_name;
|
|
||||||
|
|
||||||
n_name = mdesc_node_name(hp, n);
|
find_back_node_value(hp, n, srch_val, func, val, depth-1);
|
||||||
if (strcmp(n_name, "cpu"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
id = mdesc_get_property(hp, n, "id", NULL);
|
|
||||||
if (*id < NR_CPUS)
|
|
||||||
cpu_data(*id).core_id = core_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __mark_core_id(struct mdesc_handle *hp, u64 node,
|
||||||
|
int core_id)
|
||||||
|
{
|
||||||
|
const u64 *id = mdesc_get_property(hp, node, "id", NULL);
|
||||||
|
|
||||||
|
if (*id < num_possible_cpus())
|
||||||
|
cpu_data(*id).core_id = core_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __mark_sock_id(struct mdesc_handle *hp, u64 node,
|
||||||
|
int sock_id)
|
||||||
|
{
|
||||||
|
const u64 *id = mdesc_get_property(hp, node, "id", NULL);
|
||||||
|
|
||||||
|
if (*id < num_possible_cpus())
|
||||||
|
cpu_data(*id).sock_id = sock_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mark_core_ids(struct mdesc_handle *hp, u64 mp,
|
||||||
|
int core_id)
|
||||||
|
{
|
||||||
|
find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mark_sock_ids(struct mdesc_handle *hp, u64 mp,
|
||||||
|
int sock_id)
|
||||||
|
{
|
||||||
|
find_back_node_value(hp, mp, "cpu", __mark_sock_id, sock_id, 10);
|
||||||
|
}
|
||||||
|
|
||||||
static void set_core_ids(struct mdesc_handle *hp)
|
static void set_core_ids(struct mdesc_handle *hp)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
u64 mp;
|
u64 mp;
|
||||||
|
|
||||||
idx = 1;
|
idx = 1;
|
||||||
|
|
||||||
|
/* Identify unique cores by looking for cpus backpointed to by
|
||||||
|
* level 1 instruction caches.
|
||||||
|
*/
|
||||||
mdesc_for_each_node_by_name(hp, mp, "cache") {
|
mdesc_for_each_node_by_name(hp, mp, "cache") {
|
||||||
const u64 *level;
|
const u64 *level;
|
||||||
const char *type;
|
const char *type;
|
||||||
|
@ -667,11 +690,72 @@ static void set_core_ids(struct mdesc_handle *hp)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mark_core_ids(hp, mp, idx);
|
mark_core_ids(hp, mp, idx);
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_sock_ids_by_cache(struct mdesc_handle *hp, int level)
|
||||||
|
{
|
||||||
|
u64 mp;
|
||||||
|
int idx = 1;
|
||||||
|
int fnd = 0;
|
||||||
|
|
||||||
|
/* Identify unique sockets by looking for cpus backpointed to by
|
||||||
|
* shared level n caches.
|
||||||
|
*/
|
||||||
|
mdesc_for_each_node_by_name(hp, mp, "cache") {
|
||||||
|
const u64 *cur_lvl;
|
||||||
|
|
||||||
|
cur_lvl = mdesc_get_property(hp, mp, "level", NULL);
|
||||||
|
if (*cur_lvl != level)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mark_sock_ids(hp, mp, idx);
|
||||||
|
idx++;
|
||||||
|
fnd = 1;
|
||||||
|
}
|
||||||
|
return fnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_sock_ids_by_socket(struct mdesc_handle *hp, u64 mp)
|
||||||
|
{
|
||||||
|
int idx = 1;
|
||||||
|
|
||||||
|
mdesc_for_each_node_by_name(hp, mp, "socket") {
|
||||||
|
u64 a;
|
||||||
|
|
||||||
|
mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
|
||||||
|
u64 t = mdesc_arc_target(hp, a);
|
||||||
|
const char *name;
|
||||||
|
const u64 *id;
|
||||||
|
|
||||||
|
name = mdesc_node_name(hp, t);
|
||||||
|
if (strcmp(name, "cpu"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
id = mdesc_get_property(hp, t, "id", NULL);
|
||||||
|
if (*id < num_possible_cpus())
|
||||||
|
cpu_data(*id).sock_id = idx;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_sock_ids(struct mdesc_handle *hp)
|
||||||
|
{
|
||||||
|
u64 mp;
|
||||||
|
|
||||||
|
/* If machine description exposes sockets data use it.
|
||||||
|
* Otherwise fallback to use shared L3 or L2 caches.
|
||||||
|
*/
|
||||||
|
mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets");
|
||||||
|
if (mp != MDESC_NODE_NULL)
|
||||||
|
return set_sock_ids_by_socket(hp, mp);
|
||||||
|
|
||||||
|
if (!set_sock_ids_by_cache(hp, 3))
|
||||||
|
set_sock_ids_by_cache(hp, 2);
|
||||||
|
}
|
||||||
|
|
||||||
static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
|
static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
|
||||||
{
|
{
|
||||||
u64 a;
|
u64 a;
|
||||||
|
@ -707,7 +791,6 @@ static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mark_proc_ids(hp, mp, idx);
|
mark_proc_ids(hp, mp, idx);
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -900,6 +983,7 @@ void mdesc_fill_in_cpu_data(cpumask_t *mask)
|
||||||
|
|
||||||
set_core_ids(hp);
|
set_core_ids(hp);
|
||||||
set_proc_ids(hp);
|
set_proc_ids(hp);
|
||||||
|
set_sock_ids(hp);
|
||||||
|
|
||||||
mdesc_release(hp);
|
mdesc_release(hp);
|
||||||
|
|
||||||
|
|
|
@ -1002,6 +1002,38 @@ static int __init pcibios_init(void)
|
||||||
subsys_initcall(pcibios_init);
|
subsys_initcall(pcibios_init);
|
||||||
|
|
||||||
#ifdef CONFIG_SYSFS
|
#ifdef CONFIG_SYSFS
|
||||||
|
|
||||||
|
#define SLOT_NAME_SIZE 11 /* Max decimal digits + null in u32 */
|
||||||
|
|
||||||
|
static void pcie_bus_slot_names(struct pci_bus *pbus)
|
||||||
|
{
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
struct pci_bus *bus;
|
||||||
|
|
||||||
|
list_for_each_entry(pdev, &pbus->devices, bus_list) {
|
||||||
|
char name[SLOT_NAME_SIZE];
|
||||||
|
struct pci_slot *pci_slot;
|
||||||
|
const u32 *slot_num;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
slot_num = of_get_property(pdev->dev.of_node,
|
||||||
|
"physical-slot#", &len);
|
||||||
|
|
||||||
|
if (slot_num == NULL || len != 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(name, sizeof(name), "%u", slot_num[0]);
|
||||||
|
pci_slot = pci_create_slot(pbus, slot_num[0], name, NULL);
|
||||||
|
|
||||||
|
if (IS_ERR(pci_slot))
|
||||||
|
pr_err("PCI: pci_create_slot returned %ld.\n",
|
||||||
|
PTR_ERR(pci_slot));
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(bus, &pbus->children, node)
|
||||||
|
pcie_bus_slot_names(bus);
|
||||||
|
}
|
||||||
|
|
||||||
static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus)
|
static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus)
|
||||||
{
|
{
|
||||||
const struct pci_slot_names {
|
const struct pci_slot_names {
|
||||||
|
@ -1053,18 +1085,29 @@ static int __init of_pci_slot_init(void)
|
||||||
|
|
||||||
while ((pbus = pci_find_next_bus(pbus)) != NULL) {
|
while ((pbus = pci_find_next_bus(pbus)) != NULL) {
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
|
||||||
if (pbus->self) {
|
pdev = list_first_entry(&pbus->devices, struct pci_dev,
|
||||||
/* PCI->PCI bridge */
|
bus_list);
|
||||||
node = pbus->self->dev.of_node;
|
|
||||||
|
if (pdev && pci_is_pcie(pdev)) {
|
||||||
|
pcie_bus_slot_names(pbus);
|
||||||
} else {
|
} else {
|
||||||
struct pci_pbm_info *pbm = pbus->sysdata;
|
|
||||||
|
|
||||||
/* Host PCI controller */
|
if (pbus->self) {
|
||||||
node = pbm->op->dev.of_node;
|
|
||||||
|
/* PCI->PCI bridge */
|
||||||
|
node = pbus->self->dev.of_node;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
struct pci_pbm_info *pbm = pbus->sysdata;
|
||||||
|
|
||||||
|
/* Host PCI controller */
|
||||||
|
node = pbm->op->dev.of_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_bus_slot_names(node, pbus);
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_bus_slot_names(node, pbus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -255,6 +255,24 @@ void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sun_m7_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
|
||||||
|
struct sun4v_2insn_patch_entry *end)
|
||||||
|
{
|
||||||
|
while (start < end) {
|
||||||
|
unsigned long addr = start->addr;
|
||||||
|
|
||||||
|
*(unsigned int *) (addr + 0) = start->insns[0];
|
||||||
|
wmb();
|
||||||
|
__asm__ __volatile__("flush %0" : : "r" (addr + 0));
|
||||||
|
|
||||||
|
*(unsigned int *) (addr + 4) = start->insns[1];
|
||||||
|
wmb();
|
||||||
|
__asm__ __volatile__("flush %0" : : "r" (addr + 4));
|
||||||
|
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void __init sun4v_patch(void)
|
static void __init sun4v_patch(void)
|
||||||
{
|
{
|
||||||
extern void sun4v_hvapi_init(void);
|
extern void sun4v_hvapi_init(void);
|
||||||
|
@ -267,6 +285,9 @@ static void __init sun4v_patch(void)
|
||||||
|
|
||||||
sun4v_patch_2insn_range(&__sun4v_2insn_patch,
|
sun4v_patch_2insn_range(&__sun4v_2insn_patch,
|
||||||
&__sun4v_2insn_patch_end);
|
&__sun4v_2insn_patch_end);
|
||||||
|
if (sun4v_chip_type == SUN4V_CHIP_SPARC_M7)
|
||||||
|
sun_m7_patch_2insn_range(&__sun_m7_2insn_patch,
|
||||||
|
&__sun_m7_2insn_patch_end);
|
||||||
|
|
||||||
sun4v_hvapi_init();
|
sun4v_hvapi_init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,8 +60,12 @@ DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
|
||||||
cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
|
cpumask_t cpu_core_map[NR_CPUS] __read_mostly =
|
||||||
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
|
{ [0 ... NR_CPUS-1] = CPU_MASK_NONE };
|
||||||
|
|
||||||
|
cpumask_t cpu_core_sib_map[NR_CPUS] __read_mostly = {
|
||||||
|
[0 ... NR_CPUS-1] = CPU_MASK_NONE };
|
||||||
|
|
||||||
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
|
EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
|
||||||
EXPORT_SYMBOL(cpu_core_map);
|
EXPORT_SYMBOL(cpu_core_map);
|
||||||
|
EXPORT_SYMBOL(cpu_core_sib_map);
|
||||||
|
|
||||||
static cpumask_t smp_commenced_mask;
|
static cpumask_t smp_commenced_mask;
|
||||||
|
|
||||||
|
@ -1243,6 +1247,15 @@ void smp_fill_in_sib_core_maps(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for_each_present_cpu(i) {
|
||||||
|
unsigned int j;
|
||||||
|
|
||||||
|
for_each_present_cpu(j) {
|
||||||
|
if (cpu_data(i).sock_id == cpu_data(j).sock_id)
|
||||||
|
cpumask_set_cpu(j, &cpu_core_sib_map[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for_each_present_cpu(i) {
|
for_each_present_cpu(i) {
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,11 @@ SECTIONS
|
||||||
*(.pause_3insn_patch)
|
*(.pause_3insn_patch)
|
||||||
__pause_3insn_patch_end = .;
|
__pause_3insn_patch_end = .;
|
||||||
}
|
}
|
||||||
|
.sun_m7_2insn_patch : {
|
||||||
|
__sun_m7_2insn_patch = .;
|
||||||
|
*(.sun_m7_2insn_patch)
|
||||||
|
__sun_m7_2insn_patch_end = .;
|
||||||
|
}
|
||||||
PERCPU_SECTION(SMP_CACHE_BYTES)
|
PERCPU_SECTION(SMP_CACHE_BYTES)
|
||||||
|
|
||||||
. = ALIGN(PAGE_SIZE);
|
. = ALIGN(PAGE_SIZE);
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
#include "init_64.h"
|
#include "init_64.h"
|
||||||
|
|
||||||
unsigned long kern_linear_pte_xor[4] __read_mostly;
|
unsigned long kern_linear_pte_xor[4] __read_mostly;
|
||||||
|
static unsigned long page_cache4v_flag;
|
||||||
|
|
||||||
/* A bitmap, two bits for every 256MB of physical memory. These two
|
/* A bitmap, two bits for every 256MB of physical memory. These two
|
||||||
* bits determine what page size we use for kernel linear
|
* bits determine what page size we use for kernel linear
|
||||||
|
@ -1909,11 +1910,24 @@ static void __init sun4u_linear_pte_xor_finalize(void)
|
||||||
|
|
||||||
static void __init sun4v_linear_pte_xor_finalize(void)
|
static void __init sun4v_linear_pte_xor_finalize(void)
|
||||||
{
|
{
|
||||||
|
unsigned long pagecv_flag;
|
||||||
|
|
||||||
|
/* Bit 9 of TTE is no longer CV bit on M7 processor and it instead
|
||||||
|
* enables MCD error. Do not set bit 9 on M7 processor.
|
||||||
|
*/
|
||||||
|
switch (sun4v_chip_type) {
|
||||||
|
case SUN4V_CHIP_SPARC_M7:
|
||||||
|
pagecv_flag = 0x00;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pagecv_flag = _PAGE_CV_4V;
|
||||||
|
break;
|
||||||
|
}
|
||||||
#ifndef CONFIG_DEBUG_PAGEALLOC
|
#ifndef CONFIG_DEBUG_PAGEALLOC
|
||||||
if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) {
|
if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) {
|
||||||
kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^
|
kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^
|
||||||
PAGE_OFFSET;
|
PAGE_OFFSET;
|
||||||
kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V |
|
kern_linear_pte_xor[1] |= (_PAGE_CP_4V | pagecv_flag |
|
||||||
_PAGE_P_4V | _PAGE_W_4V);
|
_PAGE_P_4V | _PAGE_W_4V);
|
||||||
} else {
|
} else {
|
||||||
kern_linear_pte_xor[1] = kern_linear_pte_xor[0];
|
kern_linear_pte_xor[1] = kern_linear_pte_xor[0];
|
||||||
|
@ -1922,7 +1936,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
|
||||||
if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) {
|
if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) {
|
||||||
kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^
|
kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^
|
||||||
PAGE_OFFSET;
|
PAGE_OFFSET;
|
||||||
kern_linear_pte_xor[2] |= (_PAGE_CP_4V | _PAGE_CV_4V |
|
kern_linear_pte_xor[2] |= (_PAGE_CP_4V | pagecv_flag |
|
||||||
_PAGE_P_4V | _PAGE_W_4V);
|
_PAGE_P_4V | _PAGE_W_4V);
|
||||||
} else {
|
} else {
|
||||||
kern_linear_pte_xor[2] = kern_linear_pte_xor[1];
|
kern_linear_pte_xor[2] = kern_linear_pte_xor[1];
|
||||||
|
@ -1931,7 +1945,7 @@ static void __init sun4v_linear_pte_xor_finalize(void)
|
||||||
if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) {
|
if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) {
|
||||||
kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^
|
kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^
|
||||||
PAGE_OFFSET;
|
PAGE_OFFSET;
|
||||||
kern_linear_pte_xor[3] |= (_PAGE_CP_4V | _PAGE_CV_4V |
|
kern_linear_pte_xor[3] |= (_PAGE_CP_4V | pagecv_flag |
|
||||||
_PAGE_P_4V | _PAGE_W_4V);
|
_PAGE_P_4V | _PAGE_W_4V);
|
||||||
} else {
|
} else {
|
||||||
kern_linear_pte_xor[3] = kern_linear_pte_xor[2];
|
kern_linear_pte_xor[3] = kern_linear_pte_xor[2];
|
||||||
|
@ -1958,6 +1972,13 @@ static phys_addr_t __init available_memory(void)
|
||||||
return available;
|
return available;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define _PAGE_CACHE_4U (_PAGE_CP_4U | _PAGE_CV_4U)
|
||||||
|
#define _PAGE_CACHE_4V (_PAGE_CP_4V | _PAGE_CV_4V)
|
||||||
|
#define __DIRTY_BITS_4U (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U)
|
||||||
|
#define __DIRTY_BITS_4V (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V)
|
||||||
|
#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R)
|
||||||
|
#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R)
|
||||||
|
|
||||||
/* We need to exclude reserved regions. This exclusion will include
|
/* We need to exclude reserved regions. This exclusion will include
|
||||||
* vmlinux and initrd. To be more precise the initrd size could be used to
|
* vmlinux and initrd. To be more precise the initrd size could be used to
|
||||||
* compute a new lower limit because it is freed later during initialization.
|
* compute a new lower limit because it is freed later during initialization.
|
||||||
|
@ -2034,6 +2055,25 @@ void __init paging_init(void)
|
||||||
memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));
|
memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* TTE.cv bit on sparc v9 occupies the same position as TTE.mcde
|
||||||
|
* bit on M7 processor. This is a conflicting usage of the same
|
||||||
|
* bit. Enabling TTE.cv on M7 would turn on Memory Corruption
|
||||||
|
* Detection error on all pages and this will lead to problems
|
||||||
|
* later. Kernel does not run with MCD enabled and hence rest
|
||||||
|
* of the required steps to fully configure memory corruption
|
||||||
|
* detection are not taken. We need to ensure TTE.mcde is not
|
||||||
|
* set on M7 processor. Compute the value of cacheability
|
||||||
|
* flag for use later taking this into consideration.
|
||||||
|
*/
|
||||||
|
switch (sun4v_chip_type) {
|
||||||
|
case SUN4V_CHIP_SPARC_M7:
|
||||||
|
page_cache4v_flag = _PAGE_CP_4V;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
page_cache4v_flag = _PAGE_CACHE_4V;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (tlb_type == hypervisor)
|
if (tlb_type == hypervisor)
|
||||||
sun4v_pgprot_init();
|
sun4v_pgprot_init();
|
||||||
else
|
else
|
||||||
|
@ -2274,13 +2314,6 @@ void free_initrd_mem(unsigned long start, unsigned long end)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _PAGE_CACHE_4U (_PAGE_CP_4U | _PAGE_CV_4U)
|
|
||||||
#define _PAGE_CACHE_4V (_PAGE_CP_4V | _PAGE_CV_4V)
|
|
||||||
#define __DIRTY_BITS_4U (_PAGE_MODIFIED_4U | _PAGE_WRITE_4U | _PAGE_W_4U)
|
|
||||||
#define __DIRTY_BITS_4V (_PAGE_MODIFIED_4V | _PAGE_WRITE_4V | _PAGE_W_4V)
|
|
||||||
#define __ACCESS_BITS_4U (_PAGE_ACCESSED_4U | _PAGE_READ_4U | _PAGE_R)
|
|
||||||
#define __ACCESS_BITS_4V (_PAGE_ACCESSED_4V | _PAGE_READ_4V | _PAGE_R)
|
|
||||||
|
|
||||||
pgprot_t PAGE_KERNEL __read_mostly;
|
pgprot_t PAGE_KERNEL __read_mostly;
|
||||||
EXPORT_SYMBOL(PAGE_KERNEL);
|
EXPORT_SYMBOL(PAGE_KERNEL);
|
||||||
|
|
||||||
|
@ -2312,8 +2345,7 @@ int __meminit vmemmap_populate(unsigned long vstart, unsigned long vend,
|
||||||
_PAGE_P_4U | _PAGE_W_4U);
|
_PAGE_P_4U | _PAGE_W_4U);
|
||||||
if (tlb_type == hypervisor)
|
if (tlb_type == hypervisor)
|
||||||
pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V |
|
pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V |
|
||||||
_PAGE_CP_4V | _PAGE_CV_4V |
|
page_cache4v_flag | _PAGE_P_4V | _PAGE_W_4V);
|
||||||
_PAGE_P_4V | _PAGE_W_4V);
|
|
||||||
|
|
||||||
pte_base |= _PAGE_PMD_HUGE;
|
pte_base |= _PAGE_PMD_HUGE;
|
||||||
|
|
||||||
|
@ -2450,14 +2482,14 @@ static void __init sun4v_pgprot_init(void)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID |
|
PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID |
|
||||||
_PAGE_CACHE_4V | _PAGE_P_4V |
|
page_cache4v_flag | _PAGE_P_4V |
|
||||||
__ACCESS_BITS_4V | __DIRTY_BITS_4V |
|
__ACCESS_BITS_4V | __DIRTY_BITS_4V |
|
||||||
_PAGE_EXEC_4V);
|
_PAGE_EXEC_4V);
|
||||||
PAGE_KERNEL_LOCKED = PAGE_KERNEL;
|
PAGE_KERNEL_LOCKED = PAGE_KERNEL;
|
||||||
|
|
||||||
_PAGE_IE = _PAGE_IE_4V;
|
_PAGE_IE = _PAGE_IE_4V;
|
||||||
_PAGE_E = _PAGE_E_4V;
|
_PAGE_E = _PAGE_E_4V;
|
||||||
_PAGE_CACHE = _PAGE_CACHE_4V;
|
_PAGE_CACHE = page_cache4v_flag;
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||||
kern_linear_pte_xor[0] = _PAGE_VALID ^ PAGE_OFFSET;
|
kern_linear_pte_xor[0] = _PAGE_VALID ^ PAGE_OFFSET;
|
||||||
|
@ -2465,8 +2497,8 @@ static void __init sun4v_pgprot_init(void)
|
||||||
kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^
|
kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^
|
||||||
PAGE_OFFSET;
|
PAGE_OFFSET;
|
||||||
#endif
|
#endif
|
||||||
kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V |
|
kern_linear_pte_xor[0] |= (page_cache4v_flag | _PAGE_P_4V |
|
||||||
_PAGE_P_4V | _PAGE_W_4V);
|
_PAGE_W_4V);
|
||||||
|
|
||||||
for (i = 1; i < 4; i++)
|
for (i = 1; i < 4; i++)
|
||||||
kern_linear_pte_xor[i] = kern_linear_pte_xor[0];
|
kern_linear_pte_xor[i] = kern_linear_pte_xor[0];
|
||||||
|
@ -2479,12 +2511,12 @@ static void __init sun4v_pgprot_init(void)
|
||||||
_PAGE_SZ4MB_4V | _PAGE_SZ512K_4V |
|
_PAGE_SZ4MB_4V | _PAGE_SZ512K_4V |
|
||||||
_PAGE_SZ64K_4V | _PAGE_SZ8K_4V);
|
_PAGE_SZ64K_4V | _PAGE_SZ8K_4V);
|
||||||
|
|
||||||
page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | _PAGE_CACHE_4V;
|
page_none = _PAGE_PRESENT_4V | _PAGE_ACCESSED_4V | page_cache4v_flag;
|
||||||
page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
|
page_shared = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
|
||||||
__ACCESS_BITS_4V | _PAGE_WRITE_4V | _PAGE_EXEC_4V);
|
__ACCESS_BITS_4V | _PAGE_WRITE_4V | _PAGE_EXEC_4V);
|
||||||
page_copy = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
|
page_copy = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
|
||||||
__ACCESS_BITS_4V | _PAGE_EXEC_4V);
|
__ACCESS_BITS_4V | _PAGE_EXEC_4V);
|
||||||
page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V |
|
page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | page_cache4v_flag |
|
||||||
__ACCESS_BITS_4V | _PAGE_EXEC_4V);
|
__ACCESS_BITS_4V | _PAGE_EXEC_4V);
|
||||||
|
|
||||||
page_exec_bit = _PAGE_EXEC_4V;
|
page_exec_bit = _PAGE_EXEC_4V;
|
||||||
|
@ -2542,7 +2574,7 @@ static unsigned long kern_large_tte(unsigned long paddr)
|
||||||
_PAGE_EXEC_4U | _PAGE_L_4U | _PAGE_W_4U);
|
_PAGE_EXEC_4U | _PAGE_L_4U | _PAGE_W_4U);
|
||||||
if (tlb_type == hypervisor)
|
if (tlb_type == hypervisor)
|
||||||
val = (_PAGE_VALID | _PAGE_SZ4MB_4V |
|
val = (_PAGE_VALID | _PAGE_SZ4MB_4V |
|
||||||
_PAGE_CP_4V | _PAGE_CV_4V | _PAGE_P_4V |
|
page_cache4v_flag | _PAGE_P_4V |
|
||||||
_PAGE_EXEC_4V | _PAGE_W_4V);
|
_PAGE_EXEC_4V | _PAGE_W_4V);
|
||||||
|
|
||||||
return val | paddr;
|
return val | paddr;
|
||||||
|
|
|
@ -2,15 +2,14 @@
|
||||||
#define BOOT_COMPRESSED_MISC_H
|
#define BOOT_COMPRESSED_MISC_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we have to be careful, because no indirections are allowed here, and
|
* Special hack: we have to be careful, because no indirections are allowed here,
|
||||||
* paravirt_ops is a kind of one. As it will only run in baremetal anyway,
|
* and paravirt_ops is a kind of one. As it will only run in baremetal anyway,
|
||||||
* we just keep it from happening
|
* we just keep it from happening. (This list needs to be extended when new
|
||||||
|
* paravirt and debugging variants are added.)
|
||||||
*/
|
*/
|
||||||
#undef CONFIG_PARAVIRT
|
#undef CONFIG_PARAVIRT
|
||||||
|
#undef CONFIG_PARAVIRT_SPINLOCKS
|
||||||
#undef CONFIG_KASAN
|
#undef CONFIG_KASAN
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
#define _ASM_X86_DESC_H 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <linux/screen_info.h>
|
#include <linux/screen_info.h>
|
||||||
|
|
|
@ -207,6 +207,7 @@ union kvm_mmu_page_role {
|
||||||
unsigned nxe:1;
|
unsigned nxe:1;
|
||||||
unsigned cr0_wp:1;
|
unsigned cr0_wp:1;
|
||||||
unsigned smep_andnot_wp:1;
|
unsigned smep_andnot_wp:1;
|
||||||
|
unsigned smap_andnot_wp:1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -400,6 +401,7 @@ struct kvm_vcpu_arch {
|
||||||
struct kvm_mmu_memory_cache mmu_page_header_cache;
|
struct kvm_mmu_memory_cache mmu_page_header_cache;
|
||||||
|
|
||||||
struct fpu guest_fpu;
|
struct fpu guest_fpu;
|
||||||
|
bool eager_fpu;
|
||||||
u64 xcr0;
|
u64 xcr0;
|
||||||
u64 guest_supported_xcr0;
|
u64 guest_supported_xcr0;
|
||||||
u32 guest_xstate_size;
|
u32 guest_xstate_size;
|
||||||
|
@ -743,6 +745,7 @@ struct kvm_x86_ops {
|
||||||
void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
|
void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
|
||||||
unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
|
unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
|
||||||
void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
|
void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
|
||||||
|
void (*fpu_activate)(struct kvm_vcpu *vcpu);
|
||||||
void (*fpu_deactivate)(struct kvm_vcpu *vcpu);
|
void (*fpu_deactivate)(struct kvm_vcpu *vcpu);
|
||||||
|
|
||||||
void (*tlb_flush)(struct kvm_vcpu *vcpu);
|
void (*tlb_flush)(struct kvm_vcpu *vcpu);
|
||||||
|
|
|
@ -107,7 +107,7 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
|
||||||
static inline int user_mode(struct pt_regs *regs)
|
static inline int user_mode(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
return (regs->cs & SEGMENT_RPL_MASK) == USER_RPL;
|
return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >= USER_RPL;
|
||||||
#else
|
#else
|
||||||
return !!(regs->cs & 3);
|
return !!(regs->cs & 3);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -231,11 +231,21 @@
|
||||||
#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES* 8)
|
#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES* 8)
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* early_idt_handler_array is an array of entry points referenced in the
|
||||||
|
* early IDT. For simplicity, it's a real array with one entry point
|
||||||
|
* every nine bytes. That leaves room for an optional 'push $0' if the
|
||||||
|
* vector has no error code (two bytes), a 'push $vector_number' (two
|
||||||
|
* bytes), and a jump to the common entry code (up to five bytes).
|
||||||
|
*/
|
||||||
|
#define EARLY_IDT_HANDLER_SIZE 9
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS][2+2+5];
|
extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE];
|
||||||
#ifdef CONFIG_TRACING
|
#ifdef CONFIG_TRACING
|
||||||
# define trace_early_idt_handlers early_idt_handlers
|
# define trace_early_idt_handler_array early_idt_handler_array
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -140,6 +140,7 @@
|
||||||
#define MSR_CORE_C3_RESIDENCY 0x000003fc
|
#define MSR_CORE_C3_RESIDENCY 0x000003fc
|
||||||
#define MSR_CORE_C6_RESIDENCY 0x000003fd
|
#define MSR_CORE_C6_RESIDENCY 0x000003fd
|
||||||
#define MSR_CORE_C7_RESIDENCY 0x000003fe
|
#define MSR_CORE_C7_RESIDENCY 0x000003fe
|
||||||
|
#define MSR_KNL_CORE_C6_RESIDENCY 0x000003ff
|
||||||
#define MSR_PKG_C2_RESIDENCY 0x0000060d
|
#define MSR_PKG_C2_RESIDENCY 0x0000060d
|
||||||
#define MSR_PKG_C8_RESIDENCY 0x00000630
|
#define MSR_PKG_C8_RESIDENCY 0x00000630
|
||||||
#define MSR_PKG_C9_RESIDENCY 0x00000631
|
#define MSR_PKG_C9_RESIDENCY 0x00000631
|
||||||
|
|
|
@ -708,6 +708,7 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
for (i = 0; i < mca_cfg.banks; i++) {
|
for (i = 0; i < mca_cfg.banks; i++) {
|
||||||
m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
|
m->status = mce_rdmsrl(MSR_IA32_MCx_STATUS(i));
|
||||||
|
@ -716,9 +717,11 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
|
||||||
if (quirk_no_way_out)
|
if (quirk_no_way_out)
|
||||||
quirk_no_way_out(i, m, regs);
|
quirk_no_way_out(i, m, regs);
|
||||||
}
|
}
|
||||||
if (mce_severity(m, mca_cfg.tolerant, msg, true) >=
|
|
||||||
MCE_PANIC_SEVERITY)
|
if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
|
||||||
|
*msg = tmp;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,6 +190,7 @@ static bool check_hw_exists(void)
|
||||||
u64 val, val_fail, val_new= ~0;
|
u64 val, val_fail, val_new= ~0;
|
||||||
int i, reg, reg_fail, ret = 0;
|
int i, reg, reg_fail, ret = 0;
|
||||||
int bios_fail = 0;
|
int bios_fail = 0;
|
||||||
|
int reg_safe = -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to see if the BIOS enabled any of the counters, if so
|
* Check to see if the BIOS enabled any of the counters, if so
|
||||||
|
@ -204,6 +205,8 @@ static bool check_hw_exists(void)
|
||||||
bios_fail = 1;
|
bios_fail = 1;
|
||||||
val_fail = val;
|
val_fail = val;
|
||||||
reg_fail = reg;
|
reg_fail = reg;
|
||||||
|
} else {
|
||||||
|
reg_safe = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,12 +224,23 @@ static bool check_hw_exists(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If all the counters are enabled, the below test will always
|
||||||
|
* fail. The tools will also become useless in this scenario.
|
||||||
|
* Just fail and disable the hardware counters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (reg_safe == -1) {
|
||||||
|
reg = reg_safe;
|
||||||
|
goto msr_fail;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the current value, change it and read it back to see if it
|
* Read the current value, change it and read it back to see if it
|
||||||
* matches, this is needed to detect certain hardware emulators
|
* matches, this is needed to detect certain hardware emulators
|
||||||
* (qemu/kvm) that don't trap on the MSR access and always return 0s.
|
* (qemu/kvm) that don't trap on the MSR access and always return 0s.
|
||||||
*/
|
*/
|
||||||
reg = x86_pmu_event_addr(0);
|
reg = x86_pmu_event_addr(reg_safe);
|
||||||
if (rdmsrl_safe(reg, &val))
|
if (rdmsrl_safe(reg, &val))
|
||||||
goto msr_fail;
|
goto msr_fail;
|
||||||
val ^= 0xffffUL;
|
val ^= 0xffffUL;
|
||||||
|
@ -611,6 +625,7 @@ struct sched_state {
|
||||||
int event; /* event index */
|
int event; /* event index */
|
||||||
int counter; /* counter index */
|
int counter; /* counter index */
|
||||||
int unassigned; /* number of events to be assigned left */
|
int unassigned; /* number of events to be assigned left */
|
||||||
|
int nr_gp; /* number of GP counters used */
|
||||||
unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
|
unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -620,27 +635,29 @@ struct sched_state {
|
||||||
struct perf_sched {
|
struct perf_sched {
|
||||||
int max_weight;
|
int max_weight;
|
||||||
int max_events;
|
int max_events;
|
||||||
struct perf_event **events;
|
int max_gp;
|
||||||
struct sched_state state;
|
|
||||||
int saved_states;
|
int saved_states;
|
||||||
|
struct event_constraint **constraints;
|
||||||
|
struct sched_state state;
|
||||||
struct sched_state saved[SCHED_STATES_MAX];
|
struct sched_state saved[SCHED_STATES_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize interator that runs through all events and counters.
|
* Initialize interator that runs through all events and counters.
|
||||||
*/
|
*/
|
||||||
static void perf_sched_init(struct perf_sched *sched, struct perf_event **events,
|
static void perf_sched_init(struct perf_sched *sched, struct event_constraint **constraints,
|
||||||
int num, int wmin, int wmax)
|
int num, int wmin, int wmax, int gpmax)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
memset(sched, 0, sizeof(*sched));
|
memset(sched, 0, sizeof(*sched));
|
||||||
sched->max_events = num;
|
sched->max_events = num;
|
||||||
sched->max_weight = wmax;
|
sched->max_weight = wmax;
|
||||||
sched->events = events;
|
sched->max_gp = gpmax;
|
||||||
|
sched->constraints = constraints;
|
||||||
|
|
||||||
for (idx = 0; idx < num; idx++) {
|
for (idx = 0; idx < num; idx++) {
|
||||||
if (events[idx]->hw.constraint->weight == wmin)
|
if (constraints[idx]->weight == wmin)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,7 +704,7 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
|
||||||
if (sched->state.event >= sched->max_events)
|
if (sched->state.event >= sched->max_events)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
c = sched->events[sched->state.event]->hw.constraint;
|
c = sched->constraints[sched->state.event];
|
||||||
/* Prefer fixed purpose counters */
|
/* Prefer fixed purpose counters */
|
||||||
if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
|
if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
|
||||||
idx = INTEL_PMC_IDX_FIXED;
|
idx = INTEL_PMC_IDX_FIXED;
|
||||||
|
@ -696,11 +713,16 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grab the first unused counter starting with idx */
|
/* Grab the first unused counter starting with idx */
|
||||||
idx = sched->state.counter;
|
idx = sched->state.counter;
|
||||||
for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
|
for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
|
||||||
if (!__test_and_set_bit(idx, sched->state.used))
|
if (!__test_and_set_bit(idx, sched->state.used)) {
|
||||||
|
if (sched->state.nr_gp++ >= sched->max_gp)
|
||||||
|
return false;
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -745,7 +767,7 @@ static bool perf_sched_next_event(struct perf_sched *sched)
|
||||||
if (sched->state.weight > sched->max_weight)
|
if (sched->state.weight > sched->max_weight)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
c = sched->events[sched->state.event]->hw.constraint;
|
c = sched->constraints[sched->state.event];
|
||||||
} while (c->weight != sched->state.weight);
|
} while (c->weight != sched->state.weight);
|
||||||
|
|
||||||
sched->state.counter = 0; /* start with first counter */
|
sched->state.counter = 0; /* start with first counter */
|
||||||
|
@ -756,12 +778,12 @@ static bool perf_sched_next_event(struct perf_sched *sched)
|
||||||
/*
|
/*
|
||||||
* Assign a counter for each event.
|
* Assign a counter for each event.
|
||||||
*/
|
*/
|
||||||
int perf_assign_events(struct perf_event **events, int n,
|
int perf_assign_events(struct event_constraint **constraints, int n,
|
||||||
int wmin, int wmax, int *assign)
|
int wmin, int wmax, int gpmax, int *assign)
|
||||||
{
|
{
|
||||||
struct perf_sched sched;
|
struct perf_sched sched;
|
||||||
|
|
||||||
perf_sched_init(&sched, events, n, wmin, wmax);
|
perf_sched_init(&sched, constraints, n, wmin, wmax, gpmax);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!perf_sched_find_counter(&sched))
|
if (!perf_sched_find_counter(&sched))
|
||||||
|
@ -788,9 +810,9 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
|
||||||
x86_pmu.start_scheduling(cpuc);
|
x86_pmu.start_scheduling(cpuc);
|
||||||
|
|
||||||
for (i = 0, wmin = X86_PMC_IDX_MAX, wmax = 0; i < n; i++) {
|
for (i = 0, wmin = X86_PMC_IDX_MAX, wmax = 0; i < n; i++) {
|
||||||
hwc = &cpuc->event_list[i]->hw;
|
cpuc->event_constraint[i] = NULL;
|
||||||
c = x86_pmu.get_event_constraints(cpuc, i, cpuc->event_list[i]);
|
c = x86_pmu.get_event_constraints(cpuc, i, cpuc->event_list[i]);
|
||||||
hwc->constraint = c;
|
cpuc->event_constraint[i] = c;
|
||||||
|
|
||||||
wmin = min(wmin, c->weight);
|
wmin = min(wmin, c->weight);
|
||||||
wmax = max(wmax, c->weight);
|
wmax = max(wmax, c->weight);
|
||||||
|
@ -801,7 +823,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
hwc = &cpuc->event_list[i]->hw;
|
hwc = &cpuc->event_list[i]->hw;
|
||||||
c = hwc->constraint;
|
c = cpuc->event_constraint[i];
|
||||||
|
|
||||||
/* never assigned */
|
/* never assigned */
|
||||||
if (hwc->idx == -1)
|
if (hwc->idx == -1)
|
||||||
|
@ -821,9 +843,26 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* slow path */
|
/* slow path */
|
||||||
if (i != n)
|
if (i != n) {
|
||||||
unsched = perf_assign_events(cpuc->event_list, n, wmin,
|
int gpmax = x86_pmu.num_counters;
|
||||||
wmax, assign);
|
|
||||||
|
/*
|
||||||
|
* Do not allow scheduling of more than half the available
|
||||||
|
* generic counters.
|
||||||
|
*
|
||||||
|
* This helps avoid counter starvation of sibling thread by
|
||||||
|
* ensuring at most half the counters cannot be in exclusive
|
||||||
|
* mode. There is no designated counters for the limits. Any
|
||||||
|
* N/2 counters can be used. This helps with events with
|
||||||
|
* specific counter constraints.
|
||||||
|
*/
|
||||||
|
if (is_ht_workaround_enabled() && !cpuc->is_fake &&
|
||||||
|
READ_ONCE(cpuc->excl_cntrs->exclusive_present))
|
||||||
|
gpmax /= 2;
|
||||||
|
|
||||||
|
unsched = perf_assign_events(cpuc->event_constraint, n, wmin,
|
||||||
|
wmax, gpmax, assign);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In case of success (unsched = 0), mark events as committed,
|
* In case of success (unsched = 0), mark events as committed,
|
||||||
|
@ -840,7 +879,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
|
||||||
e = cpuc->event_list[i];
|
e = cpuc->event_list[i];
|
||||||
e->hw.flags |= PERF_X86_EVENT_COMMITTED;
|
e->hw.flags |= PERF_X86_EVENT_COMMITTED;
|
||||||
if (x86_pmu.commit_scheduling)
|
if (x86_pmu.commit_scheduling)
|
||||||
x86_pmu.commit_scheduling(cpuc, e, assign[i]);
|
x86_pmu.commit_scheduling(cpuc, i, assign[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1292,8 +1331,10 @@ static void x86_pmu_del(struct perf_event *event, int flags)
|
||||||
x86_pmu.put_event_constraints(cpuc, event);
|
x86_pmu.put_event_constraints(cpuc, event);
|
||||||
|
|
||||||
/* Delete the array entry. */
|
/* Delete the array entry. */
|
||||||
while (++i < cpuc->n_events)
|
while (++i < cpuc->n_events) {
|
||||||
cpuc->event_list[i-1] = cpuc->event_list[i];
|
cpuc->event_list[i-1] = cpuc->event_list[i];
|
||||||
|
cpuc->event_constraint[i-1] = cpuc->event_constraint[i];
|
||||||
|
}
|
||||||
--cpuc->n_events;
|
--cpuc->n_events;
|
||||||
|
|
||||||
perf_event_update_userpage(event);
|
perf_event_update_userpage(event);
|
||||||
|
|
|
@ -74,6 +74,7 @@ struct event_constraint {
|
||||||
#define PERF_X86_EVENT_EXCL 0x0040 /* HT exclusivity on counter */
|
#define PERF_X86_EVENT_EXCL 0x0040 /* HT exclusivity on counter */
|
||||||
#define PERF_X86_EVENT_DYNAMIC 0x0080 /* dynamic alloc'd constraint */
|
#define PERF_X86_EVENT_DYNAMIC 0x0080 /* dynamic alloc'd constraint */
|
||||||
#define PERF_X86_EVENT_RDPMC_ALLOWED 0x0100 /* grant rdpmc permission */
|
#define PERF_X86_EVENT_RDPMC_ALLOWED 0x0100 /* grant rdpmc permission */
|
||||||
|
#define PERF_X86_EVENT_EXCL_ACCT 0x0200 /* accounted EXCL event */
|
||||||
|
|
||||||
|
|
||||||
struct amd_nb {
|
struct amd_nb {
|
||||||
|
@ -134,8 +135,6 @@ enum intel_excl_state_type {
|
||||||
struct intel_excl_states {
|
struct intel_excl_states {
|
||||||
enum intel_excl_state_type init_state[X86_PMC_IDX_MAX];
|
enum intel_excl_state_type init_state[X86_PMC_IDX_MAX];
|
||||||
enum intel_excl_state_type state[X86_PMC_IDX_MAX];
|
enum intel_excl_state_type state[X86_PMC_IDX_MAX];
|
||||||
int num_alloc_cntrs;/* #counters allocated */
|
|
||||||
int max_alloc_cntrs;/* max #counters allowed */
|
|
||||||
bool sched_started; /* true if scheduling has started */
|
bool sched_started; /* true if scheduling has started */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -144,6 +143,11 @@ struct intel_excl_cntrs {
|
||||||
|
|
||||||
struct intel_excl_states states[2];
|
struct intel_excl_states states[2];
|
||||||
|
|
||||||
|
union {
|
||||||
|
u16 has_exclusive[2];
|
||||||
|
u32 exclusive_present;
|
||||||
|
};
|
||||||
|
|
||||||
int refcnt; /* per-core: #HT threads */
|
int refcnt; /* per-core: #HT threads */
|
||||||
unsigned core_id; /* per-core: core id */
|
unsigned core_id; /* per-core: core id */
|
||||||
};
|
};
|
||||||
|
@ -172,7 +176,11 @@ struct cpu_hw_events {
|
||||||
added in the current transaction */
|
added in the current transaction */
|
||||||
int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
|
int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */
|
||||||
u64 tags[X86_PMC_IDX_MAX];
|
u64 tags[X86_PMC_IDX_MAX];
|
||||||
|
|
||||||
struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
|
struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */
|
||||||
|
struct event_constraint *event_constraint[X86_PMC_IDX_MAX];
|
||||||
|
|
||||||
|
int n_excl; /* the number of exclusive events */
|
||||||
|
|
||||||
unsigned int group_flag;
|
unsigned int group_flag;
|
||||||
int is_fake;
|
int is_fake;
|
||||||
|
@ -519,9 +527,7 @@ struct x86_pmu {
|
||||||
void (*put_event_constraints)(struct cpu_hw_events *cpuc,
|
void (*put_event_constraints)(struct cpu_hw_events *cpuc,
|
||||||
struct perf_event *event);
|
struct perf_event *event);
|
||||||
|
|
||||||
void (*commit_scheduling)(struct cpu_hw_events *cpuc,
|
void (*commit_scheduling)(struct cpu_hw_events *cpuc, int idx, int cntr);
|
||||||
struct perf_event *event,
|
|
||||||
int cntr);
|
|
||||||
|
|
||||||
void (*start_scheduling)(struct cpu_hw_events *cpuc);
|
void (*start_scheduling)(struct cpu_hw_events *cpuc);
|
||||||
|
|
||||||
|
@ -717,8 +723,8 @@ static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
|
||||||
|
|
||||||
void x86_pmu_enable_all(int added);
|
void x86_pmu_enable_all(int added);
|
||||||
|
|
||||||
int perf_assign_events(struct perf_event **events, int n,
|
int perf_assign_events(struct event_constraint **constraints, int n,
|
||||||
int wmin, int wmax, int *assign);
|
int wmin, int wmax, int gpmax, int *assign);
|
||||||
int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
|
int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
|
||||||
|
|
||||||
void x86_pmu_stop(struct perf_event *event, int flags);
|
void x86_pmu_stop(struct perf_event *event, int flags);
|
||||||
|
@ -929,4 +935,8 @@ static inline struct intel_shared_regs *allocate_shared_regs(int cpu)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int is_ht_workaround_enabled(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* CONFIG_CPU_SUP_INTEL */
|
#endif /* CONFIG_CPU_SUP_INTEL */
|
||||||
|
|
|
@ -1923,7 +1923,6 @@ intel_start_scheduling(struct cpu_hw_events *cpuc)
|
||||||
xl = &excl_cntrs->states[tid];
|
xl = &excl_cntrs->states[tid];
|
||||||
|
|
||||||
xl->sched_started = true;
|
xl->sched_started = true;
|
||||||
xl->num_alloc_cntrs = 0;
|
|
||||||
/*
|
/*
|
||||||
* lock shared state until we are done scheduling
|
* lock shared state until we are done scheduling
|
||||||
* in stop_event_scheduling()
|
* in stop_event_scheduling()
|
||||||
|
@ -2000,6 +1999,11 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
|
||||||
* across HT threads
|
* across HT threads
|
||||||
*/
|
*/
|
||||||
is_excl = c->flags & PERF_X86_EVENT_EXCL;
|
is_excl = c->flags & PERF_X86_EVENT_EXCL;
|
||||||
|
if (is_excl && !(event->hw.flags & PERF_X86_EVENT_EXCL_ACCT)) {
|
||||||
|
event->hw.flags |= PERF_X86_EVENT_EXCL_ACCT;
|
||||||
|
if (!cpuc->n_excl++)
|
||||||
|
WRITE_ONCE(excl_cntrs->has_exclusive[tid], 1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xl = state of current HT
|
* xl = state of current HT
|
||||||
|
@ -2008,18 +2012,6 @@ intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
|
||||||
xl = &excl_cntrs->states[tid];
|
xl = &excl_cntrs->states[tid];
|
||||||
xlo = &excl_cntrs->states[o_tid];
|
xlo = &excl_cntrs->states[o_tid];
|
||||||
|
|
||||||
/*
|
|
||||||
* do not allow scheduling of more than max_alloc_cntrs
|
|
||||||
* which is set to half the available generic counters.
|
|
||||||
* this helps avoid counter starvation of sibling thread
|
|
||||||
* by ensuring at most half the counters cannot be in
|
|
||||||
* exclusive mode. There is not designated counters for the
|
|
||||||
* limits. Any N/2 counters can be used. This helps with
|
|
||||||
* events with specifix counter constraints
|
|
||||||
*/
|
|
||||||
if (xl->num_alloc_cntrs++ == xl->max_alloc_cntrs)
|
|
||||||
return &emptyconstraint;
|
|
||||||
|
|
||||||
cx = c;
|
cx = c;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2106,7 +2098,7 @@ static struct event_constraint *
|
||||||
intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
|
intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
|
||||||
struct perf_event *event)
|
struct perf_event *event)
|
||||||
{
|
{
|
||||||
struct event_constraint *c1 = event->hw.constraint;
|
struct event_constraint *c1 = cpuc->event_constraint[idx];
|
||||||
struct event_constraint *c2;
|
struct event_constraint *c2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2150,6 +2142,11 @@ static void intel_put_excl_constraints(struct cpu_hw_events *cpuc,
|
||||||
|
|
||||||
xl = &excl_cntrs->states[tid];
|
xl = &excl_cntrs->states[tid];
|
||||||
xlo = &excl_cntrs->states[o_tid];
|
xlo = &excl_cntrs->states[o_tid];
|
||||||
|
if (hwc->flags & PERF_X86_EVENT_EXCL_ACCT) {
|
||||||
|
hwc->flags &= ~PERF_X86_EVENT_EXCL_ACCT;
|
||||||
|
if (!--cpuc->n_excl)
|
||||||
|
WRITE_ONCE(excl_cntrs->has_exclusive[tid], 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* put_constraint may be called from x86_schedule_events()
|
* put_constraint may be called from x86_schedule_events()
|
||||||
|
@ -2188,8 +2185,6 @@ intel_put_shared_regs_event_constraints(struct cpu_hw_events *cpuc,
|
||||||
static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
|
static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
|
||||||
struct perf_event *event)
|
struct perf_event *event)
|
||||||
{
|
{
|
||||||
struct event_constraint *c = event->hw.constraint;
|
|
||||||
|
|
||||||
intel_put_shared_regs_event_constraints(cpuc, event);
|
intel_put_shared_regs_event_constraints(cpuc, event);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2197,19 +2192,14 @@ static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
|
||||||
* all events are subject to and must call the
|
* all events are subject to and must call the
|
||||||
* put_excl_constraints() routine
|
* put_excl_constraints() routine
|
||||||
*/
|
*/
|
||||||
if (c && cpuc->excl_cntrs)
|
if (cpuc->excl_cntrs)
|
||||||
intel_put_excl_constraints(cpuc, event);
|
intel_put_excl_constraints(cpuc, event);
|
||||||
|
|
||||||
/* cleanup dynamic constraint */
|
|
||||||
if (c && (c->flags & PERF_X86_EVENT_DYNAMIC))
|
|
||||||
event->hw.constraint = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intel_commit_scheduling(struct cpu_hw_events *cpuc,
|
static void intel_commit_scheduling(struct cpu_hw_events *cpuc, int idx, int cntr)
|
||||||
struct perf_event *event, int cntr)
|
|
||||||
{
|
{
|
||||||
struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
|
struct intel_excl_cntrs *excl_cntrs = cpuc->excl_cntrs;
|
||||||
struct event_constraint *c = event->hw.constraint;
|
struct event_constraint *c = cpuc->event_constraint[idx];
|
||||||
struct intel_excl_states *xlo, *xl;
|
struct intel_excl_states *xlo, *xl;
|
||||||
int tid = cpuc->excl_thread_id;
|
int tid = cpuc->excl_thread_id;
|
||||||
int o_tid = 1 - tid;
|
int o_tid = 1 - tid;
|
||||||
|
@ -2639,8 +2629,6 @@ static void intel_pmu_cpu_starting(int cpu)
|
||||||
cpuc->lbr_sel = &cpuc->shared_regs->regs[EXTRA_REG_LBR];
|
cpuc->lbr_sel = &cpuc->shared_regs->regs[EXTRA_REG_LBR];
|
||||||
|
|
||||||
if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
|
if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
|
||||||
int h = x86_pmu.num_counters >> 1;
|
|
||||||
|
|
||||||
for_each_cpu(i, topology_thread_cpumask(cpu)) {
|
for_each_cpu(i, topology_thread_cpumask(cpu)) {
|
||||||
struct intel_excl_cntrs *c;
|
struct intel_excl_cntrs *c;
|
||||||
|
|
||||||
|
@ -2654,11 +2642,6 @@ static void intel_pmu_cpu_starting(int cpu)
|
||||||
}
|
}
|
||||||
cpuc->excl_cntrs->core_id = core_id;
|
cpuc->excl_cntrs->core_id = core_id;
|
||||||
cpuc->excl_cntrs->refcnt++;
|
cpuc->excl_cntrs->refcnt++;
|
||||||
/*
|
|
||||||
* set hard limit to half the number of generic counters
|
|
||||||
*/
|
|
||||||
cpuc->excl_cntrs->states[0].max_alloc_cntrs = h;
|
|
||||||
cpuc->excl_cntrs->states[1].max_alloc_cntrs = h;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -706,9 +706,9 @@ void intel_pmu_pebs_disable(struct perf_event *event)
|
||||||
|
|
||||||
cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
|
cpuc->pebs_enabled &= ~(1ULL << hwc->idx);
|
||||||
|
|
||||||
if (event->hw.constraint->flags & PERF_X86_EVENT_PEBS_LDLAT)
|
if (event->hw.flags & PERF_X86_EVENT_PEBS_LDLAT)
|
||||||
cpuc->pebs_enabled &= ~(1ULL << (hwc->idx + 32));
|
cpuc->pebs_enabled &= ~(1ULL << (hwc->idx + 32));
|
||||||
else if (event->hw.constraint->flags & PERF_X86_EVENT_PEBS_ST)
|
else if (event->hw.flags & PERF_X86_EVENT_PEBS_ST)
|
||||||
cpuc->pebs_enabled &= ~(1ULL << 63);
|
cpuc->pebs_enabled &= ~(1ULL << 63);
|
||||||
|
|
||||||
if (cpuc->enabled)
|
if (cpuc->enabled)
|
||||||
|
|
|
@ -151,7 +151,7 @@ static int __init pt_pmu_hw_init(void)
|
||||||
|
|
||||||
de_attr->attr.attr.name = pt_caps[i].name;
|
de_attr->attr.attr.name = pt_caps[i].name;
|
||||||
|
|
||||||
sysfs_attr_init(&de_attrs->attr.attr);
|
sysfs_attr_init(&de_attr->attr.attr);
|
||||||
|
|
||||||
de_attr->attr.attr.mode = S_IRUGO;
|
de_attr->attr.attr.mode = S_IRUGO;
|
||||||
de_attr->attr.show = pt_cap_show;
|
de_attr->attr.show = pt_cap_show;
|
||||||
|
@ -615,7 +615,8 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
|
||||||
struct perf_output_handle *handle)
|
struct perf_output_handle *handle)
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned long idx, npages, end;
|
unsigned long head = local64_read(&buf->head);
|
||||||
|
unsigned long idx, npages, wakeup;
|
||||||
|
|
||||||
if (buf->snapshot)
|
if (buf->snapshot)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -634,17 +635,26 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
|
||||||
buf->topa_index[buf->stop_pos]->stop = 0;
|
buf->topa_index[buf->stop_pos]->stop = 0;
|
||||||
buf->topa_index[buf->intr_pos]->intr = 0;
|
buf->topa_index[buf->intr_pos]->intr = 0;
|
||||||
|
|
||||||
if (pt_cap_get(PT_CAP_topa_multiple_entries)) {
|
/* how many pages till the STOP marker */
|
||||||
npages = (handle->size + 1) >> PAGE_SHIFT;
|
npages = handle->size >> PAGE_SHIFT;
|
||||||
end = (local64_read(&buf->head) >> PAGE_SHIFT) + npages;
|
|
||||||
/*if (end > handle->wakeup >> PAGE_SHIFT)
|
/* if it's on a page boundary, fill up one more page */
|
||||||
end = handle->wakeup >> PAGE_SHIFT;*/
|
if (!offset_in_page(head + handle->size + 1))
|
||||||
idx = end & (buf->nr_pages - 1);
|
npages++;
|
||||||
buf->stop_pos = idx;
|
|
||||||
idx = (local64_read(&buf->head) >> PAGE_SHIFT) + npages - 1;
|
idx = (head >> PAGE_SHIFT) + npages;
|
||||||
idx &= buf->nr_pages - 1;
|
idx &= buf->nr_pages - 1;
|
||||||
buf->intr_pos = idx;
|
buf->stop_pos = idx;
|
||||||
}
|
|
||||||
|
wakeup = handle->wakeup >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
/* in the worst case, wake up the consumer one page before hard stop */
|
||||||
|
idx = (head >> PAGE_SHIFT) + npages - 1;
|
||||||
|
if (idx > wakeup)
|
||||||
|
idx = wakeup;
|
||||||
|
|
||||||
|
idx &= buf->nr_pages - 1;
|
||||||
|
buf->intr_pos = idx;
|
||||||
|
|
||||||
buf->topa_index[buf->stop_pos]->stop = 1;
|
buf->topa_index[buf->stop_pos]->stop = 1;
|
||||||
buf->topa_index[buf->intr_pos]->intr = 1;
|
buf->topa_index[buf->intr_pos]->intr = 1;
|
||||||
|
|
|
@ -365,9 +365,8 @@ static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int
|
||||||
bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX);
|
bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX);
|
||||||
|
|
||||||
for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) {
|
for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) {
|
||||||
hwc = &box->event_list[i]->hw;
|
|
||||||
c = uncore_get_event_constraint(box, box->event_list[i]);
|
c = uncore_get_event_constraint(box, box->event_list[i]);
|
||||||
hwc->constraint = c;
|
box->event_constraint[i] = c;
|
||||||
wmin = min(wmin, c->weight);
|
wmin = min(wmin, c->weight);
|
||||||
wmax = max(wmax, c->weight);
|
wmax = max(wmax, c->weight);
|
||||||
}
|
}
|
||||||
|
@ -375,7 +374,7 @@ static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int
|
||||||
/* fastpath, try to reuse previous register */
|
/* fastpath, try to reuse previous register */
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
hwc = &box->event_list[i]->hw;
|
hwc = &box->event_list[i]->hw;
|
||||||
c = hwc->constraint;
|
c = box->event_constraint[i];
|
||||||
|
|
||||||
/* never assigned */
|
/* never assigned */
|
||||||
if (hwc->idx == -1)
|
if (hwc->idx == -1)
|
||||||
|
@ -395,8 +394,8 @@ static int uncore_assign_events(struct intel_uncore_box *box, int assign[], int
|
||||||
}
|
}
|
||||||
/* slow path */
|
/* slow path */
|
||||||
if (i != n)
|
if (i != n)
|
||||||
ret = perf_assign_events(box->event_list, n,
|
ret = perf_assign_events(box->event_constraint, n,
|
||||||
wmin, wmax, assign);
|
wmin, wmax, n, assign);
|
||||||
|
|
||||||
if (!assign || ret) {
|
if (!assign || ret) {
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
|
|
|
@ -97,6 +97,7 @@ struct intel_uncore_box {
|
||||||
atomic_t refcnt;
|
atomic_t refcnt;
|
||||||
struct perf_event *events[UNCORE_PMC_IDX_MAX];
|
struct perf_event *events[UNCORE_PMC_IDX_MAX];
|
||||||
struct perf_event *event_list[UNCORE_PMC_IDX_MAX];
|
struct perf_event *event_list[UNCORE_PMC_IDX_MAX];
|
||||||
|
struct event_constraint *event_constraint[UNCORE_PMC_IDX_MAX];
|
||||||
unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
|
unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
|
||||||
u64 tags[UNCORE_PMC_IDX_MAX];
|
u64 tags[UNCORE_PMC_IDX_MAX];
|
||||||
struct pci_dev *pci_dev;
|
struct pci_dev *pci_dev;
|
||||||
|
|
|
@ -167,7 +167,7 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
|
||||||
clear_bss();
|
clear_bss();
|
||||||
|
|
||||||
for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
|
for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
|
||||||
set_intr_gate(i, early_idt_handlers[i]);
|
set_intr_gate(i, early_idt_handler_array[i]);
|
||||||
load_idt((const struct desc_ptr *)&idt_descr);
|
load_idt((const struct desc_ptr *)&idt_descr);
|
||||||
|
|
||||||
copy_bootdata(__va(real_mode_data));
|
copy_bootdata(__va(real_mode_data));
|
||||||
|
|
|
@ -478,21 +478,22 @@ is486:
|
||||||
__INIT
|
__INIT
|
||||||
setup_once:
|
setup_once:
|
||||||
/*
|
/*
|
||||||
* Set up a idt with 256 entries pointing to ignore_int,
|
* Set up a idt with 256 interrupt gates that push zero if there
|
||||||
* interrupt gates. It doesn't actually load idt - that needs
|
* is no error code and then jump to early_idt_handler_common.
|
||||||
* to be done on each CPU. Interrupts are enabled elsewhere,
|
* It doesn't actually load the idt - that needs to be done on
|
||||||
* when we can be relatively sure everything is ok.
|
* each CPU. Interrupts are enabled elsewhere, when we can be
|
||||||
|
* relatively sure everything is ok.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
movl $idt_table,%edi
|
movl $idt_table,%edi
|
||||||
movl $early_idt_handlers,%eax
|
movl $early_idt_handler_array,%eax
|
||||||
movl $NUM_EXCEPTION_VECTORS,%ecx
|
movl $NUM_EXCEPTION_VECTORS,%ecx
|
||||||
1:
|
1:
|
||||||
movl %eax,(%edi)
|
movl %eax,(%edi)
|
||||||
movl %eax,4(%edi)
|
movl %eax,4(%edi)
|
||||||
/* interrupt gate, dpl=0, present */
|
/* interrupt gate, dpl=0, present */
|
||||||
movl $(0x8E000000 + __KERNEL_CS),2(%edi)
|
movl $(0x8E000000 + __KERNEL_CS),2(%edi)
|
||||||
addl $9,%eax
|
addl $EARLY_IDT_HANDLER_SIZE,%eax
|
||||||
addl $8,%edi
|
addl $8,%edi
|
||||||
loop 1b
|
loop 1b
|
||||||
|
|
||||||
|
@ -524,26 +525,28 @@ setup_once:
|
||||||
andl $0,setup_once_ref /* Once is enough, thanks */
|
andl $0,setup_once_ref /* Once is enough, thanks */
|
||||||
ret
|
ret
|
||||||
|
|
||||||
ENTRY(early_idt_handlers)
|
ENTRY(early_idt_handler_array)
|
||||||
# 36(%esp) %eflags
|
# 36(%esp) %eflags
|
||||||
# 32(%esp) %cs
|
# 32(%esp) %cs
|
||||||
# 28(%esp) %eip
|
# 28(%esp) %eip
|
||||||
# 24(%rsp) error code
|
# 24(%rsp) error code
|
||||||
i = 0
|
i = 0
|
||||||
.rept NUM_EXCEPTION_VECTORS
|
.rept NUM_EXCEPTION_VECTORS
|
||||||
.if (EXCEPTION_ERRCODE_MASK >> i) & 1
|
.ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1
|
||||||
ASM_NOP2
|
|
||||||
.else
|
|
||||||
pushl $0 # Dummy error code, to make stack frame uniform
|
pushl $0 # Dummy error code, to make stack frame uniform
|
||||||
.endif
|
.endif
|
||||||
pushl $i # 20(%esp) Vector number
|
pushl $i # 20(%esp) Vector number
|
||||||
jmp early_idt_handler
|
jmp early_idt_handler_common
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
.fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
|
||||||
.endr
|
.endr
|
||||||
ENDPROC(early_idt_handlers)
|
ENDPROC(early_idt_handler_array)
|
||||||
|
|
||||||
/* This is global to keep gas from relaxing the jumps */
|
early_idt_handler_common:
|
||||||
ENTRY(early_idt_handler)
|
/*
|
||||||
|
* The stack is the hardware frame, an error code or zero, and the
|
||||||
|
* vector number.
|
||||||
|
*/
|
||||||
cld
|
cld
|
||||||
|
|
||||||
cmpl $2,(%esp) # X86_TRAP_NMI
|
cmpl $2,(%esp) # X86_TRAP_NMI
|
||||||
|
@ -603,7 +606,7 @@ ex_entry:
|
||||||
is_nmi:
|
is_nmi:
|
||||||
addl $8,%esp /* drop vector number and error code */
|
addl $8,%esp /* drop vector number and error code */
|
||||||
iret
|
iret
|
||||||
ENDPROC(early_idt_handler)
|
ENDPROC(early_idt_handler_common)
|
||||||
|
|
||||||
/* This is the default interrupt "handler" :-) */
|
/* This is the default interrupt "handler" :-) */
|
||||||
ALIGN
|
ALIGN
|
||||||
|
|
|
@ -321,26 +321,28 @@ bad_address:
|
||||||
jmp bad_address
|
jmp bad_address
|
||||||
|
|
||||||
__INIT
|
__INIT
|
||||||
.globl early_idt_handlers
|
ENTRY(early_idt_handler_array)
|
||||||
early_idt_handlers:
|
|
||||||
# 104(%rsp) %rflags
|
# 104(%rsp) %rflags
|
||||||
# 96(%rsp) %cs
|
# 96(%rsp) %cs
|
||||||
# 88(%rsp) %rip
|
# 88(%rsp) %rip
|
||||||
# 80(%rsp) error code
|
# 80(%rsp) error code
|
||||||
i = 0
|
i = 0
|
||||||
.rept NUM_EXCEPTION_VECTORS
|
.rept NUM_EXCEPTION_VECTORS
|
||||||
.if (EXCEPTION_ERRCODE_MASK >> i) & 1
|
.ifeq (EXCEPTION_ERRCODE_MASK >> i) & 1
|
||||||
ASM_NOP2
|
|
||||||
.else
|
|
||||||
pushq $0 # Dummy error code, to make stack frame uniform
|
pushq $0 # Dummy error code, to make stack frame uniform
|
||||||
.endif
|
.endif
|
||||||
pushq $i # 72(%rsp) Vector number
|
pushq $i # 72(%rsp) Vector number
|
||||||
jmp early_idt_handler
|
jmp early_idt_handler_common
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
.fill early_idt_handler_array + i*EARLY_IDT_HANDLER_SIZE - ., 1, 0xcc
|
||||||
.endr
|
.endr
|
||||||
|
ENDPROC(early_idt_handler_array)
|
||||||
|
|
||||||
/* This is global to keep gas from relaxing the jumps */
|
early_idt_handler_common:
|
||||||
ENTRY(early_idt_handler)
|
/*
|
||||||
|
* The stack is the hardware frame, an error code or zero, and the
|
||||||
|
* vector number.
|
||||||
|
*/
|
||||||
cld
|
cld
|
||||||
|
|
||||||
cmpl $2,(%rsp) # X86_TRAP_NMI
|
cmpl $2,(%rsp) # X86_TRAP_NMI
|
||||||
|
@ -412,7 +414,7 @@ ENTRY(early_idt_handler)
|
||||||
is_nmi:
|
is_nmi:
|
||||||
addq $16,%rsp # drop vector number and error code
|
addq $16,%rsp # drop vector number and error code
|
||||||
INTERRUPT_RETURN
|
INTERRUPT_RETURN
|
||||||
ENDPROC(early_idt_handler)
|
ENDPROC(early_idt_handler_common)
|
||||||
|
|
||||||
__INITDATA
|
__INITDATA
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,21 @@ static void init_thread_xstate(void)
|
||||||
xstate_size = sizeof(struct i387_fxsave_struct);
|
xstate_size = sizeof(struct i387_fxsave_struct);
|
||||||
else
|
else
|
||||||
xstate_size = sizeof(struct i387_fsave_struct);
|
xstate_size = sizeof(struct i387_fsave_struct);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quirk: we don't yet handle the XSAVES* instructions
|
||||||
|
* correctly, as we don't correctly convert between
|
||||||
|
* standard and compacted format when interfacing
|
||||||
|
* with user-space - so disable it for now.
|
||||||
|
*
|
||||||
|
* The difference is small: with recent CPUs the
|
||||||
|
* compacted format is only marginally smaller than
|
||||||
|
* the standard FPU state format.
|
||||||
|
*
|
||||||
|
* ( This is easy to backport while we are fixing
|
||||||
|
* XSAVES* support. )
|
||||||
|
*/
|
||||||
|
setup_clear_cpu_cap(X86_FEATURE_XSAVES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#include <asm/i387.h> /* For use_eager_fpu. Ugh! */
|
||||||
|
#include <asm/fpu-internal.h> /* For use_eager_fpu. Ugh! */
|
||||||
#include <asm/user.h>
|
#include <asm/user.h>
|
||||||
#include <asm/xsave.h>
|
#include <asm/xsave.h>
|
||||||
#include "cpuid.h"
|
#include "cpuid.h"
|
||||||
|
@ -95,6 +97,8 @@ int kvm_update_cpuid(struct kvm_vcpu *vcpu)
|
||||||
if (best && (best->eax & (F(XSAVES) | F(XSAVEC))))
|
if (best && (best->eax & (F(XSAVES) | F(XSAVEC))))
|
||||||
best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
|
best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
|
||||||
|
|
||||||
|
vcpu->arch.eager_fpu = guest_cpuid_has_mpx(vcpu);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The existing code assumes virtual address is 48-bit in the canonical
|
* The existing code assumes virtual address is 48-bit in the canonical
|
||||||
* address checks; exit if it is ever changed.
|
* address checks; exit if it is ever changed.
|
||||||
|
|
|
@ -117,4 +117,12 @@ static inline bool guest_cpuid_has_rtm(struct kvm_vcpu *vcpu)
|
||||||
best = kvm_find_cpuid_entry(vcpu, 7, 0);
|
best = kvm_find_cpuid_entry(vcpu, 7, 0);
|
||||||
return best && (best->ebx & bit(X86_FEATURE_RTM));
|
return best && (best->ebx & bit(X86_FEATURE_RTM));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool guest_cpuid_has_mpx(struct kvm_vcpu *vcpu)
|
||||||
|
{
|
||||||
|
struct kvm_cpuid_entry2 *best;
|
||||||
|
|
||||||
|
best = kvm_find_cpuid_entry(vcpu, 7, 0);
|
||||||
|
return best && (best->ebx & bit(X86_FEATURE_MPX));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3736,8 +3736,8 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_permission_bitmask(struct kvm_vcpu *vcpu,
|
static void update_permission_bitmask(struct kvm_vcpu *vcpu,
|
||||||
struct kvm_mmu *mmu, bool ept)
|
struct kvm_mmu *mmu, bool ept)
|
||||||
{
|
{
|
||||||
unsigned bit, byte, pfec;
|
unsigned bit, byte, pfec;
|
||||||
u8 map;
|
u8 map;
|
||||||
|
@ -3918,6 +3918,7 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
|
||||||
void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu)
|
void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
bool smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
|
bool smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
|
||||||
|
bool smap = kvm_read_cr4_bits(vcpu, X86_CR4_SMAP);
|
||||||
struct kvm_mmu *context = &vcpu->arch.mmu;
|
struct kvm_mmu *context = &vcpu->arch.mmu;
|
||||||
|
|
||||||
MMU_WARN_ON(VALID_PAGE(context->root_hpa));
|
MMU_WARN_ON(VALID_PAGE(context->root_hpa));
|
||||||
|
@ -3936,6 +3937,8 @@ void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu)
|
||||||
context->base_role.cr0_wp = is_write_protection(vcpu);
|
context->base_role.cr0_wp = is_write_protection(vcpu);
|
||||||
context->base_role.smep_andnot_wp
|
context->base_role.smep_andnot_wp
|
||||||
= smep && !is_write_protection(vcpu);
|
= smep && !is_write_protection(vcpu);
|
||||||
|
context->base_role.smap_andnot_wp
|
||||||
|
= smap && !is_write_protection(vcpu);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kvm_init_shadow_mmu);
|
EXPORT_SYMBOL_GPL(kvm_init_shadow_mmu);
|
||||||
|
|
||||||
|
@ -4207,12 +4210,18 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||||
const u8 *new, int bytes)
|
const u8 *new, int bytes)
|
||||||
{
|
{
|
||||||
gfn_t gfn = gpa >> PAGE_SHIFT;
|
gfn_t gfn = gpa >> PAGE_SHIFT;
|
||||||
union kvm_mmu_page_role mask = { .word = 0 };
|
|
||||||
struct kvm_mmu_page *sp;
|
struct kvm_mmu_page *sp;
|
||||||
LIST_HEAD(invalid_list);
|
LIST_HEAD(invalid_list);
|
||||||
u64 entry, gentry, *spte;
|
u64 entry, gentry, *spte;
|
||||||
int npte;
|
int npte;
|
||||||
bool remote_flush, local_flush, zap_page;
|
bool remote_flush, local_flush, zap_page;
|
||||||
|
union kvm_mmu_page_role mask = (union kvm_mmu_page_role) {
|
||||||
|
.cr0_wp = 1,
|
||||||
|
.cr4_pae = 1,
|
||||||
|
.nxe = 1,
|
||||||
|
.smep_andnot_wp = 1,
|
||||||
|
.smap_andnot_wp = 1,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we don't have indirect shadow pages, it means no page is
|
* If we don't have indirect shadow pages, it means no page is
|
||||||
|
@ -4238,7 +4247,6 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
||||||
++vcpu->kvm->stat.mmu_pte_write;
|
++vcpu->kvm->stat.mmu_pte_write;
|
||||||
kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE);
|
kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE);
|
||||||
|
|
||||||
mask.cr0_wp = mask.cr4_pae = mask.nxe = 1;
|
|
||||||
for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn) {
|
for_each_gfn_indirect_valid_sp(vcpu->kvm, sp, gfn) {
|
||||||
if (detect_write_misaligned(sp, gpa, bytes) ||
|
if (detect_write_misaligned(sp, gpa, bytes) ||
|
||||||
detect_write_flooding(sp)) {
|
detect_write_flooding(sp)) {
|
||||||
|
|
|
@ -71,8 +71,6 @@ enum {
|
||||||
int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct);
|
int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct);
|
||||||
void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu);
|
void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu);
|
||||||
void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly);
|
void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly);
|
||||||
void update_permission_bitmask(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
|
||||||
bool ept);
|
|
||||||
|
|
||||||
static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
|
static inline unsigned int kvm_mmu_available_pages(struct kvm *kvm)
|
||||||
{
|
{
|
||||||
|
@ -166,6 +164,8 @@ static inline bool permission_fault(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
|
||||||
int index = (pfec >> 1) +
|
int index = (pfec >> 1) +
|
||||||
(smap >> (X86_EFLAGS_AC_BIT - PFERR_RSVD_BIT + 1));
|
(smap >> (X86_EFLAGS_AC_BIT - PFERR_RSVD_BIT + 1));
|
||||||
|
|
||||||
|
WARN_ON(pfec & PFERR_RSVD_MASK);
|
||||||
|
|
||||||
return (mmu->permissions[index] >> pte_access) & 1;
|
return (mmu->permissions[index] >> pte_access) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -718,6 +718,13 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
|
||||||
mmu_is_nested(vcpu));
|
mmu_is_nested(vcpu));
|
||||||
if (likely(r != RET_MMIO_PF_INVALID))
|
if (likely(r != RET_MMIO_PF_INVALID))
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* page fault with PFEC.RSVD = 1 is caused by shadow
|
||||||
|
* page fault, should not be used to walk guest page
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
|
error_code &= ~PFERR_RSVD_MASK;
|
||||||
};
|
};
|
||||||
|
|
||||||
r = mmu_topup_memory_caches(vcpu);
|
r = mmu_topup_memory_caches(vcpu);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue