Merge 6deccafcb4 ("Merge tag 'parisc-for-7.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux") into android-mainline
Steps on the way to v7.0-rc3 Change-Id: Ifb1142bd686d07518615e63635bcf065742bcd4b Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
commit
fa41e682ca
97 files changed
+589
-458
No files matched your search
@@ -16,7 +16,6 @@ description: |
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- kontron,sa67mcu-hwmon
|
||||
- kontron,sl28cpld-fan
|
||||
|
||||
reg:
|
||||
|
||||
@@ -57,7 +57,7 @@ Supported chips:
|
||||
- https://ww1.microchip.com/downloads/en/DeviceDoc/EMC1438%20DS%20Rev.%201.0%20(04-29-10).pdf
|
||||
|
||||
Author:
|
||||
Kalhan Trisal <kalhan.trisal@intel.com
|
||||
Kalhan Trisal <kalhan.trisal@intel.com>
|
||||
|
||||
|
||||
Description
|
||||
|
||||
@@ -220,7 +220,6 @@ Hardware Monitoring Kernel Drivers
|
||||
q54sj108a2
|
||||
qnap-mcu-hwmon
|
||||
raspberrypi-hwmon
|
||||
sa67
|
||||
sbrmi
|
||||
sbtsi_temp
|
||||
sch5627
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
Kernel driver sa67mcu
|
||||
=====================
|
||||
|
||||
Supported chips:
|
||||
|
||||
* Kontron sa67mcu
|
||||
|
||||
Prefix: 'sa67mcu'
|
||||
|
||||
Datasheet: not available
|
||||
|
||||
Authors: Michael Walle <mwalle@kernel.org>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The sa67mcu is a board management controller which also exposes a hardware
|
||||
monitoring controller.
|
||||
|
||||
The controller has two voltage and one temperature sensor. The values are
|
||||
hold in two 8 bit registers to form one 16 bit value. Reading the lower byte
|
||||
will also capture the high byte to make the access atomic. The unit of the
|
||||
volatge sensors are 1mV and the unit of the temperature sensor is 0.1degC.
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
The following attributes are supported.
|
||||
|
||||
======================= ========================================================
|
||||
in0_label "VDDIN"
|
||||
in0_input Measured VDDIN voltage.
|
||||
|
||||
in1_label "VDD_RTC"
|
||||
in1_input Measured VDD_RTC voltage.
|
||||
|
||||
temp1_input MCU temperature. Roughly the board temperature.
|
||||
======================= ========================================================
|
||||
|
||||
@@ -24327,7 +24327,6 @@ F: Documentation/devicetree/bindings/interrupt-controller/kontron,sl28cpld-intc.
|
||||
F: Documentation/devicetree/bindings/pwm/kontron,sl28cpld-pwm.yaml
|
||||
F: Documentation/devicetree/bindings/watchdog/kontron,sl28cpld-wdt.yaml
|
||||
F: drivers/gpio/gpio-sl28cpld.c
|
||||
F: drivers/hwmon/sa67mcu-hwmon.c
|
||||
F: drivers/hwmon/sl28cpld-hwmon.c
|
||||
F: drivers/irqchip/irq-sl28cpld.c
|
||||
F: drivers/pwm/pwm-sl28cpld.c
|
||||
|
||||
@@ -1525,13 +1525,13 @@ ifneq ($(wildcard $(resolve_btfids_O)),)
|
||||
$(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean
|
||||
endif
|
||||
|
||||
PHONY += objtool_clean
|
||||
PHONY += objtool_clean objtool_mrproper
|
||||
|
||||
objtool_O = $(abspath $(objtree))/tools/objtool
|
||||
|
||||
objtool_clean:
|
||||
objtool_clean objtool_mrproper:
|
||||
ifneq ($(wildcard $(objtool_O)),)
|
||||
$(Q)$(MAKE) -sC $(abs_srctree)/tools/objtool O=$(objtool_O) srctree=$(abs_srctree) clean
|
||||
$(Q)$(MAKE) -sC $(abs_srctree)/tools/objtool O=$(objtool_O) srctree=$(abs_srctree) $(patsubst objtool_%,%,$@)
|
||||
endif
|
||||
|
||||
tools/: FORCE
|
||||
@@ -1716,7 +1716,7 @@ PHONY += $(mrproper-dirs) mrproper
|
||||
$(mrproper-dirs):
|
||||
$(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
|
||||
|
||||
mrproper: clean $(mrproper-dirs)
|
||||
mrproper: clean objtool_mrproper $(mrproper-dirs)
|
||||
$(call cmd,rmfiles)
|
||||
@find . $(RCS_FIND_IGNORE) \
|
||||
\( -name '*.rmeta' \) \
|
||||
|
||||
@@ -71,6 +71,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
|
||||
@@ -123,6 +123,7 @@ SECTIONS
|
||||
_end = . ;
|
||||
|
||||
STABS_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
DISCARDS
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ SECTIONS
|
||||
COMMON_DISCARDS
|
||||
*(.ARM.exidx*)
|
||||
*(.ARM.extab*)
|
||||
*(.modinfo)
|
||||
*(.note.*)
|
||||
*(.rel.*)
|
||||
*(.printk_index)
|
||||
|
||||
@@ -154,6 +154,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ARM_DETAILS
|
||||
|
||||
ARM_ASSERTS
|
||||
|
||||
@@ -153,6 +153,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ARM_DETAILS
|
||||
|
||||
ARM_ASSERTS
|
||||
|
||||
@@ -91,8 +91,9 @@ __XCHG_GEN(_mb)
|
||||
#define __xchg_wrapper(sfx, ptr, x) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) __ret; \
|
||||
__ret = (__typeof__(*(ptr))) \
|
||||
__arch_xchg##sfx((unsigned long)(x), (ptr), sizeof(*(ptr))); \
|
||||
__ret = (__force __typeof__(*(ptr))) \
|
||||
__arch_xchg##sfx((__force unsigned long)(x), (ptr), \
|
||||
sizeof(*(ptr))); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
@@ -175,9 +176,10 @@ __CMPXCHG_GEN(_mb)
|
||||
#define __cmpxchg_wrapper(sfx, ptr, o, n) \
|
||||
({ \
|
||||
__typeof__(*(ptr)) __ret; \
|
||||
__ret = (__typeof__(*(ptr))) \
|
||||
__cmpxchg##sfx((ptr), (unsigned long)(o), \
|
||||
(unsigned long)(n), sizeof(*(ptr))); \
|
||||
__ret = (__force __typeof__(*(ptr))) \
|
||||
__cmpxchg##sfx((ptr), (__force unsigned long)(o), \
|
||||
(__force unsigned long)(n), \
|
||||
sizeof(*(ptr))); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
|
||||
@@ -50,11 +50,11 @@
|
||||
|
||||
#define _PAGE_DEFAULT (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL))
|
||||
|
||||
#define _PAGE_KERNEL (PROT_NORMAL)
|
||||
#define _PAGE_KERNEL_RO ((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY)
|
||||
#define _PAGE_KERNEL_ROX ((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY)
|
||||
#define _PAGE_KERNEL_EXEC (PROT_NORMAL & ~PTE_PXN)
|
||||
#define _PAGE_KERNEL_EXEC_CONT ((PROT_NORMAL & ~PTE_PXN) | PTE_CONT)
|
||||
#define _PAGE_KERNEL (PROT_NORMAL | PTE_DIRTY)
|
||||
#define _PAGE_KERNEL_RO ((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY | PTE_DIRTY)
|
||||
#define _PAGE_KERNEL_ROX ((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY | PTE_DIRTY)
|
||||
#define _PAGE_KERNEL_EXEC ((PROT_NORMAL & ~PTE_PXN) | PTE_DIRTY)
|
||||
#define _PAGE_KERNEL_EXEC_CONT ((PROT_NORMAL & ~PTE_PXN) | PTE_CONT | PTE_DIRTY)
|
||||
|
||||
#define _PAGE_SHARED (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
|
||||
#define _PAGE_SHARED_EXEC (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE)
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
#ifndef _ASM_RUNTIME_CONST_H
|
||||
#define _ASM_RUNTIME_CONST_H
|
||||
|
||||
#ifdef MODULE
|
||||
#error "Cannot use runtime-const infrastructure from modules"
|
||||
#endif
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
/* Sigh. You can still run arm64 in BE mode */
|
||||
|
||||
@@ -350,6 +350,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
HEAD_SYMBOLS
|
||||
|
||||
+49
-4
@@ -599,6 +599,27 @@ void contpte_clear_young_dirty_ptes(struct vm_area_struct *vma,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(contpte_clear_young_dirty_ptes);
|
||||
|
||||
static bool contpte_all_subptes_match_access_flags(pte_t *ptep, pte_t entry)
|
||||
{
|
||||
pte_t *cont_ptep = contpte_align_down(ptep);
|
||||
/*
|
||||
* PFNs differ per sub-PTE. Match only bits consumed by
|
||||
* __ptep_set_access_flags(): AF, DIRTY and write permission.
|
||||
*/
|
||||
const pteval_t cmp_mask = PTE_RDONLY | PTE_AF | PTE_WRITE | PTE_DIRTY;
|
||||
pteval_t entry_cmp = pte_val(entry) & cmp_mask;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CONT_PTES; i++) {
|
||||
pteval_t pte_cmp = pte_val(__ptep_get(cont_ptep + i)) & cmp_mask;
|
||||
|
||||
if (pte_cmp != entry_cmp)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int contpte_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
unsigned long addr, pte_t *ptep,
|
||||
pte_t entry, int dirty)
|
||||
@@ -608,13 +629,37 @@ int contpte_ptep_set_access_flags(struct vm_area_struct *vma,
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Gather the access/dirty bits for the contiguous range. If nothing has
|
||||
* changed, its a noop.
|
||||
* Check whether all sub-PTEs in the CONT block already match the
|
||||
* requested access flags/write permission, using raw per-PTE values
|
||||
* rather than the gathered ptep_get() view.
|
||||
*
|
||||
* __ptep_set_access_flags() can update AF, dirty and write
|
||||
* permission, but only to make the mapping more permissive.
|
||||
*
|
||||
* ptep_get() gathers AF/dirty state across the whole CONT block,
|
||||
* which is correct for a CPU with FEAT_HAFDBS. But page-table
|
||||
* walkers that evaluate each descriptor individually (e.g. a CPU
|
||||
* without DBM support, or an SMMU without HTTU, or with HA/HD
|
||||
* disabled in CD.TCR) can keep faulting on the target sub-PTE if
|
||||
* only a sibling has been updated. Gathering can therefore cause
|
||||
* false no-ops when only a sibling has been updated:
|
||||
* - write faults: target still has PTE_RDONLY (needs PTE_RDONLY cleared)
|
||||
* - read faults: target still lacks PTE_AF
|
||||
*
|
||||
* Per Arm ARM (DDI 0487) D8.7.1, any sub-PTE in a CONT range may
|
||||
* become the effective cached translation, so all entries must have
|
||||
* consistent attributes. Check the full CONT block before returning
|
||||
* no-op, and when any sub-PTE mismatches, proceed to update the whole
|
||||
* range.
|
||||
*/
|
||||
orig_pte = pte_mknoncont(ptep_get(ptep));
|
||||
if (pte_val(orig_pte) == pte_val(entry))
|
||||
if (contpte_all_subptes_match_access_flags(ptep, entry))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Use raw target pte (not gathered) for write-bit unfold decision.
|
||||
*/
|
||||
orig_pte = pte_mknoncont(__ptep_get(ptep));
|
||||
|
||||
/*
|
||||
* We can fix up access/dirty bits without having to unfold the contig
|
||||
* range. But if the write bit is changing, we must unfold.
|
||||
|
||||
@@ -109,6 +109,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
|
||||
@@ -62,6 +62,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
.hexagon.attributes 0 : { *(.hexagon.attributes) }
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
#ifdef CONFIG_EFI_STUB
|
||||
|
||||
@@ -85,6 +85,7 @@ SECTIONS {
|
||||
_end = .;
|
||||
|
||||
STABS_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
/* Sections to be discarded */
|
||||
|
||||
@@ -58,6 +58,7 @@ SECTIONS
|
||||
_end = . ;
|
||||
|
||||
STABS_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
/* Sections to be discarded */
|
||||
|
||||
@@ -51,6 +51,7 @@ __init_begin = .;
|
||||
_end = . ;
|
||||
|
||||
STABS_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
/* Sections to be discarded */
|
||||
|
||||
@@ -217,6 +217,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
/* These must appear regardless of . */
|
||||
|
||||
@@ -57,6 +57,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
|
||||
@@ -101,6 +101,7 @@ SECTIONS
|
||||
/* Throw in the debugging sections */
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
/* Sections to be discarded -- must be last */
|
||||
|
||||
@@ -90,6 +90,7 @@ SECTIONS
|
||||
/* Sections to be discarded */
|
||||
DISCARDS
|
||||
/DISCARD/ : {
|
||||
*(.modinfo)
|
||||
#ifdef CONFIG_64BIT
|
||||
/* temporary hack until binutils is fixed to not emit these
|
||||
* for static binaries
|
||||
|
||||
@@ -85,7 +85,7 @@ extern void __update_cache(pte_t pte);
|
||||
printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e))
|
||||
|
||||
/* This is the size of the initially mapped kernel memory */
|
||||
#if defined(CONFIG_64BIT)
|
||||
#if defined(CONFIG_64BIT) || defined(CONFIG_KALLSYMS)
|
||||
#define KERNEL_INITIAL_ORDER 26 /* 1<<26 = 64MB */
|
||||
#else
|
||||
#define KERNEL_INITIAL_ORDER 25 /* 1<<25 = 32MB */
|
||||
|
||||
@@ -56,6 +56,7 @@ ENTRY(parisc_kernel_start)
|
||||
|
||||
.import __bss_start,data
|
||||
.import __bss_stop,data
|
||||
.import __end,data
|
||||
|
||||
load32 PA(__bss_start),%r3
|
||||
load32 PA(__bss_stop),%r4
|
||||
@@ -149,7 +150,11 @@ $cpu_ok:
|
||||
* everything ... it will get remapped correctly later */
|
||||
ldo 0+_PAGE_KERNEL_RWX(%r0),%r3 /* Hardwired 0 phys addr start */
|
||||
load32 (1<<(KERNEL_INITIAL_ORDER-PAGE_SHIFT)),%r11 /* PFN count */
|
||||
load32 PA(pg0),%r1
|
||||
load32 PA(_end),%r1
|
||||
SHRREG %r1,PAGE_SHIFT,%r1 /* %r1 is PFN count for _end symbol */
|
||||
cmpb,<<,n %r11,%r1,1f
|
||||
copy %r1,%r11 /* %r1 PFN count smaller than %r11 */
|
||||
1: load32 PA(pg0),%r1
|
||||
|
||||
$pgt_fill_loop:
|
||||
STREGM %r3,ASM_PTE_ENTRY_SIZE(%r1)
|
||||
|
||||
@@ -120,14 +120,6 @@ void __init setup_arch(char **cmdline_p)
|
||||
#endif
|
||||
printk(KERN_CONT ".\n");
|
||||
|
||||
/*
|
||||
* Check if initial kernel page mappings are sufficient.
|
||||
* panic early if not, else we may access kernel functions
|
||||
* and variables which can't be reached.
|
||||
*/
|
||||
if (__pa((unsigned long) &_end) >= KERNEL_INITIAL_SIZE)
|
||||
panic("KERNEL_INITIAL_ORDER too small!");
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
if(parisc_narrow_firmware) {
|
||||
printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
|
||||
@@ -279,6 +271,18 @@ void __init start_parisc(void)
|
||||
int ret, cpunum;
|
||||
struct pdc_coproc_cfg coproc_cfg;
|
||||
|
||||
/*
|
||||
* Check if initial kernel page mapping is sufficient.
|
||||
* Print warning if not, because we may access kernel functions and
|
||||
* variables which can't be reached yet through the initial mappings.
|
||||
* Note that the panic() and printk() functions are not functional
|
||||
* yet, so we need to use direct iodc() firmware calls instead.
|
||||
*/
|
||||
const char warn1[] = "CRITICAL: Kernel may crash because "
|
||||
"KERNEL_INITIAL_ORDER is too small.\n";
|
||||
if (__pa((unsigned long) &_end) >= KERNEL_INITIAL_SIZE)
|
||||
pdc_iodc_print(warn1, sizeof(warn1) - 1);
|
||||
|
||||
/* check QEMU/SeaBIOS marker in PAGE0 */
|
||||
running_on_qemu = (memcmp(&PAGE0->pad0, "SeaBIOS", 8) == 0);
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ SECTIONS
|
||||
_end = . ;
|
||||
|
||||
STABS_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
.note 0 : { *(.note) }
|
||||
|
||||
|
||||
@@ -397,6 +397,7 @@ SECTIONS
|
||||
_end = . ;
|
||||
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
|
||||
@@ -170,6 +170,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
.riscv.attributes 0 : { *(.riscv.attributes) }
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ static __always_inline void __stackleak_poison(unsigned long erase_low,
|
||||
" j 4f\n"
|
||||
"3: mvc 8(1,%[addr]),0(%[addr])\n"
|
||||
"4:"
|
||||
: [addr] "+&a" (erase_low), [count] "+&d" (count), [tmp] "=&a" (tmp)
|
||||
: [addr] "+&a" (erase_low), [count] "+&a" (count), [tmp] "=&a" (tmp)
|
||||
: [poison] "d" (poison)
|
||||
: "memory", "cc"
|
||||
);
|
||||
|
||||
@@ -221,6 +221,7 @@ SECTIONS
|
||||
/* Debugging sections. */
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
/*
|
||||
|
||||
+5
-6
@@ -28,8 +28,8 @@ static void xor_xc_2(unsigned long bytes, unsigned long * __restrict p1,
|
||||
" j 3f\n"
|
||||
"2: xc 0(1,%1),0(%2)\n"
|
||||
"3:"
|
||||
: : "d" (bytes), "a" (p1), "a" (p2)
|
||||
: "0", "cc", "memory");
|
||||
: "+a" (bytes), "+a" (p1), "+a" (p2)
|
||||
: : "0", "cc", "memory");
|
||||
}
|
||||
|
||||
static void xor_xc_3(unsigned long bytes, unsigned long * __restrict p1,
|
||||
@@ -54,7 +54,7 @@ static void xor_xc_3(unsigned long bytes, unsigned long * __restrict p1,
|
||||
"2: xc 0(1,%1),0(%2)\n"
|
||||
"3: xc 0(1,%1),0(%3)\n"
|
||||
"4:"
|
||||
: "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3)
|
||||
: "+a" (bytes), "+a" (p1), "+a" (p2), "+a" (p3)
|
||||
: : "0", "cc", "memory");
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ static void xor_xc_4(unsigned long bytes, unsigned long * __restrict p1,
|
||||
"3: xc 0(1,%1),0(%3)\n"
|
||||
"4: xc 0(1,%1),0(%4)\n"
|
||||
"5:"
|
||||
: "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4)
|
||||
: "+a" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4)
|
||||
: : "0", "cc", "memory");
|
||||
}
|
||||
|
||||
@@ -96,7 +96,6 @@ static void xor_xc_5(unsigned long bytes, unsigned long * __restrict p1,
|
||||
const unsigned long * __restrict p5)
|
||||
{
|
||||
asm volatile(
|
||||
" larl 1,2f\n"
|
||||
" aghi %0,-1\n"
|
||||
" jm 6f\n"
|
||||
" srlg 0,%0,8\n"
|
||||
@@ -122,7 +121,7 @@ static void xor_xc_5(unsigned long bytes, unsigned long * __restrict p1,
|
||||
"4: xc 0(1,%1),0(%4)\n"
|
||||
"5: xc 0(1,%1),0(%5)\n"
|
||||
"6:"
|
||||
: "+d" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4),
|
||||
: "+a" (bytes), "+a" (p1), "+a" (p2), "+a" (p3), "+a" (p4),
|
||||
"+a" (p5)
|
||||
: : "0", "cc", "memory");
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
|
||||
@@ -191,6 +191,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
|
||||
@@ -172,6 +172,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
|
||||
@@ -113,6 +113,7 @@ SECTIONS
|
||||
|
||||
STABS_DEBUG
|
||||
DWARF_DEBUG
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
|
||||
@@ -88,7 +88,7 @@ SECTIONS
|
||||
/DISCARD/ : {
|
||||
*(.dynamic) *(.dynsym) *(.dynstr) *(.dynbss)
|
||||
*(.hash) *(.gnu.hash)
|
||||
*(.note.*)
|
||||
*(.note.*) *(.modinfo)
|
||||
}
|
||||
|
||||
.got.plt (INFO) : {
|
||||
|
||||
@@ -19,10 +19,8 @@
|
||||
extern p4d_t level4_kernel_pgt[512];
|
||||
extern p4d_t level4_ident_pgt[512];
|
||||
extern pud_t level3_kernel_pgt[512];
|
||||
extern pud_t level3_ident_pgt[512];
|
||||
extern pmd_t level2_kernel_pgt[512];
|
||||
extern pmd_t level2_fixmap_pgt[512];
|
||||
extern pmd_t level2_ident_pgt[512];
|
||||
extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM];
|
||||
extern pgd_t init_top_pgt[];
|
||||
|
||||
|
||||
@@ -616,38 +616,10 @@ SYM_DATA(early_recursion_flag, .long 0)
|
||||
|
||||
.data
|
||||
|
||||
#if defined(CONFIG_XEN_PV) || defined(CONFIG_PVH)
|
||||
SYM_DATA_START_PTI_ALIGNED(init_top_pgt)
|
||||
.quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
|
||||
.org init_top_pgt + L4_PAGE_OFFSET*8, 0
|
||||
.quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
|
||||
.org init_top_pgt + L4_START_KERNEL*8, 0
|
||||
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
|
||||
.quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC
|
||||
.fill PTI_USER_PGD_FILL,8,0
|
||||
SYM_DATA_END(init_top_pgt)
|
||||
|
||||
SYM_DATA_START_PAGE_ALIGNED(level3_ident_pgt)
|
||||
.quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE_NOENC
|
||||
.fill 511, 8, 0
|
||||
SYM_DATA_END(level3_ident_pgt)
|
||||
SYM_DATA_START_PAGE_ALIGNED(level2_ident_pgt)
|
||||
/*
|
||||
* Since I easily can, map the first 1G.
|
||||
* Don't set NX because code runs from these pages.
|
||||
*
|
||||
* Note: This sets _PAGE_GLOBAL despite whether
|
||||
* the CPU supports it or it is enabled. But,
|
||||
* the CPU should ignore the bit.
|
||||
*/
|
||||
PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD)
|
||||
SYM_DATA_END(level2_ident_pgt)
|
||||
#else
|
||||
SYM_DATA_START_PTI_ALIGNED(init_top_pgt)
|
||||
.fill 512,8,0
|
||||
.fill PTI_USER_PGD_FILL,8,0
|
||||
SYM_DATA_END(init_top_pgt)
|
||||
#endif
|
||||
|
||||
SYM_DATA_START_PAGE_ALIGNED(level4_kernel_pgt)
|
||||
.fill 511,8,0
|
||||
|
||||
@@ -427,6 +427,7 @@ SECTIONS
|
||||
.llvm_bb_addr_map : { *(.llvm_bb_addr_map) }
|
||||
#endif
|
||||
|
||||
MODINFO
|
||||
ELF_DETAILS
|
||||
|
||||
DISCARDS
|
||||
|
||||
@@ -25,11 +25,6 @@ struct hvm_start_info __initdata pvh_start_info;
|
||||
|
||||
const unsigned int __initconst pvh_start_info_sz = sizeof(pvh_start_info);
|
||||
|
||||
static u64 __init pvh_get_root_pointer(void)
|
||||
{
|
||||
return pvh_start_info.rsdp_paddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Xen guests are able to obtain the memory map from the hypervisor via the
|
||||
* HYPERVISOR_memory_op hypercall.
|
||||
@@ -95,7 +90,7 @@ static void __init init_pvh_bootparams(bool xen_guest)
|
||||
pvh_bootparams.hdr.version = (2 << 8) | 12;
|
||||
pvh_bootparams.hdr.type_of_loader = ((xen_guest ? 0x9 : 0xb) << 4) | 0;
|
||||
|
||||
x86_init.acpi.get_root_pointer = pvh_get_root_pointer;
|
||||
pvh_bootparams.acpi_rsdp_addr = pvh_start_info.rsdp_paddr;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -392,7 +392,7 @@ static void __init xen_init_capabilities(void)
|
||||
|
||||
/*
|
||||
* Xen PV would need some work to support PCID: CR3 handling as well
|
||||
* as xen_flush_tlb_others() would need updating.
|
||||
* as xen_flush_tlb_multi() would need updating.
|
||||
*/
|
||||
setup_clear_cpu_cap(X86_FEATURE_PCID);
|
||||
|
||||
|
||||
@@ -105,6 +105,9 @@ pte_t xen_make_pte_init(pteval_t pte);
|
||||
static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss;
|
||||
#endif
|
||||
|
||||
static pud_t level3_ident_pgt[PTRS_PER_PUD] __page_aligned_bss;
|
||||
static pmd_t level2_ident_pgt[PTRS_PER_PMD] __page_aligned_bss;
|
||||
|
||||
/*
|
||||
* Protects atomic reservation decrease/increase against concurrent increases.
|
||||
* Also protects non-atomic updates of current_pages and balloon lists.
|
||||
@@ -1777,6 +1780,12 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
|
||||
/* Zap identity mapping */
|
||||
init_top_pgt[0] = __pgd(0);
|
||||
|
||||
init_top_pgt[pgd_index(__PAGE_OFFSET_BASE_L4)].pgd =
|
||||
__pa_symbol(level3_ident_pgt) + _KERNPG_TABLE_NOENC;
|
||||
init_top_pgt[pgd_index(__START_KERNEL_map)].pgd =
|
||||
__pa_symbol(level3_kernel_pgt) + _PAGE_TABLE_NOENC;
|
||||
level3_ident_pgt[0].pud = __pa_symbol(level2_ident_pgt) + _KERNPG_TABLE_NOENC;
|
||||
|
||||
/* Pre-constructed entries are in pfn, so convert to mfn */
|
||||
/* L4[273] -> level3_ident_pgt */
|
||||
/* L4[511] -> level3_kernel_pgt */
|
||||
|
||||
@@ -1927,16 +1927,6 @@ config SENSORS_RASPBERRYPI_HWMON
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called raspberrypi-hwmon.
|
||||
|
||||
config SENSORS_SA67MCU
|
||||
tristate "Kontron sa67mcu hardware monitoring driver"
|
||||
depends on MFD_SL28CPLD || COMPILE_TEST
|
||||
help
|
||||
If you say yes here you get support for the voltage and temperature
|
||||
monitor of the sa67 board management controller.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called sa67mcu-hwmon.
|
||||
|
||||
config SENSORS_SL28CPLD
|
||||
tristate "Kontron sl28cpld hardware monitoring driver"
|
||||
depends on MFD_SL28CPLD || COMPILE_TEST
|
||||
|
||||
@@ -199,7 +199,6 @@ obj-$(CONFIG_SENSORS_PT5161L) += pt5161l.o
|
||||
obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
|
||||
obj-$(CONFIG_SENSORS_QNAP_MCU_HWMON) += qnap-mcu-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_SA67MCU) += sa67mcu-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_SBTSI) += sbtsi_temp.o
|
||||
obj-$(CONFIG_SENSORS_SBRMI) += sbrmi.o
|
||||
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
|
||||
|
||||
@@ -37,7 +37,9 @@
|
||||
#define AHT10_CMD_MEAS 0b10101100
|
||||
#define AHT10_CMD_RST 0b10111010
|
||||
|
||||
#define DHT20_CMD_INIT 0x71
|
||||
#define AHT20_CMD_INIT 0b10111110
|
||||
|
||||
#define DHT20_CMD_INIT 0b01110001
|
||||
|
||||
/*
|
||||
* Flags in the answer byte/command
|
||||
@@ -341,7 +343,7 @@ static int aht10_probe(struct i2c_client *client)
|
||||
data->meas_size = AHT20_MEAS_SIZE;
|
||||
data->crc8 = true;
|
||||
crc8_populate_msb(crc8_table, AHT20_CRC8_POLY);
|
||||
data->init_cmd = AHT10_CMD_INIT;
|
||||
data->init_cmd = AHT20_CMD_INIT;
|
||||
break;
|
||||
case dht20:
|
||||
data->meas_size = AHT20_MEAS_SIZE;
|
||||
|
||||
@@ -3590,10 +3590,13 @@ static int it87_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct it87_data *data = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
it87_resume_sio(pdev);
|
||||
|
||||
it87_lock(data);
|
||||
err = it87_lock(data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
it87_check_pwm(dev);
|
||||
it87_check_limit_regs(data);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/mfd/macsmc.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
@@ -130,7 +131,7 @@ static int macsmc_hwmon_read_ioft_scaled(struct apple_smc *smc, smc_key key,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*p = mult_frac(val, scale, 65536);
|
||||
*p = mul_u64_u32_div(val, scale, 65536);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -140,7 +141,7 @@ static int macsmc_hwmon_read_ioft_scaled(struct apple_smc *smc, smc_key key,
|
||||
* them.
|
||||
*/
|
||||
static int macsmc_hwmon_read_f32_scaled(struct apple_smc *smc, smc_key key,
|
||||
int *p, int scale)
|
||||
long *p, int scale)
|
||||
{
|
||||
u32 fval;
|
||||
u64 val;
|
||||
@@ -162,21 +163,21 @@ static int macsmc_hwmon_read_f32_scaled(struct apple_smc *smc, smc_key key,
|
||||
val = 0;
|
||||
else if (exp < 0)
|
||||
val >>= -exp;
|
||||
else if (exp != 0 && (val & ~((1UL << (64 - exp)) - 1))) /* overflow */
|
||||
else if (exp != 0 && (val & ~((1ULL << (64 - exp)) - 1))) /* overflow */
|
||||
val = U64_MAX;
|
||||
else
|
||||
val <<= exp;
|
||||
|
||||
if (fval & FLT_SIGN_MASK) {
|
||||
if (val > (-(s64)INT_MIN))
|
||||
*p = INT_MIN;
|
||||
if (val > (u64)LONG_MAX + 1)
|
||||
*p = LONG_MIN;
|
||||
else
|
||||
*p = -val;
|
||||
*p = -(long)val;
|
||||
} else {
|
||||
if (val > INT_MAX)
|
||||
*p = INT_MAX;
|
||||
if (val > (u64)LONG_MAX)
|
||||
*p = LONG_MAX;
|
||||
else
|
||||
*p = val;
|
||||
*p = (long)val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -195,7 +196,7 @@ static int macsmc_hwmon_read_key(struct apple_smc *smc,
|
||||
switch (sensor->info.type_code) {
|
||||
/* 32-bit IEEE 754 float */
|
||||
case __SMC_KEY('f', 'l', 't', ' '): {
|
||||
u32 flt_ = 0;
|
||||
long flt_ = 0;
|
||||
|
||||
ret = macsmc_hwmon_read_f32_scaled(smc, sensor->macsmc_key,
|
||||
&flt_, scale);
|
||||
@@ -214,7 +215,10 @@ static int macsmc_hwmon_read_key(struct apple_smc *smc,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = (long)ioft;
|
||||
if (ioft > LONG_MAX)
|
||||
*val = LONG_MAX;
|
||||
else
|
||||
*val = (long)ioft;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -224,29 +228,26 @@ static int macsmc_hwmon_read_key(struct apple_smc *smc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int macsmc_hwmon_write_f32(struct apple_smc *smc, smc_key key, int value)
|
||||
static int macsmc_hwmon_write_f32(struct apple_smc *smc, smc_key key, long value)
|
||||
{
|
||||
u64 val;
|
||||
u32 fval = 0;
|
||||
int exp = 0, neg;
|
||||
int exp, neg;
|
||||
|
||||
neg = value < 0;
|
||||
val = abs(value);
|
||||
neg = val != value;
|
||||
|
||||
if (val) {
|
||||
int msb = __fls(val) - exp;
|
||||
exp = __fls(val);
|
||||
|
||||
if (msb > 23) {
|
||||
val >>= msb - FLT_MANT_BIAS;
|
||||
exp -= msb - FLT_MANT_BIAS;
|
||||
} else if (msb < 23) {
|
||||
val <<= FLT_MANT_BIAS - msb;
|
||||
exp += msb;
|
||||
}
|
||||
if (exp > 23)
|
||||
val >>= exp - 23;
|
||||
else
|
||||
val <<= 23 - exp;
|
||||
|
||||
fval = FIELD_PREP(FLT_SIGN_MASK, neg) |
|
||||
FIELD_PREP(FLT_EXP_MASK, exp + FLT_EXP_BIAS) |
|
||||
FIELD_PREP(FLT_MANT_MASK, val);
|
||||
FIELD_PREP(FLT_MANT_MASK, val & FLT_MANT_MASK);
|
||||
}
|
||||
|
||||
return apple_smc_write_u32(smc, key, fval);
|
||||
@@ -663,8 +664,8 @@ static int macsmc_hwmon_populate_sensors(struct macsmc_hwmon *hwmon,
|
||||
if (!hwmon->volt.sensors)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_child_of_node_with_prefix(hwmon_node, key_node, "volt-") {
|
||||
sensor = &hwmon->temp.sensors[hwmon->temp.count];
|
||||
for_each_child_of_node_with_prefix(hwmon_node, key_node, "voltage-") {
|
||||
sensor = &hwmon->volt.sensors[hwmon->volt.count];
|
||||
if (!macsmc_hwmon_create_sensor(hwmon->dev, hwmon->smc, key_node, sensor)) {
|
||||
sensor->attrs = HWMON_I_INPUT;
|
||||
|
||||
|
||||
@@ -607,7 +607,7 @@ static int max6639_init_client(struct i2c_client *client,
|
||||
return err;
|
||||
|
||||
/* Fans PWM polarity high by default */
|
||||
err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x00);
|
||||
err = regmap_write(data->regmap, MAX6639_REG_FAN_CONFIG2a(i), 0x02);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
@@ -79,7 +79,8 @@ static ssize_t q54sj108a2_debugfs_read(struct file *file, char __user *buf,
|
||||
int idx = *idxp;
|
||||
struct q54sj108a2_data *psu = to_psu(idxp, idx);
|
||||
char data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
|
||||
char data_char[I2C_SMBUS_BLOCK_MAX + 2] = { 0 };
|
||||
char data_char[I2C_SMBUS_BLOCK_MAX * 2 + 2] = { 0 };
|
||||
char *out = data;
|
||||
char *res;
|
||||
|
||||
switch (idx) {
|
||||
@@ -150,27 +151,27 @@ static ssize_t q54sj108a2_debugfs_read(struct file *file, char __user *buf,
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
res = bin2hex(data, data_char, 32);
|
||||
rc = res - data;
|
||||
|
||||
res = bin2hex(data_char, data, rc);
|
||||
rc = res - data_char;
|
||||
out = data_char;
|
||||
break;
|
||||
case Q54SJ108A2_DEBUGFS_FLASH_KEY:
|
||||
rc = i2c_smbus_read_block_data(psu->client, PMBUS_FLASH_KEY_WRITE, data);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
res = bin2hex(data, data_char, 4);
|
||||
rc = res - data;
|
||||
|
||||
res = bin2hex(data_char, data, rc);
|
||||
rc = res - data_char;
|
||||
out = data_char;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data[rc] = '\n';
|
||||
out[rc] = '\n';
|
||||
rc += 2;
|
||||
|
||||
return simple_read_from_buffer(buf, count, ppos, data, rc);
|
||||
return simple_read_from_buffer(buf, count, ppos, out, rc);
|
||||
}
|
||||
|
||||
static ssize_t q54sj108a2_debugfs_write(struct file *file, const char __user *buf,
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* sl67mcu hardware monitoring driver
|
||||
*
|
||||
* Copyright 2025 Kontron Europe GmbH
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define SA67MCU_VOLTAGE(n) (0x00 + ((n) * 2))
|
||||
#define SA67MCU_TEMP(n) (0x04 + ((n) * 2))
|
||||
|
||||
struct sa67mcu_hwmon {
|
||||
struct regmap *regmap;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
static int sa67mcu_hwmon_read(struct device *dev,
|
||||
enum hwmon_sensor_types type, u32 attr,
|
||||
int channel, long *input)
|
||||
{
|
||||
struct sa67mcu_hwmon *hwmon = dev_get_drvdata(dev);
|
||||
unsigned int offset;
|
||||
u8 reg[2];
|
||||
int ret;
|
||||
|
||||
switch (type) {
|
||||
case hwmon_in:
|
||||
switch (attr) {
|
||||
case hwmon_in_input:
|
||||
offset = hwmon->offset + SA67MCU_VOLTAGE(channel);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
case hwmon_temp:
|
||||
switch (attr) {
|
||||
case hwmon_temp_input:
|
||||
offset = hwmon->offset + SA67MCU_TEMP(channel);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Reading the low byte will capture the value */
|
||||
ret = regmap_bulk_read(hwmon->regmap, offset, reg, ARRAY_SIZE(reg));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*input = reg[1] << 8 | reg[0];
|
||||
|
||||
/* Temperatures are s16 and in 0.1degC steps. */
|
||||
if (type == hwmon_temp)
|
||||
*input = sign_extend32(*input, 15) * 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hwmon_channel_info * const sa67mcu_hwmon_info[] = {
|
||||
HWMON_CHANNEL_INFO(in,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL,
|
||||
HWMON_I_INPUT | HWMON_I_LABEL),
|
||||
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const sa67mcu_hwmon_in_labels[] = {
|
||||
"VDDIN",
|
||||
"VDD_RTC",
|
||||
};
|
||||
|
||||
static int sa67mcu_hwmon_read_string(struct device *dev,
|
||||
enum hwmon_sensor_types type, u32 attr,
|
||||
int channel, const char **str)
|
||||
{
|
||||
switch (type) {
|
||||
case hwmon_in:
|
||||
switch (attr) {
|
||||
case hwmon_in_label:
|
||||
*str = sa67mcu_hwmon_in_labels[channel];
|
||||
return 0;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct hwmon_ops sa67mcu_hwmon_ops = {
|
||||
.visible = 0444,
|
||||
.read = sa67mcu_hwmon_read,
|
||||
.read_string = sa67mcu_hwmon_read_string,
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info sa67mcu_hwmon_chip_info = {
|
||||
.ops = &sa67mcu_hwmon_ops,
|
||||
.info = sa67mcu_hwmon_info,
|
||||
};
|
||||
|
||||
static int sa67mcu_hwmon_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sa67mcu_hwmon *hwmon;
|
||||
struct device *hwmon_dev;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.parent)
|
||||
return -ENODEV;
|
||||
|
||||
hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL);
|
||||
if (!hwmon)
|
||||
return -ENOMEM;
|
||||
|
||||
hwmon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!hwmon->regmap)
|
||||
return -ENODEV;
|
||||
|
||||
ret = device_property_read_u32(&pdev->dev, "reg", &hwmon->offset);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
|
||||
"sa67mcu_hwmon", hwmon,
|
||||
&sa67mcu_hwmon_chip_info,
|
||||
NULL);
|
||||
if (IS_ERR(hwmon_dev))
|
||||
dev_err(&pdev->dev, "failed to register as hwmon device");
|
||||
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
|
||||
static const struct of_device_id sa67mcu_hwmon_of_match[] = {
|
||||
{ .compatible = "kontron,sa67mcu-hwmon", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sa67mcu_hwmon_of_match);
|
||||
|
||||
static struct platform_driver sa67mcu_hwmon_driver = {
|
||||
.probe = sa67mcu_hwmon_probe,
|
||||
.driver = {
|
||||
.name = "sa67mcu-hwmon",
|
||||
.of_match_table = sa67mcu_hwmon_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(sa67mcu_hwmon_driver);
|
||||
|
||||
MODULE_DESCRIPTION("sa67mcu Hardware Monitoring Driver");
|
||||
MODULE_AUTHOR("Michael Walle <mwalle@kernel.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
+17
-17
@@ -1646,7 +1646,7 @@ static int xennet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
|
||||
|
||||
/* avoid the race with XDP headroom adjustment */
|
||||
wait_event(module_wq,
|
||||
xenbus_read_driver_state(np->xbdev->otherend) ==
|
||||
xenbus_read_driver_state(np->xbdev, np->xbdev->otherend) ==
|
||||
XenbusStateReconfigured);
|
||||
np->netfront_xdp_enabled = true;
|
||||
|
||||
@@ -1764,9 +1764,9 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
|
||||
do {
|
||||
xenbus_switch_state(dev, XenbusStateInitialising);
|
||||
err = wait_event_timeout(module_wq,
|
||||
xenbus_read_driver_state(dev->otherend) !=
|
||||
xenbus_read_driver_state(dev, dev->otherend) !=
|
||||
XenbusStateClosed &&
|
||||
xenbus_read_driver_state(dev->otherend) !=
|
||||
xenbus_read_driver_state(dev, dev->otherend) !=
|
||||
XenbusStateUnknown, XENNET_TIMEOUT);
|
||||
} while (!err);
|
||||
|
||||
@@ -2626,31 +2626,31 @@ static void xennet_bus_close(struct xenbus_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
|
||||
if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
|
||||
return;
|
||||
do {
|
||||
xenbus_switch_state(dev, XenbusStateClosing);
|
||||
ret = wait_event_timeout(module_wq,
|
||||
xenbus_read_driver_state(dev->otherend) ==
|
||||
XenbusStateClosing ||
|
||||
xenbus_read_driver_state(dev->otherend) ==
|
||||
XenbusStateClosed ||
|
||||
xenbus_read_driver_state(dev->otherend) ==
|
||||
XenbusStateUnknown,
|
||||
XENNET_TIMEOUT);
|
||||
xenbus_read_driver_state(dev, dev->otherend) ==
|
||||
XenbusStateClosing ||
|
||||
xenbus_read_driver_state(dev, dev->otherend) ==
|
||||
XenbusStateClosed ||
|
||||
xenbus_read_driver_state(dev, dev->otherend) ==
|
||||
XenbusStateUnknown,
|
||||
XENNET_TIMEOUT);
|
||||
} while (!ret);
|
||||
|
||||
if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
|
||||
if (xenbus_read_driver_state(dev, dev->otherend) == XenbusStateClosed)
|
||||
return;
|
||||
|
||||
do {
|
||||
xenbus_switch_state(dev, XenbusStateClosed);
|
||||
ret = wait_event_timeout(module_wq,
|
||||
xenbus_read_driver_state(dev->otherend) ==
|
||||
XenbusStateClosed ||
|
||||
xenbus_read_driver_state(dev->otherend) ==
|
||||
XenbusStateUnknown,
|
||||
XENNET_TIMEOUT);
|
||||
xenbus_read_driver_state(dev, dev->otherend) ==
|
||||
XenbusStateClosed ||
|
||||
xenbus_read_driver_state(dev, dev->otherend) ==
|
||||
XenbusStateUnknown,
|
||||
XENNET_TIMEOUT);
|
||||
} while (!ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -856,7 +856,7 @@ static void pcifront_try_connect(struct pcifront_device *pdev)
|
||||
int err;
|
||||
|
||||
/* Only connect once */
|
||||
if (xenbus_read_driver_state(pdev->xdev->nodename) !=
|
||||
if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
|
||||
XenbusStateInitialised)
|
||||
return;
|
||||
|
||||
@@ -876,7 +876,7 @@ static int pcifront_try_disconnect(struct pcifront_device *pdev)
|
||||
enum xenbus_state prev_state;
|
||||
|
||||
|
||||
prev_state = xenbus_read_driver_state(pdev->xdev->nodename);
|
||||
prev_state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
|
||||
|
||||
if (prev_state >= XenbusStateClosing)
|
||||
goto out;
|
||||
@@ -895,7 +895,7 @@ out:
|
||||
|
||||
static void pcifront_attach_devices(struct pcifront_device *pdev)
|
||||
{
|
||||
if (xenbus_read_driver_state(pdev->xdev->nodename) ==
|
||||
if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) ==
|
||||
XenbusStateReconfiguring)
|
||||
pcifront_connect(pdev);
|
||||
}
|
||||
@@ -909,7 +909,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)
|
||||
struct pci_dev *pci_dev;
|
||||
char str[64];
|
||||
|
||||
state = xenbus_read_driver_state(pdev->xdev->nodename);
|
||||
state = xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename);
|
||||
if (state == XenbusStateInitialised) {
|
||||
dev_dbg(&pdev->xdev->dev, "Handle skipped connect.\n");
|
||||
/* We missed Connected and need to initialize. */
|
||||
|
||||
@@ -1175,7 +1175,7 @@ static void scsifront_backend_changed(struct xenbus_device *dev,
|
||||
return;
|
||||
}
|
||||
|
||||
if (xenbus_read_driver_state(dev->nodename) ==
|
||||
if (xenbus_read_driver_state(dev, dev->nodename) ==
|
||||
XenbusStateInitialised)
|
||||
scsifront_do_lun_hotplug(info, VSCSIFRONT_OP_ADD_LUN);
|
||||
|
||||
|
||||
@@ -378,11 +378,8 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
acpi_psd[acpi_id].domain);
|
||||
}
|
||||
|
||||
status = acpi_evaluate_object(handle, "_CST", NULL, &buffer);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
if (!pblk)
|
||||
return AE_OK;
|
||||
}
|
||||
if (!pblk && !acpi_has_method(handle, "_CST"))
|
||||
return AE_OK;
|
||||
/* .. and it has a C-state */
|
||||
__set_bit(acpi_id, acpi_id_cst_present);
|
||||
|
||||
|
||||
@@ -149,12 +149,12 @@ static int xen_pcibk_attach(struct xen_pcibk_device *pdev)
|
||||
|
||||
mutex_lock(&pdev->dev_lock);
|
||||
/* Make sure we only do this setup once */
|
||||
if (xenbus_read_driver_state(pdev->xdev->nodename) !=
|
||||
if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
|
||||
XenbusStateInitialised)
|
||||
goto out;
|
||||
|
||||
/* Wait for frontend to state that it has published the configuration */
|
||||
if (xenbus_read_driver_state(pdev->xdev->otherend) !=
|
||||
if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->otherend) !=
|
||||
XenbusStateInitialised)
|
||||
goto out;
|
||||
|
||||
@@ -374,7 +374,7 @@ static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev,
|
||||
dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
|
||||
|
||||
mutex_lock(&pdev->dev_lock);
|
||||
if (xenbus_read_driver_state(pdev->xdev->nodename) != state)
|
||||
if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) != state)
|
||||
goto out;
|
||||
|
||||
err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
|
||||
@@ -572,7 +572,7 @@ static int xen_pcibk_setup_backend(struct xen_pcibk_device *pdev)
|
||||
/* It's possible we could get the call to setup twice, so make sure
|
||||
* we're not already connected.
|
||||
*/
|
||||
if (xenbus_read_driver_state(pdev->xdev->nodename) !=
|
||||
if (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename) !=
|
||||
XenbusStateInitWait)
|
||||
goto out;
|
||||
|
||||
@@ -662,7 +662,7 @@ static void xen_pcibk_be_watch(struct xenbus_watch *watch,
|
||||
struct xen_pcibk_device *pdev =
|
||||
container_of(watch, struct xen_pcibk_device, be_watch);
|
||||
|
||||
switch (xenbus_read_driver_state(pdev->xdev->nodename)) {
|
||||
switch (xenbus_read_driver_state(pdev->xdev, pdev->xdev->nodename)) {
|
||||
case XenbusStateInitWait:
|
||||
xen_pcibk_setup_backend(pdev);
|
||||
break;
|
||||
|
||||
@@ -226,8 +226,9 @@ __xenbus_switch_state(struct xenbus_device *dev,
|
||||
struct xenbus_transaction xbt;
|
||||
int current_state;
|
||||
int err, abort;
|
||||
bool vanished = false;
|
||||
|
||||
if (state == dev->state)
|
||||
if (state == dev->state || dev->vanished)
|
||||
return 0;
|
||||
|
||||
again:
|
||||
@@ -242,6 +243,10 @@ again:
|
||||
err = xenbus_scanf(xbt, dev->nodename, "state", "%d", ¤t_state);
|
||||
if (err != 1)
|
||||
goto abort;
|
||||
if (current_state != dev->state && current_state == XenbusStateInitialising) {
|
||||
vanished = true;
|
||||
goto abort;
|
||||
}
|
||||
|
||||
err = xenbus_printf(xbt, dev->nodename, "state", "%d", state);
|
||||
if (err) {
|
||||
@@ -256,7 +261,7 @@ abort:
|
||||
if (err == -EAGAIN && !abort)
|
||||
goto again;
|
||||
xenbus_switch_fatal(dev, depth, err, "ending transaction");
|
||||
} else
|
||||
} else if (!vanished)
|
||||
dev->state = state;
|
||||
|
||||
return 0;
|
||||
@@ -931,14 +936,20 @@ static int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr)
|
||||
|
||||
/**
|
||||
* xenbus_read_driver_state - read state from a store path
|
||||
* @dev: xenbus device pointer
|
||||
* @path: path for driver
|
||||
*
|
||||
* Returns: the state of the driver rooted at the given store path, or
|
||||
* XenbusStateUnknown if no state can be read.
|
||||
*/
|
||||
enum xenbus_state xenbus_read_driver_state(const char *path)
|
||||
enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
|
||||
const char *path)
|
||||
{
|
||||
enum xenbus_state result;
|
||||
|
||||
if (dev && dev->vanished)
|
||||
return XenbusStateUnknown;
|
||||
|
||||
int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
|
||||
if (err)
|
||||
result = XenbusStateUnknown;
|
||||
|
||||
@@ -191,7 +191,7 @@ void xenbus_otherend_changed(struct xenbus_watch *watch,
|
||||
return;
|
||||
}
|
||||
|
||||
state = xenbus_read_driver_state(dev->otherend);
|
||||
state = xenbus_read_driver_state(dev, dev->otherend);
|
||||
|
||||
dev_dbg(&dev->dev, "state is %d, (%s), %s, %s\n",
|
||||
state, xenbus_strstate(state), dev->otherend_watch.node, path);
|
||||
@@ -364,7 +364,7 @@ void xenbus_dev_remove(struct device *_dev)
|
||||
* closed.
|
||||
*/
|
||||
if (!drv->allow_rebind ||
|
||||
xenbus_read_driver_state(dev->nodename) == XenbusStateClosing)
|
||||
xenbus_read_driver_state(dev, dev->nodename) == XenbusStateClosing)
|
||||
xenbus_switch_state(dev, XenbusStateClosed);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xenbus_dev_remove);
|
||||
@@ -444,6 +444,9 @@ static void xenbus_cleanup_devices(const char *path, struct bus_type *bus)
|
||||
info.dev = NULL;
|
||||
bus_for_each_dev(bus, NULL, &info, cleanup_dev);
|
||||
if (info.dev) {
|
||||
dev_warn(&info.dev->dev,
|
||||
"device forcefully removed from xenstore\n");
|
||||
info.dev->vanished = true;
|
||||
device_unregister(&info.dev->dev);
|
||||
put_device(&info.dev->dev);
|
||||
}
|
||||
@@ -514,7 +517,7 @@ int xenbus_probe_node(struct xen_bus_type *bus,
|
||||
size_t stringlen;
|
||||
char *tmpstring;
|
||||
|
||||
enum xenbus_state state = xenbus_read_driver_state(nodename);
|
||||
enum xenbus_state state = xenbus_read_driver_state(NULL, nodename);
|
||||
|
||||
if (state != XenbusStateInitialising) {
|
||||
/* Device is not new, so ignore it. This can happen if a
|
||||
@@ -659,6 +662,39 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
|
||||
return;
|
||||
|
||||
dev = xenbus_device_find(root, &bus->bus);
|
||||
/*
|
||||
* Backend domain crash results in not coordinated frontend removal,
|
||||
* without going through XenbusStateClosing. If this is a new instance
|
||||
* of the same device Xen tools will have reset the state to
|
||||
* XenbusStateInitializing.
|
||||
* It might be that the backend crashed early during the init phase of
|
||||
* device setup, in which case the known state would have been
|
||||
* XenbusStateInitializing. So test the backend domid to match the
|
||||
* saved one. In case the new backend happens to have the same domid as
|
||||
* the old one, we can just carry on, as there is no inconsistency
|
||||
* resulting in this case.
|
||||
*/
|
||||
if (dev && !strcmp(bus->root, "device")) {
|
||||
enum xenbus_state state = xenbus_read_driver_state(dev, dev->nodename);
|
||||
unsigned int backend = xenbus_read_unsigned(root, "backend-id",
|
||||
dev->otherend_id);
|
||||
|
||||
if (state == XenbusStateInitialising &&
|
||||
(state != dev->state || backend != dev->otherend_id)) {
|
||||
/*
|
||||
* State has been reset, assume the old one vanished
|
||||
* and new one needs to be probed.
|
||||
*/
|
||||
dev_warn(&dev->dev,
|
||||
"state reset occurred, reconnecting\n");
|
||||
dev->vanished = true;
|
||||
}
|
||||
if (dev->vanished) {
|
||||
device_unregister(&dev->dev);
|
||||
put_device(&dev->dev);
|
||||
dev = NULL;
|
||||
}
|
||||
}
|
||||
if (!dev)
|
||||
xenbus_probe_node(bus, type, root);
|
||||
else
|
||||
|
||||
@@ -253,7 +253,7 @@ static int print_device_status(struct device *dev, void *data)
|
||||
} else if (xendev->state < XenbusStateConnected) {
|
||||
enum xenbus_state rstate = XenbusStateUnknown;
|
||||
if (xendev->otherend)
|
||||
rstate = xenbus_read_driver_state(xendev->otherend);
|
||||
rstate = xenbus_read_driver_state(xendev, xendev->otherend);
|
||||
pr_warn("Timeout connecting to device: %s (local state %d, remote state %d)\n",
|
||||
xendev->nodename, xendev->state, rstate);
|
||||
}
|
||||
|
||||
@@ -848,12 +848,14 @@
|
||||
|
||||
/* Required sections not related to debugging. */
|
||||
#define ELF_DETAILS \
|
||||
.modinfo : { *(.modinfo) . = ALIGN(8); } \
|
||||
.comment 0 : { *(.comment) } \
|
||||
.symtab 0 : { *(.symtab) } \
|
||||
.strtab 0 : { *(.strtab) } \
|
||||
.shstrtab 0 : { *(.shstrtab) }
|
||||
|
||||
#define MODINFO \
|
||||
.modinfo : { *(.modinfo) . = ALIGN(8); }
|
||||
|
||||
#ifdef CONFIG_GENERIC_BUG
|
||||
#define BUG_TABLE \
|
||||
. = ALIGN(8); \
|
||||
|
||||
@@ -80,6 +80,7 @@ struct xenbus_device {
|
||||
const char *devicetype;
|
||||
const char *nodename;
|
||||
const char *otherend;
|
||||
bool vanished;
|
||||
int otherend_id;
|
||||
struct xenbus_watch otherend_watch;
|
||||
struct device dev;
|
||||
@@ -228,7 +229,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr);
|
||||
int xenbus_alloc_evtchn(struct xenbus_device *dev, evtchn_port_t *port);
|
||||
int xenbus_free_evtchn(struct xenbus_device *dev, evtchn_port_t port);
|
||||
|
||||
enum xenbus_state xenbus_read_driver_state(const char *path);
|
||||
enum xenbus_state xenbus_read_driver_state(const struct xenbus_device *dev,
|
||||
const char *path);
|
||||
|
||||
__printf(3, 4)
|
||||
void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...);
|
||||
|
||||
@@ -1002,10 +1002,8 @@ int bpf_trampoline_link_cgroup_shim(struct bpf_prog *prog,
|
||||
mutex_lock(&tr->mutex);
|
||||
|
||||
shim_link = cgroup_shim_find(tr, bpf_func);
|
||||
if (shim_link) {
|
||||
if (shim_link && !IS_ERR(bpf_link_inc_not_zero(&shim_link->link.link))) {
|
||||
/* Reusing existing shim attached by the other program. */
|
||||
bpf_link_inc(&shim_link->link.link);
|
||||
|
||||
mutex_unlock(&tr->mutex);
|
||||
bpf_trampoline_put(tr); /* bpf_trampoline_get above */
|
||||
return 0;
|
||||
|
||||
+34
-3
@@ -2511,6 +2511,30 @@ static void __reg32_deduce_bounds(struct bpf_reg_state *reg)
|
||||
if ((u32)reg->s32_min_value <= (u32)reg->s32_max_value) {
|
||||
reg->u32_min_value = max_t(u32, reg->s32_min_value, reg->u32_min_value);
|
||||
reg->u32_max_value = min_t(u32, reg->s32_max_value, reg->u32_max_value);
|
||||
} else {
|
||||
if (reg->u32_max_value < (u32)reg->s32_min_value) {
|
||||
/* See __reg64_deduce_bounds() for detailed explanation.
|
||||
* Refine ranges in the following situation:
|
||||
*
|
||||
* 0 U32_MAX
|
||||
* | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
|
||||
* |----------------------------|----------------------------|
|
||||
* |xxxxx s32 range xxxxxxxxx] [xxxxxxx|
|
||||
* 0 S32_MAX S32_MIN -1
|
||||
*/
|
||||
reg->s32_min_value = (s32)reg->u32_min_value;
|
||||
reg->u32_max_value = min_t(u32, reg->u32_max_value, reg->s32_max_value);
|
||||
} else if ((u32)reg->s32_max_value < reg->u32_min_value) {
|
||||
/*
|
||||
* 0 U32_MAX
|
||||
* | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
|
||||
* |----------------------------|----------------------------|
|
||||
* |xxxxxxxxx] [xxxxxxxxxxxx s32 range |
|
||||
* 0 S32_MAX S32_MIN -1
|
||||
*/
|
||||
reg->s32_max_value = (s32)reg->u32_max_value;
|
||||
reg->u32_min_value = max_t(u32, reg->u32_min_value, reg->s32_min_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17335,17 +17359,24 @@ static void __collect_linked_regs(struct linked_regs *reg_set, struct bpf_reg_st
|
||||
* in verifier state, save R in linked_regs if R->id == id.
|
||||
* If there are too many Rs sharing same id, reset id for leftover Rs.
|
||||
*/
|
||||
static void collect_linked_regs(struct bpf_verifier_state *vstate, u32 id,
|
||||
static void collect_linked_regs(struct bpf_verifier_env *env,
|
||||
struct bpf_verifier_state *vstate,
|
||||
u32 id,
|
||||
struct linked_regs *linked_regs)
|
||||
{
|
||||
struct bpf_insn_aux_data *aux = env->insn_aux_data;
|
||||
struct bpf_func_state *func;
|
||||
struct bpf_reg_state *reg;
|
||||
u16 live_regs;
|
||||
int i, j;
|
||||
|
||||
id = id & ~BPF_ADD_CONST;
|
||||
for (i = vstate->curframe; i >= 0; i--) {
|
||||
live_regs = aux[frame_insn_idx(vstate, i)].live_regs_before;
|
||||
func = vstate->frame[i];
|
||||
for (j = 0; j < BPF_REG_FP; j++) {
|
||||
if (!(live_regs & BIT(j)))
|
||||
continue;
|
||||
reg = &func->regs[j];
|
||||
__collect_linked_regs(linked_regs, reg, id, i, j, true);
|
||||
}
|
||||
@@ -17560,9 +17591,9 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
|
||||
* if parent state is created.
|
||||
*/
|
||||
if (BPF_SRC(insn->code) == BPF_X && src_reg->type == SCALAR_VALUE && src_reg->id)
|
||||
collect_linked_regs(this_branch, src_reg->id, &linked_regs);
|
||||
collect_linked_regs(env, this_branch, src_reg->id, &linked_regs);
|
||||
if (dst_reg->type == SCALAR_VALUE && dst_reg->id)
|
||||
collect_linked_regs(this_branch, dst_reg->id, &linked_regs);
|
||||
collect_linked_regs(env, this_branch, dst_reg->id, &linked_regs);
|
||||
if (linked_regs.cnt > 1) {
|
||||
err = push_jmp_history(env, this_branch, 0, linked_regs_pack(&linked_regs));
|
||||
if (err)
|
||||
|
||||
@@ -6404,6 +6404,7 @@ int update_ftrace_direct_add(struct ftrace_ops *ops, struct ftrace_hash *hash)
|
||||
new_filter_hash = old_filter_hash;
|
||||
}
|
||||
} else {
|
||||
guard(mutex)(&ftrace_lock);
|
||||
err = ftrace_update_ops(ops, new_filter_hash, EMPTY_HASH);
|
||||
/*
|
||||
* new_filter_hash is dup-ed, so we need to release it anyway,
|
||||
@@ -6530,6 +6531,7 @@ int update_ftrace_direct_del(struct ftrace_ops *ops, struct ftrace_hash *hash)
|
||||
ops->func_hash->filter_hash = NULL;
|
||||
}
|
||||
} else {
|
||||
guard(mutex)(&ftrace_lock);
|
||||
err = ftrace_update_ops(ops, new_filter_hash, EMPTY_HASH);
|
||||
/*
|
||||
* new_filter_hash is dup-ed, so we need to release it anyway,
|
||||
|
||||
@@ -9348,7 +9348,7 @@ static void setup_trace_scratch(struct trace_array *tr,
|
||||
}
|
||||
|
||||
static int
|
||||
allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, int size)
|
||||
allocate_trace_buffer(struct trace_array *tr, struct array_buffer *buf, unsigned long size)
|
||||
{
|
||||
enum ring_buffer_flags rb_flags;
|
||||
struct trace_scratch *tscratch;
|
||||
@@ -9403,7 +9403,7 @@ static void free_trace_buffer(struct array_buffer *buf)
|
||||
}
|
||||
}
|
||||
|
||||
static int allocate_trace_buffers(struct trace_array *tr, int size)
|
||||
static int allocate_trace_buffers(struct trace_array *tr, unsigned long size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -10767,7 +10767,7 @@ __init static void enable_instances(void)
|
||||
|
||||
__init static int tracer_alloc_buffers(void)
|
||||
{
|
||||
int ring_buf_size;
|
||||
unsigned long ring_buf_size;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
|
||||
|
||||
@@ -4493,7 +4493,11 @@ static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata;
|
||||
|
||||
static __init int setup_trace_event(char *str)
|
||||
{
|
||||
strscpy(bootup_event_buf, str, COMMAND_LINE_SIZE);
|
||||
if (bootup_event_buf[0] != '\0')
|
||||
strlcat(bootup_event_buf, ",", COMMAND_LINE_SIZE);
|
||||
|
||||
strlcat(bootup_event_buf, str, COMMAND_LINE_SIZE);
|
||||
|
||||
trace_set_ring_buffer_expanded(NULL);
|
||||
disable_tracing_selftest("running event tracing");
|
||||
|
||||
|
||||
@@ -50,6 +50,9 @@ static int trigger_kthread_fn(void *ignore)
|
||||
|
||||
void trigger_data_free(struct event_trigger_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (data->cmd_ops->set_filter)
|
||||
data->cmd_ops->set_filter(NULL, data, NULL);
|
||||
|
||||
|
||||
@@ -325,8 +325,8 @@ direct_declarator:
|
||||
{ $$ = $4; }
|
||||
| direct_declarator BRACKET_PHRASE
|
||||
{ $$ = $2; }
|
||||
| '(' declarator ')'
|
||||
{ $$ = $3; }
|
||||
| '(' attribute_opt declarator ')'
|
||||
{ $$ = $4; }
|
||||
;
|
||||
|
||||
/* Nested declarators differ from regular declarators in that they do
|
||||
|
||||
@@ -32,6 +32,10 @@ mkdir -p "${destdir}"
|
||||
echo tools/objtool/objtool
|
||||
fi
|
||||
|
||||
if is_enabled CONFIG_DEBUG_INFO_BTF_MODULES; then
|
||||
echo tools/bpf/resolve_btfids/resolve_btfids
|
||||
fi
|
||||
|
||||
echo Module.symvers
|
||||
echo "arch/${SRCARCH}/include/generated"
|
||||
echo include/config/auto.conf
|
||||
|
||||
@@ -142,13 +142,15 @@ $(LIBSUBCMD)-clean:
|
||||
$(Q)$(RM) -r -- $(LIBSUBCMD_OUTPUT)
|
||||
|
||||
clean: $(LIBSUBCMD)-clean
|
||||
$(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL)
|
||||
$(Q)find $(OUTPUT) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
|
||||
$(Q)find $(OUTPUT) \( -name '*.o' -o -name '\.*.cmd' -o -name '\.*.d' \) -type f -print | xargs $(RM)
|
||||
$(Q)$(RM) $(OUTPUT)arch/x86/lib/cpu-feature-names.c $(OUTPUT)fixdep
|
||||
$(Q)$(RM) $(OUTPUT)arch/x86/lib/inat-tables.c $(OUTPUT)fixdep
|
||||
$(Q)$(RM) -- $(OUTPUT)FEATURE-DUMP.objtool
|
||||
$(Q)$(RM) -r -- $(OUTPUT)feature
|
||||
|
||||
mrproper: clean
|
||||
$(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL)
|
||||
|
||||
FORCE:
|
||||
|
||||
.PHONY: clean FORCE
|
||||
.PHONY: clean mrproper FORCE
|
||||
@@ -475,8 +475,8 @@ static void sve2_sigill(void)
|
||||
|
||||
static void sve2p1_sigill(void)
|
||||
{
|
||||
/* BFADD Z0.H, Z0.H, Z0.H */
|
||||
asm volatile(".inst 0x65000000" : : : "z0");
|
||||
/* LD1Q {Z0.Q}, P0/Z, [Z0.D, X0] */
|
||||
asm volatile(".inst 0xC400A000" : : : "z0");
|
||||
}
|
||||
|
||||
static void sve2p2_sigill(void)
|
||||
|
||||
@@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
|
||||
}
|
||||
}
|
||||
|
||||
static struct range range_improve(enum num_t t, struct range old, struct range new)
|
||||
static struct range range_intersection(enum num_t t, struct range old, struct range new)
|
||||
{
|
||||
return range(t, max_t(t, old.a, new.a), min_t(t, old.b, new.b));
|
||||
}
|
||||
|
||||
/*
|
||||
* Result is precise when 'x' and 'y' overlap or form a continuous range,
|
||||
* result is an over-approximation if 'x' and 'y' do not overlap.
|
||||
*/
|
||||
static struct range range_union(enum num_t t, struct range x, struct range y)
|
||||
{
|
||||
if (!is_valid_range(t, x))
|
||||
return y;
|
||||
if (!is_valid_range(t, y))
|
||||
return x;
|
||||
return range(t, min_t(t, x.a, y.a), max_t(t, x.b, y.b));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function attempts to improve x range intersecting it with y.
|
||||
* range_cast(... to_t ...) looses precision for ranges that pass to_t
|
||||
* min/max boundaries. To avoid such precision loses this function
|
||||
* splits both x and y into halves corresponding to non-overflowing
|
||||
* sub-ranges: [0, smin] and [smax, -1].
|
||||
* Final result is computed as follows:
|
||||
*
|
||||
* ((x ∩ [0, smax]) ∩ (y ∩ [0, smax])) ∪
|
||||
* ((x ∩ [smin,-1]) ∩ (y ∩ [smin,-1]))
|
||||
*
|
||||
* Precision might still be lost if final union is not a continuous range.
|
||||
*/
|
||||
static struct range range_refine_in_halves(enum num_t x_t, struct range x,
|
||||
enum num_t y_t, struct range y)
|
||||
{
|
||||
struct range x_pos, x_neg, y_pos, y_neg, r_pos, r_neg;
|
||||
u64 smax, smin, neg_one;
|
||||
|
||||
if (t_is_32(x_t)) {
|
||||
smax = (u64)(u32)S32_MAX;
|
||||
smin = (u64)(u32)S32_MIN;
|
||||
neg_one = (u64)(u32)(s32)(-1);
|
||||
} else {
|
||||
smax = (u64)S64_MAX;
|
||||
smin = (u64)S64_MIN;
|
||||
neg_one = U64_MAX;
|
||||
}
|
||||
x_pos = range_intersection(x_t, x, range(x_t, 0, smax));
|
||||
x_neg = range_intersection(x_t, x, range(x_t, smin, neg_one));
|
||||
y_pos = range_intersection(y_t, y, range(x_t, 0, smax));
|
||||
y_neg = range_intersection(y_t, y, range(y_t, smin, neg_one));
|
||||
r_pos = range_intersection(x_t, x_pos, range_cast(y_t, x_t, y_pos));
|
||||
r_neg = range_intersection(x_t, x_neg, range_cast(y_t, x_t, y_neg));
|
||||
return range_union(x_t, r_pos, r_neg);
|
||||
|
||||
}
|
||||
|
||||
static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t, struct range y)
|
||||
{
|
||||
struct range y_cast;
|
||||
|
||||
if (t_is_32(x_t) == t_is_32(y_t))
|
||||
x = range_refine_in_halves(x_t, x, y_t, y);
|
||||
|
||||
y_cast = range_cast(y_t, x_t, y);
|
||||
|
||||
/* If we know that
|
||||
@@ -444,7 +498,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
|
||||
*/
|
||||
if (x_t == S64 && y_t == S32 && y_cast.a <= S32_MAX && y_cast.b <= S32_MAX &&
|
||||
(s64)x.a >= S32_MIN && (s64)x.b <= S32_MAX)
|
||||
return range_improve(x_t, x, y_cast);
|
||||
return range_intersection(x_t, x, y_cast);
|
||||
|
||||
/* the case when new range knowledge, *y*, is a 32-bit subregister
|
||||
* range, while previous range knowledge, *x*, is a full register
|
||||
@@ -462,25 +516,11 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
|
||||
x_swap = range(x_t, swap_low32(x.a, y_cast.a), swap_low32(x.b, y_cast.b));
|
||||
if (!is_valid_range(x_t, x_swap))
|
||||
return x;
|
||||
return range_improve(x_t, x, x_swap);
|
||||
}
|
||||
|
||||
if (!t_is_32(x_t) && !t_is_32(y_t) && x_t != y_t) {
|
||||
if (x_t == S64 && x.a > x.b) {
|
||||
if (x.b < y.a && x.a <= y.b)
|
||||
return range(x_t, x.a, y.b);
|
||||
if (x.a > y.b && x.b >= y.a)
|
||||
return range(x_t, y.a, x.b);
|
||||
} else if (x_t == U64 && y.a > y.b) {
|
||||
if (y.b < x.a && y.a <= x.b)
|
||||
return range(x_t, y.a, x.b);
|
||||
if (y.a > x.b && y.b >= x.a)
|
||||
return range(x_t, x.a, y.b);
|
||||
}
|
||||
return range_intersection(x_t, x, x_swap);
|
||||
}
|
||||
|
||||
/* otherwise, plain range cast and intersection works */
|
||||
return range_improve(x_t, x, y_cast);
|
||||
return range_intersection(x_t, x, y_cast);
|
||||
}
|
||||
|
||||
/* =======================
|
||||
|
||||
@@ -18,43 +18,43 @@
|
||||
return *(u64 *)num; \
|
||||
}
|
||||
|
||||
__msg(": R0=0xffffffff80000000")
|
||||
__msg("R{{.}}=0xffffffff80000000")
|
||||
check_assert(s64, ==, eq_int_min, INT_MIN);
|
||||
__msg(": R0=0x7fffffff")
|
||||
__msg("R{{.}}=0x7fffffff")
|
||||
check_assert(s64, ==, eq_int_max, INT_MAX);
|
||||
__msg(": R0=0")
|
||||
__msg("R{{.}}=0")
|
||||
check_assert(s64, ==, eq_zero, 0);
|
||||
__msg(": R0=0x8000000000000000 R1=0x8000000000000000")
|
||||
__msg("R{{.}}=0x8000000000000000")
|
||||
check_assert(s64, ==, eq_llong_min, LLONG_MIN);
|
||||
__msg(": R0=0x7fffffffffffffff R1=0x7fffffffffffffff")
|
||||
__msg("R{{.}}=0x7fffffffffffffff")
|
||||
check_assert(s64, ==, eq_llong_max, LLONG_MAX);
|
||||
|
||||
__msg(": R0=scalar(id=1,smax=0x7ffffffe)")
|
||||
__msg("R{{.}}=scalar(id=1,smax=0x7ffffffe)")
|
||||
check_assert(s64, <, lt_pos, INT_MAX);
|
||||
__msg(": R0=scalar(id=1,smax=-1,umin=0x8000000000000000,var_off=(0x8000000000000000; 0x7fffffffffffffff))")
|
||||
__msg("R{{.}}=scalar(id=1,smax=-1,umin=0x8000000000000000,var_off=(0x8000000000000000; 0x7fffffffffffffff))")
|
||||
check_assert(s64, <, lt_zero, 0);
|
||||
__msg(": R0=scalar(id=1,smax=0xffffffff7fffffff")
|
||||
__msg("R{{.}}=scalar(id=1,smax=0xffffffff7fffffff")
|
||||
check_assert(s64, <, lt_neg, INT_MIN);
|
||||
|
||||
__msg(": R0=scalar(id=1,smax=0x7fffffff)")
|
||||
__msg("R{{.}}=scalar(id=1,smax=0x7fffffff)")
|
||||
check_assert(s64, <=, le_pos, INT_MAX);
|
||||
__msg(": R0=scalar(id=1,smax=0)")
|
||||
__msg("R{{.}}=scalar(id=1,smax=0)")
|
||||
check_assert(s64, <=, le_zero, 0);
|
||||
__msg(": R0=scalar(id=1,smax=0xffffffff80000000")
|
||||
__msg("R{{.}}=scalar(id=1,smax=0xffffffff80000000")
|
||||
check_assert(s64, <=, le_neg, INT_MIN);
|
||||
|
||||
__msg(": R0=scalar(id=1,smin=umin=0x80000000,umax=0x7fffffffffffffff,var_off=(0x0; 0x7fffffffffffffff))")
|
||||
__msg("R{{.}}=scalar(id=1,smin=umin=0x80000000,umax=0x7fffffffffffffff,var_off=(0x0; 0x7fffffffffffffff))")
|
||||
check_assert(s64, >, gt_pos, INT_MAX);
|
||||
__msg(": R0=scalar(id=1,smin=umin=1,umax=0x7fffffffffffffff,var_off=(0x0; 0x7fffffffffffffff))")
|
||||
__msg("R{{.}}=scalar(id=1,smin=umin=1,umax=0x7fffffffffffffff,var_off=(0x0; 0x7fffffffffffffff))")
|
||||
check_assert(s64, >, gt_zero, 0);
|
||||
__msg(": R0=scalar(id=1,smin=0xffffffff80000001")
|
||||
__msg("R{{.}}=scalar(id=1,smin=0xffffffff80000001")
|
||||
check_assert(s64, >, gt_neg, INT_MIN);
|
||||
|
||||
__msg(": R0=scalar(id=1,smin=umin=0x7fffffff,umax=0x7fffffffffffffff,var_off=(0x0; 0x7fffffffffffffff))")
|
||||
__msg("R{{.}}=scalar(id=1,smin=umin=0x7fffffff,umax=0x7fffffffffffffff,var_off=(0x0; 0x7fffffffffffffff))")
|
||||
check_assert(s64, >=, ge_pos, INT_MAX);
|
||||
__msg(": R0=scalar(id=1,smin=0,umax=0x7fffffffffffffff,var_off=(0x0; 0x7fffffffffffffff))")
|
||||
__msg("R{{.}}=scalar(id=1,smin=0,umax=0x7fffffffffffffff,var_off=(0x0; 0x7fffffffffffffff))")
|
||||
check_assert(s64, >=, ge_zero, 0);
|
||||
__msg(": R0=scalar(id=1,smin=0xffffffff80000000")
|
||||
__msg("R{{.}}=scalar(id=1,smin=0xffffffff80000000")
|
||||
check_assert(s64, >=, ge_neg, INT_MIN);
|
||||
|
||||
SEC("?tc")
|
||||
|
||||
@@ -1148,7 +1148,7 @@ l0_%=: r0 = 0; \
|
||||
SEC("xdp")
|
||||
__description("bound check with JMP32_JSLT for crossing 32-bit signed boundary")
|
||||
__success __retval(0)
|
||||
__flag(!BPF_F_TEST_REG_INVARIANTS) /* known invariants violation */
|
||||
__flag(BPF_F_TEST_REG_INVARIANTS)
|
||||
__naked void crossing_32_bit_signed_boundary_2(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
@@ -2000,4 +2000,41 @@ __naked void bounds_refinement_multiple_overlaps(void *ctx)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("socket")
|
||||
__success
|
||||
__flag(BPF_F_TEST_REG_INVARIANTS)
|
||||
__naked void signed_unsigned_intersection32_case1(void *ctx)
|
||||
{
|
||||
asm volatile(" \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
w0 &= 0xffffffff; \
|
||||
if w0 < 0x3 goto 1f; /* on fall-through u32 range [3..U32_MAX] */ \
|
||||
if w0 s> 0x1 goto 1f; /* on fall-through s32 range [S32_MIN..1] */ \
|
||||
if w0 s< 0x0 goto 1f; /* range can be narrowed to [S32_MIN..-1] */ \
|
||||
r10 = 0; /* thus predicting the jump. */ \
|
||||
1: exit; \
|
||||
" :
|
||||
: __imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
SEC("socket")
|
||||
__success
|
||||
__flag(BPF_F_TEST_REG_INVARIANTS)
|
||||
__naked void signed_unsigned_intersection32_case2(void *ctx)
|
||||
{
|
||||
asm volatile(" \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
w0 &= 0xffffffff; \
|
||||
if w0 > 0x80000003 goto 1f; /* on fall-through u32 range [0..S32_MIN+3] */ \
|
||||
if w0 s< -3 goto 1f; /* on fall-through s32 range [-3..S32_MAX] */ \
|
||||
if w0 s> 5 goto 1f; /* on fall-through s32 range [-3..5] */ \
|
||||
if w0 <= 5 goto 1f; /* range can be narrowed to [0..5] */ \
|
||||
r10 = 0; /* thus predicting the jump */ \
|
||||
1: exit; \
|
||||
" :
|
||||
: __imm(bpf_get_prandom_u32)
|
||||
: __clobber_all);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
@@ -363,4 +363,68 @@ void alu32_negative_offset(void)
|
||||
__sink(path[0]);
|
||||
}
|
||||
|
||||
void dummy_calls(void)
|
||||
{
|
||||
bpf_iter_num_new(0, 0, 0);
|
||||
bpf_iter_num_next(0);
|
||||
bpf_iter_num_destroy(0);
|
||||
}
|
||||
|
||||
SEC("socket")
|
||||
__success
|
||||
__flag(BPF_F_TEST_STATE_FREQ)
|
||||
int spurious_precision_marks(void *ctx)
|
||||
{
|
||||
struct bpf_iter_num iter;
|
||||
|
||||
asm volatile(
|
||||
"r1 = %[iter];"
|
||||
"r2 = 0;"
|
||||
"r3 = 10;"
|
||||
"call %[bpf_iter_num_new];"
|
||||
"1:"
|
||||
"r1 = %[iter];"
|
||||
"call %[bpf_iter_num_next];"
|
||||
"if r0 == 0 goto 4f;"
|
||||
"r7 = *(u32 *)(r0 + 0);"
|
||||
"r8 = *(u32 *)(r0 + 0);"
|
||||
/* This jump can't be predicted and does not change r7 or r8 state. */
|
||||
"if r7 > r8 goto 2f;"
|
||||
/* Branch explored first ties r2 and r7 as having the same id. */
|
||||
"r2 = r7;"
|
||||
"goto 3f;"
|
||||
"2:"
|
||||
/* Branch explored second does not tie r2 and r7 but has a function call. */
|
||||
"call %[bpf_get_prandom_u32];"
|
||||
"3:"
|
||||
/*
|
||||
* A checkpoint.
|
||||
* When first branch is explored, this would inject linked registers
|
||||
* r2 and r7 into the jump history.
|
||||
* When second branch is explored, this would be a cache hit point,
|
||||
* triggering propagate_precision().
|
||||
*/
|
||||
"if r7 <= 42 goto +0;"
|
||||
/*
|
||||
* Mark r7 as precise using an if condition that is always true.
|
||||
* When reached via the second branch, this triggered a bug in the backtrack_insn()
|
||||
* because r2 (tied to r7) was propagated as precise to a call.
|
||||
*/
|
||||
"if r7 <= 0xffffFFFF goto +0;"
|
||||
"goto 1b;"
|
||||
"4:"
|
||||
"r1 = %[iter];"
|
||||
"call %[bpf_iter_num_destroy];"
|
||||
:
|
||||
: __imm_ptr(iter),
|
||||
__imm(bpf_iter_num_new),
|
||||
__imm(bpf_iter_num_next),
|
||||
__imm(bpf_iter_num_destroy),
|
||||
__imm(bpf_get_prandom_u32)
|
||||
: __clobber_common, "r7", "r8"
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
@@ -40,6 +40,9 @@ __naked void linked_regs_bpf_k(void)
|
||||
*/
|
||||
"r3 = r10;"
|
||||
"r3 += r0;"
|
||||
/* Mark r1 and r2 as alive. */
|
||||
"r1 = r1;"
|
||||
"r2 = r2;"
|
||||
"r0 = 0;"
|
||||
"exit;"
|
||||
:
|
||||
@@ -73,6 +76,9 @@ __naked void linked_regs_bpf_x_src(void)
|
||||
*/
|
||||
"r4 = r10;"
|
||||
"r4 += r0;"
|
||||
/* Mark r1 and r2 as alive. */
|
||||
"r1 = r1;"
|
||||
"r2 = r2;"
|
||||
"r0 = 0;"
|
||||
"exit;"
|
||||
:
|
||||
@@ -106,6 +112,10 @@ __naked void linked_regs_bpf_x_dst(void)
|
||||
*/
|
||||
"r4 = r10;"
|
||||
"r4 += r3;"
|
||||
/* Mark r1 and r2 as alive. */
|
||||
"r0 = r0;"
|
||||
"r1 = r1;"
|
||||
"r2 = r2;"
|
||||
"r0 = 0;"
|
||||
"exit;"
|
||||
:
|
||||
@@ -143,6 +153,9 @@ __naked void linked_regs_broken_link(void)
|
||||
*/
|
||||
"r3 = r10;"
|
||||
"r3 += r0;"
|
||||
/* Mark r1 and r2 as alive. */
|
||||
"r1 = r1;"
|
||||
"r2 = r2;"
|
||||
"r0 = 0;"
|
||||
"exit;"
|
||||
:
|
||||
@@ -156,16 +169,16 @@ __naked void linked_regs_broken_link(void)
|
||||
*/
|
||||
SEC("socket")
|
||||
__success __log_level(2)
|
||||
__msg("12: (0f) r2 += r1")
|
||||
__msg("17: (0f) r2 += r1")
|
||||
/* Current state */
|
||||
__msg("frame2: last_idx 12 first_idx 11 subseq_idx -1 ")
|
||||
__msg("frame2: regs=r1 stack= before 11: (bf) r2 = r10")
|
||||
__msg("frame2: last_idx 17 first_idx 14 subseq_idx -1 ")
|
||||
__msg("frame2: regs=r1 stack= before 16: (bf) r2 = r10")
|
||||
__msg("frame2: parent state regs=r1 stack=")
|
||||
__msg("frame1: parent state regs= stack=")
|
||||
__msg("frame0: parent state regs= stack=")
|
||||
/* Parent state */
|
||||
__msg("frame2: last_idx 10 first_idx 10 subseq_idx 11 ")
|
||||
__msg("frame2: regs=r1 stack= before 10: (25) if r1 > 0x7 goto pc+0")
|
||||
__msg("frame2: last_idx 13 first_idx 13 subseq_idx 14 ")
|
||||
__msg("frame2: regs=r1 stack= before 13: (25) if r1 > 0x7 goto pc+0")
|
||||
__msg("frame2: parent state regs=r1 stack=")
|
||||
/* frame1.r{6,7} are marked because mark_precise_scalar_ids()
|
||||
* looks for all registers with frame2.r1.id in the current state
|
||||
@@ -173,20 +186,20 @@ __msg("frame2: parent state regs=r1 stack=")
|
||||
__msg("frame1: parent state regs=r6,r7 stack=")
|
||||
__msg("frame0: parent state regs=r6 stack=")
|
||||
/* Parent state */
|
||||
__msg("frame2: last_idx 8 first_idx 8 subseq_idx 10")
|
||||
__msg("frame2: regs=r1 stack= before 8: (85) call pc+1")
|
||||
__msg("frame2: last_idx 9 first_idx 9 subseq_idx 13")
|
||||
__msg("frame2: regs=r1 stack= before 9: (85) call pc+3")
|
||||
/* frame1.r1 is marked because of backtracking of call instruction */
|
||||
__msg("frame1: parent state regs=r1,r6,r7 stack=")
|
||||
__msg("frame0: parent state regs=r6 stack=")
|
||||
/* Parent state */
|
||||
__msg("frame1: last_idx 7 first_idx 6 subseq_idx 8")
|
||||
__msg("frame1: regs=r1,r6,r7 stack= before 7: (bf) r7 = r1")
|
||||
__msg("frame1: regs=r1,r6 stack= before 6: (bf) r6 = r1")
|
||||
__msg("frame1: last_idx 8 first_idx 7 subseq_idx 9")
|
||||
__msg("frame1: regs=r1,r6,r7 stack= before 8: (bf) r7 = r1")
|
||||
__msg("frame1: regs=r1,r6 stack= before 7: (bf) r6 = r1")
|
||||
__msg("frame1: parent state regs=r1 stack=")
|
||||
__msg("frame0: parent state regs=r6 stack=")
|
||||
/* Parent state */
|
||||
__msg("frame1: last_idx 4 first_idx 4 subseq_idx 6")
|
||||
__msg("frame1: regs=r1 stack= before 4: (85) call pc+1")
|
||||
__msg("frame1: last_idx 4 first_idx 4 subseq_idx 7")
|
||||
__msg("frame1: regs=r1 stack= before 4: (85) call pc+2")
|
||||
__msg("frame0: parent state regs=r1,r6 stack=")
|
||||
/* Parent state */
|
||||
__msg("frame0: last_idx 3 first_idx 1 subseq_idx 4")
|
||||
@@ -204,6 +217,7 @@ __naked void precision_many_frames(void)
|
||||
"r1 = r0;"
|
||||
"r6 = r0;"
|
||||
"call precision_many_frames__foo;"
|
||||
"r6 = r6;" /* mark r6 as live */
|
||||
"exit;"
|
||||
:
|
||||
: __imm(bpf_ktime_get_ns)
|
||||
@@ -220,6 +234,8 @@ void precision_many_frames__foo(void)
|
||||
"r6 = r1;"
|
||||
"r7 = r1;"
|
||||
"call precision_many_frames__bar;"
|
||||
"r6 = r6;" /* mark r6 as live */
|
||||
"r7 = r7;" /* mark r7 as live */
|
||||
"exit"
|
||||
::: __clobber_all);
|
||||
}
|
||||
@@ -229,6 +245,8 @@ void precision_many_frames__bar(void)
|
||||
{
|
||||
asm volatile (
|
||||
"if r1 > 7 goto +0;"
|
||||
"r6 = 0;" /* mark r6 as live */
|
||||
"r7 = 0;" /* mark r7 as live */
|
||||
/* force r1 to be precise, this eventually marks:
|
||||
* - bar frame r1
|
||||
* - foo frame r{1,6,7}
|
||||
@@ -340,6 +358,8 @@ __naked void precision_two_ids(void)
|
||||
"r3 += r7;"
|
||||
/* force r9 to be precise, this also marks r8 */
|
||||
"r3 += r9;"
|
||||
"r6 = r6;" /* mark r6 as live */
|
||||
"r8 = r8;" /* mark r8 as live */
|
||||
"exit;"
|
||||
:
|
||||
: __imm(bpf_ktime_get_ns)
|
||||
@@ -353,7 +373,7 @@ __flag(BPF_F_TEST_STATE_FREQ)
|
||||
* collect_linked_regs() can't tie more than 6 registers for a single insn.
|
||||
*/
|
||||
__msg("8: (25) if r0 > 0x7 goto pc+0 ; R0=scalar(id=1")
|
||||
__msg("9: (bf) r6 = r6 ; R6=scalar(id=2")
|
||||
__msg("14: (bf) r6 = r6 ; R6=scalar(id=2")
|
||||
/* check that r{0-5} are marked precise after 'if' */
|
||||
__msg("frame0: regs=r0 stack= before 8: (25) if r0 > 0x7 goto pc+0")
|
||||
__msg("frame0: parent state regs=r0,r1,r2,r3,r4,r5 stack=:")
|
||||
@@ -372,6 +392,12 @@ __naked void linked_regs_too_many_regs(void)
|
||||
"r6 = r0;"
|
||||
/* propagate range for r{0-6} */
|
||||
"if r0 > 7 goto +0;"
|
||||
/* keep r{1-5} live */
|
||||
"r1 = r1;"
|
||||
"r2 = r2;"
|
||||
"r3 = r3;"
|
||||
"r4 = r4;"
|
||||
"r5 = r5;"
|
||||
/* make r6 appear in the log */
|
||||
"r6 = r6;"
|
||||
/* force r0 to be precise,
|
||||
@@ -517,7 +543,7 @@ __naked void check_ids_in_regsafe_2(void)
|
||||
"*(u64*)(r10 - 8) = r1;"
|
||||
/* r9 = pointer to stack */
|
||||
"r9 = r10;"
|
||||
"r9 += -8;"
|
||||
"r9 += -16;"
|
||||
/* r8 = ktime_get_ns() */
|
||||
"call %[bpf_ktime_get_ns];"
|
||||
"r8 = r0;"
|
||||
@@ -538,6 +564,8 @@ __naked void check_ids_in_regsafe_2(void)
|
||||
"if r7 > 4 goto l2_%=;"
|
||||
/* Access memory at r9[r6] */
|
||||
"r9 += r6;"
|
||||
"r9 += r7;"
|
||||
"r9 += r8;"
|
||||
"r0 = *(u8*)(r9 + 0);"
|
||||
"l2_%=:"
|
||||
"r0 = 0;"
|
||||
|
||||
@@ -44,9 +44,9 @@
|
||||
mark_precise: frame0: regs=r2 stack= before 23\
|
||||
mark_precise: frame0: regs=r2 stack= before 22\
|
||||
mark_precise: frame0: regs=r2 stack= before 20\
|
||||
mark_precise: frame0: parent state regs=r2,r9 stack=:\
|
||||
mark_precise: frame0: parent state regs=r2 stack=:\
|
||||
mark_precise: frame0: last_idx 19 first_idx 10\
|
||||
mark_precise: frame0: regs=r2,r9 stack= before 19\
|
||||
mark_precise: frame0: regs=r2 stack= before 19\
|
||||
mark_precise: frame0: regs=r9 stack= before 18\
|
||||
mark_precise: frame0: regs=r8,r9 stack= before 17\
|
||||
mark_precise: frame0: regs=r0,r9 stack= before 15\
|
||||
@@ -107,9 +107,9 @@
|
||||
mark_precise: frame0: parent state regs=r2 stack=:\
|
||||
mark_precise: frame0: last_idx 20 first_idx 20\
|
||||
mark_precise: frame0: regs=r2 stack= before 20\
|
||||
mark_precise: frame0: parent state regs=r2,r9 stack=:\
|
||||
mark_precise: frame0: parent state regs=r2 stack=:\
|
||||
mark_precise: frame0: last_idx 19 first_idx 17\
|
||||
mark_precise: frame0: regs=r2,r9 stack= before 19\
|
||||
mark_precise: frame0: regs=r2 stack= before 19\
|
||||
mark_precise: frame0: regs=r9 stack= before 18\
|
||||
mark_precise: frame0: regs=r8,r9 stack= before 17\
|
||||
mark_precise: frame0: parent state regs= stack=:",
|
||||
|
||||
@@ -2,7 +2,9 @@ CONFIG_RCU_TRACE=n
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=4
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
#CHECK#CONFIG_RCU_EXPERT=n
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=n
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=n
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
@@ -7,4 +8,3 @@ CONFIG_PREEMPT_DYNAMIC=n
|
||||
CONFIG_RCU_TRACE=n
|
||||
CONFIG_DEBUG_LOCK_ALLOC=n
|
||||
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
|
||||
CONFIG_PREEMPT_COUNT=n
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=n
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=n
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
@@ -11,4 +12,3 @@ CONFIG_RCU_TRACE=n
|
||||
#CHECK#CONFIG_RCU_STALL_COMMON=n
|
||||
CONFIG_DEBUG_LOCK_ALLOC=n
|
||||
CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
|
||||
CONFIG_PREEMPT_COUNT=n
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=n
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=5
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=8
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=y
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
#CHECK#CONFIG_TREE_RCU=y
|
||||
#CHECK#CONFIG_PREEMPT_RCU=n
|
||||
CONFIG_HZ_PERIODIC=n
|
||||
CONFIG_NO_HZ_IDLE=n
|
||||
CONFIG_NO_HZ_FULL=y
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=8
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
#CHECK#CONFIG_TREE_RCU=y
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=8
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
#CHECK#CONFIG_TREE_RCU=y
|
||||
#CHECK#CONFIG_PREEMPT_RCU=n
|
||||
CONFIG_HZ_PERIODIC=n
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NO_HZ_FULL=n
|
||||
|
||||
@@ -6,6 +6,7 @@ CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
#CHECK#CONFIG_TREE_RCU=y
|
||||
CONFIG_PREEMPT_RCU=n
|
||||
CONFIG_HZ_PERIODIC=n
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NO_HZ_FULL=n
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_NR_CPUS=8
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_HZ_PERIODIC=n
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=n
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=n
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_SMP=y
|
||||
CONFIG_PREEMPT_NONE=y
|
||||
CONFIG_PREEMPT_LAZY=y
|
||||
CONFIG_PREEMPT_NONE=n
|
||||
CONFIG_PREEMPT_VOLUNTARY=n
|
||||
CONFIG_PREEMPT=n
|
||||
CONFIG_PREEMPT_DYNAMIC=n
|
||||
|
||||
Reference in new issue
Block a user