Merge branch 'linus' into locking/core, to pick up fixes

Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2016-11-22 12:37:38 +01:00
commit 02cb689b2c
575 changed files with 6536 additions and 3296 deletions

View File

@ -1,4 +1,4 @@
What: state
What: /sys/devices/system/ibm_rtl/state
Date: Sep 2010
KernelVersion: 2.6.37
Contact: Vernon Mauery <vernux@us.ibm.com>
@ -10,7 +10,7 @@ Description: The state file allows a means by which to change in and
Users: The ibm-prtm userspace daemon uses this interface.
What: version
What: /sys/devices/system/ibm_rtl/version
Date: Sep 2010
KernelVersion: 2.6.37
Contact: Vernon Mauery <vernux@us.ibm.com>

View File

@ -6,7 +6,7 @@ perform in-band IPMI communication with their host.
Required properties:
- compatible : should be "aspeed,ast2400-bt-bmc"
- compatible : should be "aspeed,ast2400-ibt-bmc"
- reg: physical address and size of the registers
Optional properties:
@ -17,7 +17,7 @@ Optional properties:
Example:
ibt@1e789140 {
compatible = "aspeed,ast2400-bt-bmc";
compatible = "aspeed,ast2400-ibt-bmc";
reg = <0x1e789140 0x18>;
interrupts = <8>;
};

View File

@ -43,6 +43,9 @@ Optional properties:
reset signal present internally in some host controller IC designs.
See Documentation/devicetree/bindings/reset/reset.txt for details.
* reset-names: request name for using "resets" property. Must be "reset".
(It will be used together with "resets" property.)
* clocks: from common clock binding: handle to biu and ciu clocks for the
bus interface unit clock and the card interface unit clock.
@ -103,6 +106,8 @@ board specific portions as listed below.
interrupts = <0 75 0>;
#address-cells = <1>;
#size-cells = <0>;
resets = <&rst 20>;
reset-names = "reset";
};
[board specific internal DMA resources]

View File

@ -26,13 +26,16 @@ Required properties:
- "sys"
- "legacy"
- "client"
- resets: Must contain five entries for each entry in reset-names.
- resets: Must contain seven entries for each entry in reset-names.
See ../reset/reset.txt for details.
- reset-names: Must include the following names
- "core"
- "mgmt"
- "mgmt-sticky"
- "pipe"
- "pm"
- "aclk"
- "pclk"
- pinctrl-names : The pin control state names
- pinctrl-0: The "default" pinctrl state
- #interrupt-cells: specifies the number of cells needed to encode an
@ -86,8 +89,10 @@ pcie0: pcie@f8000000 {
reg = <0x0 0xf8000000 0x0 0x2000000>, <0x0 0xfd000000 0x0 0x1000000>;
reg-names = "axi-base", "apb-base";
resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
<&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>;
reset-names = "core", "mgmt", "mgmt-sticky", "pipe";
<&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE> ,
<&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, <&cru SRST_A_PCIE>;
reset-names = "core", "mgmt", "mgmt-sticky", "pipe",
"pm", "pclk", "aclk";
phys = <&pcie_phy>;
phy-names = "pcie-phy";
pinctrl-names = "default";

View File

@ -14,11 +14,6 @@ Required properies:
- #size-cells : The value of this property must be 1
- ranges : defines mapping between pin controller node (parent) to
gpio-bank node (children).
- interrupt-parent: phandle of the interrupt parent to which the external
GPIO interrupts are forwarded to.
- st,syscfg: Should be phandle/offset pair. The phandle to the syscon node
which includes IRQ mux selection register, and the offset of the IRQ mux
selection register.
- pins-are-numbered: Specify the subnodes are using numbered pinmux to
specify pins.
@ -37,6 +32,11 @@ Required properties:
Optional properties:
- reset: : Reference to the reset controller
- interrupt-parent: phandle of the interrupt parent to which the external
GPIO interrupts are forwarded to.
- st,syscfg: Should be phandle/offset pair. The phandle to the syscon node
which includes IRQ mux selection register, and the offset of the IRQ mux
selection register.
Example:
#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>

View File

@ -12,7 +12,7 @@ Required properties:
Optional properties:
- ti,dmic: phandle for the OMAP dmic node if the machine have it connected
- ti,jack_detection: Need to be present if the board capable to detect jack
- ti,jack-detection: Need to be present if the board capable to detect jack
insertion, removal.
Available audio endpoints for the audio-routing table:

View File

@ -447,7 +447,6 @@ prototypes:
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t start, loff_t end, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*readv) (struct file *, const struct iovec *, unsigned long,

View File

@ -828,7 +828,6 @@ struct file_operations {
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);

View File

@ -326,7 +326,7 @@ Two parent-locked sibling muxes
This is a good topology.
.--------.
.--------.
.----------. .--| dev D1 |
| parent- |--' '--------'
.--| locked | .--------.
@ -350,7 +350,7 @@ Mux-locked and parent-locked sibling muxes
This is a good topology.
.--------.
.--------.
.----------. .--| dev D1 |
| mux- |--' '--------'
.--| locked | .--------.

View File

@ -67,13 +67,14 @@ Note that DSA does not currently create network interfaces for the "cpu" and
Switch tagging protocols
------------------------
DSA currently supports 4 different tagging protocols, and a tag-less mode as
DSA currently supports 5 different tagging protocols, and a tag-less mode as
well. The different protocols are implemented in:
net/dsa/tag_trailer.c: Marvell's 4 trailer tag mode (legacy)
net/dsa/tag_dsa.c: Marvell's original DSA tag
net/dsa/tag_edsa.c: Marvell's enhanced DSA tag
net/dsa/tag_brcm.c: Broadcom's 4 bytes tag
net/dsa/tag_qca.c: Qualcomm's 2 bytes tag
The exact format of the tag protocol is vendor specific, but in general, they
all contain something which:

View File

@ -777,6 +777,17 @@ Gets the current timestamp of kvmclock as seen by the current guest. In
conjunction with KVM_SET_CLOCK, it is used to ensure monotonicity on scenarios
such as migration.
When KVM_CAP_ADJUST_CLOCK is passed to KVM_CHECK_EXTENSION, it returns the
set of bits that KVM can return in struct kvm_clock_data's flag member.
The only flag defined now is KVM_CLOCK_TSC_STABLE. If set, the returned
value is the exact kvmclock value seen by all VCPUs at the instant
when KVM_GET_CLOCK was called. If clear, the returned value is simply
CLOCK_MONOTONIC plus a constant offset; the offset can be modified
with KVM_SET_CLOCK. KVM will try to make all VCPUs follow this clock,
but the exact value read by each VCPU could differ, because the host
TSC is not stable.
struct kvm_clock_data {
__u64 clock; /* kvmclock current value */
__u32 flags;

View File

@ -7084,6 +7084,7 @@ F: drivers/scsi/53c700*
LED SUBSYSTEM
M: Richard Purdie <rpurdie@rpsys.net>
M: Jacek Anaszewski <j.anaszewski@samsung.com>
M: Pavel Machek <pavel@ucw.cz>
L: linux-leds@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds.git
S: Maintained
@ -8057,6 +8058,7 @@ F: drivers/infiniband/hw/mlx4/
F: include/linux/mlx4/
MELLANOX MLX5 core VPI driver
M: Saeed Mahameed <saeedm@mellanox.com>
M: Matan Barak <matanb@mellanox.com>
M: Leon Romanovsky <leonro@mellanox.com>
L: netdev@vger.kernel.org
@ -9335,7 +9337,7 @@ PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
M: Keith Busch <keith.busch@intel.com>
L: linux-pci@vger.kernel.org
S: Supported
F: arch/x86/pci/vmd.c
F: drivers/pci/host/vmd.c
PCIE DRIVER FOR ST SPEAR13XX
M: Pratyush Anand <pratyush.anand@gmail.com>

View File

@ -1,7 +1,7 @@
VERSION = 4
PATCHLEVEL = 9
SUBLEVEL = 0
EXTRAVERSION = -rc4
EXTRAVERSION = -rc6
NAME = Psychotic Stoned Sheep
# *DOCUMENTATION*
@ -370,7 +370,7 @@ LDFLAGS_MODULE =
CFLAGS_KERNEL =
AFLAGS_KERNEL =
LDFLAGS_vmlinux =
CFLAGS_GCOV = -fprofile-arcs -ftest-coverage -fno-tree-loop-im
CFLAGS_GCOV = -fprofile-arcs -ftest-coverage -fno-tree-loop-im -Wno-maybe-uninitialized
CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)
@ -399,11 +399,12 @@ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common \
-Werror-implicit-function-declaration \
-Wno-format-security \
-std=gnu89
-std=gnu89 $(call cc-option,-fno-PIE)
KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL :=
KBUILD_AFLAGS := -D__ASSEMBLY__
KBUILD_AFLAGS := -D__ASSEMBLY__ $(call cc-option,-fno-PIE)
KBUILD_AFLAGS_MODULE := -DMODULE
KBUILD_CFLAGS_MODULE := -DMODULE
KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
@ -620,7 +621,6 @@ ARCH_CFLAGS :=
include arch/$(SRCARCH)/Makefile
KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,)
KBUILD_CFLAGS += $(call cc-disable-warning,maybe-uninitialized,)
KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,)
ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
@ -629,15 +629,18 @@ KBUILD_CFLAGS += $(call cc-option,-fdata-sections,)
endif
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS += -Os
KBUILD_CFLAGS += -Os $(call cc-disable-warning,maybe-uninitialized,)
else
ifdef CONFIG_PROFILE_ALL_BRANCHES
KBUILD_CFLAGS += -O2
KBUILD_CFLAGS += -O2 $(call cc-disable-warning,maybe-uninitialized,)
else
KBUILD_CFLAGS += -O2
endif
endif
KBUILD_CFLAGS += $(call cc-ifversion, -lt, 0409, \
$(call cc-disable-warning,maybe-uninitialized,))
# Tell gcc to never replace conditional load with a non-conditional one
KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0)

View File

@ -50,6 +50,9 @@ atleast_gcc44 := $(call cc-ifversion, -ge, 0404, y)
cflags-$(atleast_gcc44) += -fsection-anchors
cflags-$(CONFIG_ARC_HAS_LLSC) += -mlock
cflags-$(CONFIG_ARC_HAS_SWAPE) += -mswape
ifdef CONFIG_ISA_ARCV2
ifndef CONFIG_ARC_HAS_LL64
@ -68,7 +71,9 @@ cflags-$(CONFIG_ARC_DW2_UNWIND) += -fasynchronous-unwind-tables $(cfi)
ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE
# Generic build system uses -O2, we want -O3
# Note: No need to add to cflags-y as that happens anyways
ARCH_CFLAGS += -O3
#
# Disable the false maybe-uninitialized warings gcc spits out at -O3
ARCH_CFLAGS += -O3 $(call cc-disable-warning,maybe-uninitialized,)
endif
# small data is default for elf32 tool-chain. If not usable, disable it

View File

@ -71,7 +71,7 @@
reg-io-width = <4>;
};
arcpmu0: pmu {
arcpct0: pct {
compatible = "snps,arc700-pct";
};
};

View File

@ -69,7 +69,7 @@
};
};
arcpmu0: pmu {
arcpct0: pct {
compatible = "snps,arc700-pct";
};
};

View File

@ -83,5 +83,9 @@
reg = <0xf0003000 0x44>;
interrupts = <7>;
};
arcpct0: pct {
compatible = "snps,arc700-pct";
};
};
};

View File

@ -14,6 +14,7 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="../arc_initramfs/"
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
CONFIG_PERF_EVENTS=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_KPROBES=y

View File

@ -14,6 +14,7 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="../../arc_initramfs_hs/"
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
CONFIG_PERF_EVENTS=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_KPROBES=y

View File

@ -12,6 +12,7 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="../arc_initramfs_hs/"
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
CONFIG_PERF_EVENTS=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_KPROBES=y

View File

@ -14,6 +14,7 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="../arc_initramfs/"
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
CONFIG_PERF_EVENTS=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_KPROBES=y

View File

@ -14,6 +14,7 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="../arc_initramfs_hs/"
CONFIG_KALLSYMS_ALL=y
CONFIG_EMBEDDED=y
CONFIG_PERF_EVENTS=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
CONFIG_KPROBES=y

View File

@ -10,6 +10,7 @@ CONFIG_IKCONFIG_PROC=y
# CONFIG_PID_NS is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="../arc_initramfs_hs/"
CONFIG_PERF_EVENTS=y
# CONFIG_COMPAT_BRK is not set
CONFIG_KPROBES=y
CONFIG_MODULES=y
@ -34,7 +35,6 @@ CONFIG_INET=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
CONFIG_DEVTMPFS=y
@ -72,7 +72,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HWMON is not set
CONFIG_DRM=y
CONFIG_DRM_ARCPGU=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y
# CONFIG_HID is not set
# CONFIG_USB_SUPPORT is not set

View File

@ -43,12 +43,14 @@
#define STATUS_AE_BIT 5 /* Exception active */
#define STATUS_DE_BIT 6 /* PC is in delay slot */
#define STATUS_U_BIT 7 /* User/Kernel mode */
#define STATUS_Z_BIT 11
#define STATUS_L_BIT 12 /* Loop inhibit */
/* These masks correspond to the status word(STATUS_32) bits */
#define STATUS_AE_MASK (1<<STATUS_AE_BIT)
#define STATUS_DE_MASK (1<<STATUS_DE_BIT)
#define STATUS_U_MASK (1<<STATUS_U_BIT)
#define STATUS_Z_MASK (1<<STATUS_Z_BIT)
#define STATUS_L_MASK (1<<STATUS_L_BIT)
/*

View File

@ -37,9 +37,9 @@ extern const char *arc_platform_smp_cpuinfo(void);
* API expected BY platform smp code (FROM arch smp code)
*
* smp_ipi_irq_setup:
* Takes @cpu and @irq to which the arch-common ISR is hooked up
* Takes @cpu and @hwirq to which the arch-common ISR is hooked up
*/
extern int smp_ipi_irq_setup(int cpu, int irq);
extern int smp_ipi_irq_setup(int cpu, irq_hw_number_t hwirq);
/*
* struct plat_smp_ops - SMP callbacks provided by platform to ARC SMP

View File

@ -31,6 +31,8 @@ static void __init arc_set_early_base_baud(unsigned long dt_root)
arc_base_baud = 166666666; /* Fixed 166.6MHz clk (TB10x) */
else if (of_flat_dt_is_compatible(dt_root, "snps,arc-sdp"))
arc_base_baud = 33333333; /* Fixed 33MHz clk (AXS10x) */
else if (of_flat_dt_is_compatible(dt_root, "ezchip,arc-nps"))
arc_base_baud = 800000000; /* Fixed 800MHz clk (NPS) */
else
arc_base_baud = 50000000; /* Fixed default 50MHz */
}

View File

