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

bioscalls.c (13255B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * bioscalls.c - the lowlevel layer of the PnPBIOS driver
      4 */
      5
      6#include <linux/types.h>
      7#include <linux/module.h>
      8#include <linux/init.h>
      9#include <linux/linkage.h>
     10#include <linux/kernel.h>
     11#include <linux/device.h>
     12#include <linux/pnp.h>
     13#include <linux/mm.h>
     14#include <linux/smp.h>
     15#include <linux/kmod.h>
     16#include <linux/completion.h>
     17#include <linux/spinlock.h>
     18
     19#include <asm/page.h>
     20#include <asm/desc.h>
     21#include <asm/byteorder.h>
     22
     23#include "pnpbios.h"
     24
     25__visible struct {
     26	u16 offset;
     27	u16 segment;
     28} pnp_bios_callpoint;
     29
     30/*
     31 * These are some opcodes for a "static asmlinkage"
     32 * As this code is *not* executed inside the linux kernel segment, but in a
     33 * alias at offset 0, we need a far return that can not be compiled by
     34 * default (please, prove me wrong! this is *really* ugly!)
     35 * This is the only way to get the bios to return into the kernel code,
     36 * because the bios code runs in 16 bit protected mode and therefore can only
     37 * return to the caller if the call is within the first 64kB, and the linux
     38 * kernel begins at offset 3GB...
     39 */
     40
     41asmlinkage __visible void pnp_bios_callfunc(void);
     42
     43__asm__(".text			\n"
     44	__ALIGN_STR "\n"
     45	".globl pnp_bios_callfunc\n"
     46	"pnp_bios_callfunc:\n"
     47	"	pushl %edx	\n"
     48	"	pushl %ecx	\n"
     49	"	pushl %ebx	\n"
     50	"	pushl %eax	\n"
     51	"	lcallw *pnp_bios_callpoint\n"
     52	"	addl $16, %esp	\n"
     53	"	lret		\n"
     54	".previous		\n");
     55
     56#define Q2_SET_SEL(cpu, selname, address, size) \
     57do { \
     58	struct desc_struct *gdt = get_cpu_gdt_rw((cpu)); \
     59	set_desc_base(&gdt[(selname) >> 3], (u32)(address)); \
     60	set_desc_limit(&gdt[(selname) >> 3], (size) - 1); \
     61} while(0)
     62
     63static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
     64			(unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1);
     65
     66/*
     67 * At some point we want to use this stack frame pointer to unwind
     68 * after PnP BIOS oopses.
     69 */
     70
     71__visible u32 pnp_bios_fault_esp;
     72__visible u32 pnp_bios_fault_eip;
     73__visible u32 pnp_bios_is_utter_crap = 0;
     74
     75static DEFINE_SPINLOCK(pnp_bios_lock);
     76
     77/*
     78 * Support Functions
     79 */
     80
     81static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
     82				u16 arg4, u16 arg5, u16 arg6, u16 arg7,
     83				void *ts1_base, u32 ts1_size,
     84				void *ts2_base, u32 ts2_size)
     85{
     86	unsigned long flags;
     87	u16 status;
     88	struct desc_struct save_desc_40;
     89	int cpu;
     90
     91	/*
     92	 * PnP BIOSes are generally not terribly re-entrant.
     93	 * Also, don't rely on them to save everything correctly.
     94	 */
     95	if (pnp_bios_is_utter_crap)
     96		return PNP_FUNCTION_NOT_SUPPORTED;
     97
     98	cpu = get_cpu();
     99	save_desc_40 = get_cpu_gdt_rw(cpu)[0x40 / 8];
    100	get_cpu_gdt_rw(cpu)[0x40 / 8] = bad_bios_desc;
    101
    102	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
    103	spin_lock_irqsave(&pnp_bios_lock, flags);
    104
    105	/* The lock prevents us bouncing CPU here */
    106	if (ts1_size)
    107		Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
    108	if (ts2_size)
    109		Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size);
    110
    111	__asm__ __volatile__("pushl %%ebp\n\t"
    112			     "pushl %%edi\n\t"
    113			     "pushl %%esi\n\t"
    114			     "pushl %%ds\n\t"
    115			     "pushl %%es\n\t"
    116			     "pushl %%fs\n\t"
    117			     "pushl %%gs\n\t"
    118			     "pushfl\n\t"
    119			     "movl %%esp, pnp_bios_fault_esp\n\t"
    120			     "movl $1f, pnp_bios_fault_eip\n\t"
    121			     "lcall %5,%6\n\t"
    122			     "1:popfl\n\t"
    123			     "popl %%gs\n\t"
    124			     "popl %%fs\n\t"
    125			     "popl %%es\n\t"
    126			     "popl %%ds\n\t"
    127			     "popl %%esi\n\t"
    128			     "popl %%edi\n\t"
    129			     "popl %%ebp\n\t":"=a"(status)
    130			     :"0"((func) | (((u32) arg1) << 16)),
    131			     "b"((arg2) | (((u32) arg3) << 16)),
    132			     "c"((arg4) | (((u32) arg5) << 16)),
    133			     "d"((arg6) | (((u32) arg7) << 16)),
    134			     "i"(PNP_CS32), "i"(0)
    135			     :"memory");
    136	spin_unlock_irqrestore(&pnp_bios_lock, flags);
    137
    138	get_cpu_gdt_rw(cpu)[0x40 / 8] = save_desc_40;
    139	put_cpu();
    140
    141	/* If we get here and this is set then the PnP BIOS faulted on us. */
    142	if (pnp_bios_is_utter_crap) {
    143		printk(KERN_ERR
    144		       "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n");
    145		printk(KERN_ERR
    146		       "PnPBIOS: You may need to reboot with the \"pnpbios=off\" option to operate stably\n");
    147		printk(KERN_ERR
    148		       "PnPBIOS: Check with your vendor for an updated BIOS\n");
    149	}
    150
    151	return status;
    152}
    153
    154void pnpbios_print_status(const char *module, u16 status)
    155{
    156	switch (status) {
    157	case PNP_SUCCESS:
    158		printk(KERN_ERR "PnPBIOS: %s: function successful\n", module);
    159		break;
    160	case PNP_NOT_SET_STATICALLY:
    161		printk(KERN_ERR "PnPBIOS: %s: unable to set static resources\n",
    162		       module);
    163		break;
    164	case PNP_UNKNOWN_FUNCTION:
    165		printk(KERN_ERR "PnPBIOS: %s: invalid function number passed\n",
    166		       module);
    167		break;
    168	case PNP_FUNCTION_NOT_SUPPORTED:
    169		printk(KERN_ERR
    170		       "PnPBIOS: %s: function not supported on this system\n",
    171		       module);
    172		break;
    173	case PNP_INVALID_HANDLE:
    174		printk(KERN_ERR "PnPBIOS: %s: invalid handle\n", module);
    175		break;
    176	case PNP_BAD_PARAMETER:
    177		printk(KERN_ERR "PnPBIOS: %s: invalid parameters were passed\n",
    178		       module);
    179		break;
    180	case PNP_SET_FAILED:
    181		printk(KERN_ERR "PnPBIOS: %s: unable to set resources\n",
    182		       module);
    183		break;
    184	case PNP_EVENTS_NOT_PENDING:
    185		printk(KERN_ERR "PnPBIOS: %s: no events are pending\n", module);
    186		break;
    187	case PNP_SYSTEM_NOT_DOCKED:
    188		printk(KERN_ERR "PnPBIOS: %s: the system is not docked\n",
    189		       module);
    190		break;
    191	case PNP_NO_ISA_PNP_CARDS:
    192		printk(KERN_ERR
    193		       "PnPBIOS: %s: no isapnp cards are installed on this system\n",
    194		       module);
    195		break;
    196	case PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES:
    197		printk(KERN_ERR
    198		       "PnPBIOS: %s: cannot determine the capabilities of the docking station\n",
    199		       module);
    200		break;
    201	case PNP_CONFIG_CHANGE_FAILED_NO_BATTERY:
    202		printk(KERN_ERR
    203		       "PnPBIOS: %s: unable to undock, the system does not have a battery\n",
    204		       module);
    205		break;
    206	case PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT:
    207		printk(KERN_ERR
    208		       "PnPBIOS: %s: could not dock due to resource conflicts\n",
    209		       module);
    210		break;
    211	case PNP_BUFFER_TOO_SMALL:
    212		printk(KERN_ERR "PnPBIOS: %s: the buffer passed is too small\n",
    213		       module);
    214		break;
    215	case PNP_USE_ESCD_SUPPORT:
    216		printk(KERN_ERR "PnPBIOS: %s: use ESCD instead\n", module);
    217		break;
    218	case PNP_MESSAGE_NOT_SUPPORTED:
    219		printk(KERN_ERR "PnPBIOS: %s: the message is unsupported\n",
    220		       module);
    221		break;
    222	case PNP_HARDWARE_ERROR:
    223		printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occurred\n",
    224		       module);
    225		break;
    226	default:
    227		printk(KERN_ERR "PnPBIOS: %s: unexpected status 0x%x\n", module,
    228		       status);
    229		break;
    230	}
    231}
    232
    233/*
    234 * PnP BIOS Low Level Calls
    235 */
    236
    237#define PNP_GET_NUM_SYS_DEV_NODES		0x00
    238#define PNP_GET_SYS_DEV_NODE			0x01
    239#define PNP_SET_SYS_DEV_NODE			0x02
    240#define PNP_GET_EVENT				0x03
    241#define PNP_SEND_MESSAGE			0x04
    242#define PNP_GET_DOCKING_STATION_INFORMATION	0x05
    243#define PNP_SET_STATIC_ALLOCED_RES_INFO		0x09
    244#define PNP_GET_STATIC_ALLOCED_RES_INFO		0x0a
    245#define PNP_GET_APM_ID_TABLE			0x0b
    246#define PNP_GET_PNP_ISA_CONFIG_STRUC		0x40
    247#define PNP_GET_ESCD_INFO			0x41
    248#define PNP_READ_ESCD				0x42
    249#define PNP_WRITE_ESCD				0x43
    250
    251/*
    252 * Call PnP BIOS with function 0x00, "get number of system device nodes"
    253 */
    254static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
    255{
    256	u16 status;
    257
    258	if (!pnp_bios_present())
    259		return PNP_FUNCTION_NOT_SUPPORTED;
    260	status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2,
    261			       PNP_TS1, PNP_DS, 0, 0, data,
    262			       sizeof(struct pnp_dev_node_info), NULL, 0);
    263	data->no_nodes &= 0xff;
    264	return status;
    265}
    266
    267int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
    268{
    269	int status = __pnp_bios_dev_node_info(data);
    270
    271	if (status)
    272		pnpbios_print_status("dev_node_info", status);
    273	return status;
    274}
    275
    276/*
    277 * Note that some PnP BIOSes (e.g., on Sony Vaio laptops) die a horrible
    278 * death if they are asked to access the "current" configuration.
    279 * Therefore, if it's a matter of indifference, it's better to call
    280 * get_dev_node() and set_dev_node() with boot=1 rather than with boot=0.
    281 */
    282
    283/* 
    284 * Call PnP BIOS with function 0x01, "get system device node"
    285 * Input: *nodenum = desired node,
    286 *        boot = whether to get nonvolatile boot (!=0)
    287 *               or volatile current (0) config
    288 * Output: *nodenum=next node or 0xff if no more nodes
    289 */
    290static int __pnp_bios_get_dev_node(u8 *nodenum, char boot,
    291				   struct pnp_bios_node *data)
    292{
    293	u16 status;
    294	u16 tmp_nodenum;
    295
    296	if (!pnp_bios_present())
    297		return PNP_FUNCTION_NOT_SUPPORTED;
    298	if (!boot && pnpbios_dont_use_current_config)
    299		return PNP_FUNCTION_NOT_SUPPORTED;
    300	tmp_nodenum = *nodenum;
    301	status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2,
    302			       boot ? 2 : 1, PNP_DS, 0, &tmp_nodenum,
    303			       sizeof(tmp_nodenum), data, 65536);
    304	*nodenum = tmp_nodenum;
    305	return status;
    306}
    307
    308int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
    309{
    310	int status;
    311
    312	status = __pnp_bios_get_dev_node(nodenum, boot, data);
    313	if (status)
    314		pnpbios_print_status("get_dev_node", status);
    315	return status;
    316}
    317
    318/*
    319 * Call PnP BIOS with function 0x02, "set system device node"
    320 * Input: *nodenum = desired node, 
    321 *        boot = whether to set nonvolatile boot (!=0)
    322 *               or volatile current (0) config
    323 */
    324static int __pnp_bios_set_dev_node(u8 nodenum, char boot,
    325				   struct pnp_bios_node *data)
    326{
    327	u16 status;
    328
    329	if (!pnp_bios_present())
    330		return PNP_FUNCTION_NOT_SUPPORTED;
    331	if (!boot && pnpbios_dont_use_current_config)
    332		return PNP_FUNCTION_NOT_SUPPORTED;
    333	status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1,
    334			       boot ? 2 : 1, PNP_DS, 0, 0, data, 65536, NULL,
    335			       0);
    336	return status;
    337}
    338
    339int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
    340{
    341	int status;
    342
    343	status = __pnp_bios_set_dev_node(nodenum, boot, data);
    344	if (status) {
    345		pnpbios_print_status("set_dev_node", status);
    346		return status;
    347	}
    348	if (!boot) {		/* Update devlist */
    349		status = pnp_bios_get_dev_node(&nodenum, boot, data);
    350		if (status)
    351			return status;
    352	}
    353	return status;
    354}
    355
    356/*
    357 * Call PnP BIOS with function 0x05, "get docking station information"
    358 */
    359int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
    360{
    361	u16 status;
    362
    363	if (!pnp_bios_present())
    364		return PNP_FUNCTION_NOT_SUPPORTED;
    365	status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1,
    366			       PNP_DS, 0, 0, 0, 0, data,
    367			       sizeof(struct pnp_docking_station_info), NULL,
    368			       0);
    369	return status;
    370}
    371
    372/*
    373 * Call PnP BIOS with function 0x0a, "get statically allocated resource
    374 * information"
    375 */
    376static int __pnp_bios_get_stat_res(char *info)
    377{
    378	u16 status;
    379
    380	if (!pnp_bios_present())
    381		return PNP_FUNCTION_NOT_SUPPORTED;
    382	status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1,
    383			       PNP_DS, 0, 0, 0, 0, info, 65536, NULL, 0);
    384	return status;
    385}
    386
    387int pnp_bios_get_stat_res(char *info)
    388{
    389	int status;
    390
    391	status = __pnp_bios_get_stat_res(info);
    392	if (status)
    393		pnpbios_print_status("get_stat_res", status);
    394	return status;
    395}
    396
    397/*
    398 * Call PnP BIOS with function 0x40, "get isa pnp configuration structure"
    399 */
    400static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
    401{
    402	u16 status;
    403
    404	if (!pnp_bios_present())
    405		return PNP_FUNCTION_NOT_SUPPORTED;
    406	status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS,
    407			       0, 0, 0, 0, data,
    408			       sizeof(struct pnp_isa_config_struc), NULL, 0);
    409	return status;
    410}
    411
    412int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
    413{
    414	int status;
    415
    416	status = __pnp_bios_isapnp_config(data);
    417	if (status)
    418		pnpbios_print_status("isapnp_config", status);
    419	return status;
    420}
    421
    422/*
    423 * Call PnP BIOS with function 0x41, "get ESCD info"
    424 */
    425static int __pnp_bios_escd_info(struct escd_info_struc *data)
    426{
    427	u16 status;
    428
    429	if (!pnp_bios_present())
    430		return ESCD_FUNCTION_NOT_SUPPORTED;
    431	status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4,
    432			       PNP_TS1, PNP_DS, data,
    433			       sizeof(struct escd_info_struc), NULL, 0);
    434	return status;
    435}
    436
    437int pnp_bios_escd_info(struct escd_info_struc *data)
    438{
    439	int status;
    440
    441	status = __pnp_bios_escd_info(data);
    442	if (status)
    443		pnpbios_print_status("escd_info", status);
    444	return status;
    445}
    446
    447/*
    448 * Call PnP BIOS function 0x42, "read ESCD"
    449 * nvram_base is determined by calling escd_info
    450 */
    451static int __pnp_bios_read_escd(char *data, u32 nvram_base)
    452{
    453	u16 status;
    454
    455	if (!pnp_bios_present())
    456		return ESCD_FUNCTION_NOT_SUPPORTED;
    457	status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0,
    458			       0, data, 65536, __va(nvram_base), 65536);
    459	return status;
    460}
    461
    462int pnp_bios_read_escd(char *data, u32 nvram_base)
    463{
    464	int status;
    465
    466	status = __pnp_bios_read_escd(data, nvram_base);
    467	if (status)
    468		pnpbios_print_status("read_escd", status);
    469	return status;
    470}
    471
    472void pnpbios_calls_init(union pnp_bios_install_struct *header)
    473{
    474	int i;
    475
    476	pnp_bios_callpoint.offset = header->fields.pm16offset;
    477	pnp_bios_callpoint.segment = PNP_CS16;
    478
    479	for_each_possible_cpu(i) {
    480		struct desc_struct *gdt = get_cpu_gdt_rw(i);
    481		if (!gdt)
    482			continue;
    483		set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_CS32],
    484			 (unsigned long)&pnp_bios_callfunc);
    485		set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_CS16],
    486			 (unsigned long)__va(header->fields.pm16cseg));
    487		set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_DS],
    488			 (unsigned long)__va(header->fields.pm16dseg));
    489	}
    490}