Merge tag 'parisc-for-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc architecture updates from Helge Deller:
 "PA-RISC now has a native eBPF JIT compiler for 32- and 64-bit kernels,
  the LED driver was rewritten to use the Linux LED framework and most
  of the parisc bootup code was switched to use *_initcall() functions.

  Summary:

   - add eBPF JIT compiler for 32- and 64-bit kernel

   - LCD/LED driver rewrite to utilize Linux LED subsystem

   - switch to generic mmap top-down layout and brk randomization

   - kernel startup cleanup by loading most drivers via arch_initcall()"

* tag 'parisc-for-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: (31 commits)
  parisc: ccio-dma: Create private runway procfs root entry
  parisc: chassis: Do not overwrite string on LCD display
  parisc: led: Rewrite LED/LCD driver to utilizize Linux LED subsystem
  parisc: led: Fix LAN receive and transmit LEDs
  parisc: lasi: Initialize LASI driver via arch_initcall()
  parisc: asp: Initialize asp driver via arch_initcall()
  parisc: wax: Initialize wax driver via arch_initcall()
  parisc: iosapic: Convert I/O Sapic driver to use arch_initcall()
  parisc: sba_iommu: Convert SBA IOMMU driver to use arch_initcall()
  parisc: led: Move register_led_regions() to late_initcall()
  parisc: lba: Convert LBA PCI bus driver to use arch_initcall()
  parisc: gsc: Convert GSC bus driver to use arch_initcall()
  parisc: ccio: Convert CCIO driver to use arch_initcall()
  parisc: eisa: Convert HP EISA bus driver to use arch_initcall()
  parisc: hppb: Convert HP PB bus driver to use arch_initcall()
  parisc: dino: Convert dino PCI bus driver to use arch_initcall()
  parisc: Makefile: Adjust order in which drivers should be loaded
  parisc: led: Reduce CPU overhead for disk & lan LED computation
  parisc: Avoid ioremap() for same addresss in iosapic_register()
  parisc: unaligned: Simplify 32-bit assembly in emulate_std()
  ...
This commit is contained in:
Linus Torvalds
2023-08-29 12:15:19 -07:00
38 changed files with 4041 additions and 927 deletions

View File

@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
obj-y += mm/ kernel/ math-emu/ obj-y += mm/ kernel/ math-emu/ net/
# for cleaning # for cleaning
subdir- += boot subdir- += boot

View File

@@ -49,6 +49,9 @@ config PARISC
select TTY # Needed for pdc_cons.c select TTY # Needed for pdc_cons.c
select HAS_IOPORT if PCI || EISA select HAS_IOPORT if PCI || EISA
select HAVE_DEBUG_STACKOVERFLOW select HAVE_DEBUG_STACKOVERFLOW
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
select HAVE_ARCH_MMAP_RND_BITS
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_HASH select HAVE_ARCH_HASH
select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL
@@ -56,6 +59,8 @@ config PARISC
select HAVE_ARCH_KFENCE select HAVE_ARCH_KFENCE
select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRACEHOOK
select HAVE_EBPF_JIT
select ARCH_WANT_DEFAULT_BPF_JIT
select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_REGS_AND_STACK_ACCESS_API
select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU select HOTPLUG_CORE_SYNC_DEAD if HOTPLUG_CPU
select GENERIC_SCHED_CLOCK select GENERIC_SCHED_CLOCK
@@ -124,6 +129,20 @@ config TIME_LOW_RES
depends on SMP depends on SMP
default y default y
config ARCH_MMAP_RND_BITS_MIN
default 18 if 64BIT
default 8
config ARCH_MMAP_RND_COMPAT_BITS_MIN
default 8
config ARCH_MMAP_RND_BITS_MAX
default 24 if 64BIT
default 17
config ARCH_MMAP_RND_COMPAT_BITS_MAX
default 17
# unless you want to implement ACPI on PA-RISC ... ;-) # unless you want to implement ACPI on PA-RISC ... ;-)
config PM config PM
bool bool

View File

@@ -13,7 +13,7 @@ config LIGHTWEIGHT_SPINLOCK_CHECK
config TLB_PTLOCK config TLB_PTLOCK
bool "Use page table locks in TLB fault handler" bool "Use page table locks in TLB fault handler"
depends on SMP depends on DEBUG_KERNEL && SMP
default n default n
help help
Select this option to enable page table locking in the TLB Select this option to enable page table locking in the TLB

View File

@@ -163,8 +163,7 @@ typedef struct elf32_fdesc {
/* Format for the Elf64 Function descriptor */ /* Format for the Elf64 Function descriptor */
typedef struct elf64_fdesc { typedef struct elf64_fdesc {
__u64 dummy[2]; /* FIXME: nothing uses these, why waste __u64 dummy[2]; /* used by 64-bit eBPF and tracing functions */
* the space */
__u64 addr; __u64 addr;
__u64 gp; __u64 gp;
} Elf64_Fdesc; } Elf64_Fdesc;

View File

@@ -11,8 +11,8 @@
#define LED1 0x02 #define LED1 0x02
#define LED0 0x01 /* bottom (or furthest left) LED */ #define LED0 0x01 /* bottom (or furthest left) LED */
#define LED_LAN_TX LED0 /* for LAN transmit activity */ #define LED_LAN_RCV LED0 /* for LAN receive activity */
#define LED_LAN_RCV LED1 /* for LAN receive activity */ #define LED_LAN_TX LED1 /* for LAN transmit activity */
#define LED_DISK_IO LED2 /* for disk activity */ #define LED_DISK_IO LED2 /* for disk activity */
#define LED_HEARTBEAT LED3 /* heartbeat */ #define LED_HEARTBEAT LED3 /* heartbeat */
@@ -25,19 +25,13 @@
#define LED_CMD_REG_NONE 0 /* NULL == no addr for the cmd register */ #define LED_CMD_REG_NONE 0 /* NULL == no addr for the cmd register */
/* register_led_driver() */ /* register_led_driver() */
int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long data_reg); int register_led_driver(int model, unsigned long cmd_reg, unsigned long data_reg);
/* registers the LED regions for procfs */
void __init register_led_regions(void);
#ifdef CONFIG_CHASSIS_LCD_LED #ifdef CONFIG_CHASSIS_LCD_LED
/* writes a string to the LCD display (if possible on this h/w) */ /* writes a string to the LCD display (if possible on this h/w) */
int lcd_print(const char *str); void lcd_print(const char *str);
#else #else
#define lcd_print(str) #define lcd_print(str) do { } while (0)
#endif #endif
/* main LED initialization function (uses PDC) */
int __init led_init(void);
#endif /* LED_H */ #endif /* LED_H */

View File

@@ -1,17 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _PARISC_MACHDEP_H
#define _PARISC_MACHDEP_H
#include <linux/notifier.h>
#define MACH_RESTART 1
#define MACH_HALT 2
#define MACH_POWER_ON 3
#define MACH_POWER_OFF 4
extern struct notifier_block *mach_notifier;
extern void pa7300lc_init(void);
extern void (*cpu_lpmc)(int, struct pt_regs *);
#endif

View File

@@ -313,15 +313,7 @@ extern void collect_boot_cpu_data(void);
extern int show_cpuinfo (struct seq_file *m, void *v); extern int show_cpuinfo (struct seq_file *m, void *v);
/* driver code in driver/parisc */ /* driver code in driver/parisc */
extern void gsc_init(void);
extern void processor_init(void); extern void processor_init(void);
extern void ccio_init(void);
extern void hppb_init(void);
extern void dino_init(void);
extern void iosapic_init(void);
extern void lba_init(void);
extern void sba_init(void);
extern void parisc_eisa_init(void);
struct parisc_device; struct parisc_device;
struct resource; struct resource;
extern void sba_distributed_lmmio(struct parisc_device *, struct resource *); extern void sba_distributed_lmmio(struct parisc_device *, struct resource *);

View File

