Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Drivers: hv: Introduce per-cpu event ring tail

Add a pointer hv_synic_eventring_tail to track the tail pointer for the
SynIC event ring buffer for each SINT.

This will be used by the mshv driver, but must be tracked independently
since the driver module could be removed and re-inserted.

Signed-off-by: Nuno Das Neves <nunodasneves@linux.microsoft.com>
Reviewed-by: Wei Liu <wei.liu@kernel.org>
Reviewed-by: Stanislav Kinsburskii <skinsburskii@linux.microsoft.com>
Link: https://lore.kernel.org/r/1741980536-3865-8-git-send-email-nunodasneves@linux.microsoft.com
Signed-off-by: Wei Liu <wei.liu@kernel.org>
Message-ID: <1741980536-3865-8-git-send-email-nunodasneves@linux.microsoft.com>

authored by

Nuno Das Neves and committed by
Wei Liu
04df7ac3 21050f61

+37 -4
+37 -4
drivers/hv/hv_common.c
··· 69 69 static struct ctl_table_header *hv_ctl_table_hdr; 70 70 71 71 /* 72 + * Per-cpu array holding the tail pointer for the SynIC event ring buffer 73 + * for each SINT. 74 + * 75 + * We cannot maintain this in mshv driver because the tail pointer should 76 + * persist even if the mshv driver is unloaded. 77 + */ 78 + u8 * __percpu *hv_synic_eventring_tail; 79 + EXPORT_SYMBOL_GPL(hv_synic_eventring_tail); 80 + 81 + /* 72 82 * Hyper-V specific initialization and shutdown code that is 73 83 * common across all architectures. Called from architecture 74 84 * specific initialization functions. ··· 100 90 101 91 free_percpu(hyperv_pcpu_input_arg); 102 92 hyperv_pcpu_input_arg = NULL; 93 + 94 + free_percpu(hv_synic_eventring_tail); 95 + hv_synic_eventring_tail = NULL; 103 96 } 104 97 105 98 /* ··· 385 372 BUG_ON(!hyperv_pcpu_output_arg); 386 373 } 387 374 375 + if (hv_root_partition()) { 376 + hv_synic_eventring_tail = alloc_percpu(u8 *); 377 + BUG_ON(!hv_synic_eventring_tail); 378 + } 379 + 388 380 hv_vp_index = kmalloc_array(nr_cpu_ids, sizeof(*hv_vp_index), 389 381 GFP_KERNEL); 390 382 if (!hv_vp_index) { ··· 478 460 int hv_common_cpu_init(unsigned int cpu) 479 461 { 480 462 void **inputarg, **outputarg; 463 + u8 **synic_eventring_tail; 481 464 u64 msr_vp_index; 482 465 gfp_t flags; 483 466 const int pgcount = hv_output_page_exists() ? 2 : 1; 484 467 void *mem; 485 - int ret; 468 + int ret = 0; 486 469 487 470 /* hv_cpu_init() can be called with IRQs disabled from hv_resume() */ 488 471 flags = irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL; ··· 491 472 inputarg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg); 492 473 493 474 /* 494 - * hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory is already 495 - * allocated if this CPU was previously online and then taken offline 475 + * The per-cpu memory is already allocated if this CPU was previously 476 + * online and then taken offline 496 477 */ 497 478 if (!*inputarg) { 498 479 mem = kmalloc(pgcount * HV_HYP_PAGE_SIZE, flags); ··· 539 520 if (msr_vp_index > hv_max_vp_index) 540 521 hv_max_vp_index = msr_vp_index; 541 522 542 - return 0; 523 + if (hv_root_partition()) { 524 + synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); 525 + *synic_eventring_tail = kcalloc(HV_SYNIC_SINT_COUNT, 526 + sizeof(u8), flags); 527 + /* No need to unwind any of the above on failure here */ 528 + if (unlikely(!*synic_eventring_tail)) 529 + ret = -ENOMEM; 530 + } 531 + 532 + return ret; 543 533 } 544 534 545 535 int hv_common_cpu_die(unsigned int cpu) 546 536 { 537 + u8 **synic_eventring_tail; 547 538 /* 548 539 * The hyperv_pcpu_input_arg and hyperv_pcpu_output_arg memory 549 540 * is not freed when the CPU goes offline as the hyperv_pcpu_input_arg ··· 565 536 * If a previously offlined CPU is brought back online again, the 566 537 * originally allocated memory is reused in hv_common_cpu_init(). 567 538 */ 539 + 540 + synic_eventring_tail = this_cpu_ptr(hv_synic_eventring_tail); 541 + kfree(*synic_eventring_tail); 542 + *synic_eventring_tail = NULL; 568 543 569 544 return 0; 570 545 }