Re: [PATCH v2 2/6] x86/tdx: Support vmalloc() for tdx_enc_status_changed()

From: Zhi Wang
Date: Thu Jan 05 2023 - 13:10:54 EST


On Thu, 5 Jan 2023 17:33:16 +0000
Dexuan Cui <decui@xxxxxxxxxxxxx> wrote:

> > From: Zhi Wang <zhi.wang.linux@xxxxxxxxx>
> > Sent: Thursday, January 5, 2023 1:45 AM
> > [...]
> > On Tue, 6 Dec 2022 16:33:21 -0800
> > Dexuan Cui <decui@xxxxxxxxxxxxx> wrote:
> >
> > > When a TDX guest runs on Hyper-V, the hv_netvsc driver's
> > > netvsc_init_buf() allocates buffers using vzalloc(), and needs to
> > > share the buffers with the host OS by calling
> > > set_memory_decrypted(), which is not working for vmalloc() yet. Add
> > > the support by handling the pages one by one.
> >
> > It seems calling set_memory_decrypted() in netvsc_init_buf() is
> > missing in this patch series. I guess there should be another one
> > extra patch to cover that.
>
> set_memory_decrypted() is not missing here. In netvsc_init_buf(), after
> the line "net_device->recv_buf = vzalloc(buf_size);", we have
>
> vmbus_establish_gpadl(device->channel, net_device->recv_buf, ...), which
>
> calls __vmbus_establish_gpadl(), which calls
>
> set_memory_decrypted((unsigned long)kbuffer, ...)
>

I see. Then do we still need the hv_map_memory()in the following
code piece in netvsc.c after {set_memoery_encrypted, decrypted}()
supporting memory from vmalloc()?

/* set_memory_decrypted() is called here. */

ret = vmbus_establish_gpadl(device->channel, net_device->recv_buf,
buf_size,
&net_device->recv_buf_gpadl_handle);
if (ret != 0) {
netdev_err(ndev,
"unable to establish receive buffer's gpadl\n");
goto cleanup;
}

/* Should we remove this? */
if (hv_isolation_type_snp()) {
vaddr = hv_map_memory(net_device->recv_buf, buf_size);
if (!vaddr) {
ret = -ENOMEM;
goto cleanup;
}

net_device->recv_original_buf = net_device->recv_buf;
net_device->recv_buf = vaddr;
}

I assume that we need an VA mapped to a shared GPA here.

The VA(net_device->recv_buf) has been associated with a shared GPA in
set_memory_decrypted() by adjusting the kernel page table. hv_map_memory()
is with similar purpose but just a different way:

void *hv_map_memory(void *addr, unsigned long size)
{
unsigned long *pfns = kcalloc(size / PAGE_SIZE,
sizeof(unsigned long), GFP_KERNEL);
void *vaddr;
int i;

if (!pfns)
return NULL;

for (i = 0; i < size / PAGE_SIZE; i++)
pfns[i] = vmalloc_to_pfn(addr + i * PAGE_SIZE) +
(ms_hyperv.shared_gpa_boundary >> PAGE_SHIFT);

vaddr = vmap_pfn(pfns, size / PAGE_SIZE, PAGE_KERNEL_IO);
kfree(pfns);

return vaddr;
}