@@ -252,7 +252,7 @@ static inline int agp_mode_mercury(void __iomem *hpa) {
** fixup_irq is to initialize PCI IRQ line support and ** fixup_irq is to initialize PCI IRQ line support and
** virtualize pcidev->irq value. To be called by pci_fixup_bus(). ** virtualize pcidev->irq value. To be called by pci_fixup_bus().
*/ */
extern void *iosapic_register(unsigned long hpa); extern void *iosapic_register(unsigned long hpa, void __iomem *vaddr);
extern int iosapic_fixup_irq(void *obj, struct pci_dev *pcidev); extern int iosapic_fixup_irq(void *obj, struct pci_dev *pcidev);
#define LBA_FUNC_ID 0x0000 /* function id */ #define LBA_FUNC_ID 0x0000 /* function id */

View File

@@ -2,9 +2,6 @@
#ifndef ASM_PARISC_RUNWAY_H #ifndef ASM_PARISC_RUNWAY_H
#define ASM_PARISC_RUNWAY_H #define ASM_PARISC_RUNWAY_H
/* declared in arch/parisc/kernel/setup.c */
extern struct proc_dir_entry * proc_runway_root;
#define RUNWAY_STATUS 0x10 #define RUNWAY_STATUS 0x10
#define RUNWAY_DEBUG 0x40 #define RUNWAY_DEBUG 0x40

View File

@@ -6,7 +6,7 @@
extra-y := vmlinux.lds extra-y := vmlinux.lds
obj-y := head.o cache.o pacache.o setup.o pdt.o traps.o time.o irq.o \ obj-y := head.o cache.o pacache.o setup.o pdt.o traps.o time.o irq.o \
pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \ syscall.o entry.o sys_parisc.o firmware.o \
ptrace.o hardware.o inventory.o drivers.o alternative.o \ ptrace.o hardware.o inventory.o drivers.o alternative.o \
signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \ signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \ process.o processor.o pdc_cons.o pdc_chassis.o unwind.o \

View File

@@ -1,51 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* linux/arch/parisc/kernel/pa7300lc.c
* - PA7300LC-specific functions
*
* Copyright (C) 2000 Philipp Rumpf */
#include <linux/sched.h>
#include <linux/sched/debug.h>
#include <linux/smp.h>
#include <linux/kernel.h>
#include <asm/io.h>
#include <asm/ptrace.h>
#include <asm/machdep.h>
/* CPU register indices */
#define MIOC_STATUS 0xf040
#define MIOC_CONTROL 0xf080
#define MDERRADD 0xf0e0
#define DMAERR 0xf0e8
#define DIOERR 0xf0ec
#define HIDMAMEM 0xf0f4
/* this returns the HPA of the CPU it was called on */
static u32 cpu_hpa(void)
{
return 0xfffb0000;
}
static void pa7300lc_lpmc(int code, struct pt_regs *regs)
{
u32 hpa;
printk(KERN_WARNING "LPMC on CPU %d\n", smp_processor_id());
show_regs(regs);
hpa = cpu_hpa();
printk(KERN_WARNING
"MIOC_CONTROL %08x\n" "MIOC_STATUS %08x\n"
"MDERRADD %08x\n" "DMAERR %08x\n"
"DIOERR %08x\n" "HIDMAMEM %08x\n",
gsc_readl(hpa+MIOC_CONTROL), gsc_readl(hpa+MIOC_STATUS),
gsc_readl(hpa+MDERRADD), gsc_readl(hpa+DMAERR),
gsc_readl(hpa+DIOERR), gsc_readl(hpa+HIDMAMEM));
}
void pa7300lc_init(void)
{
cpu_lpmc = pa7300lc_lpmc;
}

View File

@@ -31,6 +31,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/pdc.h> #include <asm/pdc.h>
#include <asm/pdcpat.h> #include <asm/pdcpat.h>
#include <asm/led.h>
#define PDC_CHASSIS_VER "0.05" #define PDC_CHASSIS_VER "0.05"
@@ -234,6 +235,11 @@ int pdc_chassis_send_status(int message)
} else retval = -1; } else retval = -1;
#endif /* CONFIG_64BIT */ #endif /* CONFIG_64BIT */
} /* if (pdc_chassis_enabled) */ } /* if (pdc_chassis_enabled) */
/* if system has LCD display, update current string */
if (retval != -1 && IS_ENABLED(CONFIG_CHASSIS_LCD_LED))
lcd_print(NULL);
#endif /* CONFIG_PDC_CHASSIS */ #endif /* CONFIG_PDC_CHASSIS */
return retval; return retval;
} }

View File

@@ -97,18 +97,12 @@ void machine_restart(char *cmd)
} }
void (*chassis_power_off)(void);
/* /*
* This routine is called from sys_reboot to actually turn off the * This routine is called from sys_reboot to actually turn off the
* machine * machine
*/ */
void machine_power_off(void) void machine_power_off(void)
{ {
/* If there is a registered power off handler, call it. */
if (chassis_power_off)
chassis_power_off();
/* Put the soft power button back under hardware control. /* Put the soft power button back under hardware control.
* If the user had already pressed the power button, the * If the user had already pressed the power button, the
* following call will immediately power off. */ * following call will immediately power off. */
@@ -284,17 +278,3 @@ __get_wchan(struct task_struct *p)
} while (count++ < MAX_UNWIND_ENTRIES); } while (count++ < MAX_UNWIND_ENTRIES);
return 0; return 0;
} }
static inline unsigned long brk_rnd(void)
{
return (get_random_u32() & BRK_RND_MASK) << PAGE_SHIFT;
}
unsigned long arch_randomize_brk(struct mm_struct *mm)
{
unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd());
if (ret < mm->brk)
return mm->brk;
return ret;
}

View File

@@ -378,10 +378,18 @@ int
show_cpuinfo (struct seq_file *m, void *v) show_cpuinfo (struct seq_file *m, void *v)
{ {
unsigned long cpu; unsigned long cpu;
char cpu_name[60], *p;
/* strip PA path from CPU name to not confuse lscpu */
strlcpy(cpu_name, per_cpu(cpu_data, 0).dev->name, sizeof(cpu_name));
p = strrchr(cpu_name, '[');
if (p)
*(--p) = 0;
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
const struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
const struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
if (0 == cpuinfo->hpa) if (0 == cpuinfo->hpa)
continue; continue;
#endif #endif
@@ -426,8 +434,7 @@ show_cpuinfo (struct seq_file *m, void *v)
seq_printf(m, "model\t\t: %s - %s\n", seq_printf(m, "model\t\t: %s - %s\n",
boot_cpu_data.pdc.sys_model_name, boot_cpu_data.pdc.sys_model_name,
cpuinfo->dev ? cpu_name);
cpuinfo->dev->name : "Unknown");
seq_printf(m, "hversion\t: 0x%08x\n" seq_printf(m, "hversion\t: 0x%08x\n"
"sversion\t: 0x%08x\n", "sversion\t: 0x%08x\n",

View File

@@ -31,7 +31,6 @@
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/pdc.h> #include <asm/pdc.h>
#include <asm/led.h> #include <asm/led.h>
#include <asm/machdep.h> /* for pa7300lc_init() proto */
#include <asm/pdc_chassis.h> #include <asm/pdc_chassis.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/setup.h> #include <asm/setup.h>
@@ -93,8 +92,6 @@ static void __init dma_ops_init(void)
"the PA-RISC 1.1 or 2.0 architecture specification.\n"); "the PA-RISC 1.1 or 2.0 architecture specification.\n");
case pcxl2: case pcxl2:
pa7300lc_init();
break;
default: default:
break; break;
} }
@@ -146,11 +143,6 @@ void __init setup_arch(char **cmdline_p)
parisc_cache_init(); parisc_cache_init();
paging_init(); paging_init();
#ifdef CONFIG_CHASSIS_LCD_LED
/* initialize the LCD/LED after boot_cpu_data is available ! */
led_init(); /* LCD/LED initialization */
#endif
#ifdef CONFIG_PA11 #ifdef CONFIG_PA11
dma_ops_init(); dma_ops_init();
#endif #endif
@@ -281,47 +273,6 @@ static int __init parisc_init(void)
apply_alternatives_all(); apply_alternatives_all();
parisc_setup_cache_timing(); parisc_setup_cache_timing();
/* These are in a non-obvious order, will fix when we have an iotree */
#if defined(CONFIG_IOSAPIC)
iosapic_init();
#endif
#if defined(CONFIG_IOMMU_SBA)
sba_init();
#endif
#if defined(CONFIG_PCI_LBA)
lba_init();
#endif
/* CCIO before any potential subdevices */
#if defined(CONFIG_IOMMU_CCIO)
ccio_init();
#endif
/*
* Need to register Asp & Wax before the EISA adapters for the IRQ
* regions. EISA must come before PCI to be sure it gets IRQ region
* 0.
*/
#if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX)
gsc_init();
#endif
#ifdef CONFIG_EISA
parisc_eisa_init();
#endif
#if defined(CONFIG_HPPB)
hppb_init();
#endif
#if defined(CONFIG_GSC_DINO)
dino_init();
#endif
#ifdef CONFIG_CHASSIS_LCD_LED
register_led_regions(); /* register LED port info in procfs */
#endif
return 0; return 0;
} }
arch_initcall(parisc_init); arch_initcall(parisc_init);

