Commit 22d6a1cba3e9ec9baf8ce4d8dd1d088e112a64f1
1 parent
36b48973b8
Exists in
master
and in
7 other branches
[SPARC64]: Report proper system soft state to the hypervisor.
Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 12 changed files with 175 additions and 7 deletions Side-by-side Diff
- arch/sparc64/kernel/Makefile
- arch/sparc64/kernel/entry.S
- arch/sparc64/kernel/hvapi.c
- arch/sparc64/kernel/power.c
- arch/sparc64/kernel/process.c
- arch/sparc64/kernel/sstate.c
- arch/sparc64/mm/init.c
- arch/sparc64/prom/misc.c
- include/asm-sparc64/bugs.h
- include/asm-sparc64/hypervisor.h
- include/asm-sparc64/oplib.h
- include/asm-sparc64/sstate.h
arch/sparc64/kernel/Makefile
... | ... | @@ -12,7 +12,7 @@ |
12 | 12 | irq.o ptrace.o time.o sys_sparc.o signal.o \ |
13 | 13 | unaligned.o central.o pci.o starfire.o semaphore.o \ |
14 | 14 | power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \ |
15 | - visemul.o prom.o of_device.o hvapi.o | |
15 | + visemul.o prom.o of_device.o hvapi.o sstate.o | |
16 | 16 | |
17 | 17 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
18 | 18 | obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \ |
arch/sparc64/kernel/entry.S
... | ... | @@ -1937,4 +1937,16 @@ |
1937 | 1937 | stx %o1, [%o4] |
1938 | 1938 | retl |
1939 | 1939 | nop |
1940 | + | |
1941 | + /* %o0: soft state | |
1942 | + * %o1: address of description string | |
1943 | + * | |
1944 | + * returns %o0: status | |
1945 | + */ | |
1946 | + .globl sun4v_mach_set_soft_state | |
1947 | +sun4v_mach_set_soft_state: | |
1948 | + mov HV_FAST_MACH_SET_SOFT_STATE, %o5 | |
1949 | + ta HV_FAST_TRAP | |
1950 | + retl | |
1951 | + nop |
arch/sparc64/kernel/hvapi.c
... | ... | @@ -9,6 +9,7 @@ |
9 | 9 | |
10 | 10 | #include <asm/hypervisor.h> |
11 | 11 | #include <asm/oplib.h> |
12 | +#include <asm/sstate.h> | |
12 | 13 | |
13 | 14 | /* If the hypervisor indicates that the API setting |
14 | 15 | * calls are unsupported, by returning HV_EBADTRAP or |
... | ... | @@ -178,6 +179,8 @@ |
178 | 179 | minor = 1; |
179 | 180 | if (sun4v_hvapi_register(group, major, &minor)) |
180 | 181 | goto bad; |
182 | + | |
183 | + sun4v_sstate_init(); | |
181 | 184 | |
182 | 185 | return; |
183 | 186 |
arch/sparc64/kernel/power.c
... | ... | @@ -19,6 +19,7 @@ |
19 | 19 | #include <asm/prom.h> |
20 | 20 | #include <asm/of_device.h> |
21 | 21 | #include <asm/io.h> |
22 | +#include <asm/sstate.h> | |
22 | 23 | |
23 | 24 | #include <linux/unistd.h> |
24 | 25 | |
... | ... | @@ -53,6 +54,7 @@ |
53 | 54 | |
54 | 55 | void machine_power_off(void) |
55 | 56 | { |
57 | + sstate_poweroff(); | |
56 | 58 | if (!serial_console || scons_pwroff) { |
57 | 59 | #ifdef CONFIG_PCI |
58 | 60 | if (power_reg) { |
arch/sparc64/kernel/process.c
... | ... | @@ -45,6 +45,7 @@ |
45 | 45 | #include <asm/mmu_context.h> |
46 | 46 | #include <asm/unistd.h> |
47 | 47 | #include <asm/hypervisor.h> |
48 | +#include <asm/sstate.h> | |
48 | 49 | |
49 | 50 | /* #define VERBOSE_SHOWREGS */ |
50 | 51 | |
... | ... | @@ -106,6 +107,7 @@ |
106 | 107 | |
107 | 108 | void machine_halt(void) |
108 | 109 | { |
110 | + sstate_halt(); | |
109 | 111 | if (!serial_console && prom_palette) |
110 | 112 | prom_palette (1); |
111 | 113 | if (prom_keyboard) |
... | ... | @@ -116,6 +118,7 @@ |
116 | 118 | |
117 | 119 | void machine_alt_power_off(void) |
118 | 120 | { |
121 | + sstate_poweroff(); | |
119 | 122 | if (!serial_console && prom_palette) |
120 | 123 | prom_palette(1); |
121 | 124 | if (prom_keyboard) |
... | ... | @@ -128,6 +131,7 @@ |
128 | 131 | { |
129 | 132 | char *p; |
130 | 133 | |
134 | + sstate_reboot(); | |
131 | 135 | p = strchr (reboot_command, '\n'); |
132 | 136 | if (p) *p = 0; |
133 | 137 | if (!serial_console && prom_palette) |
arch/sparc64/kernel/sstate.c
1 | +/* sstate.c: System soft state support. | |
2 | + * | |
3 | + * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | |
4 | + */ | |
5 | + | |
6 | +#include <linux/kernel.h> | |
7 | +#include <linux/notifier.h> | |
8 | +#include <linux/init.h> | |
9 | + | |
10 | +#include <asm/hypervisor.h> | |
11 | +#include <asm/sstate.h> | |
12 | +#include <asm/oplib.h> | |
13 | +#include <asm/head.h> | |
14 | +#include <asm/io.h> | |
15 | + | |
16 | +static int hv_supports_soft_state; | |
17 | + | |
18 | +static unsigned long kimage_addr_to_ra(const char *p) | |
19 | +{ | |
20 | + unsigned long val = (unsigned long) p; | |
21 | + | |
22 | + return kern_base + (val - KERNBASE); | |
23 | +} | |
24 | + | |
25 | +static void do_set_sstate(unsigned long state, const char *msg) | |
26 | +{ | |
27 | + unsigned long err; | |
28 | + | |
29 | + if (!hv_supports_soft_state) | |
30 | + return; | |
31 | + | |
32 | + err = sun4v_mach_set_soft_state(state, kimage_addr_to_ra(msg)); | |
33 | + if (err) { | |
34 | + printk(KERN_WARNING "SSTATE: Failed to set soft-state to " | |
35 | + "state[%lx] msg[%s], err=%lu\n", | |
36 | + state, msg, err); | |
37 | + } | |
38 | +} | |
39 | + | |
40 | +static const char booting_msg[32] __attribute__((aligned(32))) = | |
41 | + "Linux booting"; | |
42 | +static const char running_msg[32] __attribute__((aligned(32))) = | |
43 | + "Linux running"; | |
44 | +static const char halting_msg[32] __attribute__((aligned(32))) = | |
45 | + "Linux halting"; | |
46 | +static const char poweroff_msg[32] __attribute__((aligned(32))) = | |
47 | + "Linux powering off"; | |
48 | +static const char rebooting_msg[32] __attribute__((aligned(32))) = | |
49 | + "Linux rebooting"; | |
50 | +static const char panicing_msg[32] __attribute__((aligned(32))) = | |
51 | + "Linux panicing"; | |
52 | + | |
53 | +void sstate_booting(void) | |
54 | +{ | |
55 | + do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); | |
56 | +} | |
57 | + | |
58 | +void sstate_running(void) | |
59 | +{ | |
60 | + do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); | |
61 | +} | |
62 | + | |
63 | +void sstate_halt(void) | |
64 | +{ | |
65 | + do_set_sstate(HV_SOFT_STATE_TRANSITION, halting_msg); | |
66 | +} | |
67 | + | |
68 | +void sstate_poweroff(void) | |
69 | +{ | |
70 | + do_set_sstate(HV_SOFT_STATE_TRANSITION, poweroff_msg); | |
71 | +} | |
72 | + | |
73 | +void sstate_reboot(void) | |
74 | +{ | |
75 | + do_set_sstate(HV_SOFT_STATE_TRANSITION, rebooting_msg); | |
76 | +} | |
77 | + | |
78 | +static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr) | |
79 | +{ | |
80 | + do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg); | |
81 | + | |
82 | + return NOTIFY_DONE; | |
83 | +} | |
84 | + | |
85 | +static struct notifier_block sstate_panic_block = { | |
86 | + .notifier_call = sstate_panic_event, | |
87 | + .priority = INT_MAX, | |
88 | +}; | |
89 | + | |
90 | +void __init sun4v_sstate_init(void) | |
91 | +{ | |
92 | + unsigned long major, minor; | |
93 | + | |
94 | + major = 1; | |
95 | + minor = 0; | |
96 | + if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor)) | |
97 | + return; | |
98 | + | |
99 | + hv_supports_soft_state = 1; | |
100 | + | |
101 | + prom_sun4v_guest_soft_state(); | |
102 | + atomic_notifier_chain_register(&panic_notifier_list, | |
103 | + &sstate_panic_block); | |
104 | +} |
arch/sparc64/mm/init.c
... | ... | @@ -43,6 +43,7 @@ |
43 | 43 | #include <asm/tsb.h> |
44 | 44 | #include <asm/hypervisor.h> |
45 | 45 | #include <asm/prom.h> |
46 | +#include <asm/sstate.h> | |
46 | 47 | |
47 | 48 | extern void device_scan(void); |
48 | 49 | |
... | ... | @@ -1347,6 +1348,8 @@ |
1347 | 1348 | |
1348 | 1349 | kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; |
1349 | 1350 | kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; |
1351 | + | |
1352 | + sstate_booting(); | |
1350 | 1353 | |
1351 | 1354 | /* Invalidate both kernel TSBs. */ |
1352 | 1355 | memset(swapper_tsb, 0x40, sizeof(swapper_tsb)); |
arch/sparc64/prom/misc.c
... | ... | @@ -15,6 +15,25 @@ |
15 | 15 | #include <asm/oplib.h> |
16 | 16 | #include <asm/system.h> |
17 | 17 | |
18 | +int prom_service_exists(const char *service_name) | |
19 | +{ | |
20 | + int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) | | |
21 | + P1275_INOUT(1, 1), service_name); | |
22 | + | |
23 | + if (err) | |
24 | + return 0; | |
25 | + return 1; | |
26 | +} | |
27 | + | |
28 | +void prom_sun4v_guest_soft_state(void) | |
29 | +{ | |
30 | + const char *svc = "SUNW,soft-state-supported"; | |
31 | + | |
32 | + if (!prom_service_exists(svc)) | |
33 | + return; | |
34 | + p1275_cmd(svc, P1275_INOUT(0, 0)); | |
35 | +} | |
36 | + | |
18 | 37 | /* Reset and reboot the machine with the command 'bcommand'. */ |
19 | 38 | void prom_reboot(const char *bcommand) |
20 | 39 | { |
include/asm-sparc64/bugs.h
1 | -/* $Id: bugs.h,v 1.1 1996/12/26 13:25:20 davem Exp $ | |
2 | - * include/asm-sparc64/bugs.h: Sparc probes for various bugs. | |
1 | +/* bugs.h: Sparc64 probes for various bugs. | |
3 | 2 | * |
4 | - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) | |
3 | + * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net) | |
5 | 4 | */ |
5 | +#include <asm/sstate.h> | |
6 | 6 | |
7 | - | |
8 | 7 | extern unsigned long loops_per_jiffy; |
9 | 8 | |
10 | 9 | static void __init check_bugs(void) |
... | ... | @@ -12,5 +11,6 @@ |
12 | 11 | #ifndef CONFIG_SMP |
13 | 12 | cpu_data(0).udelay_val = loops_per_jiffy; |
14 | 13 | #endif |
14 | + sstate_running(); | |
15 | 15 | } |
include/asm-sparc64/hypervisor.h
... | ... | @@ -162,10 +162,15 @@ |
162 | 162 | * terminated 7-bit ASCII string of up to 31 characters not including the |
163 | 163 | * NULL termination. |
164 | 164 | */ |
165 | -#define HV_FAST_MACH_SET_SOFT_STATE 0x03 | |
165 | +#define HV_FAST_MACH_SET_SOFT_STATE 0x70 | |
166 | 166 | #define HV_SOFT_STATE_NORMAL 0x01 |
167 | 167 | #define HV_SOFT_STATE_TRANSITION 0x02 |
168 | 168 | |
169 | +#ifndef __ASSEMBLY__ | |
170 | +extern unsigned long sun4v_mach_set_soft_state(unsigned long soft_state, | |
171 | + unsigned long msg_string_ra); | |
172 | +#endif | |
173 | + | |
169 | 174 | /* mach_get_soft_state() |
170 | 175 | * TRAP: HV_FAST_TRAP |
171 | 176 | * FUNCTION: HV_FAST_MACH_GET_SOFT_STATE |
... | ... | @@ -181,7 +186,7 @@ |
181 | 186 | * for the software state pointer are the same as for mach_set_soft_state() |
182 | 187 | * above. |
183 | 188 | */ |
184 | -#define HV_FAST_MACH_GET_SOFT_STATE 0x04 | |
189 | +#define HV_FAST_MACH_GET_SOFT_STATE 0x71 | |
185 | 190 | |
186 | 191 | /* CPU services. |
187 | 192 | * |
... | ... | @@ -2204,6 +2209,7 @@ |
2204 | 2209 | extern int sun4v_hvapi_get(unsigned long group, |
2205 | 2210 | unsigned long *major, |
2206 | 2211 | unsigned long *minor); |
2212 | +extern void sun4v_hvapi_init(void); | |
2207 | 2213 | #endif |
2208 | 2214 | |
2209 | 2215 | #endif /* !(_SPARC64_HYPERVISOR_H) */ |
include/asm-sparc64/oplib.h
... | ... | @@ -316,6 +316,8 @@ |
316 | 316 | |
317 | 317 | extern int prom_pathtoinode(const char *path); |
318 | 318 | extern int prom_inst2pkg(int); |
319 | +extern int prom_service_exists(const char *service_name); | |
320 | +extern void prom_sun4v_guest_soft_state(void); | |
319 | 321 | |
320 | 322 | /* CPU probing helpers. */ |
321 | 323 | struct device_node; |
include/asm-sparc64/sstate.h
1 | +#ifndef _SPARC64_SSTATE_H | |
2 | +#define _SPARC64_SSTATE_H | |
3 | + | |
4 | +extern void sstate_booting(void); | |
5 | +extern void sstate_running(void); | |
6 | +extern void sstate_halt(void); | |
7 | +extern void sstate_poweroff(void); | |
8 | +extern void sstate_panic(void); | |
9 | +extern void sstate_reboot(void); | |
10 | + | |
11 | +extern void sun4v_sstate_init(void); | |
12 | + | |
13 | +#endif /* _SPARC64_SSTATE_H */ |