xref: /kvm-unit-tests/lib/x86/fwcfg.c (revision 5b70cbdb7bc2ea65096b51565c75815cc95945b8)
1 #include "fwcfg.h"
2 #include "smp.h"
3 #include "libcflat.h"
4 
5 static struct spinlock lock;
6 
7 static long fw_override[FW_CFG_MAX_ENTRY];
8 static bool fw_override_done;
9 
10 bool no_test_device;
11 
12 static void read_cfg_override(void)
13 {
14 	const char *str;
15 	int i;
16 
17 	/* Initialize to negative value that would be considered as invalid */
18 	for (i = 0; i < FW_CFG_MAX_ENTRY; i++)
19 		fw_override[i] = -1;
20 
21 	if ((str = getenv("NR_CPUS")))
22 		fw_override[FW_CFG_NB_CPUS] = atol(str);
23 
24 	/* MEMSIZE is in megabytes */
25 	if ((str = getenv("MEMSIZE")))
26 		fw_override[FW_CFG_RAM_SIZE] = atol(str) * 1024 * 1024;
27 
28 	if ((str = getenv("TEST_DEVICE")))
29 		no_test_device = !atol(str);
30 
31     fw_override_done = true;
32 }
33 
34 static uint64_t fwcfg_get_u(uint16_t index, int bytes)
35 {
36     uint64_t r = 0;
37     uint8_t b;
38     int i;
39 
40     if (!fw_override_done)
41         read_cfg_override();
42 
43     if (index < FW_CFG_MAX_ENTRY && fw_override[index] >= 0)
44 	    return fw_override[index];
45 
46     spin_lock(&lock);
47     asm volatile ("out %0, %1" : : "a"(index), "d"((uint16_t)BIOS_CFG_IOPORT));
48     for (i = 0; i < bytes; ++i) {
49         asm volatile ("in %1, %0" : "=a"(b) : "d"((uint16_t)(BIOS_CFG_IOPORT + 1)));
50         r |= (uint64_t)b << (i * 8);
51     }
52     spin_unlock(&lock);
53     return r;
54 }
55 
56 uint8_t fwcfg_get_u8(unsigned index)
57 {
58     return fwcfg_get_u(index, 1);
59 }
60 
61 uint16_t fwcfg_get_u16(unsigned index)
62 {
63     return fwcfg_get_u(index, 2);
64 }
65 
66 uint32_t fwcfg_get_u32(unsigned index)
67 {
68     return fwcfg_get_u(index, 4);
69 }
70 
71 uint64_t fwcfg_get_u64(unsigned index)
72 {
73     return fwcfg_get_u(index, 8);
74 }
75 
76 unsigned fwcfg_get_nb_cpus(void)
77 {
78     return fwcfg_get_u16(FW_CFG_NB_CPUS);
79 }
80