View File

@@ -161,7 +161,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
} }
info.flags = 0; info.flags = 0;
info.low_limit = mm->mmap_legacy_base; info.low_limit = mm->mmap_base;
info.high_limit = mmap_upper_limit(NULL); info.high_limit = mmap_upper_limit(NULL);
return vm_unmapped_area(&info); return vm_unmapped_area(&info);
} }
@@ -181,58 +181,6 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
addr, len, pgoff, flags, DOWN); addr, len, pgoff, flags, DOWN);
} }
static int mmap_is_legacy(void)
{
if (current->personality & ADDR_COMPAT_LAYOUT)
return 1;
/* parisc stack always grows up - so a unlimited stack should
* not be an indicator to use the legacy memory layout.
* if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
* return 1;
*/
return sysctl_legacy_va_layout;
}
static unsigned long mmap_rnd(void)
{
unsigned long rnd = 0;
if (current->flags & PF_RANDOMIZE)
rnd = get_random_u32() & MMAP_RND_MASK;
return rnd << PAGE_SHIFT;
}
unsigned long arch_mmap_rnd(void)
{
return (get_random_u32() & MMAP_RND_MASK) << PAGE_SHIFT;
}
static unsigned long mmap_legacy_base(void)
{
return TASK_UNMAPPED_BASE + mmap_rnd();
}
/*
* This function, called very early during the creation of a new
* process VM image, sets up which VM layout function to use:
*/
void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
{
mm->mmap_legacy_base = mmap_legacy_base();
mm->mmap_base = mmap_upper_limit(rlim_stack);
if (mmap_is_legacy()) {
mm->mmap_base = mm->mmap_legacy_base;
mm->get_unmapped_area = arch_get_unmapped_area;
} else {
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
}
asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long fd, unsigned long prot, unsigned long flags, unsigned long fd,
unsigned long pgoff) unsigned long pgoff)

View File

@@ -335,9 +335,6 @@ static void default_trap(int code, struct pt_regs *regs)
show_regs(regs); show_regs(regs);
} }
void (*cpu_lpmc) (int code, struct pt_regs *regs) __read_mostly = default_trap;
static void transfer_pim_to_trap_frame(struct pt_regs *regs) static void transfer_pim_to_trap_frame(struct pt_regs *regs)
{ {
register int i; register int i;
@@ -557,7 +554,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
flush_cache_all(); flush_cache_all();
flush_tlb_all(); flush_tlb_all();
cpu_lpmc(5, regs); default_trap(code, regs);
return; return;
case PARISC_ITLB_TRAP: case PARISC_ITLB_TRAP:

View File

@@ -338,25 +338,24 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
: "r19", "r20", "r21", "r22", "r1" ); : "r19", "r20", "r21", "r22", "r1" );
#else #else
{ {
unsigned long valh = (val >> 32), vall = (val & 0xffffffffl);
__asm__ __volatile__ ( __asm__ __volatile__ (
" mtsp %4, %%sr1\n" " mtsp %3, %%sr1\n"
" zdep %2, 29, 2, %%r19\n" " zdep %R1, 29, 2, %%r19\n"
" dep %%r0, 31, 2, %3\n" " dep %%r0, 31, 2, %2\n"
" mtsar %%r19\n" " mtsar %%r19\n"
" zvdepi -2, 32, %%r19\n" " zvdepi -2, 32, %%r19\n"
"1: ldw 0(%%sr1,%3),%%r20\n" "1: ldw 0(%%sr1,%2),%%r20\n"
"2: ldw 8(%%sr1,%3),%%r21\n" "2: ldw 8(%%sr1,%2),%%r21\n"
" vshd %1, %2, %%r1\n" " vshd %1, %R1, %%r1\n"
" vshd %%r0, %1, %1\n" " vshd %%r0, %1, %1\n"
" vshd %2, %%r0, %2\n" " vshd %R1, %%r0, %R1\n"
" and %%r20, %%r19, %%r20\n" " and %%r20, %%r19, %%r20\n"
" andcm %%r21, %%r19, %%r21\n" " andcm %%r21, %%r19, %%r21\n"
" or %1, %%r20, %1\n" " or %1, %%r20, %1\n"
" or %2, %%r21, %2\n" " or %R1, %%r21, %R1\n"
"3: stw %1,0(%%sr1,%3)\n" "3: stw %1,0(%%sr1,%2)\n"
"4: stw %%r1,4(%%sr1,%3)\n" "4: stw %%r1,4(%%sr1,%2)\n"
"5: stw %2,8(%%sr1,%3)\n" "5: stw %R1,8(%%sr1,%2)\n"
"6: \n" "6: \n"
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 6b) ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 6b)
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 6b) ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 6b)
@@ -364,7 +363,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(4b, 6b) ASM_EXCEPTIONTABLE_ENTRY_EFAULT(4b, 6b)
ASM_EXCEPTIONTABLE_ENTRY_EFAULT(5b, 6b) ASM_EXCEPTIONTABLE_ENTRY_EFAULT(5b, 6b)
: "+r" (ret) : "+r" (ret)
: "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr) : "r" (val), "r" (regs->ior), "r" (regs->isr)
: "r19", "r20", "r21", "r1" ); : "r19", "r20", "r21", "r1" );
} }
#endif #endif

9
arch/parisc/net/Makefile Normal file
View File

@@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_BPF_JIT) += bpf_jit_core.o
ifeq ($(CONFIG_64BIT),y)
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp64.o
else
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp32.o
endif

479
arch/parisc/net/bpf_jit.h Normal file
View File

