mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-22 23:04:43 +00:00
Drivers: hv: vmbus: Introduce types of GPADL
This patch introduces two types of GPADL: HV_GPADL_{BUFFER, RING}. The types of GPADL are purely the concept in the guest, IOW the hypervisor treat them as the same. The reason of introducing the types for GPADL is to support guests whose page size is not 4k (the page size of Hyper-V hypervisor). In these guests, both the headers and the data parts of the ringbuffers need to be aligned to the PAGE_SIZE, because 1) some of the ringbuffers will be mapped into userspace and 2) we use "double mapping" mechanism to support fast wrap-around, and "double mapping" relies on ringbuffers being page-aligned. However, the Hyper-V hypervisor only uses 4k (HV_HYP_PAGE_SIZE) headers. Our solution to this is that we always make the headers of ringbuffers take one guest page and when GPADL is established between the guest and hypervisor, the only first 4k of header is used. To handle this special case, we need the types of GPADL to differ different guest memory usage for GPADL. Type enum is introduced along with several general interfaces to describe the differences between normal buffer GPADL and ringbuffer GPADL. Signed-off-by: Boqun Feng <boqun.feng@gmail.com> Reviewed-by: Michael Kelley <mikelley@microsoft.com> Link: https://lore.kernel.org/r/20200916034817.30282-4-boqun.feng@gmail.com Signed-off-by: Wei Liu <wei.liu@kernel.org>
This commit is contained in:
parent
edd9bbc1d9
commit
c1135c7fd0
2 changed files with 187 additions and 21 deletions
|
@ -29,6 +29,48 @@
|
|||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/*
|
||||
* Types for GPADL, decides is how GPADL header is created.
|
||||
*
|
||||
* It doesn't make much difference between BUFFER and RING if PAGE_SIZE is the
|
||||
* same as HV_HYP_PAGE_SIZE.
|
||||
*
|
||||
* If PAGE_SIZE is bigger than HV_HYP_PAGE_SIZE, the headers of ring buffers
|
||||
* will be of PAGE_SIZE, however, only the first HV_HYP_PAGE will be put
|
||||
* into gpadl, therefore the number for HV_HYP_PAGE and the indexes of each
|
||||
* HV_HYP_PAGE will be different between different types of GPADL, for example
|
||||
* if PAGE_SIZE is 64K:
|
||||
*
|
||||
* BUFFER:
|
||||
*
|
||||
* gva: |-- 64k --|-- 64k --| ... |
|
||||
* gpa: | 4k | 4k | ... | 4k | 4k | 4k | ... | 4k |
|
||||
* index: 0 1 2 15 16 17 18 .. 31 32 ...
|
||||
* | | ... | | | ... | ...
|
||||
* v V V V V V
|
||||
* gpadl: | 4k | 4k | ... | 4k | 4k | 4k | ... | 4k | ... |
|
||||
* index: 0 1 2 ... 15 16 17 18 .. 31 32 ...
|
||||
*
|
||||
* RING:
|
||||
*
|
||||
* | header | data | header | data |
|
||||
* gva: |-- 64k --|-- 64k --| ... |-- 64k --|-- 64k --| ... |
|
||||
* gpa: | 4k | .. | 4k | 4k | ... | 4k | ... | 4k | .. | 4k | .. | ... |
|
||||
* index: 0 1 16 17 18 31 ... n n+1 n+16 ... 2n
|
||||
* | / / / | / /
|
||||
* | / / / | / /
|
||||
* | / / ... / ... | / ... /
|
||||
* | / / / | / /
|
||||
* | / / / | / /
|
||||
* V V V V V V v
|
||||
* gpadl: | 4k | 4k | ... | ... | 4k | 4k | ... |
|
||||
* index: 0 1 2 ... 16 ... n-15 n-14 n-13 ... 2n-30
|
||||
*/
|
||||
enum hv_gpadl_type {
|
||||
HV_GPADL_BUFFER,
|
||||
HV_GPADL_RING
|
||||
};
|
||||
|
||||
/* Single-page buffer */
|
||||
struct hv_page_buffer {
|
||||
u32 len;
|
||||
|
@ -111,7 +153,7 @@ struct hv_ring_buffer {
|
|||
} feature_bits;
|
||||
|
||||
/* Pad it to PAGE_SIZE so that data starts on page boundary */
|
||||
u8 reserved2[4028];
|
||||
u8 reserved2[PAGE_SIZE - 68];
|
||||
|
||||
/*
|
||||
* Ring data starts here + RingDataStartOffset
|
||||
|
@ -120,6 +162,10 @@ struct hv_ring_buffer {
|
|||
u8 buffer[];
|
||||
} __packed;
|
||||
|
||||
/* Calculate the proper size of a ringbuffer, it must be page-aligned */
|
||||
#define VMBUS_RING_SIZE(payload_sz) PAGE_ALIGN(sizeof(struct hv_ring_buffer) + \
|
||||
(payload_sz))
|
||||
|
||||
struct hv_ring_buffer_info {
|
||||
struct hv_ring_buffer *ring_buffer;
|
||||
u32 ring_size; /* Include the shared header */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue