From nobody Fri Sep 25 00:40:14 2026 Received: from mail-qv2-f12.google.com (mail-qv2-f12.google.com [74.125.230.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E483339E184 for ; Fri, 18 Sep 2026 01:40:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.230.140 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789695628; cv=none; b=StTKWx/VYq4Ybv8iMqJ/DAvPKSf/s9m9cdptNg4KsIsdvup0B7WZzBrvY63HIYTKIQEZ4Dkw42gYkPQ18YNa6ACuCabBiI6FYJD59WJ2VR9iCseutL2jPFY4XeDeS8brktmrYmZ4IS4b4onKoyMGStQ4jDEf5/izalcX3X2vUgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789695628; c=relaxed/simple; bh=yTYDUqcwFkJ+mQb7ZSXeToQmp7rvyhF0lR3QiMuHDOk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tq7DME+1Iqlw4oOxlMmKsAyuaFWJbBbrxmR1CuZDG2nGVHqrzcTRf8nbEuaTzbjMRbeGPuerMJFus/LKwH0Qbph7IOGePzhTqyUL5vXSBbuh/vDCDJ82DmGRISffeO5l/U5r54qSes2/fTjai5dbBgNrJj+JotEF6belrF4rCIo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=G3cKMRhH; arc=none smtp.client-ip=74.125.230.140 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G3cKMRhH" Received: by mail-qv2-f12.google.com with SMTP id 6a1803df08f44-90cdfbd148aso2562536d6.2 for ; Thu, 17 Sep 2026 18:40:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789695624; x=1790300424; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=VokQt3PCInSeNOo/Tg+pYrBPXpRCo2iy3+S4MYEH2ts=; b=G3cKMRhHmK/SGKz0h0viXnysKeawPZSfE4NhKkKDoPDD0qJlZfBj0RnUSFuVigMOIx x2fOlu1UtX4SLyOykAdsVbaXxSlJ6Kx6KRYubvsLi48YKMkR9it0eAMtJjdS5+kuT0U2 TN/fi5RIp6/5S4jgDjgpxy39/GhayU3LQe0q+e906uJuIa9KJn6no07zV/6eeevSqWY5 4GEKGSAvYsXndGjU4PcluIs0/vpHXrncI22bivrIEPutREW9wHg72ASizTxRfJ+V+fsk AjH/0xTORnkqE8NB/WqLYYFzSTyOgkz3bAJN4x3tgWK4cKP5aUMDs0D2SeT46ZBciWSk XSdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789695624; x=1790300424; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=VokQt3PCInSeNOo/Tg+pYrBPXpRCo2iy3+S4MYEH2ts=; b=pO97IgarJuI1TJwdE6ym9SGp4K1aVQiRFP3ZGcJIOnowyHgRJ8PEJQGf/xN6dV08SK WKVXuFuYzaMrlkPhdvDX2uI9uOQEHUQp8GD874TgfiOBnTuuTWlzu6hBChiQX6kuAuHZ aTwx2jv5WlDksc2MoHLRZlmbhxUjjJZAuhuXlxsjxJAL7sd4WNn3IMbFE5IQBg4OmkQ3 xuPCxJfaYlhu9he2ia6d8y7SG1CshNE8BMGQ7taEN9KfJVHcsTtz7p3MJiwArFzUXFsA 39A/TMrVL8841vnNPQkSyd4OEuxdnwLQ4up6mUV4qIW3dknhsvTBGw5rhbh+n7QDzFKx WPiQ== X-Forwarded-Encrypted: i=1; AKwUvBy2spMyB4RuY52Keu8wGJRbbPcZ4wuXWrgbakuozKKURgUaK2EvwevppvWTRIMVJVvxh4NCBcmtFzyIK1A=@vger.kernel.org X-Gm-Message-State: AFuF++kmDjUVNdF6irn8ifMpMzXkOiNxyufArYWvtqFvoJ0ugVu8xphD bn9dQj11V3khYnsxacLlvBMw3AnJm7uRywmwh3ynB1ehD1gWYP/HmMk3 X-Gm-Gg: AYBFou13AVb7GYKp4Epc8hy390oj6Xi/e5Vkuuu5P1nTu7LfyEeiLNYqUy8H7ZirubD bU/NSx6jkFTgI1F3WdH2xA+Fma668NU4JdtQ2BNqcHS62BXFuMU/2Ao91RTvHqidrcxDzxrbnY6 rThnmbbo2/gHidl7j9+2E8sUrVoeqa/w+EpFWXHL4KYp8MEp39wbYAx4XWlUSNdCpTM0Kv5w+2o YtyJ+cUe2hWchya6JPdUDDxOBMwAjoKoS9yq568P/dWSDajowoZOBhIno5gbJ+eEzM2Isa6hUGG uzEptd8+AaWJDZDhNk5bBosVTFltOD9KPIz6vcn56JNBBgQGnFCnDLEGaX8lDsK10FE+KXmmIRw HxhE8JzXylzwWvwtGOqj6GTGxwhYhiSHWrUH3pf/nTkr551fPuWw3fUFkpB0EXnl98b1ylnEhF3 pMScsrABY08+RqZVffI0n60hjtTTqnMK96vay0ARTSvaNYXAxwnj1+O9CccWUr69r/ZmxnPbUaP ofFPuXO85+DsoImzE/Apg== X-Received: by 2002:a05:620a:3187:b0:93b:cb6d:6d73 with SMTP id af79cd13be357-93bdc730deemr128890985a.32.1789695624426; Thu, 17 Sep 2026 18:40:24 -0700 (PDT) Received: from emedev.tailf75c28.ts.net ([148.222.209.140]) by smtp.gmail.com with ESMTPSA id af79cd13be357-93be0e4f987sm13002285a.14.2026.09.17.18.40.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Sep 2026 18:40:23 -0700 (PDT) From: Emerson Busson To: linux-hyperv@vger.kernel.org Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org, decui@microsoft.com, linux-kernel@vger.kernel.org, emersonbusson@gmail.com Subject: [PATCH 1/2] hv: vmbus: prevent control-plane starvation and balloon thrash under memory pressure Date: Thu, 17 Sep 2026 22:40:16 -0300 Message-ID: <20260918014017.2536753-2-emersonbusson@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260918014017.2536753-1-emersonbusson@gmail.com> References: <20260918014017.2536753-1-emersonbusson@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Under Microsoft WSL2 and Hyper-V guest environments, workloads generating heavy memory allocation and rapid page dirtiness can drive the guest kernel into aggressive direct reclaim. When guest available memory drops below critical thresholds (~400-512 MB), atomic page allocations (GFP_ATOMIC) for synthetic VMBus packet rings, virtual networking (netvsc), and balloon management fail. Because the guest is unable to allocate atomic buffers to service host heartbeats, the Windows Host Compute System (HCS) and Hyper-V watchdog infer that the guest kernel has hard-locked. This triggers an abrupt virtual network switch teardown (Hyper-V-VmSwitch Event 102/291) and forces a VM restart before the guest Linux OOM killer can intervene. Furthermore, under such memory pressure, the host balloon driver may simultaneously request balloon inflation, exacerbating memory starvation. This patch addresses the issue in two architecture-neutral ways: 1. Auto-calibrates `vm.min_free_kbytes` during `late_initcall` via `ms_hyperv_init_memory_headroom` in `drivers/hv/hv_common.c` to a dynamic floor scaled to total guest RAM (clamped between 64 MiB and 512 MiB). Running as `late_initcall` ensures `totalram_pages()` is fully cataloged. This guarantees that physical pages remain permanently reserved for kernel atomic allocations and VMBus communication. 2. Introduces a memory pressure check in `drivers/hv/hv_balloon.c` to defer balloon inflation whenever available memory drops below the critical threshold (`totalram_pages() / 32`), avoiding competing with kswapd. Signed-off-by: Emerson Busson --- drivers/hv/hv_balloon.c | 12 ++++++++++++ drivers/hv/hv_common.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 2b4080e51..41cf97329 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -26,6 +26,7 @@ #include #include #include +#include =20 #include #include @@ -1205,6 +1206,17 @@ static unsigned int alloc_balloon_pages(struct hv_dy= nmem_device *dm, unsigned int i, j; struct page *pg; =20 + /* + * Defer balloon inflation if guest is in critical reclaim zone. + * Competing with kswapd under pressure starves VMBus channels. + * Evaluates against 3.125% of total system RAM to avoid forbidden + * out-of-core extern mutations while maintaining memory headroom. + */ + if (si_mem_available() < (totalram_pages() / 32)) { + pr_warn_ratelimited("hv_balloon: balloon inflation deferred; guest memor= y constrained\n"); + return 0; + } + for (i =3D 0; i < num_pages / alloc_unit; i++) { if (bl_resp->hdr.size + sizeof(union dm_mem_page_range) > HV_HYP_PAGE_SIZE) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index 71fd3ea4f..8a7ee00b6 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include =20 @@ -397,6 +399,36 @@ int __init hv_common_init(void) return 0; } =20 +extern int min_free_kbytes; +extern void setup_per_zone_wmarks(void); + +/* + * Ensure sufficient atomic page headroom for Hyper-V synthetic devices + * (vmbus, netvsc, balloon) to prevent host watchdog timeouts under pressu= re. + */ +static int __init ms_hyperv_init_memory_headroom(void) +{ + unsigned long total_ram_kb; + unsigned long min_headroom_kb; + + if (!hv_is_hyperv_initialized()) + return 0; + + total_ram_kb =3D totalram_pages() * (PAGE_SIZE / 1024); + /* Scale headroom: 3.125% of RAM, clamped between 64MB and 512MB */ + min_headroom_kb =3D clamp_t(unsigned long, total_ram_kb / 32, 64 * 1024, = 512 * 1024); + + if (min_free_kbytes < min_headroom_kb) { + pr_info("Hyper-V: Calibrating min_free_kbytes from %d kB to %lu kB for V= MBus resilience\n", + min_free_kbytes, min_headroom_kb); + min_free_kbytes =3D min_headroom_kb; + setup_per_zone_wmarks(); + } + + return 0; +} +late_initcall(ms_hyperv_init_memory_headroom); + void __init ms_hyperv_late_init(void) { struct acpi_table_header *header; --=20 2.43.0 From nobody Fri Sep 25 00:40:14 2026 Received: from mail-qv2-f18.google.com (mail-qv2-f18.google.com [74.125.230.146]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F1D629D29F for ; Fri, 18 Sep 2026 01:40:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.230.146 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789695633; cv=none; b=vB2gdDsk6mULipm69XBpCOgj3ZDM3pvcCQR2guM/F9CrynEzVOo9/TFjCmm/jUqMQITEsylUwAxcUQiX20YkUXegoPs9yE7/oVxtyOiThso3wv4l7L25ylJBOshRKZ9fJPYPC5CZNuNqy0bKtSe30fJtzBReSkXIwgy6DYX7yeA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789695633; c=relaxed/simple; bh=MjA16pExLkaZIqlRpPXEjMeSmR5rlH/+8EC5lPDOKJ0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=si7d12XU+N20xaWkDYFfoRANvjbs1ar0M3SFuFrKyoIkPwZCSVsC4JaIN9ML2N8JAytIlIj9GNvByBpYyaFAKi8yBN5d6cFYfv5wWufTx701cNCqJyY3I2F9z+hMMBnCpYlu7LCeD9il5ghLGx6134hnCO5sQKACusRSeDeuU7I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=HB9sg9YM; arc=none smtp.client-ip=74.125.230.146 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HB9sg9YM" Received: by mail-qv2-f18.google.com with SMTP id 6a1803df08f44-90cdfc6db0bso2448306d6.3 for ; Thu, 17 Sep 2026 18:40:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789695628; x=1790300428; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=nRAjD5Twbhw4VbK5DrLWKjqqcqzlujpu2AVb3G2zojo=; b=HB9sg9YMxiPeQiuT9r7zNza//AmM2kh7Zjtd4c4dz7V/mdISvY+0FiKuhIDhVxJeGl nUH7PRKL5EN506Nb2PAKQr0su73lPoY4o1b7EhUwe3bCrUhSrcqRpamsncvyRydD9uR7 bh97wXviwn1mIoOsxE9BjDSbfJJuy5bgKuAFYaj+iehxueYsSKja15/V/DDByTtZK8K0 HyoFMgCWZJRcyQSIdz1xuKaHa4uNysMeijmCxHBrhfOKORzZZMmV0J0bXJRfa8dvsGA9 RJnyS6vAb1KfxCYYvPifXH6O6zXP4+SO9GzWB1qQW+6YcKoDUMoLHFV+ZiAeDgL1AXos 7Bsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789695628; x=1790300428; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=nRAjD5Twbhw4VbK5DrLWKjqqcqzlujpu2AVb3G2zojo=; b=K+rURBI7tLfQ+BwEWecxGovwGS0YZaaO2YjiUQ4IG2+DG/01qiVE5oW06N8B4OHII+ ZkVa0HZbIVodssUzgQ7879ljCyet6hKmYM9/rbzBV2aJbBz4mpl7qA17wsfq0ryGdR1d fNt2F7fj4DiZojjH7+dulObbwb6IgXsckUgVp2LcZiMzctdBDBAdn4LpyJehWfbhoUdH 9qTYF8g2A++IKae1QKbcI0GS9H3VbzD4PIHamK3f20l2nOCyXhElTv/1F0Gjzb9zxfOV I2ra/C3N0KVTrlOk7qjeDIUzh/EWZsljolEepnqnyZxpN3E7MF3Cvvu4HllgC6MzeHn0 bjuA== X-Forwarded-Encrypted: i=1; AKwUvBye6igdY03blg9pmDCJoxz97fJqOwz5biGF99gX3vQ8XlH0qK86zSH/0meSdQQeD+QkBnA/fJljk3EbjPA=@vger.kernel.org X-Gm-Message-State: AFuF++m1nYLbKrVBkoqqSx8NUXjD1g8Fw2+uwh5zzfumvRBkqJZBAwYw zfCSRyO6zglDrLv86+H+s8v3GAYsPKv5Rd3lZVIh8BIWMewkHkbyRipZ X-Gm-Gg: AYBFou1NgDsJawmcrcmUXI/3z+7c8feuO/RZQo3SYek9+/ETcsp/UCw3EzFLkm5+OOj 5XE1L+2QNkEUfhNFGMHfAHJC8ChTyowwTzrRw5w393mkrLSkdxPucnGNC58NmWqFuo29A2OVPG7 Gb/h7S9STqQ46gGFSWHNxxC/F0kG8VD5pAIa5XuhSaX8R9EZCB31BhxNDty40c6hiE45MTjH6wn 4QkSoBACq+tYtKKjaJfjCma+X4u6Rc81aU6ZiZJxoGJDX7eWIXaa7nxiRYDWgSCBFLBUsI6IiwZ sfqDtxK1V6ev/1vkGvvTZbowxL1Fu6UTu3yMRZLqAJ9wIrKHjmXPkH7arfjBoQc2nokc/04r5nF r/bF4J9s71UnTmV8uTY38lZ588O5MVj3I9aomPl7cd/C/LC0u4zhYo48rel6qtxO3W1D3zy96pB T7nq9Qs0t/V3tdcJ9OMjBxgA0KGO0Xrj6j/fkyoHHW7/UZZyQWS0NkWHA33XmwOxNLsYUXzELmm Fr+szuKhpmTIvLWZwB5j2zW8o8DYeNz X-Received: by 2002:a05:620a:1a17:b0:93b:d79b:9a64 with SMTP id af79cd13be357-93bdca9c9eemr126662685a.69.1789695627605; Thu, 17 Sep 2026 18:40:27 -0700 (PDT) Received: from emedev.tailf75c28.ts.net ([148.222.209.140]) by smtp.gmail.com with ESMTPSA id af79cd13be357-93be0e4f987sm13002285a.14.2026.09.17.18.40.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Sep 2026 18:40:27 -0700 (PDT) From: Emerson Busson To: linux-hyperv@vger.kernel.org Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org, decui@microsoft.com, linux-kernel@vger.kernel.org, emersonbusson@gmail.com Subject: [PATCH 2/2] hv: vmbus: add virtual memory fallback for ring buffer allocations under memory pressure Date: Thu, 17 Sep 2026 22:40:17 -0300 Message-ID: <20260918014017.2536753-3-emersonbusson@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260918014017.2536753-1-emersonbusson@gmail.com> References: <20260918014017.2536753-1-emersonbusson@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When VMBus sub-channels (such as synthetic SCSI, network, or vsock channels) are dynamically opened during periods of sustained memory load or memory tier eviction, `vmbus_alloc_ring()` attempts to allocate physically contiguous memory using `alloc_pages(GFP_KERNEL | __GFP_ZERO, order)`. For standard rings (order-7, 512 KiB contiguous memory), high buddy allocator fragmentation under memory pressure frequently causes `alloc_pages()` to fail with -ENOMEM even when ample total virtual memory is available. This manifests in userspace as connection timeouts (e.g. `accept4 failed 110: Connection timed out` on WSL2 vsock control planes). This patch introduces a resilient fallback mechanism: 1. When `alloc_pages()` fails due to external fragmentation, `vmbus_alloc_ring()` falls back to `vzalloc_node()` (or `vzalloc()`) to satisfy the buffer allocation from virtually contiguous pages. 2. In `hv_ringbuffer_init()`, detects `is_vmalloc_addr(virt_addr)` and populates the `pages_wraparound` mapping array using `vmalloc_to_page()`. 3. In `vmbus_free_ring()`, tracks `ringbuffer_is_vmalloc` and calls `vfree()` safely, preserving Confidential VM (CoCo) memory re-encryption isolation checks prior to release. Signed-off-by: Emerson Busson --- drivers/hv/channel.c | 46 ++++++++++++++++++++++++++++++++++----- drivers/hv/hyperv_vmbus.h | 2 +- drivers/hv/ring_buffer.c | 19 +++++++++++----- include/linux/hyperv.h | 2 ++ 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 162d6aeec..f0fb3dd8f 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -153,13 +154,20 @@ void vmbus_free_ring(struct vmbus_channel *channel) hv_ringbuffer_cleanup(&channel->outbound); hv_ringbuffer_cleanup(&channel->inbound); =20 - if (channel->ringbuffer_page) { + if (channel->ringbuffer_is_vmalloc && channel->ringbuffer_page_virt) { + /* In a CoCo VM leak the memory if it didn't get re-encrypted */ + if (!channel->ringbuffer_gpadlhandle.decrypted) + vfree(channel->ringbuffer_page_virt); + channel->ringbuffer_page_virt =3D NULL; + channel->ringbuffer_is_vmalloc =3D false; + } else if (channel->ringbuffer_page) { /* In a CoCo VM leak the memory if it didn't get re-encrypted */ if (!channel->ringbuffer_gpadlhandle.decrypted) __free_pages(channel->ringbuffer_page, get_order(channel->ringbuffer_pagecount << PAGE_SHIFT)); channel->ringbuffer_page =3D NULL; + channel->ringbuffer_page_virt =3D NULL; } } EXPORT_SYMBOL_GPL(vmbus_free_ring); @@ -182,10 +190,26 @@ int vmbus_alloc_ring(struct vmbus_channel *newchannel, if (!page) page =3D alloc_pages(GFP_KERNEL|__GFP_ZERO, order); =20 - if (!page) - return -ENOMEM; + if (!page) { + /* Fallback to virtual memory allocation under buddy fragmentation */ + void *virt_addr =3D vzalloc_node(send_size + recv_size, + cpu_to_node(newchannel->target_cpu)); + + if (!virt_addr) + virt_addr =3D vzalloc(send_size + recv_size); + + if (!virt_addr) + return -ENOMEM; + + newchannel->ringbuffer_page =3D NULL; + newchannel->ringbuffer_page_virt =3D virt_addr; + newchannel->ringbuffer_is_vmalloc =3D true; + } else { + newchannel->ringbuffer_page =3D page; + newchannel->ringbuffer_page_virt =3D page_address(page); + newchannel->ringbuffer_is_vmalloc =3D false; + } =20 - newchannel->ringbuffer_page =3D page; newchannel->ringbuffer_pagecount =3D (send_size + recv_size) >> PAGE_SHIF= T; newchannel->ringbuffer_send_offset =3D send_size >> PAGE_SHIFT; =20 @@ -639,6 +663,7 @@ static int __vmbus_open(struct vmbus_channel *newchanne= l, struct vmbus_channel_open_channel *open_msg; struct vmbus_channel_msginfo *open_info =3D NULL; struct page *page =3D newchannel->ringbuffer_page; + void *inbound_virt =3D NULL; u32 send_pages, recv_pages; unsigned long flags; int err; @@ -669,6 +694,8 @@ static int __vmbus_open(struct vmbus_channel *newchanne= l, newchannel->ringbuffer_gpadlhandle.gpadl_handle =3D 0; =20 err =3D __vmbus_establish_gpadl(newchannel, HV_GPADL_RING, + newchannel->ringbuffer_page_virt ? + newchannel->ringbuffer_page_virt : page_address(newchannel->ringbuffer_page), (send_pages + recv_pages) << PAGE_SHIFT, newchannel->ringbuffer_send_offset << PAGE_SHIFT, @@ -677,11 +704,18 @@ static int __vmbus_open(struct vmbus_channel *newchan= nel, goto error_clean_ring; =20 err =3D hv_ringbuffer_init(&newchannel->outbound, - page, send_pages, 0); + page, newchannel->ringbuffer_page_virt, + send_pages, 0); if (err) goto error_free_gpadl; =20 - err =3D hv_ringbuffer_init(&newchannel->inbound, &page[send_pages], + if (newchannel->ringbuffer_page_virt) + inbound_virt =3D newchannel->ringbuffer_page_virt + + (send_pages << PAGE_SHIFT); + + err =3D hv_ringbuffer_init(&newchannel->inbound, + page ? &page[send_pages] : NULL, + inbound_virt, recv_pages, newchannel->max_pkt_size); if (err) goto error_free_gpadl; diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 34943de7d..ec06c30d2 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -182,7 +182,7 @@ extern int hv_synic_cleanup(unsigned int cpu); void hv_ringbuffer_pre_init(struct vmbus_channel *channel); =20 int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, - struct page *pages, u32 pagecnt, u32 max_pkt_size); + struct page *pages, void *virt_addr, u32 pagecnt, u32 max_pkt_siz= e); =20 void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info); =20 diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index 23ce1fb70..e6d4cf185 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -184,7 +184,7 @@ void hv_ringbuffer_pre_init(struct vmbus_channel *chann= el) =20 /* Initialize the ring buffer. */ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, - struct page *pages, u32 page_cnt, u32 max_pkt_size) + struct page *pages, void *virt_addr, u32 page_cnt, u32 max_pkt_si= ze) { struct page **pages_wraparound; int i; @@ -201,10 +201,19 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ri= ng_info, if (!pages_wraparound) return -ENOMEM; =20 - pages_wraparound[0] =3D pages; - for (i =3D 0; i < 2 * (page_cnt - 1); i++) - pages_wraparound[i + 1] =3D - &pages[i % (page_cnt - 1) + 1]; + if (virt_addr && is_vmalloc_addr(virt_addr)) { + pages_wraparound[0] =3D vmalloc_to_page(virt_addr); + for (i =3D 0; i < 2 * (page_cnt - 1); i++) { + void *curr_virt =3D virt_addr + ((i % (page_cnt - 1) + 1) << PAGE_SHIFT= ); + + pages_wraparound[i + 1] =3D vmalloc_to_page(curr_virt); + } + } else { + pages_wraparound[0] =3D pages; + for (i =3D 0; i < 2 * (page_cnt - 1); i++) + pages_wraparound[i + 1] =3D + &pages[i % (page_cnt - 1) + 1]; + } =20 ring_info->ring_buffer =3D (struct hv_ring_buffer *) vmap(pages_wraparound, page_cnt * 2 - 1, VM_MAP, diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index a76f556f5..63203df4d 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -807,6 +807,8 @@ struct vmbus_channel { =20 /* Allocated memory for ring buffer */ struct page *ringbuffer_page; + void *ringbuffer_page_virt; + bool ringbuffer_is_vmalloc; u32 ringbuffer_pagecount; u32 ringbuffer_send_offset; struct hv_ring_buffer_info outbound; /* send to parent */ --=20 2.43.0