@@ -0,0 +1,479 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Common functionality for PARISC32 and PARISC64 BPF JIT compilers
*
* Copyright (c) 2023 Helge Deller <deller@gmx.de>
*
*/
#ifndef _BPF_JIT_H
#define _BPF_JIT_H
#include <linux/bpf.h>
#include <linux/filter.h>
#include <asm/cacheflush.h>
#define HPPA_JIT_DEBUG 0
#define HPPA_JIT_REBOOT 0
#define HPPA_JIT_DUMP 0
#define OPTIMIZE_HPPA 1 /* enable some asm optimizations */
// echo 1 > /proc/sys/net/core/bpf_jit_enable
#define HPPA_R(nr) nr /* use HPPA register #nr */
enum {
HPPA_REG_ZERO = 0, /* The constant value 0 */
HPPA_REG_R1 = 1, /* used for addil */
HPPA_REG_RP = 2, /* Return address */
HPPA_REG_ARG7 = 19, /* ARG4-7 used in 64-bit ABI */
HPPA_REG_ARG6 = 20,
HPPA_REG_ARG5 = 21,
HPPA_REG_ARG4 = 22,
HPPA_REG_ARG3 = 23, /* ARG0-3 in 32- and 64-bit ABI */
HPPA_REG_ARG2 = 24,
HPPA_REG_ARG1 = 25,
HPPA_REG_ARG0 = 26,
HPPA_REG_GP = 27, /* Global pointer */
HPPA_REG_RET0 = 28, /* Return value, HI in 32-bit */
HPPA_REG_RET1 = 29, /* Return value, LOW in 32-bit */
HPPA_REG_SP = 30, /* Stack pointer */
HPPA_REG_R31 = 31,
#ifdef CONFIG_64BIT
HPPA_REG_TCC = 3,
HPPA_REG_TCC_SAVED = 4,
HPPA_REG_TCC_IN_INIT = HPPA_REG_R31,
#else
HPPA_REG_TCC = 18,
HPPA_REG_TCC_SAVED = 17,
HPPA_REG_TCC_IN_INIT = HPPA_REG_R31,
#endif
HPPA_REG_T0 = HPPA_REG_R1, /* Temporaries */
HPPA_REG_T1 = HPPA_REG_R31,
HPPA_REG_T2 = HPPA_REG_ARG4,
#ifndef CONFIG_64BIT
HPPA_REG_T3 = HPPA_REG_ARG5, /* not used in 64-bit */
HPPA_REG_T4 = HPPA_REG_ARG6,
HPPA_REG_T5 = HPPA_REG_ARG7,
#endif
};
struct hppa_jit_context {
struct bpf_prog *prog;
u32 *insns; /* HPPA insns */
int ninsns;
int reg_seen_collect;
int reg_seen;
int body_len;
int epilogue_offset;
int prologue_len;
int *offset; /* BPF to HPPA */
};
#define REG_SET_SEEN(ctx, nr) { if (ctx->reg_seen_collect) ctx->reg_seen |= BIT(nr); }
#define REG_SET_SEEN_ALL(ctx) { if (ctx->reg_seen_collect) ctx->reg_seen = -1; }
#define REG_FORCE_SEEN(ctx, nr) { ctx->reg_seen |= BIT(nr); }
#define REG_WAS_SEEN(ctx, nr) (ctx->reg_seen & BIT(nr))
#define REG_ALL_SEEN(ctx) (ctx->reg_seen == -1)
#define HPPA_INSN_SIZE 4 /* bytes per HPPA asm instruction */
#define REG_SIZE REG_SZ /* bytes per native "long" word */
/* subtract hppa displacement on branches which is .+8 */
#define HPPA_BRANCH_DISPLACEMENT 2 /* instructions */
/* asm statement indicator to execute delay slot */
#define EXEC_NEXT_INSTR 0
#define NOP_NEXT_INSTR 1
#define im11(val) (((u32)(val)) & 0x07ff)
#define hppa_ldil(addr, reg) \
hppa_t5_insn(0x08, reg, ((u32)(addr)) >> 11) /* ldil im21,reg */
#define hppa_addil(addr, reg) \
hppa_t5_insn(0x0a, reg, ((u32)(addr)) >> 11) /* addil im21,reg -> result in gr1 */
#define hppa_ldo(im14, reg, target) \
hppa_t1_insn(0x0d, reg, target, im14) /* ldo val14(reg),target */
#define hppa_ldi(im14, reg) \
hppa_ldo(im14, HPPA_REG_ZERO, reg) /* ldi val14,reg */
#define hppa_or(reg1, reg2, target) \
hppa_t6_insn(0x02, reg2, reg1, 0, 0, 0x09, target) /* or reg1,reg2,target */
#define hppa_or_cond(reg1, reg2, cond, f, target) \
hppa_t6_insn(0x02, reg2, reg1, cond, f, 0x09, target)
#define hppa_and(reg1, reg2, target) \
hppa_t6_insn(0x02, reg2, reg1, 0, 0, 0x08, target) /* and reg1,reg2,target */
#define hppa_and_cond(reg1, reg2, cond, f, target) \
hppa_t6_insn(0x02, reg2, reg1, cond, f, 0x08, target)
#define hppa_xor(reg1, reg2, target) \
hppa_t6_insn(0x02, reg2, reg1, 0, 0, 0x0a, target) /* xor reg1,reg2,target */
#define hppa_add(reg1, reg2, target) \
hppa_t6_insn(0x02, reg2, reg1, 0, 0, 0x18, target) /* add reg1,reg2,target */
#define hppa_addc(reg1, reg2, target) \
hppa_t6_insn(0x02, reg2, reg1, 0, 0, 0x1c, target) /* add,c reg1,reg2,target */
#define hppa_sub(reg1, reg2, target) \
hppa_t6_insn(0x02, reg2, reg1, 0, 0, 0x10, target) /* sub reg1,reg2,target */
#define hppa_subb(reg1, reg2, target) \
hppa_t6_insn(0x02, reg2, reg1, 0, 0, 0x14, target) /* sub,b reg1,reg2,target */
#define hppa_nop() \
hppa_or(0,0,0) /* nop: or 0,0,0 */
#define hppa_addi(val11, reg, target) \
hppa_t7_insn(0x2d, reg, target, val11) /* addi im11,reg,target */
#define hppa_subi(val11, reg, target) \
hppa_t7_insn(0x25, reg, target, val11) /* subi im11,reg,target */
#define hppa_copy(reg, target) \
hppa_or(reg, HPPA_REG_ZERO, target) /* copy reg,target */
#define hppa_ldw(val14, reg, target) \
hppa_t1_insn(0x12, reg, target, val14) /* ldw im14(reg),target */
#define hppa_ldb(val14, reg, target) \
hppa_t1_insn(0x10, reg, target, val14) /* ldb im14(reg),target */
#define hppa_ldh(val14, reg, target) \
hppa_t1_insn(0x11, reg, target, val14) /* ldh im14(reg),target */
#define hppa_stw(reg, val14, base) \
hppa_t1_insn(0x1a, base, reg, val14) /* stw reg,im14(base) */
#define hppa_stb(reg, val14, base) \
hppa_t1_insn(0x18, base, reg, val14) /* stb reg,im14(base) */
#define hppa_sth(reg, val14, base) \
hppa_t1_insn(0x19, base, reg, val14) /* sth reg,im14(base) */
#define hppa_stwma(reg, val14, base) \
hppa_t1_insn(0x1b, base, reg, val14) /* stw,ma reg,im14(base) */
#define hppa_bv(reg, base, nop) \
hppa_t11_insn(0x3a, base, reg, 0x06, 0, nop) /* bv(,n) reg(base) */
#define hppa_be(offset, base) \
hppa_t12_insn(0x38, base, offset, 0x00, 1) /* be,n offset(0,base) */
#define hppa_be_l(offset, base, nop) \
hppa_t12_insn(0x39, base, offset, 0x00, nop) /* ble(,nop) offset(0,base) */
#define hppa_mtctl(reg, cr) \
hppa_t21_insn(0x00, cr, reg, 0xc2, 0) /* mtctl reg,cr */
#define hppa_mtsar(reg) \
hppa_mtctl(reg, 11) /* mtsar reg */
#define hppa_zdep(r, p, len, target) \
hppa_t10_insn(0x35, target, r, 0, 2, p, len) /* zdep r,a,b,t */
#define hppa_shl(r, len, target) \
hppa_zdep(r, len, len, lo(rd))
#define hppa_depwz(r, p, len, target) \
hppa_t10_insn(0x35, target, r, 0, 3, 31-(p), 32-(len)) /* depw,z r,p,len,ret1 */
#define hppa_depwz_sar(reg, target) \
hppa_t1_insn(0x35, target, reg, 0) /* depw,z reg,sar,32,target */
#define hppa_shrpw_sar(reg, target) \
hppa_t10_insn(0x34, reg, 0, 0, 0, 0, target) /* shrpw r0,reg,sar,target */
#define hppa_shrpw(r1, r2, p, target) \
hppa_t10_insn(0x34, r2, r1, 0, 2, 31-(p), target) /* shrpw r1,r2,p,target */
#define hppa_shd(r1, r2, p, target) \
hppa_t10_insn(0x34, r2, r1, 0, 2, 31-(p), target) /* shrpw r1,r2,p,tarfer */
#define hppa_extrws_sar(reg, target) \
hppa_t10_insn(0x34, reg, target, 0, 5, 0, 0) /* extrw,s reg,sar,32,ret0 */
#define hppa_extrws(reg, p, len, target) \
hppa_t10_insn(0x34, reg, target, 0, 7, p, len) /* extrw,s reg,p,len,target */
#define hppa_extru(r, p, len, target) \
hppa_t10_insn(0x34, r, target, 0, 6, p, 32-(len))
#define hppa_shr(r, len, target) \
hppa_extru(r, 31-(len), 32-(len), target)
#define hppa_bl(imm17, rp) \
hppa_t12_insn(0x3a, rp, imm17, 0x00, 1) /* bl,n target_addr,rp */
#define hppa_sh2add(r1, r2, target) \
hppa_t6_insn(0x02, r2, r1, 0, 0, 0x1a, target) /* sh2add r1,r2,target */
#define hppa_combt(r1, r2, target_addr, condition, nop) \
hppa_t11_insn(IS_ENABLED(CONFIG_64BIT) ? 0x27 : 0x20, \
r2, r1, condition, target_addr, nop) /* combt,cond,n r1,r2,addr */
#define hppa_beq(r1, r2, target_addr) \
hppa_combt(r1, r2, target_addr, 1, NOP_NEXT_INSTR)
#define hppa_blt(r1, r2, target_addr) \
hppa_combt(r1, r2, target_addr, 2, NOP_NEXT_INSTR)
#define hppa_ble(r1, r2, target_addr) \
hppa_combt(r1, r2, target_addr, 3, NOP_NEXT_INSTR)
#define hppa_bltu(r1, r2, target_addr) \
hppa_combt(r1, r2, target_addr, 4, NOP_NEXT_INSTR)
#define hppa_bleu(r1, r2, target_addr) \
hppa_combt(r1, r2, target_addr, 5, NOP_NEXT_INSTR)
#define hppa_combf(r1, r2, target_addr, condition, nop) \
hppa_t11_insn(IS_ENABLED(CONFIG_64BIT) ? 0x2f : 0x22, \
r2, r1, condition, target_addr, nop) /* combf,cond,n r1,r2,addr */
#define hppa_bne(r1, r2, target_addr) \
hppa_combf(r1, r2, target_addr, 1, NOP_NEXT_INSTR)
#define hppa_bge(r1, r2, target_addr) \
hppa_combf(r1, r2, target_addr, 2, NOP_NEXT_INSTR)
#define hppa_bgt(r1, r2, target_addr) \
hppa_combf(r1, r2, target_addr, 3, NOP_NEXT_INSTR)
#define hppa_bgeu(r1, r2, target_addr) \
hppa_combf(r1, r2, target_addr, 4, NOP_NEXT_INSTR)
#define hppa_bgtu(r1, r2, target_addr) \
hppa_combf(r1, r2, target_addr, 5, NOP_NEXT_INSTR)
/* 64-bit instructions */
#ifdef CONFIG_64BIT
#define hppa64_ldd_reg(reg, b, target) \
hppa_t10_insn(0x03, b, reg, 0, 0, 3<<1, target)
#define hppa64_ldd_im5(im5, b, target) \
hppa_t10_insn(0x03, b, low_sign_unext(im5,5), 0, 1<<2, 3<<1, target)
#define hppa64_ldd_im16(im16, b, target) \
hppa_t10_insn(0x14, b, target, 0, 0, 0, 0) | re_assemble_16(im16)
#define hppa64_std_im5(src, im5, b) \
hppa_t10_insn(0x03, b, src, 0, 1<<2, 0xB<<1, low_sign_unext(im5,5))
#define hppa64_std_im16(src, im16, b) \
hppa_t10_insn(0x1c, b, src, 0, 0, 0, 0) | re_assemble_16(im16)
#define hppa64_bl_long(offs22) \
hppa_t12_L_insn(0x3a, offs22, 1)
#define hppa64_mtsarcm(reg) \
hppa_t21_insn(0x00, 11, reg, 0xc6, 0)
#define hppa64_shrpd_sar(reg, target) \
hppa_t10_insn(0x34, reg, 0, 0, 0, 1<<4, target)
#define hppa64_shladd(r1, sa, r2, target) \
hppa_t6_insn(0x02, r2, r1, 0, 0, 1<<4|1<<3|sa, target)
#define hppa64_depdz_sar(reg, target) \
hppa_t21_insn(0x35, target, reg, 3<<3, 0)
#define hppa_extrd_sar(reg, target, se) \
hppa_t10_insn(0x34, reg, target, 0, 0, 0, 0) | 2<<11 | (se&1)<<10 | 1<<9 | 1<<8
#define hppa64_bve_l_rp(base) \
(0x3a << 26) | (base << 21) | 0xf000
#define hppa64_permh_3210(r, target) \
(0x3e << 26) | (r << 21) | (r << 16) | (target) | 0x00006900
#define hppa64_hshl(r, sa, target) \
(0x3e << 26) | (0 << 21) | (r << 16) | (sa << 6) | (target) | 0x00008800
#define hppa64_hshr_u(r, sa, target) \
(0x3e << 26) | (r << 21) | (0 << 16) | (sa << 6) | (target) | 0x0000c800
#endif
struct hppa_jit_data {
struct bpf_binary_header *header;
u8 *image;
struct hppa_jit_context ctx;
};
static inline void bpf_fill_ill_insns(void *area, unsigned int size)
{
memset(area, 0, size);
}
static inline void bpf_flush_icache(void *start, void *end)
{
flush_icache_range((unsigned long)start, (unsigned long)end);
}
/* Emit a 4-byte HPPA instruction. */
static inline void emit(const u32 insn, struct hppa_jit_context *ctx)
{
if (ctx->insns) {
ctx->insns[ctx->ninsns] = insn;
}
ctx->ninsns++;
}
static inline int epilogue_offset(struct hppa_jit_context *ctx)
{
int to = ctx->epilogue_offset, from = ctx->ninsns;
return (to - from);
}
/* Return -1 or inverted cond. */
static inline int invert_bpf_cond(u8 cond)
{
switch (cond) {
case BPF_JEQ:
return BPF_JNE;
case BPF_JGT:
return BPF_JLE;
case BPF_JLT:
return BPF_JGE;
case BPF_JGE:
return BPF_JLT;
case BPF_JLE:
return BPF_JGT;
case BPF_JNE:
return BPF_JEQ;
case BPF_JSGT:
return BPF_JSLE;
case BPF_JSLT:
return BPF_JSGE;
case BPF_JSGE:
return BPF_JSLT;
case BPF_JSLE:
return BPF_JSGT;
}
return -1;
}
static inline signed long hppa_offset(int insn, int off, struct hppa_jit_context *ctx)
{
signed long from, to;
off++; /* BPF branch is from PC+1 */
from = (insn > 0) ? ctx->offset[insn - 1] : 0;
to = (insn + off > 0) ? ctx->offset[insn + off - 1] : 0;
return (to - from);
}
/* does the signed value fits into a given number of bits ? */
static inline int check_bits_int(signed long val, int bits)
{
return ((val >= 0) && ((val >> bits) == 0)) ||
((val < 0) && (((~((u32)val)) >> (bits-1)) == 0));
}
/* can the signed value be used in relative code ? */
static inline int relative_bits_ok(signed long val, int bits)
{
return ((val >= 0) && (val < (1UL << (bits-1)))) || /* XXX */
((val < 0) && (((~((unsigned long)val)) >> (bits-1)) == 0)
&& (val & (1UL << (bits-1))));
}
/* can the signed value be used in relative branches ? */
static inline int relative_branch_ok(signed long val, int bits)
{
return ((val >= 0) && (val < (1UL << (bits-2)))) || /* XXX */
((val < 0) && (((~((unsigned long)val)) < (1UL << (bits-2))))
&& (val & (1UL << (bits-1))));
}
#define is_5b_int(val) check_bits_int(val, 5)
static inline unsigned sign_unext(unsigned x, unsigned len)
{
unsigned len_ones;
len_ones = (1 << len) - 1;
return x & len_ones;
}
static inline unsigned low_sign_unext(unsigned x, unsigned len)
{
unsigned temp;
unsigned sign;
sign = (x >> (len-1)) & 1;
temp = sign_unext (x, len-1);
return (temp << 1) | sign;
}
static inline unsigned re_assemble_12(unsigned as12)
{
return (( (as12 & 0x800) >> 11)
| ((as12 & 0x400) >> (10 - 2))
| ((as12 & 0x3ff) << (1 + 2)));
}
static inline unsigned re_assemble_14(unsigned as14)
{
return (( (as14 & 0x1fff) << 1)
| ((as14 & 0x2000) >> 13));
}
#ifdef CONFIG_64BIT
static inline unsigned re_assemble_16(unsigned as16)
{
unsigned s, t;
/* Unusual 16-bit encoding, for wide mode only. */
t = (as16 << 1) & 0xffff;
s = (as16 & 0x8000);
return (t ^ s ^ (s >> 1)) | (s >> 15);
}
#endif
static inline unsigned re_assemble_17(unsigned as17)
{
return (( (as17 & 0x10000) >> 16)
| ((as17 & 0x0f800) << (16 - 11))
| ((as17 & 0x00400) >> (10 - 2))
| ((as17 & 0x003ff) << (1 + 2)));
}
static inline unsigned re_assemble_21(unsigned as21)
{
return (( (as21 & 0x100000) >> 20)
| ((as21 & 0x0ffe00) >> 8)
| ((as21 & 0x000180) << 7)
| ((as21 & 0x00007c) << 14)
| ((as21 & 0x000003) << 12));
}
static inline unsigned re_assemble_22(unsigned as22)
{
return (( (as22 & 0x200000) >> 21)
| ((as22 & 0x1f0000) << (21 - 16))
| ((as22 & 0x00f800) << (16 - 11))
| ((as22 & 0x000400) >> (10 - 2))
| ((as22 & 0x0003ff) << (1 + 2)));
}
/* Various HPPA instruction formats. */
/* see https://parisc.wiki.kernel.org/images-parisc/6/68/Pa11_acd.pdf, appendix C */
static inline u32 hppa_t1_insn(u8 opcode, u8 b, u8 r, s16 im14)
{
return ((opcode << 26) | (b << 21) | (r << 16) | re_assemble_14(im14));
}
static inline u32 hppa_t5_insn(u8 opcode, u8 tr, u32 val21)
{
return ((opcode << 26) | (tr << 21) | re_assemble_21(val21));
}
static inline u32 hppa_t6_insn(u8 opcode, u8 r2, u8 r1, u8 c, u8 f, u8 ext6, u16 t)
{
return ((opcode << 26) | (r2 << 21) | (r1 << 16) | (c << 13) | (f << 12) |
(ext6 << 6) | t);
}
/* 7. Arithmetic immediate */
static inline u32 hppa_t7_insn(u8 opcode, u8 r, u8 t, u32 im11)
{
return ((opcode << 26) | (r << 21) | (t << 16) | low_sign_unext(im11, 11));
}
/* 10. Shift instructions */
static inline u32 hppa_t10_insn(u8 opcode, u8 r2, u8 r1, u8 c, u8 ext3, u8 cp, u8 t)
{
return ((opcode << 26) | (r2 << 21) | (r1 << 16) | (c << 13) |
(ext3 << 10) | (cp << 5) | t);
}
/* 11. Conditional branch instructions */
static inline u32 hppa_t11_insn(u8 opcode, u8 r2, u8 r1, u8 c, u32 w, u8 nop)
{
u32 ra = re_assemble_12(w);
// ra = low_sign_unext(w,11) | (w & (1<<10)
return ((opcode << 26) | (r2 << 21) | (r1 << 16) | (c << 13) | (nop << 1) | ra);
}
/* 12. Branch instructions */
static inline u32 hppa_t12_insn(u8 opcode, u8 rp, u32 w, u8 ext3, u8 nop)
{
return ((opcode << 26) | (rp << 21) | (ext3 << 13) | (nop << 1) | re_assemble_17(w));
}
static inline u32 hppa_t12_L_insn(u8 opcode, u32 w, u8 nop)
{
return ((opcode << 26) | (0x05 << 13) | (nop << 1) | re_assemble_22(w));
}
/* 21. Move to control register */
static inline u32 hppa_t21_insn(u8 opcode, u8 r2, u8 r1, u8 ext8, u8 t)
{
return ((opcode << 26) | (r2 << 21) | (r1 << 16) | (ext8 << 5) | t);
}
/* Helper functions called by jit code on HPPA32 and HPPA64. */
u64 hppa_div64(u64 div, u64 divisor);
u64 hppa_div64_rem(u64 div, u64 divisor);
/* Helper functions that emit HPPA instructions when possible. */
void bpf_jit_build_prologue(struct hppa_jit_context *ctx);
void bpf_jit_build_epilogue(struct hppa_jit_context *ctx);
int bpf_jit_emit_insn(const struct bpf_insn *insn, struct hppa_jit_context *ctx,
bool extra_pass);
#endif /* _BPF_JIT_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,201 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Common functionality for HPPA32 and HPPA64 BPF JIT compilers
*
* Copyright (c) 2023 Helge Deller <deller@gmx.de>
*
*/
#include <linux/bpf.h>
#include <linux/filter.h>
#include "bpf_jit.h"
/* Number of iterations to try until offsets converge. */
#define NR_JIT_ITERATIONS 35
static int build_body(struct hppa_jit_context *ctx, bool extra_pass, int *offset)
{
const struct bpf_prog *prog = ctx->prog;
int i;
ctx->reg_seen_collect = true;
for (i = 0; i < prog->len; i++) {
const struct bpf_insn *insn = &prog->insnsi[i];
int ret;
ret = bpf_jit_emit_insn(insn, ctx, extra_pass);
/* BPF_LD | BPF_IMM | BPF_DW: skip the next instruction. */
if (ret > 0)
i++;
if (offset)
offset[i] = ctx->ninsns;
if (ret < 0)
return ret;
}
ctx->reg_seen_collect = false;
return 0;
}
bool bpf_jit_needs_zext(void)
{
return true;
}
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
{
unsigned int prog_size = 0, extable_size = 0;
bool tmp_blinded = false, extra_pass = false;
struct bpf_prog *tmp, *orig_prog = prog;
int pass = 0, prev_ninsns = 0, prologue_len, i;
struct hppa_jit_data *jit_data;
struct hppa_jit_context *ctx;
if (!prog->jit_requested)
return orig_prog;
tmp = bpf_jit_blind_constants(prog);
if (IS_ERR(tmp))
return orig_prog;
if (tmp != prog) {
tmp_blinded = true;
prog = tmp;
}
jit_data = prog->aux->jit_data;
if (!jit_data) {
jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL);
if (!jit_data) {
prog = orig_prog;
goto out;
}
prog->aux->jit_data = jit_data;
}
ctx = &jit_data->ctx;
if (ctx->offset) {
extra_pass = true;
prog_size = sizeof(*ctx->insns) * ctx->ninsns;
goto skip_init_ctx;
}
ctx->prog = prog;
ctx->offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
if (!ctx->offset) {
prog = orig_prog;
goto out_offset;
}
for (i = 0; i < prog->len; i++) {
prev_ninsns += 20;
ctx->offset[i] = prev_ninsns;
}
for (i = 0; i < NR_JIT_ITERATIONS; i++) {
pass++;
ctx->ninsns = 0;
if (build_body(ctx, extra_pass, ctx->offset)) {
prog = orig_prog;
goto out_offset;
}
ctx->body_len = ctx->ninsns;
bpf_jit_build_prologue(ctx);
ctx->prologue_len = ctx->ninsns - ctx->body_len;
ctx->epilogue_offset = ctx->ninsns;
bpf_jit_build_epilogue(ctx);
if (ctx->ninsns == prev_ninsns) {
if (jit_data->header)
break;
/* obtain the actual image size */
extable_size = prog->aux->num_exentries *
sizeof(struct exception_table_entry);
prog_size = sizeof(*ctx->insns) * ctx->ninsns;
jit_data->header =
bpf_jit_binary_alloc(prog_size + extable_size,
&jit_data->image,
sizeof(u32),
bpf_fill_ill_insns);
if (!jit_data->header) {
prog = orig_prog;
goto out_offset;
}
ctx->insns = (u32 *)jit_data->image;
/*
* Now, when the image is allocated, the image can
* potentially shrink more (auipc/jalr -> jal).
*/
}
prev_ninsns = ctx->ninsns;
}
if (i == NR_JIT_ITERATIONS) {
pr_err("bpf-jit: image did not converge in <%d passes!\n", i);
if (jit_data->header)
bpf_jit_binary_free(jit_data->header);
prog = orig_prog;
goto out_offset;
}
if (extable_size)
prog->aux->extable = (void *)ctx->insns + prog_size;
skip_init_ctx:
pass++;
ctx->ninsns = 0;
bpf_jit_build_prologue(ctx);
if (build_body(ctx, extra_pass, NULL)) {
bpf_jit_binary_free(jit_data->header);
prog = orig_prog;
goto out_offset;
}
bpf_jit_build_epilogue(ctx);
if (HPPA_JIT_DEBUG || bpf_jit_enable > 1) {
if (HPPA_JIT_DUMP)
bpf_jit_dump(prog->len, prog_size, pass, ctx->insns);
if (HPPA_JIT_REBOOT)
{ extern int machine_restart(char *); machine_restart(""); }
}
prog->bpf_func = (void *)ctx->insns;
prog->jited = 1;
prog->jited_len = prog_size;
bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
if (!prog->is_func || extra_pass) {
bpf_jit_binary_lock_ro(jit_data->header);
prologue_len = ctx->epilogue_offset - ctx->body_len;
for (i = 0; i < prog->len; i++)
ctx->offset[i] += prologue_len;
bpf_prog_fill_jited_linfo(prog, ctx->offset);
out_offset:
kfree(ctx->offset);
kfree(jit_data);
prog->aux->jit_data = NULL;
}
out:
if (HPPA_JIT_REBOOT)
{ extern int machine_restart(char *); machine_restart(""); }
if (tmp_blinded)
bpf_jit_prog_release_other(prog, prog == orig_prog ?
tmp : orig_prog);
return prog;
}
u64 hppa_div64(u64 div, u64 divisor)
{
div = div64_u64(div, divisor);
return div;
}
u64 hppa_div64_rem(u64 div, u64 divisor)
{
u64 rem;
div64_u64_rem(div, divisor, &rem);
return rem;
}

