qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Phil Dennis-Jordan <phil@philjordan.eu>
To: qemu-devel@nongnu.org, pbonzini@redhat.com, agraf@csgraf.de,
	graf@amazon.com, marcandre.lureau@redhat.com,
	berrange@redhat.com, thuth@redhat.com, philmd@linaro.org,
	peter.maydell@linaro.org, akihiko.odaki@daynix.com,
	phil@philjordan.eu, lists@philjordan.eu
Subject: [PATCH 12/26] hw/display/apple-gfx: Task memory mapping cleanup
Date: Mon, 15 Jul 2024 23:06:51 +0200	[thread overview]
Message-ID: <20240715210705.32365-13-phil@philjordan.eu> (raw)
In-Reply-To: <20240715210705.32365-1-phil@philjordan.eu>

macOS' PV Graphics framework first requests a contiguous host-virtual
address range ("PGTask"), and subsequently requests guest-physical
memory ranges to be mapped into subranges of the tasks.

It is easier (and less threading error prone) to use the host's Mach
memory subsystem on the host to perform this subsequent remapping,
rather than tracking the mapping state directly.

Additionally, there is absolutely no need to pick a magic number
for a virtual memory base address - we can simply allocate some
appropriate virtual memory pages and let the OS choose an available
address range.

Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
---
 hw/display/apple-gfx.m  | 106 +++++++++++++++-------------------------
 hw/display/trace-events |   2 +-
 2 files changed, 40 insertions(+), 68 deletions(-)

diff --git a/hw/display/apple-gfx.m b/hw/display/apple-gfx.m
index 6537e32806..a23f731ddc 100644
--- a/hw/display/apple-gfx.m
+++ b/hw/display/apple-gfx.m
@@ -26,6 +26,7 @@
 #include "monitor/monitor.h"
 #include "qapi/error.h"
 #include "migration/blocker.h"
+#include <mach/mach_vm.h>
 #import <ParavirtualizedGraphics/ParavirtualizedGraphics.h>
 
 #define TYPE_APPLE_GFX          "apple-gfx"
@@ -35,13 +36,6 @@
     { .x = 1280, .y = 1024 },
 };
 