@ -181,6 +181,8 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
{
unsigned long flags;
cpumask_t online;
unsigned int destination_bits;
unsigned int distribution_mode;
/* errout if no online cpu per @cpumask */
if (!cpumask_and(&online, cpumask, cpu_online_mask))
@ -188,8 +190,15 @@ idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
raw_spin_lock_irqsave(&mcip_lock, flags);
idu_set_dest(data->hwirq, cpumask_bits(&online)[0]);
idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
destination_bits = cpumask_bits(&online)[0];
idu_set_dest(data->hwirq, destination_bits);
if (ffs(destination_bits) == fls(destination_bits))
distribution_mode = IDU_M_DISTRI_DEST;
else
distribution_mode = IDU_M_DISTRI_RR;
idu_set_mode(data->hwirq, IDU_M_TRIG_LEVEL, distribution_mode);
raw_spin_unlock_irqrestore(&mcip_lock, flags);
@ -207,16 +216,15 @@ static struct irq_chip idu_irq_chip = {
};
static int idu_first_irq;
static irq_hw_number_t idu_first_hwirq;
static void idu_cascade_isr(struct irq_desc *desc)
{
struct irq_domain *domain = irq_desc_get_handler_data(desc);
unsigned int core_irq = irq_desc_get_irq(desc);
unsigned int idu_irq;
struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
idu_irq = core_irq - idu_first_irq;
generic_handle_irq(irq_find_mapping(domain, idu_irq));
generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
}
static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq)
@ -282,7 +290,7 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
struct irq_domain *domain;
/* Read IDU BCR to confirm nr_irqs */
int nr_irqs = of_irq_count(intc);
int i, irq;
int i, virq;
struct mcip_bcr mp;
READ_BCR(ARC_REG_MCIP_BCR, mp);
@ -303,11 +311,11 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
* however we need it to get the parent virq and set IDU handler
* as first level isr
*/
irq = irq_of_parse_and_map(intc, i);
virq = irq_of_parse_and_map(intc, i);
if (!i)
idu_first_irq = irq;
idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
irq_set_chained_handler_and_data(irq, idu_cascade_isr, domain);
irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
}
__mcip_cmd(CMD_IDU_ENABLE, 0);

View File

@ -43,8 +43,8 @@ SYSCALL_DEFINE0(arc_gettls)
SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new)
{
int uval;
int ret;
struct pt_regs *regs = current_pt_regs();
int uval = -EFAULT;
/*
* This is only for old cores lacking LLOCK/SCOND, which by defintion
@ -54,24 +54,26 @@ SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new)
*/
WARN_ON_ONCE(IS_ENABLED(CONFIG_SMP));
/* Z indicates to userspace if operation succeded */
regs->status32 &= ~STATUS_Z_MASK;
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
return -EFAULT;
preempt_disable();
ret = __get_user(uval, uaddr);
if (ret)
if (__get_user(uval, uaddr))
goto done;
if (uval != expected)
ret = -EAGAIN;
else
ret = __put_user(new, uaddr);
if (uval == expected) {
if (!__put_user(new, uaddr))
regs->status32 |= STATUS_Z_MASK;
}
done:
preempt_enable();
return ret;
return uval;
}
void arch_cpu_idle(void)

View File

@ -22,6 +22,7 @@
#include <linux/atomic.h>
#include <linux/cpumask.h>
#include <linux/reboot.h>
#include <linux/irqdomain.h>
#include <asm/processor.h>
#include <asm/setup.h>
#include <asm/mach_desc.h>
@ -67,11 +68,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
int i;
/*
* Initialise the present map, which describes the set of CPUs
* actually populated at the present time.
* if platform didn't set the present map already, do it now
* boot cpu is set to present already by init/main.c
*/
for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true);
if (num_present_cpus() <= 1) {
for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true);
}
}
void __init smp_cpus_done(unsigned int max_cpus)
@ -351,20 +354,24 @@ irqreturn_t do_IPI(int irq, void *dev_id)
*/
static DEFINE_PER_CPU(int, ipi_dev);
int smp_ipi_irq_setup(int cpu, int irq)
int smp_ipi_irq_setup(int cpu, irq_hw_number_t hwirq)
{
int *dev = per_cpu_ptr(&ipi_dev, cpu);
unsigned int virq = irq_find_mapping(NULL, hwirq);
if (!virq)
panic("Cannot find virq for root domain and hwirq=%lu", hwirq);
/* Boot cpu calls request, all call enable */
if (!cpu) {
int rc;
rc = request_percpu_irq(irq, do_IPI, "IPI Interrupt", dev);
rc = request_percpu_irq(virq, do_IPI, "IPI Interrupt", dev);
if (rc)
panic("Percpu IRQ request failed for %d\n", irq);
panic("Percpu IRQ request failed for %u\n", virq);
}
enable_percpu_irq(irq, 0);
enable_percpu_irq(virq, 0);
return 0;
}

View File

@ -152,14 +152,17 @@ static cycle_t arc_read_rtc(struct clocksource *cs)
cycle_t full;
} stamp;
__asm__ __volatile(
"1: \n"
" lr %0, [AUX_RTC_LOW] \n"
" lr %1, [AUX_RTC_HIGH] \n"
" lr %2, [AUX_RTC_CTRL] \n"
" bbit0.nt %2, 31, 1b \n"
: "=r" (stamp.low), "=r" (stamp.high), "=r" (status));
/*
* hardware has an internal state machine which tracks readout of
* low/high and updates the CTRL.status if
* - interrupt/exception taken between the two reads
* - high increments after low has been read
*/
do {
stamp.low = read_aux_reg(AUX_RTC_LOW);
stamp.high = read_aux_reg(AUX_RTC_HIGH);
status = read_aux_reg(AUX_RTC_CTRL);
} while (!(status & _BITUL(31)));
return stamp.full;
}

View File

@ -105,6 +105,31 @@ static void arc_dma_free(struct device *dev, size_t size, void *vaddr,
__free_pages(page, get_order(size));
}
static int arc_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
unsigned long attrs)
{
unsigned long user_count = vma_pages(vma);
unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
unsigned long pfn = __phys_to_pfn(plat_dma_to_phys(dev, dma_addr));
unsigned long off = vma->vm_pgoff;
int ret = -ENXIO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
return ret;
if (off < count && user_count <= (count - off)) {
ret = remap_pfn_range(vma, vma->vm_start,
pfn + off,
user_count << PAGE_SHIFT,
vma->vm_page_prot);
}
return ret;
}
/*
* streaming DMA Mapping API...
* CPU accesses page via normal paddr, thus needs to explicitly made
@ -193,6 +218,7 @@ static int arc_dma_supported(struct device *dev, u64 dma_mask)
struct dma_map_ops arc_dma_ops = {
.alloc = arc_dma_alloc,
.free = arc_dma_free,
.mmap = arc_dma_mmap,
.map_page = arc_dma_map_page,
.map_sg = arc_dma_map_sg,
.sync_single_for_device = arc_dma_sync_single_for_device,

View File

@ -140,16 +140,10 @@ static void eznps_init_per_cpu(int cpu)
mtm_enable_core(cpu);
}
static void eznps_ipi_clear(int irq)
{
write_aux_reg(CTOP_AUX_IACK, 1 << irq);
}
struct plat_smp_ops plat_smp_ops = {
.info = smp_cpuinfo_buf,
.init_early_smp = eznps_init_cpumasks,
.cpu_kick = eznps_smp_wakeup_cpu,
.ipi_send = eznps_ipi_send,
.init_per_cpu = eznps_init_per_cpu,
.ipi_clear = eznps_ipi_clear,
};

View File

@ -64,8 +64,8 @@
};
ldo3_reg: ldo3 {
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1800000>;
regulator-min-microvolt = <1725000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
@ -76,8 +76,8 @@
};
ldo5_reg: ldo5 {
regulator-min-microvolt = <1725000>;
regulator-max-microvolt = <3300000>;
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
regulator-always-on;
};
@ -100,14 +100,14 @@
};
ldo9_reg: ldo9 {
regulator-min-microvolt = <1200000>;
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <3600000>;
regulator-always-on;
};
ldo10_reg: ldo10 {
regulator-min-microvolt = <1250000>;
regulator-max-microvolt = <3650000>;
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
regulator-always-on;
};
};

View File

@ -13,6 +13,11 @@
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0>;
};
wl12xx_vmmc: wl12xx_vmmc {
compatible = "regulator-fixed";
regulator-name = "vwl1271";

View File

@ -13,9 +13,9 @@
};
};
memory@0 {
memory@80000000 {
device_type = "memory";
reg = <0 0>;
reg = <0x80000000 0>;
};
leds {

View File

@ -124,6 +124,7 @@
compatible = "ti,abe-twl6040";
ti,model = "omap5-uevm";
ti,jack-detection;
ti,mclk-freq = <19200000>;
ti,mcpdm = <&mcpdm>;
@ -415,7 +416,7 @@
ti,backup-battery-charge-high-current;
};
gpadc {
gpadc: gpadc {
compatible = "ti,palmas-gpadc";
interrupts = <18 0
16 0
@ -475,8 +476,8 @@
smps6_reg: smps6 {
/* VDD_DDR3 - over VDD_SMPS6 */
regulator-name = "smps6";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
};

View File

@ -74,7 +74,7 @@
/* Low speed expansion connector */
spi0: spi@9844000 {
label = "LS-SPI0";
cs-gpio = <&pio30 3 0>;
cs-gpios = <&pio30 3 0>;
status = "okay";
};

View File