View File

@@ -100,8 +100,9 @@ config SUPERIO
config CHASSIS_LCD_LED config CHASSIS_LCD_LED
bool "Chassis LCD and LED support" bool "Chassis LCD and LED support"
depends on LEDS_CLASS=y
default y default y
select VM_EVENT_COUNTERS select LEDS_TRIGGERS
help help
Say Y here if you want to enable support for the Heartbeat, Say Y here if you want to enable support for the Heartbeat,
Disk/Network activities LEDs on some PA-RISC machines, Disk/Network activities LEDs on some PA-RISC machines,

View File

@@ -1,25 +1,27 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# #
# Makefile for most of the non-PCI devices in PA-RISC machines # Makefile PCI and non-PCI devices in PA-RISC machines
#
# Keep the order below, e.g.
# - ccio before any potential subdevices
# - gsc is required before lasi and wax
# - asp and wax before the EISA adapters for the IRQ regions
# - EISA must come before PCI to be sure it gets IRQ region
# #
# I/O SAPIC is also on IA64 platforms.
# The two could be merged into a common source some day.
obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_IOSAPIC) += iosapic.o
obj-$(CONFIG_IOMMU_SBA) += sba_iommu.o obj-$(CONFIG_IOMMU_SBA) += sba_iommu.o
obj-$(CONFIG_PCI_LBA) += lba_pci.o obj-$(CONFIG_PCI_LBA) += lba_pci.o
obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o
obj-$(CONFIG_GSC) += gsc.o obj-$(CONFIG_GSC) += gsc.o
obj-$(CONFIG_HPPB) += hppb.o
obj-$(CONFIG_GSC_DINO) += dino.o
obj-$(CONFIG_GSC_LASI) += lasi.o asp.o obj-$(CONFIG_GSC_LASI) += lasi.o asp.o
obj-$(CONFIG_GSC_WAX) += wax.o obj-$(CONFIG_GSC_WAX) += wax.o
obj-$(CONFIG_EISA) += eisa.o eisa_enumerator.o eisa_eeprom.o obj-$(CONFIG_EISA) += eisa.o eisa_enumerator.o eisa_eeprom.o
obj-$(CONFIG_HPPB) += hppb.o
obj-$(CONFIG_GSC_DINO) += dino.o
obj-$(CONFIG_SUPERIO) += superio.o obj-$(CONFIG_SUPERIO) += superio.o
obj-$(CONFIG_CHASSIS_LCD_LED) += led.o obj-$(CONFIG_CHASSIS_LCD_LED) += led.o
obj-$(CONFIG_PDC_STABLE) += pdc_stable.o obj-$(CONFIG_PDC_STABLE) += pdc_stable.o
obj-y += power.o obj-y += power.o