-/*
- * We have to map PVG memory into our address space. Use the one below
- * as base start address. In normal linker setups it points to a free
- * memory range.
- */
-#define APPLE_GFX_BASE_VA ((void *)(uintptr_t)0x500000000000UL)
-
 /*
  * ParavirtualizedGraphics.Framework only ships header files for the x86
  * variant which does not include IOSFC descriptors and host devices. We add
@@ -68,18 +62,9 @@ -(uint32_t)mmioReadAtOffset:(size_t) offset;
 -(void)mmioWriteAtOffset:(size_t) offset value:(uint32_t)value;
 @end
 
-typedef struct AppleGFXMR {
-    QTAILQ_ENTRY(AppleGFXMR) node;
-    hwaddr pa;
-    void *va;
-    uint64_t len;
-} AppleGFXMR;
-
-typedef QTAILQ_HEAD(, AppleGFXMR) AppleGFXMRList;
-
 typedef struct AppleGFXTask {
     QTAILQ_ENTRY(AppleGFXTask) node;
-    void *mem;
+    mach_vm_address_t address;
     uint64_t len;
 } AppleGFXTask;
 
@@ -95,7 +80,6 @@ -(void)mmioWriteAtOffset:(size_t) offset value:(uint32_t)value;
     id<PGDevice> pgdev;
     id<PGDisplay> pgdisp;
     PGIOSurfaceHostDevice *pgiosfc;
-    AppleGFXMRList mrs;
     AppleGFXTaskList tasks;
     QemuConsole *con;
     void *vram;
@@ -115,37 +99,24 @@ -(void)mmioWriteAtOffset:(size_t) offset value:(uint32_t)value;
 
 static AppleGFXTask *apple_gfx_new_task(AppleGFXState *s, uint64_t len)
 {
-    void *base = APPLE_GFX_BASE_VA;
+    mach_vm_address_t task_mem;
     AppleGFXTask *task;
+    kern_return_t r;
 
-    QTAILQ_FOREACH(task, &s->tasks, node) {
-        if ((task->mem + task->len) > base) {
-            base = task->mem + task->len;
-        }
+    r = mach_vm_allocate(mach_task_self(), &task_mem, len, VM_FLAGS_ANYWHERE);
+    if (r != KERN_SUCCESS || task_mem == 0) {
+        return NULL;
     }
 
     task = g_new0(AppleGFXTask, 1);
 
+    task->address = task_mem;
     task->len = len;
-    task->mem = base;
     QTAILQ_INSERT_TAIL(&s->tasks, task, node);
 
     return task;
 }
 
-static AppleGFXMR *apple_gfx_mapMemory(AppleGFXState *s, AppleGFXTask *task,
-                                       uint64_t voff, uint64_t phys, uint64_t len)
-{
-    AppleGFXMR *mr = g_new0(AppleGFXMR, 1);
-
-    mr->pa = phys;
-    mr->len = len;
-    mr->va = task->mem + voff;
-    QTAILQ_INSERT_TAIL(&s->mrs, mr, node);
-
-    return mr;
-}
-
 static uint64_t apple_gfx_read(void *opaque, hwaddr offset, unsigned size)
 {
     AppleGFXState *s = opaque;
@@ -411,7 +382,7 @@ static void apple_gfx_realize(DeviceState *dev, Error **errp)
 
     desc.createTask = ^(uint64_t vmSize, void * _Nullable * _Nonnull baseAddress) {
         AppleGFXTask *task = apple_gfx_new_task(s, vmSize);
-        *baseAddress = task->mem;
+        *baseAddress = (void*)task->address;
         trace_apple_gfx_create_task(vmSize, *baseAddress);
         return (PGTask_t *)task;
     };
@@ -420,60 +391,62 @@ static void apple_gfx_realize(DeviceState *dev, Error **errp)
         AppleGFXTask *task = (AppleGFXTask *)_task;
         trace_apple_gfx_destroy_task(task);
         QTAILQ_REMOVE(&s->tasks, task, node);
+        mach_vm_deallocate(mach_task_self(), task->address, task->len);
         g_free(task);
     };
 
     desc.mapMemory = ^(PGTask_t * _Nonnull _task, uint32_t rangeCount, uint64_t virtualOffset, bool readOnly, PGPhysicalMemoryRange_t * _Nonnull ranges) {
         AppleGFXTask *task = (AppleGFXTask*)_task;
-       mach_port_t mtask = mach_task_self();
+        kern_return_t r;
+        mach_vm_address_t target, source;
         trace_apple_gfx_map_memory(task, rangeCount, virtualOffset, readOnly);
         for (int i = 0; i < rangeCount; i++) {
             PGPhysicalMemoryRange_t *range = &ranges[i];
             MemoryRegion *tmp_mr;
             /* TODO: Bounds checks? r/o? */
             bql_lock();
-            AppleGFXMR *mr = apple_gfx_mapMemory(s, task, virtualOffset,
-                                                 range->physicalAddress,
-                                                 range->physicalLength);
 
-            trace_apple_gfx_map_memory_range(i, range->physicalAddress, range->physicalLength, mr->va);
+            trace_apple_gfx_map_memory_range(i, range->physicalAddress,
+                                             range->physicalLength);
 
-            vm_address_t target = (vm_address_t)mr->va;
-            uint64_t mask = 0;
-            bool anywhere = false;
-            vm_address_t source = (vm_address_t)gpa2hva(&tmp_mr, mr->pa, mr->len, NULL);
+            target = task->address + virtualOffset;
+            source = (mach_vm_address_t)gpa2hva(&tmp_mr,
+                                                range->physicalAddress,
+                                                range->physicalLength, NULL);
             vm_prot_t cur_protection = 0;
             vm_prot_t max_protection = 0;
