cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

misc_64.c (9021B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * misc.c:  Miscellaneous prom functions that don't belong
      4 *          anywhere else.
      5 *
      6 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
      7 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
      8 */
      9
     10#include <linux/types.h>
     11#include <linux/kernel.h>
     12#include <linux/sched.h>
     13#include <linux/interrupt.h>
     14#include <linux/delay.h>
     15#include <linux/module.h>
     16
     17#include <asm/openprom.h>
     18#include <asm/oplib.h>
     19#include <asm/ldc.h>
     20
     21static int prom_service_exists(const char *service_name)
     22{
     23	unsigned long args[5];
     24
     25	args[0] = (unsigned long) "test";
     26	args[1] = 1;
     27	args[2] = 1;
     28	args[3] = (unsigned long) service_name;
     29	args[4] = (unsigned long) -1;
     30
     31	p1275_cmd_direct(args);
     32
     33	if (args[4])
     34		return 0;
     35	return 1;
     36}
     37
     38void prom_sun4v_guest_soft_state(void)
     39{
     40	const char *svc = "SUNW,soft-state-supported";
     41	unsigned long args[3];
     42
     43	if (!prom_service_exists(svc))
     44		return;
     45	args[0] = (unsigned long) svc;
     46	args[1] = 0;
     47	args[2] = 0;
     48	p1275_cmd_direct(args);
     49}
     50
     51/* Reset and reboot the machine with the command 'bcommand'. */
     52void prom_reboot(const char *bcommand)
     53{
     54	unsigned long args[4];
     55
     56#ifdef CONFIG_SUN_LDOMS
     57	if (ldom_domaining_enabled)
     58		ldom_reboot(bcommand);
     59#endif
     60	args[0] = (unsigned long) "boot";
     61	args[1] = 1;
     62	args[2] = 0;
     63	args[3] = (unsigned long) bcommand;
     64
     65	p1275_cmd_direct(args);
     66}
     67
     68/* Forth evaluate the expression contained in 'fstring'. */
     69void prom_feval(const char *fstring)
     70{
     71	unsigned long args[5];
     72
     73	if (!fstring || fstring[0] == 0)
     74		return;
     75	args[0] = (unsigned long) "interpret";
     76	args[1] = 1;
     77	args[2] = 1;
     78	args[3] = (unsigned long) fstring;
     79	args[4] = (unsigned long) -1;
     80
     81	p1275_cmd_direct(args);
     82}
     83EXPORT_SYMBOL(prom_feval);
     84
     85/* Drop into the prom, with the chance to continue with the 'go'
     86 * prom command.
     87 */
     88void prom_cmdline(void)
     89{
     90	unsigned long args[3];
     91	unsigned long flags;
     92
     93	local_irq_save(flags);
     94
     95#ifdef CONFIG_SMP
     96	smp_capture();
     97#endif
     98
     99	args[0] = (unsigned long) "enter";
    100	args[1] = 0;
    101	args[2] = 0;
    102
    103	p1275_cmd_direct(args);
    104
    105#ifdef CONFIG_SMP
    106	smp_release();
    107#endif
    108
    109	local_irq_restore(flags);
    110}
    111
    112/* Drop into the prom, but completely terminate the program.
    113 * No chance of continuing.
    114 */
    115void notrace prom_halt(void)
    116{
    117	unsigned long args[3];
    118
    119#ifdef CONFIG_SUN_LDOMS
    120	if (ldom_domaining_enabled)
    121		ldom_power_off();
    122#endif
    123again:
    124	args[0] = (unsigned long) "exit";
    125	args[1] = 0;
    126	args[2] = 0;
    127	p1275_cmd_direct(args);
    128	goto again; /* PROM is out to get me -DaveM */
    129}
    130
    131void prom_halt_power_off(void)
    132{
    133	unsigned long args[3];
    134
    135#ifdef CONFIG_SUN_LDOMS
    136	if (ldom_domaining_enabled)
    137		ldom_power_off();
    138#endif
    139	args[0] = (unsigned long) "SUNW,power-off";
    140	args[1] = 0;
    141	args[2] = 0;
    142	p1275_cmd_direct(args);
    143
    144	/* if nothing else helps, we just halt */
    145	prom_halt();
    146}
    147
    148/* Get the idprom and stuff it into buffer 'idbuf'.  Returns the
    149 * format type.  'num_bytes' is the number of bytes that your idbuf
    150 * has space for.  Returns 0xff on error.
    151 */
    152unsigned char prom_get_idprom(char *idbuf, int num_bytes)
    153{
    154	int len;
    155
    156	len = prom_getproplen(prom_root_node, "idprom");
    157	if ((len >num_bytes) || (len == -1))
    158		return 0xff;
    159	if (!prom_getproperty(prom_root_node, "idprom", idbuf, num_bytes))
    160		return idbuf[0];
    161
    162	return 0xff;
    163}
    164
    165int prom_get_mmu_ihandle(void)
    166{
    167	phandle node;
    168	int ret;
    169
    170	if (prom_mmu_ihandle_cache != 0)
    171		return prom_mmu_ihandle_cache;
    172
    173	node = prom_finddevice(prom_chosen_path);
    174	ret = prom_getint(node, prom_mmu_name);
    175	if (ret == -1 || ret == 0)
    176		prom_mmu_ihandle_cache = -1;
    177	else
    178		prom_mmu_ihandle_cache = ret;
    179
    180	return ret;
    181}
    182
    183static int prom_get_memory_ihandle(void)
    184{
    185	static int memory_ihandle_cache;
    186	phandle node;
    187	int ret;
    188
    189	if (memory_ihandle_cache != 0)
    190		return memory_ihandle_cache;
    191
    192	node = prom_finddevice("/chosen");
    193	ret = prom_getint(node, "memory");
    194	if (ret == -1 || ret == 0)
    195		memory_ihandle_cache = -1;
    196	else
    197		memory_ihandle_cache = ret;
    198
    199	return ret;
    200}
    201
    202/* Load explicit I/D TLB entries. */
    203static long tlb_load(const char *type, unsigned long index,
    204		     unsigned long tte_data, unsigned long vaddr)
    205{
    206	unsigned long args[9];
    207
    208	args[0] = (unsigned long) prom_callmethod_name;
    209	args[1] = 5;
    210	args[2] = 1;
    211	args[3] = (unsigned long) type;
    212	args[4] = (unsigned int) prom_get_mmu_ihandle();
    213	args[5] = vaddr;
    214	args[6] = tte_data;
    215	args[7] = index;
    216	args[8] = (unsigned long) -1;
    217
    218	p1275_cmd_direct(args);
    219
    220	return (long) args[8];
    221}
    222
    223long prom_itlb_load(unsigned long index,
    224		    unsigned long tte_data,
    225		    unsigned long vaddr)
    226{
    227	return tlb_load("SUNW,itlb-load", index, tte_data, vaddr);
    228}
    229
    230long prom_dtlb_load(unsigned long index,
    231		    unsigned long tte_data,
    232		    unsigned long vaddr)
    233{
    234	return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr);
    235}
    236
    237int prom_map(int mode, unsigned long size,
    238	     unsigned long vaddr, unsigned long paddr)
    239{
    240	unsigned long args[11];
    241	int ret;
    242
    243	args[0] = (unsigned long) prom_callmethod_name;
    244	args[1] = 7;
    245	args[2] = 1;
    246	args[3] = (unsigned long) prom_map_name;
    247	args[4] = (unsigned int) prom_get_mmu_ihandle();
    248	args[5] = (unsigned int) mode;
    249	args[6] = size;
    250	args[7] = vaddr;
    251	args[8] = 0;
    252	args[9] = paddr;
    253	args[10] = (unsigned long) -1;
    254
    255	p1275_cmd_direct(args);
    256
    257	ret = (int) args[10];
    258	if (ret == 0)
    259		ret = -1;
    260	return ret;
    261}
    262
    263void prom_unmap(unsigned long size, unsigned long vaddr)
    264{
    265	unsigned long args[7];
    266
    267	args[0] = (unsigned long) prom_callmethod_name;
    268	args[1] = 4;
    269	args[2] = 0;
    270	args[3] = (unsigned long) prom_unmap_name;
    271	args[4] = (unsigned int) prom_get_mmu_ihandle();
    272	args[5] = size;
    273	args[6] = vaddr;
    274
    275	p1275_cmd_direct(args);
    276}
    277
    278/* Set aside physical memory which is not touched or modified
    279 * across soft resets.
    280 */
    281int prom_retain(const char *name, unsigned long size,
    282		unsigned long align, unsigned long *paddr)
    283{
    284	unsigned long args[11];
    285
    286	args[0] = (unsigned long) prom_callmethod_name;
    287	args[1] = 5;
    288	args[2] = 3;
    289	args[3] = (unsigned long) "SUNW,retain";
    290	args[4] = (unsigned int) prom_get_memory_ihandle();
    291	args[5] = align;
    292	args[6] = size;
    293	args[7] = (unsigned long) name;
    294	args[8] = (unsigned long) -1;
    295	args[9] = (unsigned long) -1;
    296	args[10] = (unsigned long) -1;
    297
    298	p1275_cmd_direct(args);
    299
    300	if (args[8])
    301		return (int) args[8];
    302
    303	/* Next we get "phys_high" then "phys_low".  On 64-bit
    304	 * the phys_high cell is don't care since the phys_low
    305	 * cell has the full value.
    306	 */
    307	*paddr = args[10];
    308
    309	return 0;
    310}
    311
    312/* Get "Unumber" string for the SIMM at the given
    313 * memory address.  Usually this will be of the form
    314 * "Uxxxx" where xxxx is a decimal number which is
    315 * etched into the motherboard next to the SIMM slot
    316 * in question.
    317 */
    318int prom_getunumber(int syndrome_code,
    319		    unsigned long phys_addr,
    320		    char *buf, int buflen)
    321{
    322	unsigned long args[12];
    323
    324	args[0] = (unsigned long) prom_callmethod_name;
    325	args[1] = 7;
    326	args[2] = 2;
    327	args[3] = (unsigned long) "SUNW,get-unumber";
    328	args[4] = (unsigned int) prom_get_memory_ihandle();
    329	args[5] = buflen;
    330	args[6] = (unsigned long) buf;
    331	args[7] = 0;
    332	args[8] = phys_addr;
    333	args[9] = (unsigned int) syndrome_code;
    334	args[10] = (unsigned long) -1;
    335	args[11] = (unsigned long) -1;
    336
    337	p1275_cmd_direct(args);
    338
    339	return (int) args[10];
    340}
    341
    342/* Power management extensions. */
    343void prom_sleepself(void)
    344{
    345	unsigned long args[3];
    346
    347	args[0] = (unsigned long) "SUNW,sleep-self";
    348	args[1] = 0;
    349	args[2] = 0;
    350	p1275_cmd_direct(args);
    351}
    352
    353int prom_sleepsystem(void)
    354{
    355	unsigned long args[4];
    356
    357	args[0] = (unsigned long) "SUNW,sleep-system";
    358	args[1] = 0;
    359	args[2] = 1;
    360	args[3] = (unsigned long) -1;
    361	p1275_cmd_direct(args);
    362
    363	return (int) args[3];
    364}
    365
    366int prom_wakeupsystem(void)
    367{
    368	unsigned long args[4];
    369
    370	args[0] = (unsigned long) "SUNW,wakeup-system";
    371	args[1] = 0;
    372	args[2] = 1;
    373	args[3] = (unsigned long) -1;
    374	p1275_cmd_direct(args);
    375
    376	return (int) args[3];
    377}
    378
    379#ifdef CONFIG_SMP
    380void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
    381{
    382	unsigned long args[6];
    383
    384	args[0] = (unsigned long) "SUNW,start-cpu";
    385	args[1] = 3;
    386	args[2] = 0;
    387	args[3] = (unsigned int) cpunode;
    388	args[4] = pc;
    389	args[5] = arg;
    390	p1275_cmd_direct(args);
    391}
    392
    393void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
    394{
    395	unsigned long args[6];
    396
    397	args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid";
    398	args[1] = 3;
    399	args[2] = 0;
    400	args[3] = (unsigned int) cpuid;
    401	args[4] = pc;
    402	args[5] = arg;
    403	p1275_cmd_direct(args);
    404}
    405
    406void prom_stopcpu_cpuid(int cpuid)
    407{
    408	unsigned long args[4];
    409
    410	args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid";
    411	args[1] = 1;
    412	args[2] = 0;
    413	args[3] = (unsigned int) cpuid;
    414	p1275_cmd_direct(args);
    415}
    416
    417void prom_stopself(void)
    418{
    419	unsigned long args[3];
    420
    421	args[0] = (unsigned long) "SUNW,stop-self";
    422	args[1] = 0;
    423	args[2] = 0;
    424	p1275_cmd_direct(args);
    425}
    426
    427void prom_idleself(void)
    428{
    429	unsigned long args[3];
    430
    431	args[0] = (unsigned long) "SUNW,idle-self";
    432	args[1] = 0;
    433	args[2] = 0;
    434	p1275_cmd_direct(args);
    435}
    436
    437void prom_resumecpu(int cpunode)
    438{
    439	unsigned long args[4];
    440
    441	args[0] = (unsigned long) "SUNW,resume-cpu";
    442	args[1] = 1;
    443	args[2] = 0;
    444	args[3] = (unsigned int) cpunode;
    445	p1275_cmd_direct(args);
    446}
    447#endif