View File

@@ -4,7 +4,7 @@
* *
* (c) Copyright 2000 The Puffin Group Inc. * (c) Copyright 2000 The Puffin Group Inc.
* *
* by Helge Deller <deller@gmx.de> * (c) 2000-2023 by Helge Deller <deller@gmx.de>
*/ */
#include <linux/errno.h> #include <linux/errno.h>
@@ -118,9 +118,16 @@ static const struct parisc_device_id asp_tbl[] __initconst = {
{ HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00070 }, { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00070 },
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(parisc, asp_tbl);
struct parisc_driver asp_driver __refdata = { static struct parisc_driver asp_driver __refdata = {
.name = "asp", .name = "asp",
.id_table = asp_tbl, .id_table = asp_tbl,
.probe = asp_init_chip, .probe = asp_init_chip,
}; };
static int __init asp_init(void)
{
return register_parisc_driver(&asp_driver);
}
arch_initcall(asp_init);

View File

@@ -8,18 +8,10 @@
** (c) Copyright 2000 Ryan Bradetich ** (c) Copyright 2000 Ryan Bradetich
** (c) Copyright 2000 Hewlett-Packard Company ** (c) Copyright 2000 Hewlett-Packard Company
** **
**
**
** "Real Mode" operation refers to U2/Uturn chip operation. ** "Real Mode" operation refers to U2/Uturn chip operation.
** U2/Uturn were designed to perform coherency checks w/o using ** U2/Uturn were designed to perform coherency checks w/o using
** the I/O MMU - basically what x86 does. ** the I/O MMU - basically what x86 does.
** **
** Philipp Rumpf has a "Real Mode" driver for PCX-W machines at:
** CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc
** cvs -z3 co linux/arch/parisc/kernel/dma-rm.c
**
** I've rewritten his code to work under TPG's tree. See ccio-rm-dma.c.
**
** Drawbacks of using Real Mode are: ** Drawbacks of using Real Mode are:
** o outbound DMA is slower - U2 won't prefetch data (GSC+ XQL signal). ** o outbound DMA is slower - U2 won't prefetch data (GSC+ XQL signal).
** o Inbound DMA less efficient - U2 can't use DMA_FAST attribute. ** o Inbound DMA less efficient - U2 can't use DMA_FAST attribute.
@@ -71,8 +63,6 @@
#undef CCIO_COLLECT_STATS #undef CCIO_COLLECT_STATS
#endif #endif
#include <asm/runway.h> /* for proc_runway_root */
#ifdef DEBUG_CCIO_INIT #ifdef DEBUG_CCIO_INIT
#define DBG_INIT(x...) printk(x) #define DBG_INIT(x...) printk(x)
#else #else
@@ -1567,11 +1557,16 @@ static int __init ccio_probe(struct parisc_device *dev)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
if (ioc_count == 0) { if (ioc_count == 0) {
proc_create_single(MODULE_NAME, 0, proc_runway_root, struct proc_dir_entry *runway;
runway = proc_mkdir("bus/runway", NULL);
if (runway) {
proc_create_single(MODULE_NAME, 0, runway,
ccio_proc_info); ccio_proc_info);
proc_create_single(MODULE_NAME"-bitmap", 0, proc_runway_root, proc_create_single(MODULE_NAME"-bitmap", 0, runway,
ccio_proc_bitmap_info); ccio_proc_bitmap_info);
} }
}
#endif #endif
ioc_count++; ioc_count++;
return 0; return 0;
@@ -1582,8 +1577,8 @@ static int __init ccio_probe(struct parisc_device *dev)
* *
* Register this driver. * Register this driver.
*/ */
void __init ccio_init(void) static int __init ccio_init(void)
{ {
register_parisc_driver(&ccio_driver); return register_parisc_driver(&ccio_driver);
} }
arch_initcall(ccio_init);

View File

@@ -1084,8 +1084,8 @@ static struct parisc_driver dino_driver __refdata = {
* This is the only routine which is NOT static. * This is the only routine which is NOT static.
* Must be called exactly once before pci_init(). * Must be called exactly once before pci_init().
*/ */
void __init dino_init(void) static int __init dino_init(void)
{ {
register_parisc_driver(&dino_driver); return register_parisc_driver(&dino_driver);
} }
arch_initcall(dino_init);

View File

@@ -400,10 +400,11 @@ static struct parisc_driver eisa_driver __refdata = {
.probe = eisa_probe, .probe = eisa_probe,
}; };
void __init parisc_eisa_init(void) static int __init parisc_eisa_init(void)
{ {
register_parisc_driver(&eisa_driver); return register_parisc_driver(&eisa_driver);
} }
arch_initcall(parisc_eisa_init);
static unsigned int eisa_irq_configured; static unsigned int eisa_irq_configured;

View File

@@ -258,18 +258,3 @@ int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic)
return 0; return 0;
} }
extern struct parisc_driver lasi_driver;
extern struct parisc_driver asp_driver;
extern struct parisc_driver wax_driver;
void __init gsc_init(void)
{
#ifdef CONFIG_GSC_LASI
register_parisc_driver(&lasi_driver);
register_parisc_driver(&asp_driver);
#endif
#ifdef CONFIG_GSC_WAX
register_parisc_driver(&wax_driver);
#endif
}