-            kern_return_t retval = vm_remap(mtask, &target, mr->len, mask,
-                                            anywhere, mtask, source, false,
-                                            &cur_protection, &max_protection,
-                                            VM_INHERIT_DEFAULT);
-            trace_apple_gfx_remap(retval, source, target);
-            g_assert(retval == KERN_SUCCESS);
+            // Map guest RAM at range->physicalAddress into PG task memory range
+            r = mach_vm_remap(mach_task_self(),
+                              &target, range->physicalLength, vm_page_size - 1,
+                              VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
+                              mach_task_self(),
+                              source, false /* shared mapping, no copy */,
+                              &cur_protection, &max_protection,
+                              VM_INHERIT_COPY);
+            trace_apple_gfx_remap(r, source, target);
+            g_assert(r == KERN_SUCCESS);
 
             bql_unlock();
 
-            virtualOffset += mr->len;
+            virtualOffset += range->physicalLength;
         }
         return (bool)true;
     };
 
     desc.unmapMemory = ^(PGTask_t * _Nonnull _task, uint64_t virtualOffset, uint64_t length) {
         AppleGFXTask *task = (AppleGFXTask *)_task;
-        AppleGFXMR *mr, *next;
+        kern_return_t r;
+        mach_vm_address_t range_address;
 
         trace_apple_gfx_unmap_memory(task, virtualOffset, length);
-        bql_lock();
-        QTAILQ_FOREACH_SAFE(mr, &s->mrs, node, next) {
-            if (mr->va >= (task->mem + virtualOffset) &&
-                (mr->va + mr->len) <= (task->mem + virtualOffset + length)) {
-                vm_address_t addr = (vm_address_t)mr->va;
-                vm_deallocate(mach_task_self(), addr, mr->len);
-                QTAILQ_REMOVE(&s->mrs, mr, node);
-                g_free(mr);
-            }
-        }
-        bql_unlock();
+
+        /* Replace task memory range with fresh pages, undoing the mapping
+         * from guest RAM. */
+        range_address = task->address + virtualOffset;
+        r = mach_vm_allocate(mach_task_self(), &range_address, length,
+                             VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE);
+        g_assert(r == KERN_SUCCESS);
+
         return (bool)true;
     };
 
@@ -582,7 +555,6 @@ static void apple_gfx_realize(DeviceState *dev, Error **errp)
         [[PGIOSurfaceHostDevice alloc] initWithDescriptor:iosfc_desc];
     [iosfc_desc release];
 
-    QTAILQ_INIT(&s->mrs);
     QTAILQ_INIT(&s->tasks);
 
     create_fb(s);
diff --git a/hw/display/trace-events b/hw/display/trace-events
index 98e1a3a3a0..4b897554c9 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -198,7 +198,7 @@ apple_gfx_write(uint64_t offset, uint64_t val) "offset=0x%"PRIx64" val=0x%"PRIx6
 apple_gfx_create_task(uint32_t vm_size, void *va) "vm_size=0x%x base_addr=%p"
 apple_gfx_destroy_task(void *task) "task=%p"
 apple_gfx_map_memory(void *task, uint32_t range_count, uint64_t virtual_offset, uint32_t read_only) "task=%p range_count=0x%x virtual_offset=0x%"PRIx64" read_only=%d"
-apple_gfx_map_memory_range(uint32_t i, uint64_t phys_addr, uint64_t phys_len, void *va) "[%d] phys_addr=0x%"PRIx64" phys_len=0x%"PRIx64" va=%p"
+apple_gfx_map_memory_range(uint32_t i, uint64_t phys_addr, uint64_t phys_len) "[%d] phys_addr=0x%"PRIx64" phys_len=0x%"PRIx64
 apple_gfx_remap(uint64_t retval, uint64_t source, uint64_t target) "retval=%"PRId64" source=0x%"PRIx64" target=0x%"PRIx64
 apple_gfx_unmap_memory(void *task, uint64_t virtual_offset, uint64_t length) "task=%p virtual_offset=0x%"PRIx64" length=0x%"PRIx64
 apple_gfx_read_memory(uint64_t phys_address, uint64_t length, void *dst) "phys_addr=0x%"PRIx64" length=0x%"PRIx64" dest=%p"
