* Re: [PATCH 1/1] target/i386/mshv: fix read/write memory across the page boundary
2026-04-09 17:53 ` [PATCH 1/1] target/i386/mshv: fix read/write " Doru Blânzeanu
@ 2026-04-09 23:38 ` Mohamed Mediouni
2026-04-10 14:52 ` Magnus Kulke
2026-04-13 11:57 ` Magnus Kulke
2 siblings, 0 replies; 5+ messages in thread
From: Mohamed Mediouni @ 2026-04-09 23:38 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Wei Liu, Magnus Kulke
> On 9. Apr 2026, at 19:53, Doru Blânzeanu <dblanzeanu@linux.microsoft.com> wrote:
>
> Previously, read_memory and write_memory performed a single GVA-to-GPA
> translation for the entire buffer. If the buffer spanned a page
> boundary, the translated GPA was only valid for the first page, causing
> incorrect reads/writes for the remainder.
>
> Fix both functions to loop over pages, translating and accessing each
> page-aligned chunk separately.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
Hi,
Reviewed-by: Mohamed Mediouni <mohamed@unpredictable.fr>
> ---
> target/i386/mshv/mshv-cpu.c | 71 +++++++++++++++++++++++++++----------
> 1 file changed, 52 insertions(+), 19 deletions(-)
>
> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
> index 2bc978deb2..afdb6b6e29 100644
> --- a/target/i386/mshv/mshv-cpu.c
> +++ b/target/i386/mshv/mshv-cpu.c
> @@ -1316,21 +1316,38 @@ static int read_memory(const CPUState *cpu, uint64_t initial_gva,
> {
> int ret;
> uint64_t gpa, flags;
> -
> - if (gva == initial_gva) {
> - gpa = initial_gpa;
> - } else {
> - flags = HV_TRANSLATE_GVA_VALIDATE_READ;
> - ret = translate_gva(cpu, gva, &gpa, flags);
> - if (ret < 0) {
> - return -1;
> + uint64_t cur_gva = gva;
> + size_t page_left, chunk;
> + uint8_t *cur_data = data;
> +
> + /*
> + * If the read spans multiple pages,
> + * we need to translate and read each page separately
> + */
> + while (len > 0) {
> + page_left = HV_HYP_PAGE_SIZE - (cur_gva & (HV_HYP_PAGE_SIZE - 1));
> + chunk = MIN(len, page_left);
> +
> + if (cur_gva == initial_gva) {
> + gpa = initial_gpa;
> + } else {
> + flags = HV_TRANSLATE_GVA_VALIDATE_READ;
> + ret = translate_gva(cpu, cur_gva, &gpa, flags);
> + if (ret < 0) {
> + return -1;
> + }
> }
>
> - ret = mshv_guest_mem_read(gpa, data, len, false, false);
> + ret = mshv_guest_mem_read(gpa, cur_data, chunk,
> + false, false);
> if (ret < 0) {
> error_report("failed to read guest mem");
> return -1;
> }
> +
> + cur_gva += chunk;
> + cur_data += chunk;
> + len -= chunk;
> }
>
> return 0;
> @@ -1341,18 +1358,34 @@ static int write_memory(const CPUState *cpu, uint64_t gva, const uint8_t *data,
> {
> int ret;
> uint64_t gpa, flags;
> + uint64_t cur_gva = gva;
> + size_t page_left, chunk;
> + const uint8_t *cur_data = data;
> +
> + /*
> + * If the write spans multiple pages,
> + * we need to translate and write each page separately
> + */
> + while (len > 0) {
> + page_left = HV_HYP_PAGE_SIZE - (cur_gva & (HV_HYP_PAGE_SIZE - 1));
> + chunk = MIN(len, page_left);
> +
> + flags = HV_TRANSLATE_GVA_VALIDATE_WRITE;
> + ret = translate_gva(cpu, cur_gva, &gpa, flags);
> + if (ret < 0) {
> + error_report("failed to translate gva to gpa");
> + return -1;
> + }
>
> - flags = HV_TRANSLATE_GVA_VALIDATE_WRITE;
> - ret = translate_gva(cpu, gva, &gpa, flags);
> - if (ret < 0) {
> - error_report("failed to translate gva to gpa");
> - return -1;
> - }
> + ret = mshv_guest_mem_write(gpa, cur_data, chunk, false);
> + if (ret != MEMTX_OK) {
> + error_report("failed to write to mmio");
> + return -1;
> + }
>
> - ret = mshv_guest_mem_write(gpa, data, len, false);
> - if (ret != MEMTX_OK) {
> - error_report("failed to write to mmio");
> - return -1;
> + cur_gva += chunk;
> + cur_data += chunk;
> + len -= chunk;
> }
>
> return 0;
> --
> 2.53.0
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH 1/1] target/i386/mshv: fix read/write memory across the page boundary
2026-04-09 17:53 ` [PATCH 1/1] target/i386/mshv: fix read/write " Doru Blânzeanu
2026-04-09 23:38 ` Mohamed Mediouni
@ 2026-04-10 14:52 ` Magnus Kulke
2026-04-13 11:57 ` Magnus Kulke
2 siblings, 0 replies; 5+ messages in thread
From: Magnus Kulke @ 2026-04-10 14:52 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Wei Liu
On Thu, Apr 09, 2026 at 08:53:34PM +0300, Doru Blânzeanu wrote:
> Previously, read_memory and write_memory performed a single GVA-to-GPA
> translation for the entire buffer. If the buffer spanned a page
> boundary, the translated GPA was only valid for the first page, causing
> incorrect reads/writes for the remainder.
>
> Fix both functions to loop over pages, translating and accessing each
> page-aligned chunk separately.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
Thanks, looks good. Confirmed with tests that the issue is resolved.
Reviewed-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/1] target/i386/mshv: fix read/write memory across the page boundary
2026-04-09 17:53 ` [PATCH 1/1] target/i386/mshv: fix read/write " Doru Blânzeanu
2026-04-09 23:38 ` Mohamed Mediouni
2026-04-10 14:52 ` Magnus Kulke
@ 2026-04-13 11:57 ` Magnus Kulke
2 siblings, 0 replies; 5+ messages in thread
From: Magnus Kulke @ 2026-04-13 11:57 UTC (permalink / raw)
To: Doru Blânzeanu; +Cc: qemu-devel, Wei Liu
On Thu, Apr 09, 2026 at 08:53:34PM +0300, Doru Blânzeanu wrote:
> Previously, read_memory and write_memory performed a single GVA-to-GPA
> translation for the entire buffer. If the buffer spanned a page
> boundary, the translated GPA was only valid for the first page, causing
> incorrect reads/writes for the remainder.
>
> Fix both functions to loop over pages, translating and accessing each
> page-aligned chunk separately.
>
> Signed-off-by: Doru Blânzeanu <dblanzeanu@linux.microsoft.com>
> ---
> target/i386/mshv/mshv-cpu.c | 71 +++++++++++++++++++++++++++----------
> 1 file changed, 52 insertions(+), 19 deletions(-)
>
> diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c
> index 2bc978deb2..afdb6b6e29 100644
> --- a/target/i386/mshv/mshv-cpu.c
> +++ b/target/i386/mshv/mshv-cpu.c
> @@ -1316,21 +1316,38 @@ static int read_memory(const CPUState *cpu, uint64_t initial_gva,
> {
> int ret;
> uint64_t gpa, flags;
> -
> - if (gva == initial_gva) {
> - gpa = initial_gpa;
> - } else {
> - flags = HV_TRANSLATE_GVA_VALIDATE_READ;
> - ret = translate_gva(cpu, gva, &gpa, flags);
> - if (ret < 0) {
> - return -1;
> + uint64_t cur_gva = gva;
> + size_t page_left, chunk;
> + uint8_t *cur_data = data;
> +
> + /*
> + * If the read spans multiple pages,
> + * we need to translate and read each page separately
> + */
> + while (len > 0) {
> + page_left = HV_HYP_PAGE_SIZE - (cur_gva & (HV_HYP_PAGE_SIZE - 1));
> + chunk = MIN(len, page_left);
> +
> + if (cur_gva == initial_gva) {
> + gpa = initial_gpa;
> + } else {
> + flags = HV_TRANSLATE_GVA_VALIDATE_READ;
> + ret = translate_gva(cpu, cur_gva, &gpa, flags);
> + if (ret < 0) {
> + return -1;
> + }
> }
>
> - ret = mshv_guest_mem_read(gpa, data, len, false, false);
> + ret = mshv_guest_mem_read(gpa, cur_data, chunk,
> + false, false);
> if (ret < 0) {
> error_report("failed to read guest mem");
> return -1;
> }
> +
> + cur_gva += chunk;
> + cur_data += chunk;
> + len -= chunk;
> }
>
> return 0;
> @@ -1341,18 +1358,34 @@ static int write_memory(const CPUState *cpu, uint64_t gva, const uint8_t *data,
> {
> int ret;
> uint64_t gpa, flags;
> + uint64_t cur_gva = gva;
> + size_t page_left, chunk;
> + const uint8_t *cur_data = data;
> +
> + /*
> + * If the write spans multiple pages,
> + * we need to translate and write each page separately
> + */
> + while (len > 0) {
> + page_left = HV_HYP_PAGE_SIZE - (cur_gva & (HV_HYP_PAGE_SIZE - 1));
> + chunk = MIN(len, page_left);
> +
> + flags = HV_TRANSLATE_GVA_VALIDATE_WRITE;
> + ret = translate_gva(cpu, cur_gva, &gpa, flags);
> + if (ret < 0) {
> + error_report("failed to translate gva to gpa");
> + return -1;
> + }
>
> - flags = HV_TRANSLATE_GVA_VALIDATE_WRITE;
> - ret = translate_gva(cpu, gva, &gpa, flags);
> - if (ret < 0) {
> - error_report("failed to translate gva to gpa");
> - return -1;
> - }
> + ret = mshv_guest_mem_write(gpa, cur_data, chunk, false);
> + if (ret != MEMTX_OK) {
> + error_report("failed to write to mmio");
> + return -1;
> + }
>
> - ret = mshv_guest_mem_write(gpa, data, len, false);
> - if (ret != MEMTX_OK) {
> - error_report("failed to write to mmio");
> - return -1;
> + cur_gva += chunk;
> + cur_data += chunk;
> + len -= chunk;
> }
>
> return 0;
> --
> 2.53.0
Fixes: 6dec60528c (target/i386/mshv: Implement mshv_vcpu_run())
^ permalink raw reply [flat|nested] 5+ messages in thread