@ -282,11 +282,15 @@
uart1_pins_a: uart1@0 {
allwinner,pins = "PG6", "PG7";
allwinner,function = "uart1";
allwinner,drive = <SUN4I_PINCTRL_10_MA>;
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
uart1_pins_cts_rts_a: uart1-cts-rts@0 {
allwinner,pins = "PG8", "PG9";
allwinner,function = "uart1";
allwinner,drive = <SUN4I_PINCTRL_10_MA>;
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
mmc0_pins_a: mmc0@0 {

View File

@ -66,6 +66,7 @@ extern char __kvm_hyp_vector[];
extern void __kvm_flush_vm_context(void);
extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);

View File

@ -57,6 +57,9 @@ struct kvm_arch {
/* VTTBR value associated with below pgd and vmid */
u64 vttbr;
/* The last vcpu id that ran on each physical CPU */
int __percpu *last_vcpu_ran;
/* Timer */
struct arch_timer_kvm timer;

View File

@ -71,6 +71,7 @@
#define ICIALLUIS __ACCESS_CP15(c7, 0, c1, 0)
#define ATS1CPR __ACCESS_CP15(c7, 0, c8, 0)
#define TLBIALLIS __ACCESS_CP15(c8, 0, c3, 0)
#define TLBIALL __ACCESS_CP15(c8, 0, c7, 0)
#define TLBIALLNSNHIS __ACCESS_CP15(c8, 4, c3, 4)
#define PRRR __ACCESS_CP15(c10, 0, c2, 0)
#define NMRR __ACCESS_CP15(c10, 0, c2, 1)

View File

@ -74,6 +74,26 @@ void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long
dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
}
void dump_backtrace_stm(u32 *stack, u32 instruction)
{
char str[80], *p;
unsigned int x;
int reg;
for (reg = 10, x = 0, p = str; reg >= 0; reg--) {
if (instruction & BIT(reg)) {
p += sprintf(p, " r%d:%08x", reg, *stack--);
if (++x == 6) {
x = 0;
p = str;
printk("%s\n", str);
}
}
}
if (p != str)
printk("%s\n", str);
}
#ifndef CONFIG_ARM_UNWIND
/*
* Stack pointers should always be within the kernels view of

View File

@ -3,6 +3,9 @@
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/
/* No __ro_after_init data in the .rodata section - which will always be ro */
#define RO_AFTER_INIT_DATA
#include <asm-generic/vmlinux.lds.h>
#include <asm/cache.h>
#include <asm/thread_info.h>
@ -223,6 +226,8 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
__init_end = .;
*(.data..ro_after_init)
NOSAVE_DATA
CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
READ_MOSTLY_DATA(L1_CACHE_BYTES)

View File

@ -114,11 +114,18 @@ void kvm_arch_check_processor_compat(void *rtn)
*/
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{
int ret = 0;
int ret, cpu;
if (type)
return -EINVAL;
kvm->arch.last_vcpu_ran = alloc_percpu(typeof(*kvm->arch.last_vcpu_ran));
if (!kvm->arch.last_vcpu_ran)
return -ENOMEM;
for_each_possible_cpu(cpu)
*per_cpu_ptr(kvm->arch.last_vcpu_ran, cpu) = -1;
ret = kvm_alloc_stage2_pgd(kvm);
if (ret)
goto out_fail_alloc;
@ -141,6 +148,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
out_free_stage2_pgd:
kvm_free_stage2_pgd(kvm);
out_fail_alloc:
free_percpu(kvm->arch.last_vcpu_ran);
kvm->arch.last_vcpu_ran = NULL;
return ret;
}
@ -168,6 +177,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
{
int i;
free_percpu(kvm->arch.last_vcpu_ran);
kvm->arch.last_vcpu_ran = NULL;
for (i = 0; i < KVM_MAX_VCPUS; ++i) {
if (kvm->vcpus[i]) {
kvm_arch_vcpu_free(kvm->vcpus[i]);
@ -312,6 +324,19 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
int *last_ran;
last_ran = this_cpu_ptr(vcpu->kvm->arch.last_vcpu_ran);
/*
* We might get preempted before the vCPU actually runs, but
* over-invalidation doesn't affect correctness.
*/
if (*last_ran != vcpu->vcpu_id) {
kvm_call_hyp(__kvm_tlb_flush_local_vmid, vcpu);
*last_ran = vcpu->vcpu_id;
}
vcpu->cpu = cpu;
vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state);

View File

@ -55,6 +55,21 @@ void __hyp_text __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
__kvm_tlb_flush_vmid(kvm);
}
void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
/* Switch to requested VMID */
write_sysreg(kvm->arch.vttbr, VTTBR);
isb();
write_sysreg(0, TLBIALL);
dsb(nsh);
isb();
write_sysreg(0, VTTBR);
}
void __hyp_text __kvm_flush_vm_context(void)
{
write_sysreg(0, TLBIALLNSNHIS);

View File

@ -10,6 +10,7 @@
* 27/03/03 Ian Molton Clean up CONFIG_CPU
*
*/
#include <linux/kern_levels.h>
#include <linux/linkage.h>
#include <asm/assembler.h>
.text
@ -83,13 +84,13 @@ for_each_frame: tst frame, mask @ Check for address exceptions
teq r3, r1, lsr #11
ldreq r0, [frame, #-8] @ get sp
subeq r0, r0, #4 @ point at the last arg
bleq .Ldumpstm @ dump saved registers
bleq dump_backtrace_stm @ dump saved registers
1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc}
ldr r3, .Ldsi @ instruction exists,
teq r3, r1, lsr #11
subeq r0, frame, #16
bleq .Ldumpstm @ dump saved registers
bleq dump_backtrace_stm @ dump saved registers
teq sv_fp, #0 @ zero saved fp means
beq no_frame @ no further frames
@ -112,38 +113,6 @@ ENDPROC(c_backtrace)
.long 1004b, 1006b
.popsection
#define instr r4
#define reg r5
#define stack r6
.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr}
mov stack, r0
mov instr, r1
mov reg, #10
mov r7, #0
1: mov r3, #1
ARM( tst instr, r3, lsl reg )
THUMB( lsl r3, reg )
THUMB( tst instr, r3 )
beq 2f
add r7, r7, #1
teq r7, #6
moveq r7, #0
adr r3, .Lcr
addne r3, r3, #1 @ skip newline
ldr r2, [stack], #-4
mov r1, reg
adr r0, .Lfp
bl printk
2: subs reg, reg, #1
bpl 1b
teq r7, #0
adrne r0, .Lcr
blne printk
ldmfd sp!, {instr, reg, stack, r7, pc}
.Lfp: .asciz " r%d:%08x%s"
.Lcr: .asciz "\n"
.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
.align
.Ldsi: .word 0xe92dd800 >> 11 @ stmfd sp!, {... fp, ip, lr, pc}

View File

@ -71,6 +71,7 @@ config SOC_AM43XX
select HAVE_ARM_TWD
select ARM_ERRATA_754322
select ARM_ERRATA_775420
select OMAP_INTERCONNECT
config SOC_DRA7XX
bool "TI DRA7XX"

View File

@ -205,11 +205,15 @@ void __init omap2xxx_check_revision(void)
#define OMAP3_SHOW_FEATURE(feat) \
if (omap3_has_ ##feat()) \
printk(#feat" ");
n += scnprintf(buf + n, sizeof(buf) - n, #feat " ");
static void __init omap3_cpuinfo(void)
{
const char *cpu_name;
char buf[64];
int n = 0;
memset(buf, 0, sizeof(buf));
/*
* OMAP3430 and OMAP3530 are assumed to be same.
@ -241,10 +245,10 @@ static void __init omap3_cpuinfo(void)
cpu_name = "OMAP3503";
}
sprintf(soc_name, "%s", cpu_name);
scnprintf(soc_name, sizeof(soc_name), "%s", cpu_name);
/* Print verbose information */
pr_info("%s %s (", soc_name, soc_rev);
n += scnprintf(buf, sizeof(buf) - n, "%s %s (", soc_name, soc_rev);
OMAP3_SHOW_FEATURE(l2cache);
OMAP3_SHOW_FEATURE(iva);
@ -252,8 +256,10 @@ static void __init omap3_cpuinfo(void)
OMAP3_SHOW_FEATURE(neon);
OMAP3_SHOW_FEATURE(isp);
OMAP3_SHOW_FEATURE(192mhz_clk);
printk(")\n");
if (*(buf + n - 1) == ' ')
n--;
n += scnprintf(buf + n, sizeof(buf) - n, ")\n");
pr_info("%s", buf);
}
#define OMAP3_CHECK_FEATURE(status,feat) \

View File

@ -319,6 +319,9 @@ void __init omap3_prm_init_pm(bool has_uart4, bool has_iva)
if (has_uart4) {
en_uart4_mask = OMAP3630_EN_UART4_MASK;
grpsel_uart4_mask = OMAP3630_GRPSEL_UART4_MASK;
} else {
en_uart4_mask = 0;
grpsel_uart4_mask = 0;
}
/* Enable wakeups in PER */

View File

@ -87,6 +87,12 @@ int voltdm_scale(struct voltagedomain *voltdm,
return -ENODATA;
}
if (!voltdm->volt_data) {
pr_err("%s: No voltage data defined for vdd_%s\n",
__func__, voltdm->name);
return -ENODATA;
}
/* Adjust voltage to the exact voltage from the OPP table */
for (i = 0; voltdm->volt_data[i].volt_nominal != 0; i++) {
if (voltdm->volt_data[i].volt_nominal >= target_volt) {

View File

@ -1167,7 +1167,7 @@ static int __init dma_debug_do_init(void)
dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
return 0;
}
fs_initcall(dma_debug_do_init);
core_initcall(dma_debug_do_init);
#ifdef CONFIG_ARM_DMA_USE_IOMMU

View File

@ -96,7 +96,7 @@ ENTRY(cpu_cm7_proc_fin)
ret lr
ENDPROC(cpu_cm7_proc_fin)
.section ".text.init", #alloc, #execinstr
.section ".init.text", #alloc, #execinstr
__v7m_cm7_setup:
mov r8, #(V7M_SCB_CCR_DC | V7M_SCB_CCR_IC| V7M_SCB_CCR_BP)

View File

@ -105,7 +105,7 @@
status = "disabled";
};
nb_perih_clk: nb-periph-clk@13000{
nb_periph_clk: nb-periph-clk@13000 {
compatible = "marvell,armada-3700-periph-clock-nb";
reg = <0x13000 0x100>;
clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>,
@ -113,7 +113,7 @@
#clock-cells = <1>;
};
sb_perih_clk: sb-periph-clk@18000{
sb_periph_clk: sb-periph-clk@18000 {
compatible = "marvell,armada-3700-periph-clock-sb";
reg = <0x18000 0x100>;
clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>,

View File

@ -130,8 +130,8 @@
reg = <0x700600 0x50>;
#address-cells = <0x1>;
#size-cells = <0x0>;
cell-index = <1>;
clocks = <&cps_syscon0 0 3>;
cell-index = <3>;
clocks = <&cps_syscon0 1 21>;
status = "disabled";
};
@ -140,7 +140,7 @@
reg = <0x700680 0x50>;
#address-cells = <1>;
#size-cells = <0>;
cell-index = <2>;
cell-index = <4>;
clocks = <&cps_syscon0 1 21>;
status = "disabled";
};

View File

@ -300,8 +300,11 @@
ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x600000
0x81000000 0x0 0xfa600000 0x0 0xfa600000 0x0 0x100000>;
resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
<&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>;
reset-names = "core", "mgmt", "mgmt-sticky", "pipe";
<&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>,
<&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>,
<&cru SRST_A_PCIE>;
reset-names = "core", "mgmt", "mgmt-sticky", "pipe",
"pm", "pclk", "aclk";
status = "disabled";
pcie0_intc: interrupt-controller {

View File

@ -54,6 +54,7 @@ extern char __kvm_hyp_vector[];
extern void __kvm_flush_vm_context(void);
extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);

View File

@ -62,6 +62,9 @@ struct kvm_arch {
/* VTTBR value associated with above pgd and vmid */
u64 vttbr;
/* The last vcpu id that ran on each physical CPU */
int __percpu *last_vcpu_ran;
/* The maximum number of vCPUs depends on the used GIC model */
int max_vcpus;

View File

@ -128,7 +128,7 @@ static inline unsigned long __kern_hyp_va(unsigned long v)
return v;
}
#define kern_hyp_va(v) (typeof(v))(__kern_hyp_va((unsigned long)(v)))
#define kern_hyp_va(v) ((typeof(v))(__kern_hyp_va((unsigned long)(v))))
/*
* We currently only support a 40bit IPA.

View File

@ -46,7 +46,15 @@
#define ARMV8_PMU_EVTYPE_MASK 0xc800ffff /* Mask for writable bits */
#define ARMV8_PMU_EVTYPE_EVENT 0xffff /* Mask for EVENT bits */
#define ARMV8_PMU_EVTYPE_EVENT_SW_INCR 0 /* Software increment event */
/*
* PMUv3 event types: required events
*/
#define ARMV8_PMUV3_PERFCTR_SW_INCR 0x00
#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03
#define ARMV8_PMUV3_PERFCTR_L1D_CACHE 0x04
#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED 0x10
#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES 0x11
#define ARMV8_PMUV3_PERFCTR_BR_PRED 0x12
/*
* Event filters for PMUv3

View File

@ -31,17 +31,9 @@
/*
* ARMv8 PMUv3 Performance Events handling code.
* Common event types.
* Common event types (some are defined in asm/perf_event.h).
*/
/* Required events. */
#define ARMV8_PMUV3_PERFCTR_SW_INCR 0x00
#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03
#define ARMV8_PMUV3_PERFCTR_L1D_CACHE 0x04
#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED 0x10
#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES 0x11
#define ARMV8_PMUV3_PERFCTR_BR_PRED 0x12
/* At least one of the following is required. */
#define ARMV8_PMUV3_PERFCTR_INST_RETIRED 0x08
#define ARMV8_PMUV3_PERFCTR_INST_SPEC 0x1B

View File

@ -64,6 +64,21 @@ void __hyp_text __kvm_tlb_flush_vmid(struct kvm *kvm)
write_sysreg(0, vttbr_el2);
}
void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
/* Switch to requested VMID */
write_sysreg(kvm->arch.vttbr, vttbr_el2);
isb();
asm volatile("tlbi vmalle1" : : );
dsb(nsh);
isb();
write_sysreg(0, vttbr_el2);
}
void __hyp_text __kvm_flush_vm_context(void)
{
dsb(ishst);

View File

@ -597,8 +597,14 @@ static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
idx = ARMV8_PMU_CYCLE_IDX;
} else {
BUG();
return false;
}
} else if (r->CRn == 0 && r->CRm == 9) {
/* PMCCNTR */
if (pmu_access_event_counter_el0_disabled(vcpu))
return false;
idx = ARMV8_PMU_CYCLE_IDX;
} else if (r->CRn == 14 && (r->CRm & 12) == 8) {
/* PMEVCNTRn_EL0 */
if (pmu_access_event_counter_el0_disabled(vcpu))
@ -606,7 +612,7 @@ static bool access_pmu_evcntr(struct kvm_vcpu *vcpu,
idx = ((r->CRm & 3) << 3) | (r->Op2 & 7);
} else {
BUG();
return false;
}
if (!pmu_counter_idx_valid(vcpu, idx))

View File

@ -324,6 +324,7 @@ static int __init nios2_time_init(struct device_node *timer)
ret = nios2_clocksource_init(timer);
break;
default:
ret = 0;
break;
}

View File

@ -91,7 +91,7 @@
*/
#define LOAD_HANDLER(reg, label) \
ld reg,PACAKBASE(r13); /* get high part of &label */ \
ori reg,reg,(FIXED_SYMBOL_ABS_ADDR(label))@l;
ori reg,reg,FIXED_SYMBOL_ABS_ADDR(label);
#define __LOAD_HANDLER(reg, label) \
ld reg,PACAKBASE(r13); \
@ -158,14 +158,17 @@ BEGIN_FTR_SECTION_NESTED(943) \
std ra,offset(r13); \
END_FTR_SECTION_NESTED(ftr,ftr,943)
#define EXCEPTION_PROLOG_0(area) \
GET_PACA(r13); \
#define EXCEPTION_PROLOG_0_PACA(area) \
std r9,area+EX_R9(r13); /* save r9 */ \
OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR); \
HMT_MEDIUM; \
std r10,area+EX_R10(r13); /* save r10 - r12 */ \
OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR)
#define EXCEPTION_PROLOG_0(area) \
GET_PACA(r13); \
EXCEPTION_PROLOG_0_PACA(area)
#define __EXCEPTION_PROLOG_1(area, extra, vec) \
OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR); \
OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR); \
@ -196,6 +199,12 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
EXCEPTION_PROLOG_1(area, extra, vec); \
EXCEPTION_PROLOG_PSERIES_1(label, h);
/* Have the PACA in r13 already */
#define EXCEPTION_PROLOG_PSERIES_PACA(area, label, h, extra, vec) \
EXCEPTION_PROLOG_0_PACA(area); \
EXCEPTION_PROLOG_1(area, extra, vec); \
EXCEPTION_PROLOG_PSERIES_1(label, h);
#define __KVMTEST(h, n) \
lbz r10,HSTATE_IN_GUEST(r13); \
cmpwi r10,0; \

View File

@ -460,5 +460,6 @@
#define PPC_SLBIA(IH) stringify_in_c(.long PPC_INST_SLBIA | \
((IH & 0x7) << 21))
#define PPC_INVALIDATE_ERAT PPC_SLBIA(7)
#endif /* _ASM_POWERPC_PPC_OPCODE_H */

View File

@ -116,7 +116,9 @@ EXC_VIRT_NONE(0x4000, 0x4100)
EXC_REAL_BEGIN(system_reset, 0x100, 0x200)
SET_SCRATCH0(r13)
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
GET_PACA(r13)
clrrdi r13,r13,1 /* Last bit of HSPRG0 is set if waking from winkle */
EXCEPTION_PROLOG_PSERIES_PACA(PACA_EXGEN, system_reset_common, EXC_STD,
IDLETEST, 0x100)
EXC_REAL_END(system_reset, 0x100, 0x200)
@ -124,6 +126,9 @@ EXC_VIRT_NONE(0x4100, 0x4200)
#ifdef CONFIG_PPC_P7_NAP
EXC_COMMON_BEGIN(system_reset_idle_common)
BEGIN_FTR_SECTION
GET_PACA(r13) /* Restore HSPRG0 to get the winkle bit in r13 */
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
bl pnv_restore_hyp_resource
li r0,PNV_THREAD_RUNNING
@ -169,7 +174,7 @@ EXC_REAL_BEGIN(machine_check, 0x200, 0x300)
SET_SCRATCH0(r13) /* save r13 */
/*
* Running native on arch 2.06 or later, we may wakeup from winkle
* inside machine check. If yes, then last bit of HSPGR0 would be set
* inside machine check. If yes, then last bit of HSPRG0 would be set
* to 1. Hence clear it unconditionally.
*/
GET_PACA(r13)
@ -388,7 +393,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
/*
* Go back to winkle. Please note that this thread was woken up in
* machine check from winkle and have not restored the per-subcore
* state. Hence before going back to winkle, set last bit of HSPGR0
* state. Hence before going back to winkle, set last bit of HSPRG0
* to 1. This will make sure that if this thread gets woken up
* again at reset vector 0x100 then it will get chance to restore
* the subcore state.

View File

@ -1215,7 +1215,7 @@ static void show_instructions(struct pt_regs *regs)
int instr;
if (!(i % 8))
printk("\n");
pr_cont("\n");
#if !defined(CONFIG_BOOKE)
/* If executing with the IMMU off, adjust pc rather
@ -1227,18 +1227,18 @@ static void show_instructions(struct pt_regs *regs)
if (!__kernel_text_address(pc) ||
probe_kernel_address((unsigned int __user *)pc, instr)) {
printk(KERN_CONT "XXXXXXXX ");
pr_cont("XXXXXXXX ");
} else {
if (regs->nip == pc)
printk(KERN_CONT "<%08x> ", instr);
pr_cont("<%08x> ", instr);
else
printk(KERN_CONT "%08x ", instr);
pr_cont("%08x ", instr);
}
pc += sizeof(int);
}
printk("\n");
pr_cont("\n");
}
struct regbit {
@ -1282,7 +1282,7 @@ static void print_bits(unsigned long val, struct regbit *bits, const char *sep)
for (; bits->bit; ++bits)
if (val & bits->bit) {
printk("%s%s", s, bits->name);
pr_cont("%s%s", s, bits->name);
s = sep;
}
}
@ -1305,9 +1305,9 @@ static void print_tm_bits(unsigned long val)
* T: Transactional (bit 34)
*/
if (val & (MSR_TM | MSR_TS_S | MSR_TS_T)) {
printk(",TM[");
pr_cont(",TM[");
print_bits(val, msr_tm_bits, "");
printk("]");
pr_cont("]");
}
}
#else
@ -1316,10 +1316,10 @@ static void print_tm_bits(unsigned long val) {}
static void print_msr_bits(unsigned long val)
{
printk("<");
pr_cont("<");
print_bits(val, msr_bits, ",");
print_tm_bits(val);
printk(">");
pr_cont(">");
}
#ifdef CONFIG_PPC64
@ -1347,29 +1347,29 @@ void show_regs(struct pt_regs * regs)
printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer);
trap = TRAP(regs);
if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
printk("CFAR: "REG" ", regs->orig_gpr3);
pr_cont("CFAR: "REG" ", regs->orig_gpr3);
if (trap == 0x200 || trap == 0x300 || trap == 0x600)
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
printk("DEAR: "REG" ESR: "REG" ", regs->dar, regs->dsisr);
pr_cont("DEAR: "REG" ESR: "REG" ", regs->dar, regs->dsisr);
#else
printk("DAR: "REG" DSISR: %08lx ", regs->dar, regs->dsisr);
pr_cont("DAR: "REG" DSISR: %08lx ", regs->dar, regs->dsisr);
#endif
#ifdef CONFIG_PPC64
printk("SOFTE: %ld ", regs->softe);
pr_cont("SOFTE: %ld ", regs->softe);
#endif
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
if (MSR_TM_ACTIVE(regs->msr))
printk("\nPACATMSCRATCH: %016llx ", get_paca()->tm_scratch);
pr_cont("\nPACATMSCRATCH: %016llx ", get_paca()->tm_scratch);
#endif
for (i = 0; i < 32; i++) {
if ((i % REGS_PER_LINE) == 0)
printk("\nGPR%02d: ", i);
printk(REG " ", regs->gpr[i]);
pr_cont("\nGPR%02d: ", i);
pr_cont(REG " ", regs->gpr[i]);
if (i == LAST_VOLATILE && !FULL_REGS(regs))
break;
}
printk("\n");
pr_cont("\n");
#ifdef CONFIG_KALLSYMS
/*
* Lookup NIP late so we have the best change of getting the
@ -1900,14 +1900,14 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
if ((ip == rth) && curr_frame >= 0) {
printk(" (%pS)",
pr_cont(" (%pS)",
(void *)current->ret_stack[curr_frame].ret);
curr_frame--;
}
#endif
if (firstframe)
printk(" (unreliable)");
printk("\n");
pr_cont(" (unreliable)");
pr_cont("\n");
}
firstframe = 0;

View File

@ -226,17 +226,25 @@ static void __init configure_exceptions(void)
if (firmware_has_feature(FW_FEATURE_OPAL))
opal_configure_cores();
/* Enable AIL if supported, and we are in hypervisor mode */
if (early_cpu_has_feature(CPU_FTR_HVMODE) &&
early_cpu_has_feature(CPU_FTR_ARCH_207S)) {
unsigned long lpcr = mfspr(SPRN_LPCR);
mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3);
}
/* AIL on native is done in cpu_ready_for_interrupts() */
}
}
static void cpu_ready_for_interrupts(void)
{
/*
* Enable AIL if supported, and we are in hypervisor mode. This
* is called once for every processor.
*
* If we are not in hypervisor mode the job is done once for
* the whole partition in configure_exceptions().
*/
if (early_cpu_has_feature(CPU_FTR_HVMODE) &&
early_cpu_has_feature(CPU_FTR_ARCH_207S)) {
unsigned long lpcr = mfspr(SPRN_LPCR);
mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3);
}
/* Set IR and DR in PACA MSR */
get_paca()->kernel_msr = MSR_KERNEL;
}