-- 
2.39.3 (Apple Git-146)



  parent reply	other threads:[~2024-07-17 11:14 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-15 21:06 Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 01/26] hw/vmapple/apple-gfx: Introduce ParavirtualizedGraphics.Framework support Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 02/26] hw/vmapple/apple-gfx: BQL renaming update Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 03/26] hw/display/apple-gfx: Moved from hw/vmapple/ Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 04/26] hw/display/apple-gfx: uses DEFINE_TYPES macro Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 05/26] hw/display/apple-gfx: native -> little endian memory ops Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 06/26] hw/display/apple-gfx: Removes dead/superfluous code Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 07/26] hw/display/apple-gfx: Makes set_mode thread & memory safe Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 08/26] hw/display/apple-gfx: Adds migration blocker Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 09/26] hw/display/apple-gfx: Wraps ObjC autorelease code in pool Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 10/26] hw/display/apple-gfx: Fixes ObjC new/init misuse, plugs leaks Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 11/26] hw/display/apple-gfx: Uses ObjC category extension for private property Phil Dennis-Jordan
2024-07-15 21:06 ` Phil Dennis-Jordan [this message]
2024-07-15 21:06 ` [PATCH 13/26] hw/display/apple-gfx: Defines PGTask_s struct instead of casting Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 14/26] hw/display/apple-gfx: Refactoring of realize function Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 15/26] hw/display/apple-gfx: Separates generic & vmapple-specific functionality Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 16/26] hw/display/apple-gfx: Asynchronous MMIO writes on x86-64 Phil Dennis-Jordan
2024-07-15 21:26   ` Philippe Mathieu-Daudé
2024-07-16 14:29     ` Phil Dennis-Jordan
2024-07-16 14:48       ` BALATON Zoltan
2024-07-17 11:09         ` Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 17/26] hw/display/apple-gfx: Asynchronous rendering and graphics update Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 18/26] hw/display/apple-gfx: Adds PCI implementation Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 19/26] ui/cocoa: Adds non-app runloop on main thread mode Phil Dennis-Jordan
2024-07-15 21:06 ` [PATCH 20/26] hw/display/apple-gfx: Fixes cursor hotspot handling Phil Dennis-Jordan
2024-07-15 21:07 ` [PATCH 21/26] hw/display/apple-gfx: Implements texture syncing for non-UMA GPUs Phil Dennis-Jordan
2024-07-15 21:07 ` [PATCH 22/26] hw/display/apple-gfx: Replaces magic number with queried MMIO length Phil Dennis-Jordan
2024-07-15 21:07 ` [PATCH 23/26] hw/display/apple-gfx: Host GPU picking improvements Phil Dennis-Jordan
2024-07-15 21:07 ` [PATCH 24/26] hw/display/apple-gfx: Adds configurable mode list Phil Dennis-Jordan
2024-07-15 21:07 ` [PATCH 25/26] MAINTAINERS: Add myself as maintainer for apple-gfx, reviewer for HVF Phil Dennis-Jordan
2024-07-15 21:07 ` [PATCH 26/26] hw/display/apple-gfx: Removes UI pointer support check Phil Dennis-Jordan
2024-07-16  6:07 ` Akihiko Odaki
2024-07-16  6:38   ` hw/display/apple-gfx Philippe Mathieu-Daudé
2024-07-16  6:47     ` hw/display/apple-gfx Akihiko Odaki
2024-07-17 11:12       ` hw/display/apple-gfx Phil Dennis-Jordan
2024-07-17 11:16   ` Phil Dennis-Jordan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240715210705.32365-13-phil@philjordan.eu \
    --to=phil@philjordan.eu \
    --cc=agraf@csgraf.de \
    --cc=akihiko.odaki@daynix.com \
    --cc=berrange@redhat.com \
    --cc=graf@amazon.com \
    --cc=lists@philjordan.eu \
    --cc=marcandre.lureau@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=philmd@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=thuth@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).