|
@@ -49,24 +49,13 @@ struct hv_context hv_context = {
|
|
|
*/
|
|
|
int hv_init(void)
|
|
|
{
|
|
|
-
|
|
|
- memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
|
|
|
- memset(hv_context.synic_message_page, 0,
|
|
|
- sizeof(void *) * NR_CPUS);
|
|
|
- memset(hv_context.post_msg_page, 0,
|
|
|
- sizeof(void *) * NR_CPUS);
|
|
|
- memset(hv_context.vp_index, 0,
|
|
|
- sizeof(int) * NR_CPUS);
|
|
|
- memset(hv_context.event_dpc, 0,
|
|
|
- sizeof(void *) * NR_CPUS);
|
|
|
- memset(hv_context.msg_dpc, 0,
|
|
|
- sizeof(void *) * NR_CPUS);
|
|
|
- memset(hv_context.clk_evt, 0,
|
|
|
- sizeof(void *) * NR_CPUS);
|
|
|
-
|
|
|
if (!hv_is_hypercall_page_setup())
|
|
|
return -ENOTSUPP;
|
|
|
|
|
|
+ hv_context.cpu_context = alloc_percpu(struct hv_per_cpu_context);
|
|
|
+ if (!hv_context.cpu_context)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -79,25 +68,24 @@ int hv_post_message(union hv_connection_id connection_id,
|
|
|
enum hv_message_type message_type,
|
|
|
void *payload, size_t payload_size)
|
|
|
{
|
|
|
-
|
|
|
struct hv_input_post_message *aligned_msg;
|
|
|
+ struct hv_per_cpu_context *hv_cpu;
|
|
|
u64 status;
|
|
|
|
|
|
if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
- aligned_msg = (struct hv_input_post_message *)
|
|
|
- hv_context.post_msg_page[get_cpu()];
|
|
|
-
|
|
|
+ hv_cpu = get_cpu_ptr(hv_context.cpu_context);
|
|
|
+ aligned_msg = hv_cpu->post_msg_page;
|
|
|
aligned_msg->connectionid = connection_id;
|
|
|
aligned_msg->reserved = 0;
|
|
|
aligned_msg->message_type = message_type;
|
|
|
aligned_msg->payload_size = payload_size;
|
|
|
memcpy((void *)aligned_msg->payload, payload, payload_size);
|
|
|
+ put_cpu_ptr(hv_cpu);
|
|
|
|
|
|
status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL);
|
|
|
|
|
|
- put_cpu();
|
|
|
return status & 0xFFFF;
|
|
|
}
|
|
|
|
|
@@ -154,8 +142,6 @@ static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu)
|
|
|
|
|
|
int hv_synic_alloc(void)
|
|
|
{
|
|
|
- size_t size = sizeof(struct tasklet_struct);
|
|
|
- size_t ced_size = sizeof(struct clock_event_device);
|
|
|
int cpu;
|
|
|
|
|
|
hv_context.hv_numa_map = kzalloc(sizeof(struct cpumask) * nr_node_ids,
|
|
@@ -166,53 +152,43 @@ int hv_synic_alloc(void)
|
|
|
}
|
|
|
|
|
|
for_each_present_cpu(cpu) {
|
|
|
- hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
|
|
|
- if (hv_context.event_dpc[cpu] == NULL) {
|
|
|
- pr_err("Unable to allocate event dpc\n");
|
|
|
- goto err;
|
|
|
- }
|
|
|
- tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu);
|
|
|
-
|
|
|
- hv_context.msg_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
|
|
|
- if (hv_context.msg_dpc[cpu] == NULL) {
|
|
|
- pr_err("Unable to allocate event dpc\n");
|
|
|
- goto err;
|
|
|
- }
|
|
|
- tasklet_init(hv_context.msg_dpc[cpu], vmbus_on_msg_dpc, cpu);
|
|
|
-
|
|
|
- hv_context.clk_evt[cpu] = kzalloc(ced_size, GFP_ATOMIC);
|
|
|
- if (hv_context.clk_evt[cpu] == NULL) {
|
|
|
+ struct hv_per_cpu_context *hv_cpu
|
|
|
+ = per_cpu_ptr(hv_context.cpu_context, cpu);
|
|
|
+
|
|
|
+ memset(hv_cpu, 0, sizeof(*hv_cpu));
|
|
|
+ tasklet_init(&hv_cpu->event_dpc,
|
|
|
+ vmbus_on_event, (unsigned long) hv_cpu);
|
|
|
+ tasklet_init(&hv_cpu->msg_dpc,
|
|
|
+ vmbus_on_msg_dpc, (unsigned long) hv_cpu);
|
|
|
+
|
|
|
+ hv_cpu->clk_evt = kzalloc(sizeof(struct clock_event_device),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (hv_cpu->clk_evt == NULL) {
|
|
|
pr_err("Unable to allocate clock event device\n");
|
|
|
goto err;
|
|
|
}
|
|
|
+ hv_init_clockevent_device(hv_cpu->clk_evt, cpu);
|
|
|
|
|
|
- hv_init_clockevent_device(hv_context.clk_evt[cpu], cpu);
|
|
|
-
|
|
|
- hv_context.synic_message_page[cpu] =
|
|
|
+ hv_cpu->synic_message_page =
|
|
|
(void *)get_zeroed_page(GFP_ATOMIC);
|
|
|
-
|
|
|
- if (hv_context.synic_message_page[cpu] == NULL) {
|
|
|
+ if (hv_cpu->synic_message_page == NULL) {
|
|
|
pr_err("Unable to allocate SYNIC message page\n");
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- hv_context.synic_event_page[cpu] =
|
|
|
- (void *)get_zeroed_page(GFP_ATOMIC);
|
|
|
-
|
|
|
- if (hv_context.synic_event_page[cpu] == NULL) {
|
|
|
+ hv_cpu->synic_event_page = (void *)get_zeroed_page(GFP_ATOMIC);
|
|
|
+ if (hv_cpu->synic_event_page == NULL) {
|
|
|
pr_err("Unable to allocate SYNIC event page\n");
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- hv_context.post_msg_page[cpu] =
|
|
|
- (void *)get_zeroed_page(GFP_ATOMIC);
|
|
|
-
|
|
|
- if (hv_context.post_msg_page[cpu] == NULL) {
|
|
|
+ hv_cpu->post_msg_page = (void *)get_zeroed_page(GFP_ATOMIC);
|
|
|
+ if (hv_cpu->post_msg_page == NULL) {
|
|
|
pr_err("Unable to allocate post msg page\n");
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- INIT_LIST_HEAD(&hv_context.percpu_list[cpu]);
|
|
|
+ INIT_LIST_HEAD(&hv_cpu->chan_list);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -220,26 +196,24 @@ err:
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
-static void hv_synic_free_cpu(int cpu)
|
|
|
-{
|
|
|
- kfree(hv_context.event_dpc[cpu]);
|
|
|
- kfree(hv_context.msg_dpc[cpu]);
|
|
|
- kfree(hv_context.clk_evt[cpu]);
|
|
|
- if (hv_context.synic_event_page[cpu])
|
|
|
- free_page((unsigned long)hv_context.synic_event_page[cpu]);
|
|
|
- if (hv_context.synic_message_page[cpu])
|
|
|
- free_page((unsigned long)hv_context.synic_message_page[cpu]);
|
|
|
- if (hv_context.post_msg_page[cpu])
|
|
|
- free_page((unsigned long)hv_context.post_msg_page[cpu]);
|
|
|
-}
|
|
|
|
|
|
void hv_synic_free(void)
|
|
|
{
|
|
|
int cpu;
|
|
|
|
|
|
+ for_each_present_cpu(cpu) {
|
|
|
+ struct hv_per_cpu_context *hv_cpu
|
|
|
+ = per_cpu_ptr(hv_context.cpu_context, cpu);
|
|
|
+
|
|
|
+ if (hv_cpu->synic_event_page)
|
|
|
+ free_page((unsigned long)hv_cpu->synic_event_page);
|
|
|
+ if (hv_cpu->synic_message_page)
|
|
|
+ free_page((unsigned long)hv_cpu->synic_message_page);
|
|
|
+ if (hv_cpu->post_msg_page)
|
|
|
+ free_page((unsigned long)hv_cpu->post_msg_page);
|
|
|
+ }
|
|
|
+
|
|
|
kfree(hv_context.hv_numa_map);
|
|
|
- for_each_present_cpu(cpu)
|
|
|
- hv_synic_free_cpu(cpu);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -251,6 +225,8 @@ void hv_synic_free(void)
|
|
|
*/
|
|
|
int hv_synic_init(unsigned int cpu)
|
|
|
{
|
|
|
+ struct hv_per_cpu_context *hv_cpu
|
|
|
+ = per_cpu_ptr(hv_context.cpu_context, cpu);
|
|
|
union hv_synic_simp simp;
|
|
|
union hv_synic_siefp siefp;
|
|
|
union hv_synic_sint shared_sint;
|
|
@@ -260,7 +236,7 @@ int hv_synic_init(unsigned int cpu)
|
|
|
/* Setup the Synic's message page */
|
|
|
hv_get_simp(simp.as_uint64);
|
|
|
simp.simp_enabled = 1;
|
|
|
- simp.base_simp_gpa = virt_to_phys(hv_context.synic_message_page[cpu])
|
|
|
+ simp.base_simp_gpa = virt_to_phys(hv_cpu->synic_message_page)
|
|
|
>> PAGE_SHIFT;
|
|
|
|
|
|
hv_set_simp(simp.as_uint64);
|
|
@@ -268,7 +244,7 @@ int hv_synic_init(unsigned int cpu)
|
|
|
/* Setup the Synic's event page */
|
|
|
hv_get_siefp(siefp.as_uint64);
|
|
|
siefp.siefp_enabled = 1;
|
|
|
- siefp.base_siefp_gpa = virt_to_phys(hv_context.synic_event_page[cpu])
|
|
|
+ siefp.base_siefp_gpa = virt_to_phys(hv_cpu->synic_event_page)
|
|
|
>> PAGE_SHIFT;
|
|
|
|
|
|
hv_set_siefp(siefp.as_uint64);
|
|
@@ -305,7 +281,7 @@ int hv_synic_init(unsigned int cpu)
|
|
|
* Register the per-cpu clockevent source.
|
|
|
*/
|
|
|
if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE)
|
|
|
- clockevents_config_and_register(hv_context.clk_evt[cpu],
|
|
|
+ clockevents_config_and_register(hv_cpu->clk_evt,
|
|
|
HV_TIMER_FREQUENCY,
|
|
|
HV_MIN_DELTA_TICKS,
|
|
|
HV_MAX_MAX_DELTA_TICKS);
|
|
@@ -322,8 +298,12 @@ void hv_synic_clockevents_cleanup(void)
|
|
|
if (!(ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE))
|
|
|
return;
|
|
|
|
|
|
- for_each_present_cpu(cpu)
|
|
|
- clockevents_unbind_device(hv_context.clk_evt[cpu], cpu);
|
|
|
+ for_each_present_cpu(cpu) {
|
|
|
+ struct hv_per_cpu_context *hv_cpu
|
|
|
+ = per_cpu_ptr(hv_context.cpu_context, cpu);
|
|
|
+
|
|
|
+ clockevents_unbind_device(hv_cpu->clk_evt, cpu);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -372,8 +352,12 @@ int hv_synic_cleanup(unsigned int cpu)
|
|
|
|
|
|
/* Turn off clockevent device */
|
|
|
if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE) {
|
|
|
- clockevents_unbind_device(hv_context.clk_evt[cpu], cpu);
|
|
|
- hv_ce_shutdown(hv_context.clk_evt[cpu]);
|
|
|
+ struct hv_per_cpu_context *hv_cpu
|
|
|
+ = this_cpu_ptr(hv_context.cpu_context);
|
|
|
+
|
|
|
+ clockevents_unbind_device(hv_cpu->clk_evt, cpu);
|
|
|
+ hv_ce_shutdown(hv_cpu->clk_evt);
|
|
|
+ put_cpu_ptr(hv_cpu);
|
|
|
}
|
|
|
|
|
|
hv_get_synint_state(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT,
|