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:
Carlos Llamas committed 2026-04-21 20:40:21 +00:00
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:
+1 -1
View File
@@ -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
-1
View File
@@ -220,7 +220,6 @@ Hardware Monitoring Kernel Drivers
q54sj108a2
qnap-mcu-hwmon
raspberrypi-hwmon
sa67
sbrmi
sbtsi_temp
sch5627
-41
View File
@@ -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.
======================= ========================================================
-1
View File
@@ -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
+4 -4
View File
@@ -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' \) \
+1
View File
@@ -71,6 +71,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
DISCARDS
+1
View File
@@ -123,6 +123,7 @@ SECTIONS
_end = . ;
STABS_DEBUG
MODINFO
ELF_DETAILS
DISCARDS
+1
View File
@@ -21,6 +21,7 @@ SECTIONS
COMMON_DISCARDS
*(.ARM.exidx*)
*(.ARM.extab*)
*(.modinfo)
*(.note.*)
*(.rel.*)
*(.printk_index)
+1
View File
@@ -154,6 +154,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ARM_DETAILS
ARM_ASSERTS
+1
View File
@@ -153,6 +153,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ARM_DETAILS
ARM_ASSERTS
+7 -5
View File
@@ -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; \
})
+5 -5
View File
@@ -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)
+4
View File
@@ -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 */
+1
View File
@@ -350,6 +350,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
HEAD_SYMBOLS
+49 -4
View File
@@ -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.
+1
View File
@@ -109,6 +109,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
DISCARDS
+1
View File
@@ -62,6 +62,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
.hexagon.attributes 0 : { *(.hexagon.attributes) }
+1
View File
@@ -147,6 +147,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
#ifdef CONFIG_EFI_STUB
+1
View File
@@ -85,6 +85,7 @@ SECTIONS {
_end = .;
STABS_DEBUG
MODINFO
ELF_DETAILS
/* Sections to be discarded */
+1
View File
@@ -58,6 +58,7 @@ SECTIONS
_end = . ;
STABS_DEBUG
MODINFO
ELF_DETAILS
/* Sections to be discarded */
+1
View File
@@ -51,6 +51,7 @@ __init_begin = .;
_end = . ;
STABS_DEBUG
MODINFO
ELF_DETAILS
/* Sections to be discarded */
+1
View File
@@ -217,6 +217,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
/* These must appear regardless of . */
+1
View File
@@ -57,6 +57,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
DISCARDS
+1
View File
@@ -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
+1 -1
View File
@@ -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 */
+6 -1
View File
@@ -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)
+12 -8
View File
@@ -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);
+1
View File
@@ -165,6 +165,7 @@ SECTIONS
_end = . ;
STABS_DEBUG
MODINFO
ELF_DETAILS
.note 0 : { *(.note) }
+1
View File
@@ -397,6 +397,7 @@ SECTIONS
_end = . ;
DWARF_DEBUG
MODINFO
ELF_DETAILS
DISCARDS
+1
View File
@@ -170,6 +170,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
.riscv.attributes 0 : { *(.riscv.attributes) }
+1 -1
View File
@@ -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"
);
+1
View File
@@ -221,6 +221,7 @@ SECTIONS
/* Debugging sections. */
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
/*
+5 -6
View File
@@ -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");
}
+1
View File
@@ -89,6 +89,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
DISCARDS
+1
View File
@@ -191,6 +191,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
DISCARDS
+1
View File
@@ -172,6 +172,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
DISCARDS
+1
View File
@@ -113,6 +113,7 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
MODINFO
ELF_DETAILS
DISCARDS
+1 -1
View File
@@ -88,7 +88,7 @@ SECTIONS
/DISCARD/ : {
*(.dynamic) *(.dynsym) *(.dynstr) *(.dynbss)
*(.hash) *(.gnu.hash)
*(.note.*)
*(.note.*) *(.modinfo)
}
.got.plt (INFO) : {
-2
View File
@@ -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[];
-28
View File
@@ -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
+1
View File
@@ -427,6 +427,7 @@ SECTIONS
.llvm_bb_addr_map : { *(.llvm_bb_addr_map) }
#endif
MODINFO
ELF_DETAILS
DISCARDS
+1 -6
View File
@@ -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;
}
/*
+1 -1
View File
@@ -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);
+9
View File
@@ -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 */
-10
View File
@@ -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
-1
View File
@@ -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
+4 -2
View File
@@ -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;
+4 -1
View File
@@ -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);
+26 -25
View File
@@ -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;
+1 -1
View File
@@ -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;
+10 -9
View File
@@ -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,
-161
View File
@@ -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
View File
@@ -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);
}
+4 -4
View File
@@ -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. */
+1 -1
View File
@@ -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);
+2 -5
View File
@@ -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);
+5 -5
View File
@@ -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;
+14 -3
View File
@@ -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", &current_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;
+39 -3
View File
@@ -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
+1 -1
View File
@@ -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);
}
+3 -1
View File
@@ -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); \
+3 -1
View File
@@ -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, ...);
+1 -3
View File
@@ -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
View File
@@ -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)
+2
View File
@@ -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,
+3 -3
View File
@@ -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;
+5 -1
View File
@@ -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");
+3
View File
@@ -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);
+2 -2
View File
@@ -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
+4
View File
@@ -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
+5 -3
View File
@@ -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
+2 -2
View File
@@ -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