View File

@@ -98,7 +98,8 @@ static struct parisc_driver hppb_driver __refdata = {
* *
* Register this driver. * Register this driver.
*/ */
void __init hppb_init(void) static int __init hppb_init(void)
{ {
register_parisc_driver(&hppb_driver); return register_parisc_driver(&hppb_driver);
} }
arch_initcall(hppb_init);

View File

@@ -348,13 +348,10 @@ iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
} }
static int __init iosapic_init(void)
void __init iosapic_init(void)
{ {
unsigned long cell = 0; unsigned long cell = 0;
DBG("iosapic_init()\n");
#ifdef __LP64__ #ifdef __LP64__
if (is_pdc_pat()) { if (is_pdc_pat()) {
int status; int status;
@@ -371,7 +368,10 @@ void __init iosapic_init(void)
irt_num_entry = iosapic_load_irt(cell, &irt_cell); irt_num_entry = iosapic_load_irt(cell, &irt_cell);
if (irt_num_entry == 0) if (irt_num_entry == 0)
irt_cell = NULL; /* old PDC w/o iosapic */ irt_cell = NULL; /* old PDC w/o iosapic */
return 0;
} }
arch_initcall(iosapic_init);
/* /*
@@ -890,7 +890,7 @@ iosapic_rd_version(struct iosapic_info *isi)
** o allocate and initialize isi_vector[] ** o allocate and initialize isi_vector[]
** o allocate irq region ** o allocate irq region
*/ */
void *iosapic_register(unsigned long hpa) void *iosapic_register(unsigned long hpa, void __iomem *vaddr)
{ {
struct iosapic_info *isi = NULL; struct iosapic_info *isi = NULL;
struct irt_entry *irte = irt_cell; struct irt_entry *irte = irt_cell;
@@ -919,7 +919,7 @@ void *iosapic_register(unsigned long hpa)
return NULL; return NULL;
} }
isi->addr = ioremap(hpa, 4096); isi->addr = vaddr;
isi->isi_hpa = hpa; isi->isi_hpa = hpa;
isi->isi_version = iosapic_rd_version(isi); isi->isi_version = iosapic_rd_version(isi);
isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;

View File

@@ -17,6 +17,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/reboot.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/hardware.h> #include <asm/hardware.h>
@@ -145,23 +146,19 @@ static void __init lasi_led_init(unsigned long lasi_hpa)
* 1 to PWR_ON_L in the Power Control Register * 1 to PWR_ON_L in the Power Control Register
* *
*/ */
static int lasi_power_off(struct sys_off_data *data)
static unsigned long lasi_power_off_hpa __read_mostly;
static void lasi_power_off(void)
{ {
unsigned long datareg; struct gsc_asic *lasi = data->cb_data;
/* calculate addr of the Power Control Register */ /* Power down the machine via Power Control Register */
datareg = lasi_power_off_hpa + 0x0000C000; gsc_writel(0x02, lasi->hpa + 0x0000C000);
/* Power down the machine */ /* might not be reached: */
gsc_writel(0x02, datareg); return NOTIFY_DONE;
} }
static int __init lasi_init_chip(struct parisc_device *dev) static int __init lasi_init_chip(struct parisc_device *dev)
{ {
extern void (*chassis_power_off)(void);
struct gsc_asic *lasi; struct gsc_asic *lasi;
int ret; int ret;
@@ -212,12 +209,9 @@ static int __init lasi_init_chip(struct parisc_device *dev)
gsc_fixup_irqs(dev, lasi, lasi_choose_irq); gsc_fixup_irqs(dev, lasi, lasi_choose_irq);
/* initialize the power off function */ /* register the LASI power off function */
/* FIXME: Record the LASI HPA for the power off function. This should register_sys_off_handler(SYS_OFF_MODE_POWER_OFF,
* ensure that only the first LASI (the one controlling the power off) SYS_OFF_PRIO_DEFAULT, lasi_power_off, lasi);
* should set the HPA here */
lasi_power_off_hpa = lasi->hpa;
chassis_power_off = lasi_power_off;
return ret; return ret;
} }
@@ -226,9 +220,16 @@ static struct parisc_device_id lasi_tbl[] __initdata = {
{ HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00081 }, { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00081 },
{ 0, } { 0, }
}; };
MODULE_DEVICE_TABLE(parisc, lasi_tbl);
struct parisc_driver lasi_driver __refdata = { static struct parisc_driver lasi_driver __refdata = {
.name = "lasi", .name = "lasi",
.id_table = lasi_tbl, .id_table = lasi_tbl,
.probe = lasi_init_chip, .probe = lasi_init_chip,
}; };
static int __init lasi_init(void)
{
return register_parisc_driver(&lasi_driver);
}
arch_initcall(lasi_init);

View File

@@ -1535,7 +1535,8 @@ lba_driver_probe(struct parisc_device *dev)
} }
/* Tell I/O SAPIC driver we have a IRQ handler/region. */ /* Tell I/O SAPIC driver we have a IRQ handler/region. */
tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE); tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE,
addr + LBA_IOSAPIC_BASE);
/* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't /* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't
** have an IRT entry will get NULL back from iosapic code. ** have an IRT entry will get NULL back from iosapic code.
@@ -1681,10 +1682,11 @@ static struct parisc_driver lba_driver __refdata = {
** One time initialization to let the world know the LBA was found. ** One time initialization to let the world know the LBA was found.
** Must be called exactly once before pci_init(). ** Must be called exactly once before pci_init().
*/ */
void __init lba_init(void) static int __init lba_init(void)
{ {
register_parisc_driver(&lba_driver); return register_parisc_driver(&lba_driver);
} }
arch_initcall(lba_init);
/* /*
** Initialize the IBASE/IMASK registers for LBA (Elroy). ** Initialize the IBASE/IMASK registers for LBA (Elroy).

File diff suppressed because it is too large Load Diff

View File

@@ -121,7 +121,7 @@ module_param(sba_reserve_agpgart, int, 0444);
MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART"); MODULE_PARM_DESC(sba_reserve_agpgart, "Reserve half of IO pdir as AGPGART");
#endif #endif
struct proc_dir_entry *proc_runway_root __ro_after_init; static struct proc_dir_entry *proc_runway_root __ro_after_init;
struct proc_dir_entry *proc_mckinley_root __ro_after_init; struct proc_dir_entry *proc_mckinley_root __ro_after_init;
/************************************ /************************************
@@ -1994,10 +1994,11 @@ static int __init sba_driver_callback(struct parisc_device *dev)
** This is the only routine which is NOT static. ** This is the only routine which is NOT static.
** Must be called exactly once before pci_init(). ** Must be called exactly once before pci_init().
*/ */
void __init sba_init(void) static int __init sba_init(void)
{ {
register_parisc_driver(&sba_driver); return register_parisc_driver(&sba_driver);
} }
arch_initcall(sba_init);
/** /**

View File

@@ -4,7 +4,7 @@
* *
* (c) Copyright 2000 The Puffin Group Inc. * (c) Copyright 2000 The Puffin Group Inc.
* *
* by Helge Deller <deller@gmx.de> * (c) 2000-2023 by Helge Deller <deller@gmx.de>
*/ */
#include <linux/errno.h> #include <linux/errno.h>
@@ -127,8 +127,14 @@ static const struct parisc_device_id wax_tbl[] __initconst = {
MODULE_DEVICE_TABLE(parisc, wax_tbl); MODULE_DEVICE_TABLE(parisc, wax_tbl);
struct parisc_driver wax_driver __refdata = { static struct parisc_driver wax_driver __refdata = {
.name = "wax", .name = "wax",
.id_table = wax_tbl, .id_table = wax_tbl,
.probe = wax_init_chip, .probe = wax_init_chip,
}; };
static int __init wax_init(void)
{
return register_parisc_driver(&wax_driver);
}
arch_initcall(wax_init);

View File

@@ -396,7 +396,10 @@ static int mmap_is_legacy(struct rlimit *rlim_stack)
if (current->personality & ADDR_COMPAT_LAYOUT) if (current->personality & ADDR_COMPAT_LAYOUT)
return 1; return 1;
if (rlim_stack->rlim_cur == RLIM_INFINITY) /* On parisc the stack always grows up - so a unlimited stack should
* not be an indicator to use the legacy memory layout. */
if (rlim_stack->rlim_cur == RLIM_INFINITY &&
!IS_ENABLED(CONFIG_STACK_GROWSUP))
return 1; return 1;
return sysctl_legacy_va_layout; return sysctl_legacy_va_layout;