vmbus_drv.c (ecb41832bd2a7a3f8ac93527cec5e51e3827daed) | vmbus_drv.c (eec4844fae7c033a0c1fc1eb3b8517aeb8b6cc49) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2009, Microsoft Corporation. 4 * 5 * Authors: 6 * Haiyang Zhang <haiyangz@microsoft.com> 7 * Hank Janssen <hjanssen@microsoft.com> 8 * K. Y. Srinivasan <kys@microsoft.com> --- 16 unchanged lines hidden (view full) --- 25 26#include <asm/mshyperv.h> 27#include <linux/notifier.h> 28#include <linux/ptrace.h> 29#include <linux/screen_info.h> 30#include <linux/kdebug.h> 31#include <linux/efi.h> 32#include <linux/random.h> | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2009, Microsoft Corporation. 4 * 5 * Authors: 6 * Haiyang Zhang <haiyangz@microsoft.com> 7 * Hank Janssen <hjanssen@microsoft.com> 8 * K. Y. Srinivasan <kys@microsoft.com> --- 16 unchanged lines hidden (view full) --- 25 26#include <asm/mshyperv.h> 27#include <linux/notifier.h> 28#include <linux/ptrace.h> 29#include <linux/screen_info.h> 30#include <linux/kdebug.h> 31#include <linux/efi.h> 32#include <linux/random.h> |
33#include <clocksource/hyperv_timer.h> |
|
33#include "hyperv_vmbus.h" 34 35struct vmbus_dynid { 36 struct list_head node; 37 struct hv_vmbus_device_id id; 38}; 39 40static struct acpi_device *hv_acpi_dev; --- 909 unchanged lines hidden (view full) --- 950 return; 951 952 ctx = container_of(work, struct onmessage_work_context, 953 work); 954 vmbus_onmessage(&ctx->msg); 955 kfree(ctx); 956} 957 | 34#include "hyperv_vmbus.h" 35 36struct vmbus_dynid { 37 struct list_head node; 38 struct hv_vmbus_device_id id; 39}; 40 41static struct acpi_device *hv_acpi_dev; --- 909 unchanged lines hidden (view full) --- 951 return; 952 953 ctx = container_of(work, struct onmessage_work_context, 954 work); 955 vmbus_onmessage(&ctx->msg); 956 kfree(ctx); 957} 958 |
958static void hv_process_timer_expiration(struct hv_message *msg, 959 struct hv_per_cpu_context *hv_cpu) 960{ 961 struct clock_event_device *dev = hv_cpu->clk_evt; 962 963 if (dev->event_handler) 964 dev->event_handler(dev); 965 966 vmbus_signal_eom(msg, HVMSG_TIMER_EXPIRED); 967} 968 | |
969void vmbus_on_msg_dpc(unsigned long data) 970{ 971 struct hv_per_cpu_context *hv_cpu = (void *)data; 972 void *page_addr = hv_cpu->synic_message_page; 973 struct hv_message *msg = (struct hv_message *)page_addr + 974 VMBUS_MESSAGE_SINT; 975 struct vmbus_channel_message_header *hdr; 976 const struct vmbus_channel_message_table_entry *entry; --- 177 unchanged lines hidden (view full) --- 1154 if (handled) 1155 vmbus_chan_sched(hv_cpu); 1156 1157 page_addr = hv_cpu->synic_message_page; 1158 msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; 1159 1160 /* Check if there are actual msgs to be processed */ 1161 if (msg->header.message_type != HVMSG_NONE) { | 959void vmbus_on_msg_dpc(unsigned long data) 960{ 961 struct hv_per_cpu_context *hv_cpu = (void *)data; 962 void *page_addr = hv_cpu->synic_message_page; 963 struct hv_message *msg = (struct hv_message *)page_addr + 964 VMBUS_MESSAGE_SINT; 965 struct vmbus_channel_message_header *hdr; 966 const struct vmbus_channel_message_table_entry *entry; --- 177 unchanged lines hidden (view full) --- 1144 if (handled) 1145 vmbus_chan_sched(hv_cpu); 1146 1147 page_addr = hv_cpu->synic_message_page; 1148 msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; 1149 1150 /* Check if there are actual msgs to be processed */ 1151 if (msg->header.message_type != HVMSG_NONE) { |
1162 if (msg->header.message_type == HVMSG_TIMER_EXPIRED) 1163 hv_process_timer_expiration(msg, hv_cpu); 1164 else | 1152 if (msg->header.message_type == HVMSG_TIMER_EXPIRED) { 1153 hv_stimer0_isr(); 1154 vmbus_signal_eom(msg, HVMSG_TIMER_EXPIRED); 1155 } else |
1165 tasklet_schedule(&hv_cpu->msg_dpc); 1166 } 1167 1168 add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0); 1169} 1170 1171/* 1172 * Boolean to control whether to report panic messages over Hyper-V. --- 28 unchanged lines hidden (view full) --- 1201 hyperv_report_panic_msg(panic_pa, bytes_written); 1202} 1203 1204static struct kmsg_dumper hv_kmsg_dumper = { 1205 .dump = hv_kmsg_dump, 1206}; 1207 1208static struct ctl_table_header *hv_ctl_table_hdr; | 1156 tasklet_schedule(&hv_cpu->msg_dpc); 1157 } 1158 1159 add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0); 1160} 1161 1162/* 1163 * Boolean to control whether to report panic messages over Hyper-V. --- 28 unchanged lines hidden (view full) --- 1192 hyperv_report_panic_msg(panic_pa, bytes_written); 1193} 1194 1195static struct kmsg_dumper hv_kmsg_dumper = { 1196 .dump = hv_kmsg_dump, 1197}; 1198 1199static struct ctl_table_header *hv_ctl_table_hdr; |
1209static int zero; 1210static int one = 1; | |
1211 1212/* 1213 * sysctl option to allow the user to control whether kmsg data should be 1214 * reported to Hyper-V on panic. 1215 */ 1216static struct ctl_table hv_ctl_table[] = { 1217 { 1218 .procname = "hyperv_record_panic_msg", 1219 .data = &sysctl_record_panic_msg, 1220 .maxlen = sizeof(int), 1221 .mode = 0644, 1222 .proc_handler = proc_dointvec_minmax, | 1200 1201/* 1202 * sysctl option to allow the user to control whether kmsg data should be 1203 * reported to Hyper-V on panic. 1204 */ 1205static struct ctl_table hv_ctl_table[] = { 1206 { 1207 .procname = "hyperv_record_panic_msg", 1208 .data = &sysctl_record_panic_msg, 1209 .maxlen = sizeof(int), 1210 .mode = 0644, 1211 .proc_handler = proc_dointvec_minmax, |
1223 .extra1 = &zero, 1224 .extra2 = &one | 1212 .extra1 = SYSCTL_ZERO, 1213 .extra2 = SYSCTL_ONE |
1225 }, 1226 {} 1227}; 1228 1229static struct ctl_table hv_root_table[] = { 1230 { 1231 .procname = "kernel", 1232 .mode = 0555, --- 25 unchanged lines hidden (view full) --- 1258 if (ret) 1259 return ret; 1260 1261 hv_setup_vmbus_irq(vmbus_isr); 1262 1263 ret = hv_synic_alloc(); 1264 if (ret) 1265 goto err_alloc; | 1214 }, 1215 {} 1216}; 1217 1218static struct ctl_table hv_root_table[] = { 1219 { 1220 .procname = "kernel", 1221 .mode = 0555, --- 25 unchanged lines hidden (view full) --- 1247 if (ret) 1248 return ret; 1249 1250 hv_setup_vmbus_irq(vmbus_isr); 1251 1252 ret = hv_synic_alloc(); 1253 if (ret) 1254 goto err_alloc; |
1255 1256 ret = hv_stimer_alloc(VMBUS_MESSAGE_SINT); 1257 if (ret < 0) 1258 goto err_alloc; 1259 |
|
1266 /* | 1260 /* |
1267 * Initialize the per-cpu interrupt state and 1268 * connect to the host. | 1261 * Initialize the per-cpu interrupt state and stimer state. 1262 * Then connect to the host. |
1269 */ 1270 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online", 1271 hv_synic_init, hv_synic_cleanup); 1272 if (ret < 0) | 1263 */ 1264 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online", 1265 hv_synic_init, hv_synic_cleanup); 1266 if (ret < 0) |
1273 goto err_alloc; | 1267 goto err_cpuhp; |
1274 hyperv_cpuhp_online = ret; 1275 1276 ret = vmbus_connect(); 1277 if (ret) 1278 goto err_connect; 1279 1280 /* 1281 * Only register if the crash MSRs are available --- 31 unchanged lines hidden (view full) --- 1313 } 1314 1315 vmbus_request_offers(); 1316 1317 return 0; 1318 1319err_connect: 1320 cpuhp_remove_state(hyperv_cpuhp_online); | 1268 hyperv_cpuhp_online = ret; 1269 1270 ret = vmbus_connect(); 1271 if (ret) 1272 goto err_connect; 1273 1274 /* 1275 * Only register if the crash MSRs are available --- 31 unchanged lines hidden (view full) --- 1307 } 1308 1309 vmbus_request_offers(); 1310 1311 return 0; 1312 1313err_connect: 1314 cpuhp_remove_state(hyperv_cpuhp_online); |
1315err_cpuhp: 1316 hv_stimer_free(); |
|
1321err_alloc: 1322 hv_synic_free(); 1323 hv_remove_vmbus_irq(); 1324 1325 bus_unregister(&hv_bus); 1326 free_page((unsigned long)hv_panic_page); 1327 unregister_sysctl_table(hv_ctl_table_hdr); 1328 hv_ctl_table_hdr = NULL; --- 730 unchanged lines hidden (view full) --- 2059 .ops = { 2060 .add = vmbus_acpi_add, 2061 .remove = vmbus_acpi_remove, 2062 }, 2063}; 2064 2065static void hv_kexec_handler(void) 2066{ | 1317err_alloc: 1318 hv_synic_free(); 1319 hv_remove_vmbus_irq(); 1320 1321 bus_unregister(&hv_bus); 1322 free_page((unsigned long)hv_panic_page); 1323 unregister_sysctl_table(hv_ctl_table_hdr); 1324 hv_ctl_table_hdr = NULL; --- 730 unchanged lines hidden (view full) --- 2055 .ops = { 2056 .add = vmbus_acpi_add, 2057 .remove = vmbus_acpi_remove, 2058 }, 2059}; 2060 2061static void hv_kexec_handler(void) 2062{ |
2067 hv_synic_clockevents_cleanup(); | 2063 hv_stimer_global_cleanup(); |
2068 vmbus_initiate_unload(false); 2069 vmbus_connection.conn_state = DISCONNECTED; 2070 /* Make sure conn_state is set as hv_synic_cleanup checks for it */ 2071 mb(); 2072 cpuhp_remove_state(hyperv_cpuhp_online); 2073 hyperv_cleanup(); 2074}; 2075 2076static void hv_crash_handler(struct pt_regs *regs) 2077{ | 2064 vmbus_initiate_unload(false); 2065 vmbus_connection.conn_state = DISCONNECTED; 2066 /* Make sure conn_state is set as hv_synic_cleanup checks for it */ 2067 mb(); 2068 cpuhp_remove_state(hyperv_cpuhp_online); 2069 hyperv_cleanup(); 2070}; 2071 2072static void hv_crash_handler(struct pt_regs *regs) 2073{ |
2074 int cpu; 2075 |
|
2078 vmbus_initiate_unload(true); 2079 /* 2080 * In crash handler we can't schedule synic cleanup for all CPUs, 2081 * doing the cleanup for current CPU only. This should be sufficient 2082 * for kdump. 2083 */ 2084 vmbus_connection.conn_state = DISCONNECTED; | 2076 vmbus_initiate_unload(true); 2077 /* 2078 * In crash handler we can't schedule synic cleanup for all CPUs, 2079 * doing the cleanup for current CPU only. This should be sufficient 2080 * for kdump. 2081 */ 2082 vmbus_connection.conn_state = DISCONNECTED; |
2085 hv_synic_cleanup(smp_processor_id()); | 2083 cpu = smp_processor_id(); 2084 hv_stimer_cleanup(cpu); 2085 hv_synic_cleanup(cpu); |
2086 hyperv_cleanup(); 2087}; 2088 2089static int __init hv_acpi_init(void) 2090{ 2091 int ret, t; 2092 2093 if (!hv_is_hyperv_initialized()) --- 32 unchanged lines hidden (view full) --- 2126 2127static void __exit vmbus_exit(void) 2128{ 2129 int cpu; 2130 2131 hv_remove_kexec_handler(); 2132 hv_remove_crash_handler(); 2133 vmbus_connection.conn_state = DISCONNECTED; | 2086 hyperv_cleanup(); 2087}; 2088 2089static int __init hv_acpi_init(void) 2090{ 2091 int ret, t; 2092 2093 if (!hv_is_hyperv_initialized()) --- 32 unchanged lines hidden (view full) --- 2126 2127static void __exit vmbus_exit(void) 2128{ 2129 int cpu; 2130 2131 hv_remove_kexec_handler(); 2132 hv_remove_crash_handler(); 2133 vmbus_connection.conn_state = DISCONNECTED; |
2134 hv_synic_clockevents_cleanup(); | 2134 hv_stimer_global_cleanup(); |
2135 vmbus_disconnect(); 2136 hv_remove_vmbus_irq(); 2137 for_each_online_cpu(cpu) { 2138 struct hv_per_cpu_context *hv_cpu 2139 = per_cpu_ptr(hv_context.cpu_context, cpu); 2140 2141 tasklet_kill(&hv_cpu->msg_dpc); 2142 } --- 13 unchanged lines hidden (view full) --- 2156 2157 cpuhp_remove_state(hyperv_cpuhp_online); 2158 hv_synic_free(); 2159 acpi_bus_unregister_driver(&vmbus_acpi_driver); 2160} 2161 2162 2163MODULE_LICENSE("GPL"); | 2135 vmbus_disconnect(); 2136 hv_remove_vmbus_irq(); 2137 for_each_online_cpu(cpu) { 2138 struct hv_per_cpu_context *hv_cpu 2139 = per_cpu_ptr(hv_context.cpu_context, cpu); 2140 2141 tasklet_kill(&hv_cpu->msg_dpc); 2142 } --- 13 unchanged lines hidden (view full) --- 2156 2157 cpuhp_remove_state(hyperv_cpuhp_online); 2158 hv_synic_free(); 2159 acpi_bus_unregister_driver(&vmbus_acpi_driver); 2160} 2161 2162 2163MODULE_LICENSE("GPL"); |
2164MODULE_DESCRIPTION("Microsoft Hyper-V VMBus Driver"); |
|
2164 2165subsys_initcall(hv_acpi_init); 2166module_exit(vmbus_exit); | 2165 2166subsys_initcall(hv_acpi_init); 2167module_exit(vmbus_exit); |