View File

@ -1029,6 +1029,10 @@ void hash__early_init_mmu_secondary(void)
{
/* Initialize hash table for that CPU */
if (!firmware_has_feature(FW_FEATURE_LPAR)) {
if (cpu_has_feature(CPU_FTR_POWER9_DD1))
update_hid_for_hash();
if (!cpu_has_feature(CPU_FTR_ARCH_300))
mtspr(SPRN_SDR1, _SDR1);
else

View File

@ -388,6 +388,10 @@ void radix__early_init_mmu_secondary(void)
* update partition table control register and UPRT
*/
if (!firmware_has_feature(FW_FEATURE_LPAR)) {
if (cpu_has_feature(CPU_FTR_POWER9_DD1))
update_hid_for_radix();
lpcr = mfspr(SPRN_LPCR);
mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR);

View File

@ -50,6 +50,8 @@ static inline void _tlbiel_pid(unsigned long pid, unsigned long ric)
for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) {
__tlbiel_pid(pid, set, ric);
}
if (cpu_has_feature(CPU_FTR_POWER9_DD1))
asm volatile(PPC_INVALIDATE_ERAT : : :"memory");
return;
}
@ -83,6 +85,8 @@ static inline void _tlbiel_va(unsigned long va, unsigned long pid,
asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
: : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
asm volatile("ptesync": : :"memory");
if (cpu_has_feature(CPU_FTR_POWER9_DD1))
asm volatile(PPC_INVALIDATE_ERAT : : :"memory");
}
static inline void _tlbie_va(unsigned long va, unsigned long pid,

View File

@ -62,9 +62,11 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
__start_ro_after_init = .;
__start_data_ro_after_init = .;
.data..ro_after_init : {
*(.data..ro_after_init)
}
__end_data_ro_after_init = .;
EXCEPTION_TABLE(16)
. = ALIGN(PAGE_SIZE);
__end_ro_after_init = .;

View File

@ -423,7 +423,7 @@ static int __s390_dma_map_sg(struct device *dev, struct scatterlist *sg,
dma_addr_t dma_addr_base, dma_addr;
int flags = ZPCI_PTE_VALID;
struct scatterlist *s;
unsigned long pa;
unsigned long pa = 0;
int ret;
size = PAGE_ALIGN(size);

View File

@ -43,6 +43,7 @@ config SPARC
select ARCH_HAS_SG_CHAIN
select CPU_NO_EFFICIENT_FFS
select HAVE_ARCH_HARDENED_USERCOPY
select PROVE_LOCKING_SMALL if PROVE_LOCKING
config SPARC32
def_bool !64BIT
@ -89,6 +90,14 @@ config ARCH_DEFCONFIG
config ARCH_PROC_KCORE_TEXT
def_bool y
config ARCH_ATU
bool
default y if SPARC64
config ARCH_DMA_ADDR_T_64BIT
bool
default y if ARCH_ATU
config IOMMU_HELPER
bool
default y if SPARC64
@ -304,6 +313,20 @@ config ARCH_SPARSEMEM_ENABLE
config ARCH_SPARSEMEM_DEFAULT
def_bool y if SPARC64
config FORCE_MAX_ZONEORDER
int "Maximum zone order"
default "13"
help
The kernel memory allocator divides physically contiguous memory
blocks into "zones", where each zone is a power of two number of
pages. This option selects the largest power of two that the kernel
keeps in the memory allocator. If you need to allocate very large
blocks of physically contiguous memory, then you may need to
increase this value.
This config option is actually maximum order plus one. For example,
a value of 13 means that the largest free memory block is 2^12 pages.
source "mm/Kconfig"
if SPARC64

View File

@ -2335,6 +2335,348 @@ unsigned long sun4v_vintr_set_target(unsigned long dev_handle,
*/
#define HV_FAST_PCI_MSG_SETVALID 0xd3
/* PCI IOMMU v2 definitions and services
*
* While the PCI IO definitions above is valid IOMMU v2 adds new PCI IO
* definitions and services.
*
* CTE Clump Table Entry. First level table entry in the ATU.
*
* pci_device_list
* A 32-bit aligned list of pci_devices.
*
* pci_device_listp
* real address of a pci_device_list. 32-bit aligned.
*
* iotte IOMMU translation table entry.
*
* iotte_attributes
* IO Attributes for IOMMU v2 mappings. In addition to
* read, write IOMMU v2 supports relax ordering
*
* io_page_list A 64-bit aligned list of real addresses. Each real
* address in an io_page_list must be properly aligned
* to the pagesize of the given IOTSB.
*
* io_page_list_p Real address of an io_page_list, 64-bit aligned.
*
* IOTSB IO Translation Storage Buffer. An aligned table of
* IOTTEs. Each IOTSB has a pagesize, table size, and
* virtual address associated with it that must match
* a pagesize and table size supported by the un-derlying
* hardware implementation. The alignment requirements
* for an IOTSB depend on the pagesize used for that IOTSB.
* Each IOTTE in an IOTSB maps one pagesize-sized page.
* The size of the IOTSB dictates how large of a virtual
* address space the IOTSB is capable of mapping.
*
* iotsb_handle An opaque identifier for an IOTSB. A devhandle plus
* iotsb_handle represents a binding of an IOTSB to a
* PCI root complex.
*
* iotsb_index Zero-based IOTTE number within an IOTSB.
*/
/* The index_count argument consists of two fields:
* bits 63:48 #iottes and bits 47:0 iotsb_index
*/
#define HV_PCI_IOTSB_INDEX_COUNT(__iottes, __iotsb_index) \
(((u64)(__iottes) << 48UL) | ((u64)(__iotsb_index)))
/* pci_iotsb_conf()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_CONF
* ARG0: devhandle
* ARG1: r_addr
* ARG2: size
* ARG3: pagesize
* ARG4: iova
* RET0: status
* RET1: iotsb_handle
* ERRORS: EINVAL Invalid devhandle, size, iova, or pagesize
* EBADALIGN r_addr is not properly aligned
* ENORADDR r_addr is not a valid real address
* ETOOMANY No further IOTSBs may be configured
* EBUSY Duplicate devhandle, raddir, iova combination
*
* Create an IOTSB suitable for the PCI root complex identified by devhandle,
* for the DMA virtual address defined by the argument iova.
*
* r_addr is the properly aligned base address of the IOTSB and size is the
* IOTSB (table) size in bytes.The IOTSB is required to be zeroed prior to
* being configured. If it contains any values other than zeros then the
* behavior is undefined.
*
* pagesize is the size of each page in the IOTSB. Note that the combination of
* size (table size) and pagesize must be valid.
*
* virt is the DMA virtual address this IOTSB will map.
*
* If successful, the opaque 64-bit handle iotsb_handle is returned in ret1.
* Once configured, privileged access to the IOTSB memory is prohibited and
* creates undefined behavior. The only permitted access is indirect via these
* services.
*/
#define HV_FAST_PCI_IOTSB_CONF 0x190
/* pci_iotsb_info()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_INFO
* ARG0: devhandle
* ARG1: iotsb_handle
* RET0: status
* RET1: r_addr
* RET2: size
* RET3: pagesize
* RET4: iova
* RET5: #bound
* ERRORS: EINVAL Invalid devhandle or iotsb_handle
*
* This service returns configuration information about an IOTSB previously
* created with pci_iotsb_conf.
*
* iotsb_handle value 0 may be used with this service to inquire about the
* legacy IOTSB that may or may not exist. If the service succeeds, the return
* values describe the legacy IOTSB and I/O virtual addresses mapped by that
* table. However, the table base address r_addr may contain the value -1 which
* indicates a memory range that cannot be accessed or be reclaimed.
*
* The return value #bound contains the number of PCI devices that iotsb_handle
* is currently bound to.
*/
#define HV_FAST_PCI_IOTSB_INFO 0x191
/* pci_iotsb_unconf()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_UNCONF
* ARG0: devhandle
* ARG1: iotsb_handle
* RET0: status
* ERRORS: EINVAL Invalid devhandle or iotsb_handle
* EBUSY The IOTSB is bound and may not be unconfigured
*
* This service unconfigures the IOTSB identified by the devhandle and
* iotsb_handle arguments, previously created with pci_iotsb_conf.
* The IOTSB must not be currently bound to any device or the service will fail
*
* If the call succeeds, iotsb_handle is no longer valid.
*/
#define HV_FAST_PCI_IOTSB_UNCONF 0x192
/* pci_iotsb_bind()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_BIND
* ARG0: devhandle
* ARG1: iotsb_handle
* ARG2: pci_device
* RET0: status
* ERRORS: EINVAL Invalid devhandle, iotsb_handle, or pci_device
* EBUSY A PCI function is already bound to an IOTSB at the same
* address range as specified by devhandle, iotsb_handle.
*
* This service binds the PCI function specified by the argument pci_device to
* the IOTSB specified by the arguments devhandle and iotsb_handle.
*
* The PCI device function is bound to the specified IOTSB with the IOVA range
* specified when the IOTSB was configured via pci_iotsb_conf. If the function
* is already bound then it is unbound first.
*/
#define HV_FAST_PCI_IOTSB_BIND 0x193
/* pci_iotsb_unbind()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_UNBIND
* ARG0: devhandle
* ARG1: iotsb_handle
* ARG2: pci_device
* RET0: status
* ERRORS: EINVAL Invalid devhandle, iotsb_handle, or pci_device
* ENOMAP The PCI function was not bound to the specified IOTSB
*
* This service unbinds the PCI device specified by the argument pci_device
* from the IOTSB identified * by the arguments devhandle and iotsb_handle.
*
* If the PCI device is not bound to the specified IOTSB then this service will
* fail with status ENOMAP
*/
#define HV_FAST_PCI_IOTSB_UNBIND 0x194
/* pci_iotsb_get_binding()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_GET_BINDING
* ARG0: devhandle
* ARG1: iotsb_handle
* ARG2: iova
* RET0: status
* RET1: iotsb_handle
* ERRORS: EINVAL Invalid devhandle, pci_device, or iova
* ENOMAP The PCI function is not bound to an IOTSB at iova
*
* This service returns the IOTSB binding, iotsb_handle, for a given pci_device
* and DMA virtual address, iova.
*
* iova must be the base address of a DMA virtual address range as defined by
* the iommu-address-ranges property in the root complex device node defined
* by the argument devhandle.
*/
#define HV_FAST_PCI_IOTSB_GET_BINDING 0x195
/* pci_iotsb_map()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_MAP
* ARG0: devhandle
* ARG1: iotsb_handle
* ARG2: index_count
* ARG3: iotte_attributes
* ARG4: io_page_list_p
* RET0: status
* RET1: #mapped
* ERRORS: EINVAL Invalid devhandle, iotsb_handle, #iottes,
* iotsb_index or iotte_attributes
* EBADALIGN Improperly aligned io_page_list_p or I/O page
* address in the I/O page list.
* ENORADDR Invalid io_page_list_p or I/O page address in
* the I/O page list.
*
* This service creates and flushes mappings in the IOTSB defined by the
* arguments devhandle, iotsb.
*
* The index_count argument consists of two fields. Bits 63:48 contain #iotte
* and bits 47:0 contain iotsb_index
*
* The first mapping is created in the IOTSB index specified by iotsb_index.
* Subsequent mappings are created at iotsb_index+1 and so on.
*
* The attributes of each mapping are defined by the argument iotte_attributes.
*
* The io_page_list_p specifies the real address of the 64-bit-aligned list of
* #iottes I/O page addresses. Each page address must be a properly aligned
* real address of a page to be mapped in the IOTSB. The first entry in the I/O
* page list contains the real address of the first page, the 2nd entry for the
* 2nd page, and so on.
*
* #iottes must be greater than zero.
*
* The return value #mapped is the actual number of mappings created, which may
* be less than or equal to the argument #iottes. If the function returns
* successfully with a #mapped value less than the requested #iottes then the
* caller should continue to invoke the service with updated iotsb_index,
* #iottes, and io_page_list_p arguments until all pages are mapped.
*
* This service must not be used to demap a mapping. In other words, all
* mappings must be valid and have one or both of the RW attribute bits set.
*
* Note:
* It is implementation-defined whether I/O page real address validity checking
* is done at time mappings are established or deferred until they are
* accessed.
*/
#define HV_FAST_PCI_IOTSB_MAP 0x196
/* pci_iotsb_map_one()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_MAP_ONE
* ARG0: devhandle
* ARG1: iotsb_handle
* ARG2: iotsb_index
* ARG3: iotte_attributes
* ARG4: r_addr
* RET0: status
* ERRORS: EINVAL Invalid devhandle,iotsb_handle, iotsb_index
* or iotte_attributes
* EBADALIGN Improperly aligned r_addr
* ENORADDR Invalid r_addr
*
* This service creates and flushes a single mapping in the IOTSB defined by the
* arguments devhandle, iotsb.
*
* The mapping for the page at r_addr is created at the IOTSB index specified by
* iotsb_index with the attributes iotte_attributes.
*
* This service must not be used to demap a mapping. In other words, the mapping
* must be valid and have one or both of the RW attribute bits set.
*
* Note:
* It is implementation-defined whether I/O page real address validity checking
* is done at time mappings are established or deferred until they are
* accessed.
*/
#define HV_FAST_PCI_IOTSB_MAP_ONE 0x197
/* pci_iotsb_demap()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_DEMAP
* ARG0: devhandle
* ARG1: iotsb_handle
* ARG2: iotsb_index
* ARG3: #iottes
* RET0: status
* RET1: #unmapped
* ERRORS: EINVAL Invalid devhandle, iotsb_handle, iotsb_index or #iottes
*
* This service unmaps and flushes up to #iottes mappings starting at index
* iotsb_index from the IOTSB defined by the arguments devhandle, iotsb.
*
* #iottes must be greater than zero.
*
* The actual number of IOTTEs unmapped is returned in #unmapped and may be less
* than or equal to the requested number of IOTTEs, #iottes.
*
* If #unmapped is less than #iottes, the caller should continue to invoke this
* service with updated iotsb_index and #iottes arguments until all pages are
* demapped.
*/
#define HV_FAST_PCI_IOTSB_DEMAP 0x198
/* pci_iotsb_getmap()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_GETMAP
* ARG0: devhandle
* ARG1: iotsb_handle
* ARG2: iotsb_index
* RET0: status
* RET1: r_addr
* RET2: iotte_attributes
* ERRORS: EINVAL Invalid devhandle, iotsb_handle, or iotsb_index
* ENOMAP No mapping was found
*
* This service returns the mapping specified by index iotsb_index from the
* IOTSB defined by the arguments devhandle, iotsb.
*
* Upon success, the real address of the mapping shall be returned in
* r_addr and thethe IOTTE mapping attributes shall be returned in
* iotte_attributes.
*
* The return value iotte_attributes may not include optional features used in
* the call to create the mapping.
*/
#define HV_FAST_PCI_IOTSB_GETMAP 0x199
/* pci_iotsb_sync_mappings()
* TRAP: HV_FAST_TRAP
* FUNCTION: HV_FAST_PCI_IOTSB_SYNC_MAPPINGS
* ARG0: devhandle
* ARG1: iotsb_handle
* ARG2: iotsb_index
* ARG3: #iottes
* RET0: status
* RET1: #synced
* ERROS: EINVAL Invalid devhandle, iotsb_handle, iotsb_index, or #iottes
*
* This service synchronizes #iottes mappings starting at index iotsb_index in
* the IOTSB defined by the arguments devhandle, iotsb.
*
* #iottes must be greater than zero.
*
* The actual number of IOTTEs synchronized is returned in #synced, which may
* be less than or equal to the requested number, #iottes.
*
* Upon a successful return, #synced is less than #iottes, the caller should
* continue to invoke this service with updated iotsb_index and #iottes
* arguments until all pages are synchronized.
*/
#define HV_FAST_PCI_IOTSB_SYNC_MAPPINGS 0x19a
/* Logical Domain Channel services. */
#define LDC_CHANNEL_DOWN 0
@ -2993,6 +3335,7 @@ unsigned long sun4v_m7_set_perfreg(unsigned long reg_num,
#define HV_GRP_SDIO 0x0108
#define HV_GRP_SDIO_ERR 0x0109
#define HV_GRP_REBOOT_DATA 0x0110
#define HV_GRP_ATU 0x0111
#define HV_GRP_M7_PERF 0x0114
#define HV_GRP_NIAG_PERF 0x0200
#define HV_GRP_FIRE_PERF 0x0201

View File

@ -24,8 +24,36 @@ struct iommu_arena {
unsigned int limit;
};
#define ATU_64_SPACE_SIZE 0x800000000 /* 32G */
/* Data structures for SPARC ATU architecture */
struct atu_iotsb {
void *table; /* IOTSB table base virtual addr*/
u64 ra; /* IOTSB table real addr */
u64 dvma_size; /* ranges[3].size or OS slected 32G size */
u64 dvma_base; /* ranges[3].base */
u64 table_size; /* IOTSB table size */
u64 page_size; /* IO PAGE size for IOTSB */
u32 iotsb_num; /* tsbnum is same as iotsb_handle */
};
struct atu_ranges {
u64 base;
u64 size;
};
struct atu {
struct atu_ranges *ranges;
struct atu_iotsb *iotsb;
struct iommu_map_table tbl;
u64 base;
u64 size;
u64 dma_addr_mask;
};
struct iommu {
struct iommu_map_table tbl;
struct atu *atu;
spinlock_t lock;
u32 dma_addr_mask;
iopte_t *page_table;

View File

@ -39,6 +39,7 @@ static struct api_info api_table[] = {
{ .group = HV_GRP_SDIO, },
{ .group = HV_GRP_SDIO_ERR, },
{ .group = HV_GRP_REBOOT_DATA, },
{ .group = HV_GRP_ATU, .flags = FLAG_PRE_API },
{ .group = HV_GRP_NIAG_PERF, .flags = FLAG_PRE_API },
{ .group = HV_GRP_FIRE_PERF, },
{ .group = HV_GRP_N2_CPU, },

View File

@ -760,8 +760,12 @@ int dma_supported(struct device *dev, u64 device_mask)
struct iommu *iommu = dev->archdata.iommu;
u64 dma_addr_mask = iommu->dma_addr_mask;
if (device_mask >= (1UL << 32UL))
return 0;
if (device_mask > DMA_BIT_MASK(32)) {
if (iommu->atu)
dma_addr_mask = iommu->atu->dma_addr_mask;
else
return 0;
}
if ((device_mask & dma_addr_mask) == dma_addr_mask)
return 1;

View File

@ -13,7 +13,6 @@
#include <linux/scatterlist.h>
#include <linux/device.h>
#include <linux/iommu-helper.h>
#include <linux/scatterlist.h>
#include <asm/iommu.h>

View File

@ -44,6 +44,9 @@ static struct vpci_version vpci_versions[] = {
{ .major = 1, .minor = 1 },
};
static unsigned long vatu_major = 1;
static unsigned long vatu_minor = 1;
#define PGLIST_NENTS (PAGE_SIZE / sizeof(u64))
struct iommu_batch {
@ -69,34 +72,57 @@ static inline void iommu_batch_start(struct device *dev, unsigned long prot, uns
}
/* Interrupts must be disabled. */
static long iommu_batch_flush(struct iommu_batch *p)
static long iommu_batch_flush(struct iommu_batch *p, u64 mask)
{
struct pci_pbm_info *pbm = p->dev->archdata.host_controller;
u64 *pglist = p->pglist;
u64 index_count;
unsigned long devhandle = pbm->devhandle;
unsigned long prot = p->prot;
unsigned long entry = p->entry;
u64 *pglist = p->pglist;
unsigned long npages = p->npages;
unsigned long iotsb_num;
unsigned long ret;
long num;
/* VPCI maj=1, min=[0,1] only supports read and write */
if (vpci_major < 2)
prot &= (HV_PCI_MAP_ATTR_READ | HV_PCI_MAP_ATTR_WRITE);
while (npages != 0) {
long num;
num = pci_sun4v_iommu_map(devhandle, HV_PCI_TSBID(0, entry),
npages, prot, __pa(pglist));
if (unlikely(num < 0)) {
if (printk_ratelimit())
printk("iommu_batch_flush: IOMMU map of "
"[%08lx:%08llx:%lx:%lx:%lx] failed with "
"status %ld\n",
devhandle, HV_PCI_TSBID(0, entry),
npages, prot, __pa(pglist), num);
return -1;
if (mask <= DMA_BIT_MASK(32)) {
num = pci_sun4v_iommu_map(devhandle,
HV_PCI_TSBID(0, entry),
npages,
prot,
__pa(pglist));
if (unlikely(num < 0)) {
pr_err_ratelimited("%s: IOMMU map of [%08lx:%08llx:%lx:%lx:%lx] failed with status %ld\n",
__func__,
devhandle,
HV_PCI_TSBID(0, entry),
npages, prot, __pa(pglist),
num);
return -1;
}
} else {
index_count = HV_PCI_IOTSB_INDEX_COUNT(npages, entry),
iotsb_num = pbm->iommu->atu->iotsb->iotsb_num;
ret = pci_sun4v_iotsb_map(devhandle,
iotsb_num,
index_count,
prot,
__pa(pglist),
&num);
if (unlikely(ret != HV_EOK)) {
pr_err_ratelimited("%s: ATU map of [%08lx:%lx:%llx:%lx:%lx] failed with status %ld\n",
__func__,
devhandle, iotsb_num,
index_count, prot,
__pa(pglist), ret);
return -1;
}
}
entry += num;
npages -= num;
pglist += num;
@ -108,19 +134,19 @@ static long iommu_batch_flush(struct iommu_batch *p)
return 0;
}
static inline void iommu_batch_new_entry(unsigned long entry)
static inline void iommu_batch_new_entry(unsigned long entry, u64 mask)
{
struct iommu_batch *p = this_cpu_ptr(&iommu_batch);
if (p->entry + p->npages == entry)
return;
if (p->entry != ~0UL)
iommu_batch_flush(p);
iommu_batch_flush(p, mask);
p->entry = entry;
}
/* Interrupts must be disabled. */
static inline long iommu_batch_add(u64 phys_page)
static inline long iommu_batch_add(u64 phys_page, u64 mask)
{
struct iommu_batch *p = this_cpu_ptr(&iommu_batch);
@ -128,28 +154,31 @@ static inline long iommu_batch_add(u64 phys_page)
p->pglist[p->npages++] = phys_page;
if (p->npages == PGLIST_NENTS)
return iommu_batch_flush(p);
return iommu_batch_flush(p, mask);
return 0;
}
/* Interrupts must be disabled. */
static inline long iommu_batch_end(void)
static inline long iommu_batch_end(u64 mask)
{
struct iommu_batch *p = this_cpu_ptr(&iommu_batch);
BUG_ON(p->npages >= PGLIST_NENTS);
return iommu_batch_flush(p);
return iommu_batch_flush(p, mask);
}
static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addrp, gfp_t gfp,
unsigned long attrs)
{
u64 mask;
unsigned long flags, order, first_page, npages, n;
unsigned long prot = 0;
struct iommu *iommu;
struct atu *atu;
struct iommu_map_table *tbl;
struct page *page;
void *ret;
long entry;
@ -174,14 +203,21 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
memset((char *)first_page, 0, PAGE_SIZE << order);
iommu = dev->archdata.iommu;
atu = iommu->atu;
entry = iommu_tbl_range_alloc(dev, &iommu->tbl, npages, NULL,
mask = dev->coherent_dma_mask;
if (mask <= DMA_BIT_MASK(32))
tbl = &iommu->tbl;
else
tbl = &atu->tbl;
entry = iommu_tbl_range_alloc(dev, tbl, npages, NULL,
(unsigned long)(-1), 0);
if (unlikely(entry == IOMMU_ERROR_CODE))
goto range_alloc_fail;
*dma_addrp = (iommu->tbl.table_map_base + (entry << IO_PAGE_SHIFT));
*dma_addrp = (tbl->table_map_base + (entry << IO_PAGE_SHIFT));
ret = (void *) first_page;
first_page = __pa(first_page);
@ -193,12 +229,12 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
entry);
for (n = 0; n < npages; n++) {
long err = iommu_batch_add(first_page + (n * PAGE_SIZE));
long err = iommu_batch_add(first_page + (n * PAGE_SIZE), mask);
if (unlikely(err < 0L))
goto iommu_map_fail;
}
if (unlikely(iommu_batch_end() < 0L))
if (unlikely(iommu_batch_end(mask) < 0L))
goto iommu_map_fail;
local_irq_restore(flags);
@ -206,25 +242,71 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
return ret;
iommu_map_fail:
iommu_tbl_range_free(&iommu->tbl, *dma_addrp, npages, IOMMU_ERROR_CODE);
iommu_tbl_range_free(tbl, *dma_addrp, npages, IOMMU_ERROR_CODE);
range_alloc_fail:
free_pages(first_page, order);
return NULL;
}
static void dma_4v_iommu_demap(void *demap_arg, unsigned long entry,
unsigned long npages)
unsigned long dma_4v_iotsb_bind(unsigned long devhandle,
unsigned long iotsb_num,
struct pci_bus *bus_dev)
{
struct pci_dev *pdev;
unsigned long err;
unsigned int bus;
unsigned int device;
unsigned int fun;
list_for_each_entry(pdev, &bus_dev->devices, bus_list) {
if (pdev->subordinate) {
/* No need to bind pci bridge */
dma_4v_iotsb_bind(devhandle, iotsb_num,
pdev->subordinate);
} else {
bus = bus_dev->number;
device = PCI_SLOT(pdev->devfn);
fun = PCI_FUNC(pdev->devfn);
err = pci_sun4v_iotsb_bind(devhandle, iotsb_num,
HV_PCI_DEVICE_BUILD(bus,
device,
fun));
/* If bind fails for one device it is going to fail
* for rest of the devices because we are sharing
* IOTSB. So in case of failure simply return with
* error.
*/
if (err)
return err;
}
}
return 0;
}
static void dma_4v_iommu_demap(struct device *dev, unsigned long devhandle,
dma_addr_t dvma, unsigned long iotsb_num,
unsigned long entry, unsigned long npages)
{
u32 devhandle = *(u32 *)demap_arg;
unsigned long num, flags;
unsigned long ret;
local_irq_save(flags);
do {
num = pci_sun4v_iommu_demap(devhandle,
HV_PCI_TSBID(0, entry),
npages);
if (dvma <= DMA_BIT_MASK(32)) {
num = pci_sun4v_iommu_demap(devhandle,
HV_PCI_TSBID(0, entry),
npages);
} else {
ret = pci_sun4v_iotsb_demap(devhandle, iotsb_num,
entry, npages, &num);
if (unlikely(ret != HV_EOK)) {
pr_err_ratelimited("pci_iotsb_demap() failed with error: %ld\n",
ret);
}
}
entry += num;
npages -= num;
} while (npages != 0);
@ -236,16 +318,28 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
{
struct pci_pbm_info *pbm;
struct iommu *iommu;
struct atu *atu;
struct iommu_map_table *tbl;
unsigned long order, npages, entry;
unsigned long iotsb_num;
u32 devhandle;
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
iommu = dev->archdata.iommu;
pbm = dev->archdata.host_controller;
atu = iommu->atu;
devhandle = pbm->devhandle;
entry = ((dvma - iommu->tbl.table_map_base) >> IO_PAGE_SHIFT);
dma_4v_iommu_demap(&devhandle, entry, npages);
iommu_tbl_range_free(&iommu->tbl, dvma, npages, IOMMU_ERROR_CODE);
if (dvma <= DMA_BIT_MASK(32)) {
tbl = &iommu->tbl;
iotsb_num = 0; /* we don't care for legacy iommu */
} else {
tbl = &atu->tbl;
iotsb_num = atu->iotsb->iotsb_num;
}
entry = ((dvma - tbl->table_map_base) >> IO_PAGE_SHIFT);
dma_4v_iommu_demap(dev, devhandle, dvma, iotsb_num, entry, npages);
iommu_tbl_range_free(tbl, dvma, npages, IOMMU_ERROR_CODE);
order = get_order(size);
if (order < 10)
free_pages((unsigned long)cpu, order);
@ -257,13 +351,17 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
unsigned long attrs)
{
struct iommu *iommu;
struct atu *atu;
struct iommu_map_table *tbl;
u64 mask;
unsigned long flags, npages, oaddr;
unsigned long i, base_paddr;
u32 bus_addr, ret;
unsigned long prot;
dma_addr_t bus_addr, ret;
long entry;
iommu = dev->archdata.iommu;
atu = iommu->atu;
if (unlikely(direction == DMA_NONE))
goto bad;
@ -272,13 +370,19 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
entry = iommu_tbl_range_alloc(dev, &iommu->tbl, npages, NULL,
mask = *dev->dma_mask;
if (mask <= DMA_BIT_MASK(32))
tbl = &iommu->tbl;
else
tbl = &atu->tbl;
entry = iommu_tbl_range_alloc(dev, tbl, npages, NULL,
(unsigned long)(-1), 0);
if (unlikely(entry == IOMMU_ERROR_CODE))
goto bad;
bus_addr = (iommu->tbl.table_map_base + (entry << IO_PAGE_SHIFT));
bus_addr = (tbl->table_map_base + (entry << IO_PAGE_SHIFT));
ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
base_paddr = __pa(oaddr & IO_PAGE_MASK);
prot = HV_PCI_MAP_ATTR_READ;
@ -293,11 +397,11 @@ static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
iommu_batch_start(dev, prot, entry);
for (i = 0; i < npages; i++, base_paddr += IO_PAGE_SIZE) {
long err = iommu_batch_add(base_paddr);
long err = iommu_batch_add(base_paddr, mask);
if (unlikely(err < 0L))
goto iommu_map_fail;
}
if (unlikely(iommu_batch_end() < 0L))
if (unlikely(iommu_batch_end(mask) < 0L))
goto iommu_map_fail;
local_irq_restore(flags);
@ -310,7 +414,7 @@ bad:
return DMA_ERROR_CODE;
iommu_map_fail:
iommu_tbl_range_free(&iommu->tbl, bus_addr, npages, IOMMU_ERROR_CODE);
iommu_tbl_range_free(tbl, bus_addr, npages, IOMMU_ERROR_CODE);
return DMA_ERROR_CODE;
}
@ -320,7 +424,10 @@ static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
{
struct pci_pbm_info *pbm;
struct iommu *iommu;
struct atu *atu;
struct iommu_map_table *tbl;
unsigned long npages;
unsigned long iotsb_num;
long entry;
u32 devhandle;
@ -332,14 +439,23 @@ static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
iommu = dev->archdata.iommu;
pbm = dev->archdata.host_controller;
atu = iommu->atu;
devhandle = pbm->devhandle;
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
npages >>= IO_PAGE_SHIFT;
bus_addr &= IO_PAGE_MASK;
entry = (bus_addr - iommu->tbl.table_map_base) >> IO_PAGE_SHIFT;
dma_4v_iommu_demap(&devhandle, entry, npages);
iommu_tbl_range_free(&iommu->tbl, bus_addr, npages, IOMMU_ERROR_CODE);
if (bus_addr <= DMA_BIT_MASK(32)) {
iotsb_num = 0; /* we don't care for legacy iommu */
tbl = &iommu->tbl;
} else {
iotsb_num = atu->iotsb->iotsb_num;
tbl = &atu->tbl;
}
entry = (bus_addr - tbl->table_map_base) >> IO_PAGE_SHIFT;
dma_4v_iommu_demap(dev, devhandle, bus_addr, iotsb_num, entry, npages);
iommu_tbl_range_free(tbl, bus_addr, npages, IOMMU_ERROR_CODE);
}
static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
@ -353,12 +469,17 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
unsigned long seg_boundary_size;
int outcount, incount, i;
struct iommu *iommu;
struct atu *atu;
struct iommu_map_table *tbl;
u64 mask;
unsigned long base_shift;
long err;
BUG_ON(direction == DMA_NONE);
iommu = dev->archdata.iommu;
atu = iommu->atu;
if (nelems == 0 || !iommu)
return 0;
@ -384,7 +505,15 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
max_seg_size = dma_get_max_seg_size(dev);
seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
IO_PAGE_SIZE) >> IO_PAGE_SHIFT;
base_shift = iommu->tbl.table_map_base >> IO_PAGE_SHIFT;
mask = *dev->dma_mask;
if (mask <= DMA_BIT_MASK(32))
tbl = &iommu->tbl;
else
tbl = &atu->tbl;
base_shift = tbl->table_map_base >> IO_PAGE_SHIFT;
for_each_sg(sglist, s, nelems, i) {
unsigned long paddr, npages, entry, out_entry = 0, slen;
@ -397,27 +526,26 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
/* Allocate iommu entries for that segment */
paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
npages = iommu_num_pages(paddr, slen, IO_PAGE_SIZE);
entry = iommu_tbl_range_alloc(dev, &iommu->tbl, npages,
entry = iommu_tbl_range_alloc(dev, tbl, npages,
&handle, (unsigned long)(-1), 0);
/* Handle failure */
if (unlikely(entry == IOMMU_ERROR_CODE)) {
if (printk_ratelimit())
printk(KERN_INFO "iommu_alloc failed, iommu %p paddr %lx"
" npages %lx\n", iommu, paddr, npages);
pr_err_ratelimited("iommu_alloc failed, iommu %p paddr %lx npages %lx\n",
tbl, paddr, npages);
goto iommu_map_failed;
}
iommu_batch_new_entry(entry);
iommu_batch_new_entry(entry, mask);
/* Convert entry to a dma_addr_t */
dma_addr = iommu->tbl.table_map_base + (entry << IO_PAGE_SHIFT);
dma_addr = tbl->table_map_base + (entry << IO_PAGE_SHIFT);
dma_addr |= (s->offset & ~IO_PAGE_MASK);
/* Insert into HW table */
paddr &= IO_PAGE_MASK;
while (npages--) {
err = iommu_batch_add(paddr);
err = iommu_batch_add(paddr, mask);
if (unlikely(err < 0L))
goto iommu_map_failed;
paddr += IO_PAGE_SIZE;
@ -452,7 +580,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
dma_next = dma_addr + slen;
}
err = iommu_batch_end();
err = iommu_batch_end(mask);
if (unlikely(err < 0L))
goto iommu_map_failed;
@ -475,7 +603,7 @@ iommu_map_failed:
vaddr = s->dma_address & IO_PAGE_MASK;
npages = iommu_num_pages(s->dma_address, s->dma_length,
IO_PAGE_SIZE);
iommu_tbl_range_free(&iommu->tbl, vaddr, npages,
iommu_tbl_range_free(tbl, vaddr, npages,
IOMMU_ERROR_CODE);
/* XXX demap? XXX */
s->dma_address = DMA_ERROR_CODE;
@ -496,13 +624,16 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
struct pci_pbm_info *pbm;
struct scatterlist *sg;
struct iommu *iommu;
struct atu *atu;
unsigned long flags, entry;
unsigned long iotsb_num;
u32 devhandle;
BUG_ON(direction == DMA_NONE);
iommu = dev->archdata.iommu;
pbm = dev->archdata.host_controller;
atu = iommu->atu;
devhandle = pbm->devhandle;
local_irq_save(flags);
@ -512,15 +643,24 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
dma_addr_t dma_handle = sg->dma_address;
unsigned int len = sg->dma_length;
unsigned long npages;
struct iommu_map_table *tbl = &iommu->tbl;
struct iommu_map_table *tbl;
unsigned long shift = IO_PAGE_SHIFT;
if (!len)
break;
npages = iommu_num_pages(dma_handle, len, IO_PAGE_SIZE);
if (dma_handle <= DMA_BIT_MASK(32)) {
iotsb_num = 0; /* we don't care for legacy iommu */
tbl = &iommu->tbl;
} else {
iotsb_num = atu->iotsb->iotsb_num;
tbl = &atu->tbl;
}
entry = ((dma_handle - tbl->table_map_base) >> shift);
dma_4v_iommu_demap(&devhandle, entry, npages);
iommu_tbl_range_free(&iommu->tbl, dma_handle, npages,
dma_4v_iommu_demap(dev, devhandle, dma_handle, iotsb_num,
entry, npages);
iommu_tbl_range_free(tbl, dma_handle, npages,
IOMMU_ERROR_CODE);
sg = sg_next(sg);
}
@ -581,6 +721,132 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
return cnt;
}
static int pci_sun4v_atu_alloc_iotsb(struct pci_pbm_info *pbm)
{
struct atu *atu = pbm->iommu->atu;
struct atu_iotsb *iotsb;
void *table;
u64 table_size;
u64 iotsb_num;
unsigned long order;
unsigned long err;
iotsb = kzalloc(sizeof(*iotsb), GFP_KERNEL);
if (!iotsb) {
err = -ENOMEM;
goto out_err;
}
atu->iotsb = iotsb;
/* calculate size of IOTSB */
table_size = (atu->size / IO_PAGE_SIZE) * 8;
order = get_order(table_size);
table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
if (!table) {
err = -ENOMEM;
goto table_failed;
}
iotsb->table = table;
iotsb->ra = __pa(table);
iotsb->dvma_size = atu->size;
iotsb->dvma_base = atu->base;
iotsb->table_size = table_size;
iotsb->page_size = IO_PAGE_SIZE;
/* configure and register IOTSB with HV */
err = pci_sun4v_iotsb_conf(pbm->devhandle,
iotsb->ra,
iotsb->table_size,
iotsb->page_size,
iotsb->dvma_base,
&iotsb_num);
if (err) {
pr_err(PFX "pci_iotsb_conf failed error: %ld\n", err);
goto iotsb_conf_failed;
}
iotsb->iotsb_num = iotsb_num;
err = dma_4v_iotsb_bind(pbm->devhandle, iotsb_num, pbm->pci_bus);
if (err) {
pr_err(PFX "pci_iotsb_bind failed error: %ld\n", err);
goto iotsb_conf_failed;
}
return 0;
iotsb_conf_failed:
free_pages((unsigned long)table, order);
table_failed:
kfree(iotsb);
out_err:
return err;
}
static int pci_sun4v_atu_init(struct pci_pbm_info *pbm)
{
struct atu *atu = pbm->iommu->atu;
unsigned long err;
const u64 *ranges;
u64 map_size, num_iotte;
u64 dma_mask;
const u32 *page_size;
int len;
ranges = of_get_property(pbm->op->dev.of_node, "iommu-address-ranges",
&len);
if (!ranges) {
pr_err(PFX "No iommu-address-ranges\n");
return -EINVAL;
}
page_size = of_get_property(pbm->op->dev.of_node, "iommu-pagesizes",
NULL);
if (!page_size) {
pr_err(PFX "No iommu-pagesizes\n");
return -EINVAL;
}
/* There are 4 iommu-address-ranges supported. Each range is pair of
* {base, size}. The ranges[0] and ranges[1] are 32bit address space
* while ranges[2] and ranges[3] are 64bit space. We want to use 64bit
* address ranges to support 64bit addressing. Because 'size' for
* address ranges[2] and ranges[3] are same we can select either of
* ranges[2] or ranges[3] for mapping. However due to 'size' is too
* large for OS to allocate IOTSB we are using fix size 32G
* (ATU_64_SPACE_SIZE) which is more than enough for all PCIe devices
* to share.
*/
atu->ranges = (struct atu_ranges *)ranges;
atu->base = atu->ranges[3].base;
atu->size = ATU_64_SPACE_SIZE;
/* Create IOTSB */
err = pci_sun4v_atu_alloc_iotsb(pbm);
if (err) {
pr_err(PFX "Error creating ATU IOTSB\n");
return err;
}
/* Create ATU iommu map.
* One bit represents one iotte in IOTSB table.
*/
dma_mask = (roundup_pow_of_two(atu->size) - 1UL);
num_iotte = atu->size / IO_PAGE_SIZE;
map_size = num_iotte / 8;
atu->tbl.table_map_base = atu->base;
atu->dma_addr_mask = dma_mask;
atu->tbl.map = kzalloc(map_size, GFP_KERNEL);
if (!atu->tbl.map)
return -ENOMEM;
iommu_tbl_pool_init(&atu->tbl, num_iotte, IO_PAGE_SHIFT,
NULL, false /* no large_pool */,
0 /* default npools */,
false /* want span boundary checking */);
return 0;
}
static int pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
{
static const u32 vdma_default[] = { 0x80000000, 0x80000000 };
@ -918,6 +1184,18 @@ static int pci_sun4v_pbm_init(struct pci_pbm_info *pbm,
pci_sun4v_scan_bus(pbm, &op->dev);
/* if atu_init fails its not complete failure.
* we can still continue using legacy iommu.
*/
if (pbm->iommu->atu) {
err = pci_sun4v_atu_init(pbm);
if (err) {
kfree(pbm->iommu->atu);
pbm->iommu->atu = NULL;
pr_err(PFX "ATU init failed, err=%d\n", err);
}
}
pbm->next = pci_pbm_root;
pci_pbm_root = pbm;
@ -931,8 +1209,10 @@ static int pci_sun4v_probe(struct platform_device *op)
struct pci_pbm_info *pbm;
struct device_node *dp;
struct iommu *iommu;
struct atu *atu;
u32 devhandle;
int i, err = -ENODEV;
static bool hv_atu = true;
dp = op->dev.of_node;
@ -954,6 +1234,19 @@ static int pci_sun4v_probe(struct platform_device *op)
pr_info(PFX "Registered hvapi major[%lu] minor[%lu]\n",
vpci_major, vpci_minor);
err = sun4v_hvapi_register(HV_GRP_ATU, vatu_major, &vatu_minor);
if (err) {
/* don't return an error if we fail to register the
* ATU group, but ATU hcalls won't be available.
*/
hv_atu = false;
pr_err(PFX "Could not register hvapi ATU err=%d\n",
err);
} else {
pr_info(PFX "Registered hvapi ATU major[%lu] minor[%lu]\n",
vatu_major, vatu_minor);
}
dma_ops = &sun4v_dma_ops;
}
@ -991,6 +1284,14 @@ static int pci_sun4v_probe(struct platform_device *op)
}
pbm->iommu = iommu;
iommu->atu = NULL;
if (hv_atu) {
atu = kzalloc(sizeof(*atu), GFP_KERNEL);
if (!atu)
pr_err(PFX "Could not allocate atu\n");
else
iommu->atu = atu;
}
err = pci_sun4v_pbm_init(pbm, op, devhandle);
if (err)
@ -1001,6 +1302,7 @@ static int pci_sun4v_probe(struct platform_device *op)
return 0;
out_free_iommu:
kfree(iommu->atu);
kfree(pbm->iommu);
out_free_controller:

View File

@ -89,4 +89,25 @@ unsigned long pci_sun4v_msg_setvalid(unsigned long devhandle,
unsigned long msinum,
unsigned long valid);
/* Sun4v HV IOMMU v2 APIs */
unsigned long pci_sun4v_iotsb_conf(unsigned long devhandle,
unsigned long ra,
unsigned long table_size,
unsigned long page_size,
unsigned long dvma_base,
u64 *iotsb_num);
unsigned long pci_sun4v_iotsb_bind(unsigned long devhandle,
unsigned long iotsb_num,
unsigned int pci_device);
unsigned long pci_sun4v_iotsb_map(unsigned long devhandle,
unsigned long iotsb_num,
unsigned long iotsb_index_iottes,
unsigned long io_attributes,
unsigned long io_page_list_pa,
long *mapped);
unsigned long pci_sun4v_iotsb_demap(unsigned long devhandle,
unsigned long iotsb_num,
unsigned long iotsb_index,
unsigned long iottes,
unsigned long *demapped);
#endif /* !(_PCI_SUN4V_H) */

View File

@ -360,3 +360,71 @@ ENTRY(pci_sun4v_msg_setvalid)
mov %o0, %o0
ENDPROC(pci_sun4v_msg_setvalid)
/*
* %o0: devhandle
* %o1: r_addr
* %o2: size
* %o3: pagesize
* %o4: virt
* %o5: &iotsb_num/&iotsb_handle
*
* returns %o0: status
* %o1: iotsb_num/iotsb_handle
*/
ENTRY(pci_sun4v_iotsb_conf)
mov %o5, %g1
mov HV_FAST_PCI_IOTSB_CONF, %o5
ta HV_FAST_TRAP
retl
stx %o1, [%g1]
ENDPROC(pci_sun4v_iotsb_conf)
/*
* %o0: devhandle
* %o1: iotsb_num/iotsb_handle
* %o2: pci_device
*
* returns %o0: status
*/
ENTRY(pci_sun4v_iotsb_bind)
mov HV_FAST_PCI_IOTSB_BIND, %o5
ta HV_FAST_TRAP
retl
nop
ENDPROC(pci_sun4v_iotsb_bind)
/*
* %o0: devhandle
* %o1: iotsb_num/iotsb_handle
* %o2: index_count
* %o3: iotte_attributes
* %o4: io_page_list_p
* %o5: &mapped
*
* returns %o0: status
* %o1: #mapped
*/
ENTRY(pci_sun4v_iotsb_map)
mov %o5, %g1
mov HV_FAST_PCI_IOTSB_MAP, %o5
ta HV_FAST_TRAP
retl
stx %o1, [%g1]
ENDPROC(pci_sun4v_iotsb_map)
/*
* %o0: devhandle
* %o1: iotsb_num/iotsb_handle
* %o2: iotsb_index
* %o3: #iottes
* %o4: &demapped
*
* returns %o0: status
* %o1: #demapped
*/
ENTRY(pci_sun4v_iotsb_demap)
mov HV_FAST_PCI_IOTSB_DEMAP, %o5
ta HV_FAST_TRAP
retl
stx %o1, [%o4]
ENDPROC(pci_sun4v_iotsb_demap)

View File

@ -89,7 +89,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */
if (!invalid_frame_pointer(sf, sizeof(*sf)))
if (invalid_frame_pointer(sf, sizeof(*sf)))
goto segv_and_exit;
if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
@ -150,7 +150,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
synchronize_user_stack();
sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
if (!invalid_frame_pointer(sf, sizeof(*sf)))
if (invalid_frame_pointer(sf, sizeof(*sf)))
goto segv;
if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))

View File

@ -802,8 +802,10 @@ struct mdesc_mblock {
};
static struct mdesc_mblock *mblocks;
static int num_mblocks;
static int find_numa_node_for_addr(unsigned long pa,
struct node_mem_mask *pnode_mask);
static unsigned long ra_to_pa(unsigned long addr)
static unsigned long __init ra_to_pa(unsigned long addr)
{
int i;
@ -819,8 +821,11 @@ static unsigned long ra_to_pa(unsigned long addr)
return addr;
}
static int find_node(unsigned long addr)
static int __init find_node(unsigned long addr)
{
static bool search_mdesc = true;
static struct node_mem_mask last_mem_mask = { ~0UL, ~0UL };
static int last_index;
int i;
addr = ra_to_pa(addr);
@ -830,13 +835,30 @@ static int find_node(unsigned long addr)
if ((addr & p->mask) == p->val)
return i;
}
/* The following condition has been observed on LDOM guests.*/
WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node"
" rule. Some physical memory will be owned by node 0.");
return 0;
/* The following condition has been observed on LDOM guests because
* node_masks only contains the best latency mask and value.
* LDOM guest's mdesc can contain a single latency group to
* cover multiple address range. Print warning message only if the
* address cannot be found in node_masks nor mdesc.
*/
if ((search_mdesc) &&
((addr & last_mem_mask.mask) != last_mem_mask.val)) {
/* find the available node in the mdesc */
last_index = find_numa_node_for_addr(addr, &last_mem_mask);
numadbg("find_node: latency group for address 0x%lx is %d\n",
addr, last_index);
if ((last_index < 0) || (last_index >= num_node_masks)) {
/* WARN_ONCE() and use default group 0 */
WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node rule. Some physical memory will be owned by node 0.");
search_mdesc = false;
last_index = 0;
}
}
return last_index;
}
static u64 memblock_nid_range(u64 start, u64 end, int *nid)
static u64 __init memblock_nid_range(u64 start, u64 end, int *nid)
{
*nid = find_node(start);
start += PAGE_SIZE;
@ -1160,6 +1182,41 @@ int __node_distance(int from, int to)
return numa_latency[from][to];
}
static int find_numa_node_for_addr(unsigned long pa,
struct node_mem_mask *pnode_mask)
{
struct mdesc_handle *md = mdesc_grab();
u64 node, arc;
int i = 0;
node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
if (node == MDESC_NODE_NULL)
goto out;
mdesc_for_each_node_by_name(md, node, "group") {
mdesc_for_each_arc(arc, md, node, MDESC_ARC_TYPE_FWD) {
u64 target = mdesc_arc_target(md, arc);
struct mdesc_mlgroup *m = find_mlgroup(target);
if (!m)
continue;
if ((pa & m->mask) == m->match) {
if (pnode_mask) {
pnode_mask->mask = m->mask;
pnode_mask->val = m->match;
}
mdesc_release(md);
return i;
}
}
i++;
}
out:
mdesc_release(md);
return -1;
}
static int __init find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp)
{
int i;

View File

@ -61,4 +61,7 @@
*/
#define __write_once __read_mostly
/* __ro_after_init is the generic name for the tile arch __write_once. */
#define __ro_after_init __read_mostly
#endif /* _ASM_TILE_CACHE_H */

View File

@ -888,7 +888,7 @@ static int helper_rfc4106_encrypt(struct aead_request *req)
unsigned long auth_tag_len = crypto_aead_authsize(tfm);
u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
struct scatter_walk src_sg_walk;
struct scatter_walk dst_sg_walk;
struct scatter_walk dst_sg_walk = {};
unsigned int i;
/* Assuming we are supporting rfc4106 64-bit extended */
@ -968,7 +968,7 @@ static int helper_rfc4106_decrypt(struct aead_request *req)
u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
u8 authTag[16];
struct scatter_walk src_sg_walk;
struct scatter_walk dst_sg_walk;
struct scatter_walk dst_sg_walk = {};
unsigned int i;
if (unlikely(req->assoclen != 16 && req->assoclen != 20))

View File

@ -8,8 +8,12 @@
#define PCI_DEVICE_ID_INTEL_HSW_IMC 0x0c00
#define PCI_DEVICE_ID_INTEL_HSW_U_IMC 0x0a04
#define PCI_DEVICE_ID_INTEL_BDW_IMC 0x1604
#define PCI_DEVICE_ID_INTEL_SKL_IMC 0x191f
#define PCI_DEVICE_ID_INTEL_SKL_U_IMC 0x190c
#define PCI_DEVICE_ID_INTEL_SKL_U_IMC 0x1904
#define PCI_DEVICE_ID_INTEL_SKL_Y_IMC 0x190c
#define PCI_DEVICE_ID_INTEL_SKL_HD_IMC 0x1900
#define PCI_DEVICE_ID_INTEL_SKL_HQ_IMC 0x1910
#define PCI_DEVICE_ID_INTEL_SKL_SD_IMC 0x190f
#define PCI_DEVICE_ID_INTEL_SKL_SQ_IMC 0x191f
/* SNB event control */
#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff
@ -616,13 +620,29 @@ static const struct pci_device_id bdw_uncore_pci_ids[] = {
static const struct pci_device_id skl_uncore_pci_ids[] = {
{ /* IMC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_IMC),
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_Y_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
},
{ /* IMC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_U_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
},
{ /* IMC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_HD_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
},
{ /* IMC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_HQ_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
},
{ /* IMC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_SD_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
},
{ /* IMC */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_SQ_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
},
{ /* end: all zeroes */ },
};
@ -666,8 +686,12 @@ static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
IMC_DEV(HSW_IMC, &hsw_uncore_pci_driver), /* 4th Gen Core Processor */
IMC_DEV(HSW_U_IMC, &hsw_uncore_pci_driver), /* 4th Gen Core ULT Mobile Processor */
IMC_DEV(BDW_IMC, &bdw_uncore_pci_driver), /* 5th Gen Core U */
IMC_DEV(SKL_IMC, &skl_uncore_pci_driver), /* 6th Gen Core */
IMC_DEV(SKL_Y_IMC, &skl_uncore_pci_driver), /* 6th Gen Core Y */
IMC_DEV(SKL_U_IMC, &skl_uncore_pci_driver), /* 6th Gen Core U */
IMC_DEV(SKL_HD_IMC, &skl_uncore_pci_driver), /* 6th Gen Core H Dual Core */
IMC_DEV(SKL_HQ_IMC, &skl_uncore_pci_driver), /* 6th Gen Core H Quad Core */
IMC_DEV(SKL_SD_IMC, &skl_uncore_pci_driver), /* 6th Gen Core S Dual Core */
IMC_DEV(SKL_SQ_IMC, &skl_uncore_pci_driver), /* 6th Gen Core S Quad Core */
{ /* end marker */ }
};

View File

@ -17,6 +17,7 @@
extern int intel_mid_pci_init(void);
extern int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state);
extern pci_power_t intel_mid_pci_get_power_state(struct pci_dev *pdev);
extern void intel_mid_pwr_power_off(void);

View File

@ -1042,8 +1042,11 @@ static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
if (apm_info.get_power_status_broken)
return APM_32_UNSUPPORTED;
if (apm_bios_call(&call))
if (apm_bios_call(&call)) {
if (!call.err)
return APM_NO_ERROR;
return call.err;
}
*status = call.ebx;
*bat = call.ecx;
if (apm_info.get_power_status_swabinminutes) {

View File

@ -347,7 +347,6 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
#ifdef CONFIG_SMP
unsigned bits;
int cpu = smp_processor_id();
unsigned int socket_id, core_complex_id;
bits = c->x86_coreid_bits;
/* Low order bits define the core id (index of core in socket) */
@ -365,10 +364,7 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
if (c->x86 != 0x17 || !cpuid_edx(0x80000006))
return;
socket_id = (c->apicid >> bits) - 1;
core_complex_id = (c->apicid & ((1 << bits) - 1)) >> 3;
per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
#endif
}

View File

@ -978,6 +978,35 @@ static void x86_init_cache_qos(struct cpuinfo_x86 *c)
}
}
/*
* The physical to logical package id mapping is initialized from the
* acpi/mptables information. Make sure that CPUID actually agrees with
* that.
*/
static void sanitize_package_id(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
unsigned int pkg, apicid, cpu = smp_processor_id();
apicid = apic->cpu_present_to_apicid(cpu);
pkg = apicid >> boot_cpu_data.x86_coreid_bits;
if (apicid != c->initial_apicid) {
pr_err(FW_BUG "CPU%u: APIC id mismatch. Firmware: %x CPUID: %x\n",
cpu, apicid, c->initial_apicid);
c->initial_apicid = apicid;
}
if (pkg != c->phys_proc_id) {
pr_err(FW_BUG "CPU%u: Using firmware package id %u instead of %u\n",
cpu, pkg, c->phys_proc_id);
c->phys_proc_id = pkg;
}
c->logical_proc_id = topology_phys_to_logical_pkg(pkg);
#else
c->logical_proc_id = 0;
#endif
}
/*
* This does the hard work of actually picking apart the CPU stuff...
*/
@ -1103,8 +1132,7 @@ static void identify_cpu(struct cpuinfo_x86 *c)
#ifdef CONFIG_NUMA
numa_add_cpu(smp_processor_id());
#endif
/* The boot/hotplug time assigment got cleared, restore it */
c->logical_proc_id = topology_phys_to_logical_pkg(c->phys_proc_id);
sanitize_package_id(c);
}
/*

View File

@ -156,6 +156,16 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
}
static int kvm_hv_set_sint(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int irq_source_id, int level,
bool line_status)
{
if (!level)
return -1;
return kvm_hv_synic_set_irq(kvm, e->hv_sint.vcpu, e->hv_sint.sint);
}
int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int irq_source_id, int level,
bool line_status)
@ -163,18 +173,26 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
struct kvm_lapic_irq irq;
int r;
if (unlikely(e->type != KVM_IRQ_ROUTING_MSI))
return -EWOULDBLOCK;
switch (e->type) {
case KVM_IRQ_ROUTING_HV_SINT:
return kvm_hv_set_sint(e, kvm, irq_source_id, level,
line_status);
if (kvm_msi_route_invalid(kvm, e))
return -EINVAL;
case KVM_IRQ_ROUTING_MSI:
if (kvm_msi_route_invalid(kvm, e))
return -EINVAL;
kvm_set_msi_irq(kvm, e, &irq);
kvm_set_msi_irq(kvm, e, &irq);
if (kvm_irq_delivery_to_apic_fast(kvm, NULL, &irq, &r, NULL))
return r;
else
return -EWOULDBLOCK;
if (kvm_irq_delivery_to_apic_fast(kvm, NULL, &irq, &r, NULL))
return r;
break;
default:
break;
}
return -EWOULDBLOCK;
}
int kvm_request_irq_source_id(struct kvm *kvm)
@ -254,16 +272,6 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
srcu_read_unlock(&kvm->irq_srcu, idx);
}
static int kvm_hv_set_sint(struct kvm_kernel_irq_routing_entry *e,
struct kvm *kvm, int irq_source_id, int level,
bool line_status)
{
if (!level)
return -1;
return kvm_hv_synic_set_irq(kvm, e->hv_sint.vcpu, e->hv_sint.sint);
}
int kvm_set_routing_entry(struct kvm *kvm,
struct kvm_kernel_irq_routing_entry *e,
const struct kvm_irq_routing_entry *ue)
@ -423,18 +431,6 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
srcu_read_unlock(&kvm->irq_srcu, idx);
}
int kvm_arch_set_irq(struct kvm_kernel_irq_routing_entry *irq, struct kvm *kvm,
int irq_source_id, int level, bool line_status)
{
switch (irq->type) {
case KVM_IRQ_ROUTING_HV_SINT:
return kvm_hv_set_sint(irq, kvm, irq_source_id, level,
line_status);
default:
return -EWOULDBLOCK;
}
}
void kvm_arch_irq_routing_update(struct kvm *kvm)
{
kvm_hv_irq_routing_update(kvm);

View File

@ -210,7 +210,18 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
struct kvm_shared_msrs *locals
= container_of(urn, struct kvm_shared_msrs, urn);
struct kvm_shared_msr_values *values;
unsigned long flags;
/*
* Disabling irqs at this point since the following code could be
* interrupted and executed through kvm_arch_hardware_disable()
*/
local_irq_save(flags);
if (locals->registered) {
locals->registered = false;
user_return_notifier_unregister(urn);
}
local_irq_restore(flags);
for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
values = &locals->values[slot];
if (values->host != values->curr) {
@ -218,8 +229,6 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
values->curr = values->host;
}
}
locals->registered = false;
user_return_notifier_unregister(urn);
}
static void shared_msr_update(unsigned slot, u32 msr)
@ -1724,18 +1733,23 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)
static u64 __get_kvmclock_ns(struct kvm *kvm)
{
struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, 0);
struct kvm_arch *ka = &kvm->arch;
s64 ns;
struct pvclock_vcpu_time_info hv_clock;
if (vcpu->arch.hv_clock.flags & PVCLOCK_TSC_STABLE_BIT) {
u64 tsc = kvm_read_l1_tsc(vcpu, rdtsc());
ns = __pvclock_read_cycles(&vcpu->arch.hv_clock, tsc);
} else {
ns = ktime_get_boot_ns() + ka->kvmclock_offset;
spin_lock(&ka->pvclock_gtod_sync_lock);
if (!ka->use_master_clock) {
spin_unlock(&ka->pvclock_gtod_sync_lock);
return ktime_get_boot_ns() + ka->kvmclock_offset;
}
return ns;
hv_clock.tsc_timestamp = ka->master_cycle_now;
hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset;
spin_unlock(&ka->pvclock_gtod_sync_lock);
kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL,
&hv_clock.tsc_shift,
&hv_clock.tsc_to_system_mul);
return __pvclock_read_cycles(&hv_clock, rdtsc());
}
u64 get_kvmclock_ns(struct kvm *kvm)
@ -2596,7 +2610,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_PIT_STATE2:
case KVM_CAP_SET_IDENTITY_MAP_ADDR:
case KVM_CAP_XEN_HVM:
case KVM_CAP_ADJUST_CLOCK:
case KVM_CAP_VCPU_EVENTS:
case KVM_CAP_HYPERV:
case KVM_CAP_HYPERV_VAPIC:
@ -2623,6 +2636,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
#endif
r = 1;
break;
case KVM_CAP_ADJUST_CLOCK:
r = KVM_CLOCK_TSC_STABLE;
break;
case KVM_CAP_X86_SMM:
/* SMBASE is usually relocated above 1M on modern chipsets,
* and SMM handlers might indeed rely on 4G segment limits,
@ -3415,6 +3431,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
};
case KVM_SET_VAPIC_ADDR: {
struct kvm_vapic_addr va;
int idx;
r = -EINVAL;
if (!lapic_in_kernel(vcpu))
@ -3422,7 +3439,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
r = -EFAULT;
if (copy_from_user(&va, argp, sizeof va))
goto out;
idx = srcu_read_lock(&vcpu->kvm->srcu);
r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
srcu_read_unlock(&vcpu->kvm->srcu, idx);
break;
}
case KVM_X86_SETUP_MCE: {
@ -4103,9 +4122,11 @@ long kvm_arch_vm_ioctl(struct file *filp,
struct kvm_clock_data user_ns;
u64 now_ns;
now_ns = get_kvmclock_ns(kvm);
local_irq_disable();
now_ns = __get_kvmclock_ns(kvm);
user_ns.clock = now_ns;
user_ns.flags = 0;
user_ns.flags = kvm->arch.use_master_clock ? KVM_CLOCK_TSC_STABLE : 0;
local_irq_enable();
memset(&user_ns.pad, 0, sizeof(user_ns.pad));
r = -EFAULT;

View File

@ -861,7 +861,7 @@ static void __init __efi_enter_virtual_mode(void)
int count = 0, pg_shift = 0;
void *new_memmap = NULL;
efi_status_t status;
phys_addr_t pa;
unsigned long pa;
efi.systab = NULL;

View File

@ -31,6 +31,7 @@
#include <linux/io.h>
#include <linux/reboot.h>
#include <linux/slab.h>
#include <linux/ucs2_string.h>
#include <asm/setup.h>
#include <asm/page.h>
@ -211,6 +212,35 @@ void efi_sync_low_kernel_mappings(void)
memcpy(pud_efi, pud_k, sizeof(pud_t) * num_entries);
}
/*
* Wrapper for slow_virt_to_phys() that handles NULL addresses.
*/
static inline phys_addr_t
virt_to_phys_or_null_size(void *va, unsigned long size)
{
bool bad_size;
if (!va)
return 0;
if (virt_addr_valid(va))
return virt_to_phys(va);
/*
* A fully aligned variable on the stack is guaranteed not to
* cross a page bounary. Try to catch strings on the stack by
* checking that 'size' is a power of two.
*/
bad_size = size > PAGE_SIZE || !is_power_of_2(size);
WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size);
return slow_virt_to_phys(va);
}
#define virt_to_phys_or_null(addr) \
virt_to_phys_or_null_size((addr), sizeof(*(addr)))
int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
{
unsigned long pfn, text;
@ -494,8 +524,8 @@ static efi_status_t efi_thunk_get_time(efi_time_t *tm, efi_time_cap_t *tc)
spin_lock(&rtc_lock);
phys_tm = virt_to_phys(tm);
phys_tc = virt_to_phys(tc);
phys_tm = virt_to_phys_or_null(tm);
phys_tc = virt_to_phys_or_null(tc);
status = efi_thunk(get_time, phys_tm, phys_tc);
@ -511,7 +541,7 @@ static efi_status_t efi_thunk_set_time(efi_time_t *tm)
spin_lock(&rtc_lock);
phys_tm = virt_to_phys(tm);
phys_tm = virt_to_phys_or_null(tm);
status = efi_thunk(set_time, phys_tm);
@ -529,9 +559,9 @@ efi_thunk_get_wakeup_time(efi_bool_t *enabled, efi_bool_t *pending,
spin_lock(&rtc_lock);
phys_enabled = virt_to_phys(enabled);
phys_pending = virt_to_phys(pending);
phys_tm = virt_to_phys(tm);
phys_enabled = virt_to_phys_or_null(enabled);
phys_pending = virt_to_phys_or_null(pending);
phys_tm = virt_to_phys_or_null(tm);
status = efi_thunk(get_wakeup_time, phys_enabled,
phys_pending, phys_tm);
@ -549,7 +579,7 @@ efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
spin_lock(&rtc_lock);
phys_tm = virt_to_phys(tm);
phys_tm = virt_to_phys_or_null(tm);
status = efi_thunk(set_wakeup_time, enabled, phys_tm);
@ -558,6 +588,10 @@ efi_thunk_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
return status;
}
static unsigned long efi_name_size(efi_char16_t *name)
{
return ucs2_strsize(name, EFI_VAR_NAME_LEN) + 1;
}
static efi_status_t
efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
@ -567,11 +601,11 @@ efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
u32 phys_name, phys_vendor, phys_attr;
u32 phys_data_size, phys_data;
phys_data_size = virt_to_phys(data_size);
phys_vendor = virt_to_phys(vendor);
phys_name = virt_to_phys(name);
phys_attr = virt_to_phys(attr);
phys_data = virt_to_phys(data);
phys_data_size = virt_to_phys_or_null(data_size);
phys_vendor = virt_to_phys_or_null(vendor);
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
phys_attr = virt_to_phys_or_null(attr);
phys_data = virt_to_phys_or_null_size(data, *data_size);
status = efi_thunk(get_variable, phys_name, phys_vendor,
phys_attr, phys_data_size, phys_data);
@ -586,9 +620,9 @@ efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
u32 phys_name, phys_vendor, phys_data;
efi_status_t status;
phys_name = virt_to_phys(name);
phys_vendor = virt_to_phys(vendor);
phys_data = virt_to_phys(data);
phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
phys_vendor = virt_to_phys_or_null(vendor);
phys_data = virt_to_phys_or_null_size(data, data_size);
/* If data_size is > sizeof(u32) we've got problems */
status = efi_thunk(set_variable, phys_name, phys_vendor,
@ -605,9 +639,9 @@ efi_thunk_get_next_variable(unsigned long *name_size,
efi_status_t status;
u32 phys_name_size, phys_name, phys_vendor;
phys_name_size = virt_to_phys(name_size);
phys_vendor = virt_to_phys(vendor);
phys_name = virt_to_phys(name);
phys_name_size = virt_to_phys_or_null(name_size);
phys_vendor = virt_to_phys_or_null(vendor);
phys_name = virt_to_phys_or_null_size(name, *name_size);
status = efi_thunk(get_next_variable, phys_name_size,
phys_name, phys_vendor);
@ -621,7 +655,7 @@ efi_thunk_get_next_high_mono_count(u32 *count)
efi_status_t status;
u32 phys_count;
phys_count = virt_to_phys(count);
phys_count = virt_to_phys_or_null(count);
status = efi_thunk(get_next_high_mono_count, phys_count);
return status;
@ -633,7 +667,7 @@ efi_thunk_reset_system(int reset_type, efi_status_t status,
{
u32 phys_data;
phys_data = virt_to_phys(data);
phys_data = virt_to_phys_or_null_size(data, data_size);
efi_thunk(reset_system, reset_type, status, data_size, phys_data);
}
@ -661,9 +695,9 @@ efi_thunk_query_variable_info(u32 attr, u64 *storage_space,
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;
phys_storage = virt_to_phys(storage_space);
phys_remaining = virt_to_phys(remaining_space);
phys_max = virt_to_phys(max_variable_size);
phys_storage = virt_to_phys_or_null(storage_space);
phys_remaining = virt_to_phys_or_null(remaining_space);
phys_max = virt_to_phys_or_null(max_variable_size);
status = efi_thunk(query_variable_info, attr, phys_storage,
phys_remaining, phys_max);

View File

@ -272,6 +272,25 @@ int intel_mid_pci_set_power_state(struct pci_dev *pdev, pci_power_t state)
}
EXPORT_SYMBOL_GPL(intel_mid_pci_set_power_state);
pci_power_t intel_mid_pci_get_power_state(struct pci_dev *pdev)
{
struct mid_pwr *pwr = midpwr;
int id, reg, bit;
u32 power;
if (!pwr || !pwr->available)
return PCI_UNKNOWN;
id = intel_mid_pwr_get_lss_id(pdev);
if (id < 0)
return PCI_UNKNOWN;
reg = (id * LSS_PWS_BITS) / 32;
bit = (id * LSS_PWS_BITS) % 32;
power = mid_pwr_get_state(pwr, reg);
return (__force pci_power_t)((power >> bit) & 3);
}
void intel_mid_pwr_power_off(void)
{
struct mid_pwr *pwr = midpwr;

View File

@ -16,6 +16,7 @@ KCOV_INSTRUMENT := n
KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large
KBUILD_CFLAGS += -m$(BITS)
KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
$(call if_changed,ld)

View File

@ -767,7 +767,14 @@ __SYSCALL(346, sys_preadv2, 6)
#define __NR_pwritev2 347
__SYSCALL(347, sys_pwritev2, 6)
#define __NR_syscall_count 348
#define __NR_pkey_mprotect 348
__SYSCALL(348, sys_pkey_mprotect, 4)
#define __NR_pkey_alloc 349
__SYSCALL(349, sys_pkey_alloc, 2)
#define __NR_pkey_free 350
__SYSCALL(350, sys_pkey_free, 1)
#define __NR_syscall_count 351
/*
* sysxtensa syscall handler

View File

@ -172,10 +172,11 @@ void __init time_init(void)
{
of_clk_init(NULL);
#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
printk("Calibrating CPU frequency ");
pr_info("Calibrating CPU frequency ");
calibrate_ccount();
printk("%d.%02d MHz\n", (int)ccount_freq/1000000,
(int)(ccount_freq/10000)%100);
pr_cont("%d.%02d MHz\n",
(int)ccount_freq / 1000000,
(int)(ccount_freq / 10000) % 100);
#else
ccount_freq = CONFIG_XTENSA_CPU_CLOCK*1000000UL;
#endif
@ -210,9 +211,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id)
void calibrate_delay(void)
{
loops_per_jiffy = ccount_freq / HZ;
printk("Calibrating delay loop (skipped)... "
"%lu.%02lu BogoMIPS preset\n",
loops_per_jiffy/(1000000/HZ),
(loops_per_jiffy/(10000/HZ)) % 100);
pr_info("Calibrating delay loop (skipped)... %lu.%02lu BogoMIPS preset\n",
loops_per_jiffy / (1000000 / HZ),
(loops_per_jiffy / (10000 / HZ)) % 100);
}
#endif

View File

@ -465,26 +465,25 @@ void show_regs(struct pt_regs * regs)
for (i = 0; i < 16; i++) {
if ((i % 8) == 0)
printk(KERN_INFO "a%02d:", i);
printk(KERN_CONT " %08lx", regs->areg[i]);
pr_info("a%02d:", i);
pr_cont(" %08lx", regs->areg[i]);
}
printk(KERN_CONT "\n");
printk("pc: %08lx, ps: %08lx, depc: %08lx, excvaddr: %08lx\n",
regs->pc, regs->ps, regs->depc, regs->excvaddr);
printk("lbeg: %08lx, lend: %08lx lcount: %08lx, sar: %08lx\n",
regs->lbeg, regs->lend, regs->lcount, regs->sar);
pr_cont("\n");
pr_info("pc: %08lx, ps: %08lx, depc: %08lx, excvaddr: %08lx\n",
regs->pc, regs->ps, regs->depc, regs->excvaddr);
pr_info("lbeg: %08lx, lend: %08lx lcount: %08lx, sar: %08lx\n",
regs->lbeg, regs->lend, regs->lcount, regs->sar);
if (user_mode(regs))
printk("wb: %08lx, ws: %08lx, wmask: %08lx, syscall: %ld\n",
regs->windowbase, regs->windowstart, regs->wmask,
regs->syscall);
pr_cont("wb: %08lx, ws: %08lx, wmask: %08lx, syscall: %ld\n",
regs->windowbase, regs->windowstart, regs->wmask,
regs->syscall);
}
static int show_trace_cb(struct stackframe *frame, void *data)
{
if (kernel_text_address(frame->pc)) {
printk(" [<%08lx>] ", frame->pc);
print_symbol("%s\n", frame->pc);
pr_cont(" [<%08lx>]", frame->pc);
print_symbol(" %s\n", frame->pc);
}
return 0;
}
@ -494,19 +493,13 @@ void show_trace(struct task_struct *task, unsigned long *sp)
if (!sp)
sp = stack_pointer(task);
printk("Call Trace:");
#ifdef CONFIG_KALLSYMS
printk("\n");
#endif
pr_info("Call Trace:\n");
walk_stackframe(sp, show_trace_cb, NULL);
printk("\n");
#ifndef CONFIG_KALLSYMS
pr_cont("\n");
#endif
}
/*
* This routine abuses get_user()/put_user() to reference pointers
* with at least a bit of error checking ...
*/
static int kstack_depth_to_print = 24;
void show_stack(struct task_struct *task, unsigned long *sp)
@ -518,52 +511,29 @@ void show_stack(struct task_struct *task, unsigned long *sp)
sp = stack_pointer(task);
stack = sp;
printk("\nStack: ");
pr_info("Stack:\n");
for (i = 0; i < kstack_depth_to_print; i++) {
if (kstack_end(sp))
break;
if (i && ((i % 8) == 0))
printk("\n ");
printk("%08lx ", *sp++);
pr_cont(" %08lx", *sp++);
if (i % 8 == 7)
pr_cont("\n");
}
printk("\n");
show_trace(task, stack);
}
void show_code(unsigned int *pc)
{
long i;
printk("\nCode:");
for(i = -3 ; i < 6 ; i++) {
unsigned long insn;
if (__get_user(insn, pc + i)) {
printk(" (Bad address in pc)\n");
break;
}
printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>'));
}
}
DEFINE_SPINLOCK(die_lock);
void die(const char * str, struct pt_regs * regs, long err)
{
static int die_counter;
int nl = 0;
console_verbose();
spin_lock_irq(&die_lock);
printk("%s: sig: %ld [#%d]\n", str, err, ++die_counter);
#ifdef CONFIG_PREEMPT
printk("PREEMPT ");
nl = 1;
#endif
if (nl)
printk("\n");
pr_info("%s: sig: %ld [#%d]%s\n", str, err, ++die_counter,
IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "");
show_regs(regs);
if (!user_mode(regs))
show_stack(NULL, (unsigned long*)regs->areg[1]);

Some files were not shown because too many files have changed in this diff Show More