18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * include/asm-parisc/processor.h 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1994 Linus Torvalds 68c2ecf20Sopenharmony_ci * Copyright (C) 2001 Grant Grundler 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef __ASM_PARISC_PROCESSOR_H 108c2ecf20Sopenharmony_ci#define __ASM_PARISC_PROCESSOR_H 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 138c2ecf20Sopenharmony_ci#include <linux/threads.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <asm/prefetch.h> 168c2ecf20Sopenharmony_ci#include <asm/hardware.h> 178c2ecf20Sopenharmony_ci#include <asm/pdc.h> 188c2ecf20Sopenharmony_ci#include <asm/ptrace.h> 198c2ecf20Sopenharmony_ci#include <asm/types.h> 208c2ecf20Sopenharmony_ci#include <asm/percpu.h> 218c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define HAVE_ARCH_PICK_MMAP_LAYOUT 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define TASK_SIZE_OF(tsk) ((tsk)->thread.task_size) 268c2ecf20Sopenharmony_ci#define TASK_SIZE TASK_SIZE_OF(current) 278c2ecf20Sopenharmony_ci#define TASK_UNMAPPED_BASE (current->thread.map_base) 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define DEFAULT_TASK_SIZE32 (0xFFF00000UL) 308c2ecf20Sopenharmony_ci#define DEFAULT_MAP_BASE32 (0x40000000UL) 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 338c2ecf20Sopenharmony_ci#define DEFAULT_TASK_SIZE (MAX_ADDRESS-0xf000000) 348c2ecf20Sopenharmony_ci#define DEFAULT_MAP_BASE (0x200000000UL) 358c2ecf20Sopenharmony_ci#else 368c2ecf20Sopenharmony_ci#define DEFAULT_TASK_SIZE DEFAULT_TASK_SIZE32 378c2ecf20Sopenharmony_ci#define DEFAULT_MAP_BASE DEFAULT_MAP_BASE32 388c2ecf20Sopenharmony_ci#endif 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* XXX: STACK_TOP actually should be STACK_BOTTOM for parisc. 438c2ecf20Sopenharmony_ci * prumpf */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define STACK_TOP TASK_SIZE 468c2ecf20Sopenharmony_ci#define STACK_TOP_MAX DEFAULT_TASK_SIZE 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* Allow bigger stacks for 64-bit processes */ 498c2ecf20Sopenharmony_ci#define STACK_SIZE_MAX (USER_WIDE_MODE \ 508c2ecf20Sopenharmony_ci ? (1 << 30) /* 1 GB */ \ 518c2ecf20Sopenharmony_ci : (CONFIG_MAX_STACK_SIZE_MB*1024*1024)) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#endif 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* 588c2ecf20Sopenharmony_ci * Data detected about CPUs at boot time which is the same for all CPU's. 598c2ecf20Sopenharmony_ci * HP boxes are SMP - ie identical processors. 608c2ecf20Sopenharmony_ci * 618c2ecf20Sopenharmony_ci * FIXME: some CPU rev info may be processor specific... 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_cistruct system_cpuinfo_parisc { 648c2ecf20Sopenharmony_ci unsigned int cpu_count; 658c2ecf20Sopenharmony_ci unsigned int cpu_hz; 668c2ecf20Sopenharmony_ci unsigned int hversion; 678c2ecf20Sopenharmony_ci unsigned int sversion; 688c2ecf20Sopenharmony_ci enum cpu_type cpu_type; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci struct { 718c2ecf20Sopenharmony_ci struct pdc_model model; 728c2ecf20Sopenharmony_ci unsigned long versions; 738c2ecf20Sopenharmony_ci unsigned long cpuid; 748c2ecf20Sopenharmony_ci unsigned long capabilities; 758c2ecf20Sopenharmony_ci char sys_model_name[81]; /* PDC-ROM returnes this model name */ 768c2ecf20Sopenharmony_ci } pdc; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci const char *cpu_name; /* e.g. "PA7300LC (PCX-L2)" */ 798c2ecf20Sopenharmony_ci const char *family_name; /* e.g. "1.1e" */ 808c2ecf20Sopenharmony_ci}; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* Per CPU data structure - ie varies per CPU. */ 848c2ecf20Sopenharmony_cistruct cpuinfo_parisc { 858c2ecf20Sopenharmony_ci unsigned long it_value; /* Interval Timer at last timer Intr */ 868c2ecf20Sopenharmony_ci unsigned long irq_count; /* number of IRQ's since boot */ 878c2ecf20Sopenharmony_ci unsigned long cpuid; /* aka slot_number or set to NO_PROC_ID */ 888c2ecf20Sopenharmony_ci unsigned long hpa; /* Host Physical address */ 898c2ecf20Sopenharmony_ci unsigned long txn_addr; /* MMIO addr of EIR or id_eid */ 908c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 918c2ecf20Sopenharmony_ci unsigned long pending_ipi; /* bitmap of type ipi_message_type */ 928c2ecf20Sopenharmony_ci#endif 938c2ecf20Sopenharmony_ci unsigned long bh_count; /* number of times bh was invoked */ 948c2ecf20Sopenharmony_ci unsigned long fp_rev; 958c2ecf20Sopenharmony_ci unsigned long fp_model; 968c2ecf20Sopenharmony_ci unsigned long cpu_num; /* CPU number from PAT firmware */ 978c2ecf20Sopenharmony_ci unsigned long cpu_loc; /* CPU location from PAT firmware */ 988c2ecf20Sopenharmony_ci unsigned int state; 998c2ecf20Sopenharmony_ci struct parisc_device *dev; 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ciextern struct system_cpuinfo_parisc boot_cpu_data; 1038c2ecf20Sopenharmony_ciDECLARE_PER_CPU(struct cpuinfo_parisc, cpu_data); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF) 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_citypedef struct { 1088c2ecf20Sopenharmony_ci int seg; 1098c2ecf20Sopenharmony_ci} mm_segment_t; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#define ARCH_MIN_TASKALIGN 8 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistruct thread_struct { 1148c2ecf20Sopenharmony_ci struct pt_regs regs; 1158c2ecf20Sopenharmony_ci unsigned long task_size; 1168c2ecf20Sopenharmony_ci unsigned long map_base; 1178c2ecf20Sopenharmony_ci unsigned long flags; 1188c2ecf20Sopenharmony_ci}; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci#define task_pt_regs(tsk) ((struct pt_regs *)&((tsk)->thread.regs)) 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci/* Thread struct flags. */ 1238c2ecf20Sopenharmony_ci#define PARISC_UAC_NOPRINT (1UL << 0) /* see prctl and unaligned.c */ 1248c2ecf20Sopenharmony_ci#define PARISC_UAC_SIGBUS (1UL << 1) 1258c2ecf20Sopenharmony_ci#define PARISC_KERNEL_DEATH (1UL << 31) /* see die_if_kernel()... */ 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci#define PARISC_UAC_SHIFT 0 1288c2ecf20Sopenharmony_ci#define PARISC_UAC_MASK (PARISC_UAC_NOPRINT|PARISC_UAC_SIGBUS) 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci#define SET_UNALIGN_CTL(task,value) \ 1318c2ecf20Sopenharmony_ci ({ \ 1328c2ecf20Sopenharmony_ci (task)->thread.flags = (((task)->thread.flags & ~PARISC_UAC_MASK) \ 1338c2ecf20Sopenharmony_ci | (((value) << PARISC_UAC_SHIFT) & \ 1348c2ecf20Sopenharmony_ci PARISC_UAC_MASK)); \ 1358c2ecf20Sopenharmony_ci 0; \ 1368c2ecf20Sopenharmony_ci }) 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci#define GET_UNALIGN_CTL(task,addr) \ 1398c2ecf20Sopenharmony_ci ({ \ 1408c2ecf20Sopenharmony_ci put_user(((task)->thread.flags & PARISC_UAC_MASK) \ 1418c2ecf20Sopenharmony_ci >> PARISC_UAC_SHIFT, (int __user *) (addr)); \ 1428c2ecf20Sopenharmony_ci }) 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci#define INIT_THREAD { \ 1458c2ecf20Sopenharmony_ci .regs = { .gr = { 0, }, \ 1468c2ecf20Sopenharmony_ci .fr = { 0, }, \ 1478c2ecf20Sopenharmony_ci .sr = { 0, }, \ 1488c2ecf20Sopenharmony_ci .iasq = { 0, }, \ 1498c2ecf20Sopenharmony_ci .iaoq = { 0, }, \ 1508c2ecf20Sopenharmony_ci .cr27 = 0, \ 1518c2ecf20Sopenharmony_ci }, \ 1528c2ecf20Sopenharmony_ci .task_size = DEFAULT_TASK_SIZE, \ 1538c2ecf20Sopenharmony_ci .map_base = DEFAULT_MAP_BASE, \ 1548c2ecf20Sopenharmony_ci .flags = 0 \ 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistruct task_struct; 1588c2ecf20Sopenharmony_civoid show_trace(struct task_struct *task, unsigned long *stack); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* 1618c2ecf20Sopenharmony_ci * Start user thread in another space. 1628c2ecf20Sopenharmony_ci * 1638c2ecf20Sopenharmony_ci * Note that we set both the iaoq and r31 to the new pc. When 1648c2ecf20Sopenharmony_ci * the kernel initially calls execve it will return through an 1658c2ecf20Sopenharmony_ci * rfi path that will use the values in the iaoq. The execve 1668c2ecf20Sopenharmony_ci * syscall path will return through the gateway page, and 1678c2ecf20Sopenharmony_ci * that uses r31 to branch to. 1688c2ecf20Sopenharmony_ci * 1698c2ecf20Sopenharmony_ci * For ELF we clear r23, because the dynamic linker uses it to pass 1708c2ecf20Sopenharmony_ci * the address of the finalizer function. 1718c2ecf20Sopenharmony_ci * 1728c2ecf20Sopenharmony_ci * We also initialize sr3 to an illegal value (illegal for our 1738c2ecf20Sopenharmony_ci * implementation, not for the architecture). 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_citypedef unsigned int elf_caddr_t; 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/* The ELF abi wants things done a "wee bit" differently than 1788c2ecf20Sopenharmony_ci * som does. Supporting this behavior here avoids 1798c2ecf20Sopenharmony_ci * having our own version of create_elf_tables. 1808c2ecf20Sopenharmony_ci * 1818c2ecf20Sopenharmony_ci * Oh, and yes, that is not a typo, we are really passing argc in r25 1828c2ecf20Sopenharmony_ci * and argv in r24 (rather than r26 and r25). This is because that's 1838c2ecf20Sopenharmony_ci * where __libc_start_main wants them. 1848c2ecf20Sopenharmony_ci * 1858c2ecf20Sopenharmony_ci * Duplicated from dl-machine.h for the benefit of readers: 1868c2ecf20Sopenharmony_ci * 1878c2ecf20Sopenharmony_ci * Our initial stack layout is rather different from everyone else's 1888c2ecf20Sopenharmony_ci * due to the unique PA-RISC ABI. As far as I know it looks like 1898c2ecf20Sopenharmony_ci * this: 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci ----------------------------------- (user startup code creates this frame) 1928c2ecf20Sopenharmony_ci | 32 bytes of magic | 1938c2ecf20Sopenharmony_ci |---------------------------------| 1948c2ecf20Sopenharmony_ci | 32 bytes argument/sp save area | 1958c2ecf20Sopenharmony_ci |---------------------------------| (bprm->p) 1968c2ecf20Sopenharmony_ci | ELF auxiliary info | 1978c2ecf20Sopenharmony_ci | (up to 28 words) | 1988c2ecf20Sopenharmony_ci |---------------------------------| 1998c2ecf20Sopenharmony_ci | NULL | 2008c2ecf20Sopenharmony_ci |---------------------------------| 2018c2ecf20Sopenharmony_ci | Environment pointers | 2028c2ecf20Sopenharmony_ci |---------------------------------| 2038c2ecf20Sopenharmony_ci | NULL | 2048c2ecf20Sopenharmony_ci |---------------------------------| 2058c2ecf20Sopenharmony_ci | Argument pointers | 2068c2ecf20Sopenharmony_ci |---------------------------------| <- argv 2078c2ecf20Sopenharmony_ci | argc (1 word) | 2088c2ecf20Sopenharmony_ci |---------------------------------| <- bprm->exec (HACK!) 2098c2ecf20Sopenharmony_ci | N bytes of slack | 2108c2ecf20Sopenharmony_ci |---------------------------------| 2118c2ecf20Sopenharmony_ci | filename passed to execve | 2128c2ecf20Sopenharmony_ci |---------------------------------| (mm->env_end) 2138c2ecf20Sopenharmony_ci | env strings | 2148c2ecf20Sopenharmony_ci |---------------------------------| (mm->env_start, mm->arg_end) 2158c2ecf20Sopenharmony_ci | arg strings | 2168c2ecf20Sopenharmony_ci |---------------------------------| 2178c2ecf20Sopenharmony_ci | additional faked arg strings if | 2188c2ecf20Sopenharmony_ci | we're invoked via binfmt_script | 2198c2ecf20Sopenharmony_ci |---------------------------------| (mm->arg_start) 2208c2ecf20Sopenharmony_ci stack base is at TASK_SIZE - rlim_max. 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cion downward growing arches, it looks like this: 2238c2ecf20Sopenharmony_ci stack base at TASK_SIZE 2248c2ecf20Sopenharmony_ci | filename passed to execve 2258c2ecf20Sopenharmony_ci | env strings 2268c2ecf20Sopenharmony_ci | arg strings 2278c2ecf20Sopenharmony_ci | faked arg strings 2288c2ecf20Sopenharmony_ci | slack 2298c2ecf20Sopenharmony_ci | ELF 2308c2ecf20Sopenharmony_ci | envps 2318c2ecf20Sopenharmony_ci | argvs 2328c2ecf20Sopenharmony_ci | argc 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci * The pleasant part of this is that if we need to skip arguments we 2358c2ecf20Sopenharmony_ci * can just decrement argc and move argv, because the stack pointer 2368c2ecf20Sopenharmony_ci * is utterly unrelated to the location of the environment and 2378c2ecf20Sopenharmony_ci * argument vectors. 2388c2ecf20Sopenharmony_ci * 2398c2ecf20Sopenharmony_ci * Note that the S/390 people took the easy way out and hacked their 2408c2ecf20Sopenharmony_ci * GCC to make the stack grow downwards. 2418c2ecf20Sopenharmony_ci * 2428c2ecf20Sopenharmony_ci * Final Note: For entry from syscall, the W (wide) bit of the PSW 2438c2ecf20Sopenharmony_ci * is stuffed into the lowest bit of the user sp (%r30), so we fill 2448c2ecf20Sopenharmony_ci * it in here from the current->personality 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci#define USER_WIDE_MODE (!is_32bit_task()) 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci#define start_thread(regs, new_pc, new_sp) do { \ 2508c2ecf20Sopenharmony_ci elf_addr_t *sp = (elf_addr_t *)new_sp; \ 2518c2ecf20Sopenharmony_ci __u32 spaceid = (__u32)current->mm->context; \ 2528c2ecf20Sopenharmony_ci elf_addr_t pc = (elf_addr_t)new_pc | 3; \ 2538c2ecf20Sopenharmony_ci elf_caddr_t *argv = (elf_caddr_t *)bprm->exec + 1; \ 2548c2ecf20Sopenharmony_ci \ 2558c2ecf20Sopenharmony_ci regs->iasq[0] = spaceid; \ 2568c2ecf20Sopenharmony_ci regs->iasq[1] = spaceid; \ 2578c2ecf20Sopenharmony_ci regs->iaoq[0] = pc; \ 2588c2ecf20Sopenharmony_ci regs->iaoq[1] = pc + 4; \ 2598c2ecf20Sopenharmony_ci regs->sr[2] = LINUX_GATEWAY_SPACE; \ 2608c2ecf20Sopenharmony_ci regs->sr[3] = 0xffff; \ 2618c2ecf20Sopenharmony_ci regs->sr[4] = spaceid; \ 2628c2ecf20Sopenharmony_ci regs->sr[5] = spaceid; \ 2638c2ecf20Sopenharmony_ci regs->sr[6] = spaceid; \ 2648c2ecf20Sopenharmony_ci regs->sr[7] = spaceid; \ 2658c2ecf20Sopenharmony_ci regs->gr[ 0] = USER_PSW | (USER_WIDE_MODE ? PSW_W : 0); \ 2668c2ecf20Sopenharmony_ci regs->fr[ 0] = 0LL; \ 2678c2ecf20Sopenharmony_ci regs->fr[ 1] = 0LL; \ 2688c2ecf20Sopenharmony_ci regs->fr[ 2] = 0LL; \ 2698c2ecf20Sopenharmony_ci regs->fr[ 3] = 0LL; \ 2708c2ecf20Sopenharmony_ci regs->gr[30] = (((unsigned long)sp + 63) &~ 63) | (USER_WIDE_MODE ? 1 : 0); \ 2718c2ecf20Sopenharmony_ci regs->gr[31] = pc; \ 2728c2ecf20Sopenharmony_ci \ 2738c2ecf20Sopenharmony_ci get_user(regs->gr[25], (argv - 1)); \ 2748c2ecf20Sopenharmony_ci regs->gr[24] = (long) argv; \ 2758c2ecf20Sopenharmony_ci regs->gr[23] = 0; \ 2768c2ecf20Sopenharmony_ci} while(0) 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistruct task_struct; 2798c2ecf20Sopenharmony_cistruct mm_struct; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci/* Free all resources held by a thread. */ 2828c2ecf20Sopenharmony_ciextern void release_thread(struct task_struct *); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ciextern unsigned long get_wchan(struct task_struct *p); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci#define KSTK_EIP(tsk) ((tsk)->thread.regs.iaoq[0]) 2878c2ecf20Sopenharmony_ci#define KSTK_ESP(tsk) ((tsk)->thread.regs.gr[30]) 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci#define cpu_relax() barrier() 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci/* 2928c2ecf20Sopenharmony_ci * parisc_requires_coherency() is used to identify the combined VIPT/PIPT 2938c2ecf20Sopenharmony_ci * cached CPUs which require a guarantee of coherency (no inequivalent aliases 2948c2ecf20Sopenharmony_ci * with different data, whether clean or not) to operate 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci#ifdef CONFIG_PA8X00 2978c2ecf20Sopenharmony_ciextern int _parisc_requires_coherency; 2988c2ecf20Sopenharmony_ci#define parisc_requires_coherency() _parisc_requires_coherency 2998c2ecf20Sopenharmony_ci#else 3008c2ecf20Sopenharmony_ci#define parisc_requires_coherency() (0) 3018c2ecf20Sopenharmony_ci#endif 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ciextern int running_on_qemu; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci#endif /* __ASM_PARISC_PROCESSOR_H */ 308