From 1ed0c75eb9636b28bfe5b21239c19991a947b85e Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Mon, 16 Feb 2026 13:39:35 +0100 Subject: [PATCH 1/8] add vfbdev and long page granting --- so3/arch/arm64/domain.c | 10 + so3/arch/arm64/virt64/include/mach/ipamap.h | 18 ++ so3/avz/include/avz/domain.h | 6 + so3/avz/include/avz/gnttab.h | 5 + so3/avz/include/avz/injector.h | 4 + so3/avz/kernel/gnttab.c | 54 +++- so3/avz/kernel/injector.c | 4 + so3/configs/virt64_capsule_defconfig | 1 + so3/devices/fb/pl111.c | 2 +- so3/devices/fb/ramfb.c | 2 +- so3/devices/fb/soo_fb.c | 102 ------ so3/devices/mem.c | 2 +- so3/dts/virt64_capsule.dts | 5 + so3/fs/vfs.c | 9 +- so3/soo/drivers/Kconfig | 3 + so3/soo/drivers/Makefile | 1 + so3/soo/drivers/vfbdevfront/Makefile | 1 + so3/soo/drivers/vfbdevfront/vfbdev.c | 334 ++++++++++++++++++++ so3/soo/include/soo/dev/vfbdev.h | 38 +++ so3/soo/include/soo/gnttab.h | 2 + so3/soo/include/soo/uapi/soo.h | 1 + so3/soo/kernel/gnttab.c | 30 ++ so3/soo/kernel/vbstore/vbstore_me.c | 12 + 23 files changed, 533 insertions(+), 113 deletions(-) delete mode 100644 so3/devices/fb/soo_fb.c create mode 100644 so3/soo/drivers/vfbdevfront/Makefile create mode 100644 so3/soo/drivers/vfbdevfront/vfbdev.c create mode 100644 so3/soo/include/soo/dev/vfbdev.h diff --git a/so3/arch/arm64/domain.c b/so3/arch/arm64/domain.c index 39632777d..29e8b8f7e 100644 --- a/so3/arch/arm64/domain.c +++ b/so3/arch/arm64/domain.c @@ -131,6 +131,16 @@ void __setup_dom_pgtable(struct domain *d, addr_t paddr_start, unsigned long map d->grant_pfn[i].pfn = phys_to_pfn(memslot[slotID].ipa_addr + map_size + 2 * PAGE_SIZE) + i; d->grant_pfn[i].free = true; } + + /* Initialize the long grant pfn area. As page count for them is unknown, they will all be mapped + * contiguously from a starting point, which is behind the last normal grant pfn. + */ + for (i = 0; i < NR_LONG_GRANT_PFN; i++) { + d->long_grant_pfn[i].pfn = 0; + d->long_grant_pfn[i].page_count = 0; + d->long_grant_pfn[i].free = true; + } + d->long_grant_start_pfn = phys_to_pfn(memslot[slotID].ipa_addr + map_size + 2 * PAGE_SIZE) + NR_GRANT_PFN; #endif /* CONFIG_SOO */ } diff --git a/so3/arch/arm64/virt64/include/mach/ipamap.h b/so3/arch/arm64/virt64/include/mach/ipamap.h index b4b0a85a2..87862289e 100644 --- a/so3/arch/arm64/virt64/include/mach/ipamap.h +++ b/so3/arch/arm64/virt64/include/mach/ipamap.h @@ -27,6 +27,24 @@ ipamap_t agency_ipamap[] = { .phys_addr = 0x08000000, .size = 0x3000000, }, + { + /* PCIe mapping */ + .ipa_addr = 0x4010000000, + .phys_addr = 0x4010000000, + .size = 0x10000000 + }, + { + /* PCIe mapping */ + .ipa_addr = 0x10000000, + .phys_addr = 0x10000000, + .size = 0x40000000 + }, + { + /* PCIe mapping */ + .ipa_addr = 0x8000000000, + .phys_addr = 0x8000000000, + .size = 0x8000000000 + }, }; /** diff --git a/so3/avz/include/avz/domain.h b/so3/avz/include/avz/domain.h index 27e1ebd9e..00d772f62 100644 --- a/so3/avz/include/avz/domain.h +++ b/so3/avz/include/avz/domain.h @@ -54,9 +54,11 @@ #include #define NR_GRANT_PFN 32 +#define NR_LONG_GRANT_PFN 8 typedef struct { addr_t pfn; + size_t page_count; bool free; } grant_pfn_t; @@ -117,6 +119,10 @@ struct domain { /* IPA reserved page frame numbers for mapping granted pages belonging to other domains */ grant_pfn_t grant_pfn[NR_GRANT_PFN]; + + /* IPA reserved information for long mapping granted pages belonging to other domains */ + grant_pfn_t long_grant_pfn[NR_LONG_GRANT_PFN]; + addr_t long_grant_start_pfn; #endif /* CONFIG_SOO */ int processor; diff --git a/so3/avz/include/avz/gnttab.h b/so3/avz/include/avz/gnttab.h index dbfa64d49..80b439e50 100644 --- a/so3/avz/include/avz/gnttab.h +++ b/so3/avz/include/avz/gnttab.h @@ -32,6 +32,11 @@ struct gnttab { /* (Real) physical frame number to be granted */ addr_t pfn; + /* Page count to be granted, if set to 0 then normal granting is used + * mapping one page. + */ + size_t page_count; + /* Unique ref ID used by the domain which refers to this page */ grant_ref_t ref; }; diff --git a/so3/avz/include/avz/injector.h b/so3/avz/include/avz/injector.h index cb411ba72..f9ffeb45d 100644 --- a/so3/avz/include/avz/injector.h +++ b/so3/avz/include/avz/injector.h @@ -55,6 +55,10 @@ struct dom_context { /* IPA reserved page frame numbers for granted pages */ grant_pfn_t grant_pfn[NR_GRANT_PFN]; + /* IPA reserved page frame numbers for long granted pages */ + grant_pfn_t long_grant_pfn[NR_LONG_GRANT_PFN]; + addr_t long_grant_start_pfn; + /* Stack frame of this domain */ struct cpu_regs stack_frame; diff --git a/so3/avz/kernel/gnttab.c b/so3/avz/kernel/gnttab.c index 333694cbf..7fed9cf0c 100644 --- a/so3/avz/kernel/gnttab.c +++ b/so3/avz/kernel/gnttab.c @@ -81,12 +81,13 @@ gnttab_t *pick_granted_entry(grant_ref_t ref, domid_t origin_domid) /** * @brief Create a new grant table entry in the gnttab of a domain - * + * * @param d The domain containing the grant table * @param target_domid The domain concerned by this grant * @param pfn The real frame number of the page to be granted + * @param page_count The number of page to grant */ -gnttab_t *new_gnttab_entry(struct domain *d, domid_t target_domid, addr_t pfn) +gnttab_t *new_gnttab_entry(struct domain *d, domid_t target_domid, addr_t pfn, size_t page_count) { gnttab_t *gnttab; @@ -96,6 +97,7 @@ gnttab_t *new_gnttab_entry(struct domain *d, domid_t target_domid, addr_t pfn) gnttab->origin_domid = d->avz_shared->domID; gnttab->target_domid = target_domid; gnttab->pfn = pfn; + gnttab->page_count = page_count; /* Determine the ref number for this entry */ gnttab->ref = get_ref_max(&d->gnttab) + 1; @@ -142,6 +144,31 @@ addr_t allocate_grant_pfn(struct domain *d) return 0; /* Make gcc happy :-) */ } +/** + * @brief Find a free long grant pfn + * + * @param d Domain to search for the free pfn + * @return grant pfn object to be used for mapping the granted pages + */ +grant_pfn_t *allocate_long_grant_pfn(struct domain *d) +{ + int i; + addr_t start_pfn = d->long_grant_start_pfn; + + for (i = 0; i < NR_LONG_GRANT_PFN; i++) { + if (d->long_grant_pfn[i].free) { + d->long_grant_pfn[i].free = false; + d->long_grant_pfn[i].pfn = start_pfn; + return &d->long_grant_pfn[i]; + } + + start_pfn += d->long_grant_pfn[i].page_count; + } + + BUG(); + return NULL; +} + /** * @brief Map the grant page associated to vbstore in the IPA domain of the ME * @@ -186,14 +213,16 @@ addr_t map_vbstore_pfn(int target_domid, int pfn) /** * @brief Hypercall entry for grant table related operations. - * + * * @param args gnttab detail structure */ void do_gnttab(gnttab_op_t *args) { struct domain *d; addr_t paddr, grant_paddr; + size_t page_count; gnttab_t *gnttab; + grant_pfn_t *grant_pfn; spin_lock(&gnttab_lock); @@ -205,8 +234,9 @@ void do_gnttab(gnttab_op_t *args) /* Create a new entry in the list of gnttab page */ paddr = ipa_to_pa(DOM_TO_MEMSLOT(d->avz_shared->domID), pfn_to_phys(args->pfn)); + page_count = args->page_count == 0 ? 1 : args->page_count; - gnttab = new_gnttab_entry(d, args->domid, phys_to_pfn(paddr)); + gnttab = new_gnttab_entry(d, args->domid, phys_to_pfn(paddr), page_count); args->ref = gnttab->ref; @@ -222,13 +252,23 @@ void do_gnttab(gnttab_op_t *args) gnttab = pick_granted_entry(args->ref, args->domid); BUG_ON(!gnttab); - /* Here, we get an IPA address corresponding to the grant page */ - grant_paddr = pfn_to_phys(allocate_grant_pfn(d)); + page_count = gnttab->page_count; + if (page_count == 1) { + /* Here, we get an IPA address corresponding to the grant page */ + grant_paddr = pfn_to_phys(allocate_grant_pfn(d)); + } else { + grant_pfn = allocate_long_grant_pfn(d); + + grant_pfn->page_count = page_count; + grant_paddr = pfn_to_phys(grant_pfn->pfn); + } /* This pfn will be exported to the domain */ args->pfn = phys_to_pfn(grant_paddr); + args->page_count = page_count; - __create_mapping((addr_t *) d->pagetable_vaddr, grant_paddr, pfn_to_phys(gnttab->pfn), PAGE_SIZE, true, S2); + __create_mapping((addr_t *) d->pagetable_vaddr, grant_paddr, pfn_to_phys(gnttab->pfn), PAGE_SIZE * page_count, + true, S2); break; diff --git a/so3/avz/kernel/injector.c b/so3/avz/kernel/injector.c index f8bb7b7f0..f951127ae 100644 --- a/so3/avz/kernel/injector.c +++ b/so3/avz/kernel/injector.c @@ -165,6 +165,8 @@ static void build_domain_context(unsigned int ME_slotID, struct domain *me, stru domctxt->pause_flags = me->pause_flags; memcpy(&domctxt->grant_pfn, &me->grant_pfn, sizeof(me->grant_pfn)); + memcpy(&domctxt->long_grant_pfn, &me->long_grant_pfn, sizeof(me->long_grant_pfn)); + memcpy(&domctxt->long_grant_start_pfn, &me->long_grant_start_pfn, sizeof(me->long_grant_start_pfn)); memcpy(&(domctxt->pause_count), &(me->pause_count), sizeof(me->pause_count)); @@ -281,6 +283,8 @@ void restore_domain_context(unsigned int ME_slotID, struct domain *me, struct do me->pause_flags = domctxt->pause_flags; memcpy(&me->grant_pfn, &domctxt->grant_pfn, sizeof(me->grant_pfn)); + memcpy(&me->long_grant_pfn, &domctxt->long_grant_pfn, sizeof(me->long_grant_pfn)); + memcpy(&me->long_grant_start_pfn, &domctxt->long_grant_start_pfn, sizeof(me->long_grant_start_pfn)); memcpy(&(me->pause_count), &(domctxt->pause_count), sizeof(me->pause_count)); diff --git a/so3/configs/virt64_capsule_defconfig b/so3/configs/virt64_capsule_defconfig index 2aa7b87c4..789ff4081 100644 --- a/so3/configs/virt64_capsule_defconfig +++ b/so3/configs/virt64_capsule_defconfig @@ -104,3 +104,4 @@ CONFIG_VUART_FRONTEND=y # CONFIG_VSENSELED_FRONTEND is not set # CONFIG_VSENSEJ_FRONTEND is not set CONFIG_VLOGS_FRONTEND=y +CONFIG_VFBDEV_FRONTEND=y diff --git a/so3/devices/fb/pl111.c b/so3/devices/fb/pl111.c index 2e7135079..0c75e86d0 100644 --- a/so3/devices/fb/pl111.c +++ b/so3/devices/fb/pl111.c @@ -106,7 +106,7 @@ int fb_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offset) create_mapping(pcb->pgtable, virt_addr + (i * PAGE_SIZE), page, PAGE_SIZE, false); } - return virt_addr; + return 0; } int fb_ioctl(int fd, unsigned long cmd, unsigned long args) diff --git a/so3/devices/fb/ramfb.c b/so3/devices/fb/ramfb.c index d046513c9..455439fbc 100644 --- a/so3/devices/fb/ramfb.c +++ b/so3/devices/fb/ramfb.c @@ -281,7 +281,7 @@ int fb_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offset) } #endif - return virt_addr; + return 0; } int fb_ioctl(int fd, unsigned long cmd, unsigned long args) diff --git a/so3/devices/fb/soo_fb.c b/so3/devices/fb/soo_fb.c deleted file mode 100644 index df0870511..000000000 --- a/so3/devices/fb/soo_fb.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2020 Nikolaos Garanis - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#if 0 -#define DEBUG -#endif - -#include -#include -#include -#include - -#include -#include - -#include -#include - -void *fb_mmap(int fd, uint32_t virt_addr, uint32_t page_count, off_t offset); -int fb_ioctl(int fd, unsigned long cmd, unsigned long args); - -struct file_operations vfb_fops = { .mmap = fb_mmap, .ioctl = fb_ioctl }; - -struct devclass vfb_cdev = { - .class = DEV_CLASS_FB, - .type = VFS_TYPE_DEV_FB, - .fops = &vfb_fops, -}; - -/* Framebuffer's physical address */ -static uint32_t fb_base = 0; - -/* Framebuffer's resolution */ -static uint32_t fb_hres; -static uint32_t fb_vres; - -int fb_init(dev_t *dev) -{ - /* Register the framebuffer so it can be accessed from user space. */ - devclass_register(dev, &vfb_cdev); - return 0; -} - -int fb_mmap(int fd, uint32_t virt_addr, uint32_t page_count, off_t offset) -{ - uint32_t i; - pcb_t *pcb = current()->pcb; - - BUG_ON(!fb_base); - - for (i = 0; i < page_count; i++) { - /* Map the process' pages to physical ones. */ - create_mapping(pcb->pgtable, virt_addr + (i * PAGE_SIZE), fb_base + i * PAGE_SIZE, PAGE_SIZE, false, false); - } - - return virt_addr; -} - -int fb_ioctl(int fd, unsigned long cmd, unsigned long args) -{ - switch (cmd) { - case IOCTL_FB_HRES: - *((uint32_t *) args) = fb_hres; - return 0; - - case IOCTL_FB_VRES: - *((uint32_t *) args) = fb_vres; - return 0; - - case IOCTL_FB_SIZE: - *((uint32_t *) args) = fb_hres * fb_vres * 4; /* assume 24bpp */ - return 0; - - default: - /* Unknown command. */ - return -1; - } -} - -void soo_fb_set_info(uint32_t base, uint32_t hres, uint32_t vres) -{ - fb_base = base; - fb_hres = hres; - fb_vres = vres; -} - -REGISTER_DRIVER_POSTCORE("fb,soo_fb", fb_init); diff --git a/so3/devices/mem.c b/so3/devices/mem.c index 716c4214e..cc03dd0e0 100644 --- a/so3/devices/mem.c +++ b/so3/devices/mem.c @@ -72,7 +72,7 @@ static int mem_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offset) if (remaining_size > 0) create_mapping(pcb->pgtable, next_virt_addr, next_phys_addr, remaining_size, true); - return virt_addr; + return 0; } static struct file_operations mem_fops = { diff --git a/so3/dts/virt64_capsule.dts b/so3/dts/virt64_capsule.dts index 3a48cfe8f..60c1cd60f 100644 --- a/so3/dts/virt64_capsule.dts +++ b/so3/dts/virt64_capsule.dts @@ -114,6 +114,11 @@ compatible = "vlogs,frontend"; status = "ok"; }; + + vfbdev { + compatible = "vfbdev,frontend"; + status = "ok"; + }; }; }; diff --git a/so3/fs/vfs.c b/so3/fs/vfs.c index 45328218c..47c5e1c42 100644 --- a/so3/fs/vfs.c +++ b/so3/fs/vfs.c @@ -470,6 +470,7 @@ static int do_write(int fd, const void *buffer, size_t count) static long do_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offset) { int gfd; + int ret; struct file_operations *fops; /* Get the fops associated to the file descriptor. */ @@ -494,8 +495,14 @@ static long do_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offset) return -EACCES; } + if (virt_addr == 0) { + virt_addr = current()->pcb->next_anon_start; + current()->pcb->next_anon_start += page_count * PAGE_SIZE; + } + /* Call the mmap fops that will do the actual mapping. */ - return (long) fops->mmap(fd, virt_addr, page_count, offset); + ret = fops->mmap(fd, virt_addr, page_count, offset); + return (ret == 0) ? virt_addr : (long) ret; } /* Low Level mmap - Anonymous case */ diff --git a/so3/soo/drivers/Kconfig b/so3/soo/drivers/Kconfig index 6fbe26ccb..72206c751 100644 --- a/so3/soo/drivers/Kconfig +++ b/so3/soo/drivers/Kconfig @@ -22,5 +22,8 @@ config VSENSEJ_FRONTEND config VLOGS_FRONTEND bool "vlogs serial driver" +config VFBDEV_FRONTEND + bool "vfbdev framebuffer driver" + endmenu diff --git a/so3/soo/drivers/Makefile b/so3/soo/drivers/Makefile index 312a9bdcb..3dca29327 100644 --- a/so3/soo/drivers/Makefile +++ b/so3/soo/drivers/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_VUIHANDLER_FRONTEND) += vuihandlerfront/ obj-$(CONFIG_VSENSELED_FRONTEND) += vsenseledfront/ obj-$(CONFIG_VSENSEJ_FRONTEND) += vsensejfront/ obj-$(CONFIG_VLOGS_FRONTEND) += vlogsfront/ +obj-$(CONFIG_VFBDEV_FRONTEND) += vfbdevfront/ diff --git a/so3/soo/drivers/vfbdevfront/Makefile b/so3/soo/drivers/vfbdevfront/Makefile new file mode 100644 index 000000000..b3e3a22f3 --- /dev/null +++ b/so3/soo/drivers/vfbdevfront/Makefile @@ -0,0 +1 @@ +obj-y := vfbdev.o diff --git a/so3/soo/drivers/vfbdevfront/vfbdev.c b/so3/soo/drivers/vfbdevfront/vfbdev.c new file mode 100644 index 000000000..99f42e2e1 --- /dev/null +++ b/so3/soo/drivers/vfbdevfront/vfbdev.c @@ -0,0 +1,334 @@ +#if 0 +#define DEBUG +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +typedef struct { + /* Must be the first field */ + vfbdev_t vfbdev; + + completion_t reader_wait; + + uint32_t hres; + uint32_t vres; + size_t size; + addr_t gnt_paddr[VFBDEV_MAX_REF]; + size_t page_count[VFBDEV_MAX_REF]; + + uint64_t count_ref; + grant_ref_t fb_ref[VFBDEV_MAX_REF]; +} vfbdev_priv_t; + +/* Our unique uart instance. */ +static struct vbus_device *vfbdev_dev = NULL; + +irq_return_t vfbdev_interrupt(int irq, void *dev_id) +{ + struct vbus_device *vdev = (struct vbus_device *) dev_id; + vfbdev_priv_t *vfbdev_priv = (vfbdev_priv_t *) dev_get_drvdata(vdev->dev); + + complete(&vfbdev_priv->reader_wait); + + return IRQ_COMPLETED; +} + +void vfbdev_probe(struct vbus_device *vdev) +{ + unsigned int evtchn; + vfbdev_sring_t *sring; + struct vbus_transaction vbt; + vfbdev_priv_t *vfbdev_priv; + + DBG0("[vfbdev] Frontend probe\n"); + + if (vdev->state == VbusStateConnected) + return; + + vfbdev_priv = dev_get_drvdata(vdev->dev); + + /* Local instance */ + vfbdev_dev = vdev; + + init_completion(&vfbdev_priv->reader_wait); + + DBG("Frontend: Setup ring\n"); + + /* Prepare to set up the ring. */ + + vfbdev_priv->vfbdev.ring_ref = GRANT_INVALID_REF; + + /* Allocate an event channel associated to the ring */ + vbus_alloc_evtchn(vdev, &evtchn); + + vfbdev_priv->vfbdev.irq = bind_evtchn_to_irq_handler(evtchn, vfbdev_interrupt, NULL, vdev); + vfbdev_priv->vfbdev.evtchn = evtchn; + + /* Allocate a shared page for the ring */ + sring = (vfbdev_sring_t *) get_free_vpage(); + if (!sring) { + lprintk("%s - line %d: Allocating shared ring failed for device %s\n", __func__, __LINE__, vdev->nodename); + BUG(); + } + + SHARED_RING_INIT(sring); + FRONT_RING_INIT(&vfbdev_priv->vfbdev.ring, sring, PAGE_SIZE); + + /* Prepare the shared to page to be visible on the other end */ + + vfbdev_priv->vfbdev.ring_ref = vbus_grant_ring(vdev, phys_to_pfn(virt_to_phys_pt((addr_t) vfbdev_priv->vfbdev.ring.sring))); + + vbus_transaction_start(&vbt); + + vbus_printf(vbt, vdev->nodename, "ring-ref", "%u", vfbdev_priv->vfbdev.ring_ref); + vbus_printf(vbt, vdev->nodename, "ring-evtchn", "%u", vfbdev_priv->vfbdev.evtchn); + + vbus_transaction_end(vbt); +} + +/* At this point, the FE is not connected. */ +void vfbdev_reconfiguring(struct vbus_device *vdev) +{ + int res; + struct vbus_transaction vbt; + vfbdev_priv_t *vfbdev_priv = dev_get_drvdata(vdev->dev); + + DBG0("[vfbdev] Frontend reconfiguring\n"); + /* The shared page already exists */ + /* Re-init */ + + gnttab_end_foreign_access(vfbdev_priv->vfbdev.ring_ref); + + DBG("Frontend: Setup ring\n"); + + /* Prepare to set up the ring. */ + + vfbdev_priv->vfbdev.ring_ref = GRANT_INVALID_REF; + + SHARED_RING_INIT(vfbdev_priv->vfbdev.ring.sring); + FRONT_RING_INIT(&vfbdev_priv->vfbdev.ring, vfbdev_priv->vfbdev.ring.sring, PAGE_SIZE); + + /* Prepare the shared to page to be visible on the other end */ + + res = vbus_grant_ring(vdev, phys_to_pfn(virt_to_phys_pt((addr_t) vfbdev_priv->vfbdev.ring.sring))); + if (res < 0) + BUG(); + + vfbdev_priv->vfbdev.ring_ref = res; + + vbus_transaction_start(&vbt); + + vbus_printf(vbt, vdev->nodename, "ring-ref", "%u", vfbdev_priv->vfbdev.ring_ref); + vbus_printf(vbt, vdev->nodename, "ring-evtchn", "%u", vfbdev_priv->vfbdev.evtchn); + + vbus_transaction_end(vbt); +} + +void vfbdev_shutdown(struct vbus_device *vdev) +{ + DBG0("[vfbdev] Frontend shutdown\n"); +} + +void vfbdev_closed(struct vbus_device *vdev) +{ + vfbdev_priv_t *vfbdev_priv = dev_get_drvdata(vdev->dev); + + DBG0("[vfbdev] Frontend close\n"); + + /** + * Free the ring and deallocate the proper data. + */ + + /* Free resources associated with old device channel. */ + if (vfbdev_priv->vfbdev.ring_ref != GRANT_INVALID_REF) { + gnttab_end_foreign_access(vfbdev_priv->vfbdev.ring_ref); + free_vpage((addr_t) vfbdev_priv->vfbdev.ring.sring); + + vfbdev_priv->vfbdev.ring_ref = GRANT_INVALID_REF; + vfbdev_priv->vfbdev.ring.sring = NULL; + } + + if (vfbdev_priv->vfbdev.irq) + unbind_from_irqhandler(vfbdev_priv->vfbdev.irq); + + vfbdev_priv->vfbdev.irq = 0; +} + +void vfbdev_suspend(struct vbus_device *vdev) +{ + DBG0("[vfbdev] Frontend suspend\n"); +} + +void vfbdev_resume(struct vbus_device *vdev) +{ + DBG0("[vfbdev] Frontend resume\n"); +} + +void vfbdev_connected(struct vbus_device *vdev) +{ + DBG0("[vfbdev] Frontend connected\n"); +} + +vdrvfront_t vfbdevdrv = { .probe = vfbdev_probe, + .reconfiguring = vfbdev_reconfiguring, + .shutdown = vfbdev_shutdown, + .closed = vfbdev_closed, + .suspend = vfbdev_suspend, + .resume = vfbdev_resume, + .connected = vfbdev_connected }; + +static int retrieve_data(vfbdev_priv_t *priv) +{ + vfbdev_request_t *ring_req; + vfbdev_response_t *ring_rsp; + size_t i; + + if (priv->count_ref != 0) { + return 1; + } + + vdevfront_processing_begin(vfbdev_dev); + + ring_req = vfbdev_new_ring_request(&priv->vfbdev.ring); + vfbdev_ring_request_ready(&priv->vfbdev.ring); + notify_remote_via_virq(priv->vfbdev.irq); + vdevfront_processing_end(vfbdev_dev); + + vdevfront_processing_begin(vfbdev_dev); + + while ((ring_rsp = vfbdev_get_ring_response(&priv->vfbdev.ring)) == NULL) { + vdevfront_processing_end(vfbdev_dev); + + wait_for_completion(&priv->reader_wait); + + vdevfront_processing_begin(vfbdev_dev); + } + + priv->hres = ring_rsp->hres; + priv->vres = ring_rsp->vres; + priv->size = ring_rsp->size; + priv->count_ref = ring_rsp->count_ref; + memcpy(priv->fb_ref, ring_rsp->fb_ref, sizeof(ring_rsp->fb_ref)); + + vdevfront_processing_end(vfbdev_dev); + + if (priv->count_ref == 0) { + return 0; + } + + for (i = 0; i < priv->count_ref; i++) { + gnttab_long_get(vfbdev_dev->otherend_id, priv->fb_ref[i], (void*)&priv->gnt_paddr[i], &priv->page_count[i]); + } + + return 1; +} + +static int vfbdev_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offset) +{ + pcb_t *pcb = current()->pcb; + struct devclass *dev; + vfbdev_priv_t *priv; + size_t i; + size_t next_page; + + dev = devclass_by_fd(fd); + priv = devclass_get_priv(dev); + + if (!retrieve_data(priv)) { + return -1; + } + + if (page_count > (priv->size / PAGE_SIZE)) { + return -1; + } + + next_page = 0; + for (i = 0; i < priv->count_ref; i++) { + create_mapping(pcb->pgtable, virt_addr + offset, priv->gnt_paddr[i], priv->page_count[i] * PAGE_SIZE, false); + offset += priv->page_count[i] * PAGE_SIZE; + } + + return 0; +} + +static int vfbdev_ioctl(int fd, unsigned long cmd, unsigned long args) +{ + struct devclass *dev; + vfbdev_priv_t *priv; + + dev = devclass_by_fd(fd); + priv = devclass_get_priv(dev); + + if (!retrieve_data(priv)) { + return -EINVAL; + } + + switch (cmd) { + case IOCTL_FB_HRES: + *((uint32_t *) args) = priv->hres; + return 0; + + case IOCTL_FB_VRES: + *((uint32_t *) args) = priv->vres; + return 0; + + case IOCTL_FB_SIZE: + *((uint32_t *) args) = priv->size; + return 0; + + default: + /* Unknown command. */ + return -1; + } +} + + +static struct file_operations vfbdev_fops = { + .mmap = vfbdev_mmap, + .ioctl = vfbdev_ioctl, +}; + +static struct devclass vfbdev_cdev = { + .class = DEV_CLASS_FB, + .type = VFS_TYPE_DEV_FB, + .fops = &vfbdev_fops, +}; + +static int vfbdev_init(dev_t *dev, int fdt_offset) +{ + vfbdev_priv_t *vfbdev_priv; + + + vfbdev_priv = malloc(sizeof(vfbdev_priv_t)); + BUG_ON(!vfbdev_priv); + + memset(vfbdev_priv, 0, sizeof(vfbdev_priv_t)); + + devclass_register(dev, &vfbdev_cdev); + devclass_set_priv(&vfbdev_cdev, vfbdev_priv); + dev_set_drvdata(dev, vfbdev_priv); + + vdevfront_init(VFBDEV_NAME, &vfbdevdrv); + + return 0; +} + +REGISTER_DRIVER_POSTCORE("vfbdev,frontend", vfbdev_init); diff --git a/so3/soo/include/soo/dev/vfbdev.h b/so3/soo/include/soo/dev/vfbdev.h new file mode 100644 index 000000000..3c86cb594 --- /dev/null +++ b/so3/soo/include/soo/dev/vfbdev.h @@ -0,0 +1,38 @@ +#ifndef VFBDEV_H +#define VFBDEV_H + +#include +#include +#include + +#define VFBDEV_NAME "vfbdev" +#define VFBDEV_PREFIX "[" VFBDEV_NAME "] " + +#define VFBDEV_MAX_REF 8 + +typedef struct { + /* Nothing */ +} vfbdev_request_t; + +typedef struct { + uint32_t hres; + uint32_t vres; + uint64_t size; + uint64_t count_ref; + grant_ref_t fb_ref[VFBDEV_MAX_REF]; +} vfbdev_response_t; + +DEFINE_RING_TYPES(vfbdev, vfbdev_request_t, vfbdev_response_t); + +typedef struct { + /* Must be the first field */ + vdevfront_t vdevfront; + + vfbdev_front_ring_t ring; + unsigned int irq; + + grant_ref_t ring_ref; + uint32_t evtchn; +} vfbdev_t; + +#endif /* VFBDEV_H */ diff --git a/so3/soo/include/soo/gnttab.h b/so3/soo/include/soo/gnttab.h index df9ad40d1..eff2e8fb6 100644 --- a/so3/soo/include/soo/gnttab.h +++ b/so3/soo/include/soo/gnttab.h @@ -27,6 +27,7 @@ int gnttab_suspend(void); int gnttab_resume(void); int gnttab_grant_foreign_access(domid_t domid, unsigned long frame); +int gnttab_long_grant_foreign_access(domid_t domid, unsigned long frame, size_t page_count); /* * Eventually end access through the given grant reference, and once that @@ -37,6 +38,7 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long frame); void gnttab_end_foreign_access(grant_ref_t ref); void gnttab_map(domid_t domid, grant_ref_t grant_ref, void **vaddr); +void gnttab_long_get(domid_t domid, grant_ref_t grant_ref, void **paddr, size_t *page_count); void postmig_gnttab_update(void); diff --git a/so3/soo/include/soo/uapi/soo.h b/so3/soo/include/soo/uapi/soo.h index e5f56463e..f5ae7caf2 100644 --- a/so3/soo/include/soo/uapi/soo.h +++ b/so3/soo/include/soo/uapi/soo.h @@ -64,6 +64,7 @@ struct gnttab_op { /* pfn to be granted or pfn associated to an existing ref */ addr_t pfn; + size_t page_count; /* Grant reference */ grant_ref_t ref; diff --git a/so3/soo/kernel/gnttab.c b/so3/soo/kernel/gnttab.c index d970e4e53..7a0653932 100644 --- a/so3/soo/kernel/gnttab.c +++ b/so3/soo/kernel/gnttab.c @@ -52,6 +52,21 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long pfn) return gnttab_op.ref; } +int gnttab_long_grant_foreign_access(domid_t domid, unsigned long pfn, size_t page_count) +{ + gnttab_op_t gnttab_op; + + /* Invoke the hypercall to grant access to domid */ + gnttab_op.cmd = GNTTAB_grant_page; + gnttab_op.domid = domid; + gnttab_op.pfn = pfn; + gnttab_op.page_count = page_count; + + avz_gnttab(&gnttab_op); + + return gnttab_op.ref; +} + /** * @brief Query the hypervisor to retrieve a pfn from a grant reference and * do a mapping and return a vaddr @@ -74,6 +89,21 @@ void gnttab_map(domid_t domid, grant_ref_t grant_ref, void **vaddr) BUG_ON(!*vaddr); } +void gnttab_long_get(domid_t domid, grant_ref_t grant_ref, void **paddr, size_t *page_count) +{ + gnttab_op_t gnttab_op; + + gnttab_op.cmd = GNTTAB_map_page; + gnttab_op.domid = domid; + gnttab_op.ref = grant_ref; + + avz_gnttab(&gnttab_op); + + *paddr = (void *) pfn_to_phys(gnttab_op.pfn); + *page_count = gnttab_op.page_count; + BUG_ON(!*paddr); +} + void gnttab_end_foreign_access(grant_ref_t ref) { gnttab_op_t gnttab_op; diff --git a/so3/soo/kernel/vbstore/vbstore_me.c b/so3/soo/kernel/vbstore/vbstore_me.c index 9d4345b42..fa88f2bea 100644 --- a/so3/soo/kernel/vbstore/vbstore_me.c +++ b/so3/soo/kernel/vbstore/vbstore_me.c @@ -247,6 +247,12 @@ void remove_vbstore_entries(void) DBG("%s: removing vsensej from vbstore...\n", __func__); vbstore_dev_remove(ME_domID(), "vsensej"); } + + fdt_node = fdt_find_compatible_node(__fdt_addr, "vfbdev,frontend"); + if (fdt_device_is_available(__fdt_addr, fdt_node)) { + DBG("%s: removing vfbdev from vbstore...\n", __func__); + vbstore_dev_remove(ME_domID(), "vfbdev"); + } } /* @@ -293,6 +299,12 @@ void vbstore_devices_populate(void) DBG("%s: init vlogs...\n", __func__); vbstore_dev_init(ME_domID(), "vlogs", false, "vlogs,frontend"); } + + fdt_node = fdt_find_compatible_node(__fdt_addr, "vfbdev,frontend"); + if (fdt_device_is_available(__fdt_addr, fdt_node)) { + DBG("%s: init vfbdev...\n", __func__); + vbstore_dev_init(ME_domID(), "vfbdev", false, "vfbdev,frontend"); + } } void vbstore_trigger_dev_probe(void) From 83f120e26590c4c4d8935a33464a3194cfdefe46 Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Thu, 19 Mar 2026 09:08:21 +0100 Subject: [PATCH 2/8] add vfbdev_gnt in AVZ and fix bugs related to EL2 entry --- so3/arch/arm64/asm-offsets.c | 5 ++ so3/arch/arm64/domain.c | 15 ++-- so3/arch/arm64/exception.S | 30 +++++++- so3/arch/arm64/include/asm/mmu.h | 10 +++ so3/arch/arm64/include/asm/processor.h | 9 +-- so3/arch/arm64/mmu.c | 11 +-- so3/avz/include/avz/domain.h | 7 +- so3/avz/include/avz/fbdev_gnt.h | 11 +++ so3/avz/include/avz/injector.h | 3 +- so3/avz/kernel/Makefile | 1 + so3/avz/kernel/fbdev_gnt.c | 97 ++++++++++++++++++++++++++ so3/avz/kernel/gnttab.c | 50 ++----------- so3/avz/kernel/hypercalls.c | 13 ++++ so3/avz/kernel/injector.c | 6 +- so3/avz/mm/memory.c | 2 +- so3/soo/include/soo/uapi/soo.h | 30 ++++++++ 16 files changed, 224 insertions(+), 76 deletions(-) create mode 100644 so3/avz/include/avz/fbdev_gnt.h create mode 100644 so3/avz/kernel/fbdev_gnt.c diff --git a/so3/arch/arm64/asm-offsets.c b/so3/arch/arm64/asm-offsets.c index 7eee77e69..0ff10b146 100644 --- a/so3/arch/arm64/asm-offsets.c +++ b/so3/arch/arm64/asm-offsets.c @@ -86,6 +86,11 @@ int main(void) DEFINE(OFFSET_PC, offsetof(struct cpu_regs, pc)); DEFINE(OFFSET_PSTATE, offsetof(struct cpu_regs, pstate)); DEFINE(OFFSET_TLS_USR, offsetof(struct cpu_regs, tls_usr)); +#ifdef CONFIG_AVZ + DEFINE(OFFSET_ELR_EL1, offsetof(struct cpu_regs, elr_el1)); + DEFINE(OFFSET_SPSR_EL1, offsetof(struct cpu_regs, spsr_el1)); +#endif + DEFINE(S_FRAME_SIZE, sizeof(struct cpu_regs)); BLANK(); diff --git a/so3/arch/arm64/domain.c b/so3/arch/arm64/domain.c index 29e8b8f7e..9d7916e60 100644 --- a/so3/arch/arm64/domain.c +++ b/so3/arch/arm64/domain.c @@ -30,6 +30,10 @@ #include #endif +#ifdef CONFIG_SOO +#include +#endif + /** * @brief Initialize the content of the EL2 stack associated to this domain. * @@ -132,15 +136,8 @@ void __setup_dom_pgtable(struct domain *d, addr_t paddr_start, unsigned long map d->grant_pfn[i].free = true; } - /* Initialize the long grant pfn area. As page count for them is unknown, they will all be mapped - * contiguously from a starting point, which is behind the last normal grant pfn. - */ - for (i = 0; i < NR_LONG_GRANT_PFN; i++) { - d->long_grant_pfn[i].pfn = 0; - d->long_grant_pfn[i].page_count = 0; - d->long_grant_pfn[i].free = true; - } - d->long_grant_start_pfn = phys_to_pfn(memslot[slotID].ipa_addr + map_size + 2 * PAGE_SIZE) + NR_GRANT_PFN; + d->fbdev_start_pfn = phys_to_pfn(memslot[slotID].ipa_addr + map_size + 2 * PAGE_SIZE) + NR_GRANT_PFN; + fbdev_set_pgtable(d, slotID); #endif /* CONFIG_SOO */ } diff --git a/so3/arch/arm64/exception.S b/so3/arch/arm64/exception.S index ddee4bf02..9377e4f89 100644 --- a/so3/arch/arm64/exception.S +++ b/so3/arch/arm64/exception.S @@ -303,7 +303,7 @@ ENTRY(pre_ret_to_el1) #endif /* CONFIG_CPU_PSCI */ -// Enter macro to jump into EL1 from EL0 *or* from EL1 +// Enter macro to jump into EL2 from EL0 or from EL1 .macro prepare_to_enter_to_el2 mrs x0, elr_el2 str x0, [sp, #OFFSET_PC] @@ -313,11 +313,23 @@ ENTRY(pre_ret_to_el1) mrs x0, spsr_el2 str x0, [sp, #OFFSET_PSTATE] + + // Save userspace register. Use OFFSET_SP as it is not used on the stack frame. + mrs x0, sp_el0 + str x0, [sp, #OFFSET_SP] + mrs x0, tpidr_el0 + str x0, [sp, #OFFSET_TLS_USR] + + // Save EL1 exception register as they may not yet be saved. + mrs x0, spsr_el1 + str x0, [sp, #OFFSET_SPSR_EL1] + mrs x0, elr_el1 + str x0, [sp, #OFFSET_ELR_EL1] + .endm -// Exit macro at the end of an exception routine -// It restores the sp_el0 as well. +// Exit macro at the end of an exception routine to restore all saved registers .macro prepare_to_exit_to_el1 ldr x0, [sp, #OFFSET_PC] msr elr_el2, x0 @@ -327,6 +339,18 @@ ENTRY(pre_ret_to_el1) ldr x0, [sp, #OFFSET_PSTATE] msr spsr_el2, x0 + + // Restore userspace register + ldr x0, [sp, #OFFSET_SP] + msr sp_el0, x0 + ldr x0, [sp, #OFFSET_TLS_USR] + msr tpidr_el0, x0 + + // Restore EL1 exception register as they may not yet be saved. + ldr x0, [sp, #OFFSET_SPSR_EL1] + msr spsr_el1, x0 + ldr x0, [sp, #OFFSET_ELR_EL1] + msr elr_el1, x0 .endm .align 5 diff --git a/so3/arch/arm64/include/asm/mmu.h b/so3/arch/arm64/include/asm/mmu.h index e5963f767..cac4fa304 100644 --- a/so3/arch/arm64/include/asm/mmu.h +++ b/so3/arch/arm64/include/asm/mmu.h @@ -606,6 +606,15 @@ static inline int pte_type(u64 *pte) ttbr; \ }) +#ifdef CONFIG_AVZ +#define cpu_get_vttbr() \ + ({ \ + unsigned long vttbr; \ + __asm__("mrs %0, vttbr_el2" : "=r"(vttbr) : : "cc"); \ + vttbr; \ + }) +#endif + /** * Check if a virtual address is within the user space range. * @@ -703,6 +712,7 @@ void *new_root_pgtable(void); void __create_mapping(void *pgtable, addr_t virt_base, addr_t phys_base, size_t size, bool nocache, mmu_stage_t stage); void __mmu_switch_kernel(void *pgtable, bool vttbr); +void mmu_get_current_domain_pgtable(addr_t *pgtable_paddr); #endif /* CONFIG_AVZ */ diff --git a/so3/arch/arm64/include/asm/processor.h b/so3/arch/arm64/include/asm/processor.h index d136b2330..58375b2ec 100644 --- a/so3/arch/arm64/include/asm/processor.h +++ b/so3/arch/arm64/include/asm/processor.h @@ -871,10 +871,6 @@ /* Safe value for MPIDR_EL1: Bit31:RES1, Bit30:U:0, Bit24:MT:0 */ #define SYS_MPIDR_SAFE_VAL (BIT(31)) -/* The stack must be 16-byte aligned */ - -#define S_FRAME_SIZE (8 * 36) - #ifdef __ASSEMBLY__ .macro current_cpu reg @@ -1132,6 +1128,11 @@ typedef struct __attribute__((packed, aligned(8))) cpu_regs { /* TLS is used by userspace to store thread context */ u64 tls_usr; +#ifdef CONFIG_AVZ + u64 elr_el1; + u64 spsr_el1; +#endif + /* Already aligned on 16 bytes no padding required */ } cpu_regs_t; diff --git a/so3/arch/arm64/mmu.c b/so3/arch/arm64/mmu.c index 31abf8ee7..6301018e9 100644 --- a/so3/arch/arm64/mmu.c +++ b/so3/arch/arm64/mmu.c @@ -46,13 +46,16 @@ void *current_pgtable(void) */ void mmu_get_current_pgtable(addr_t *pgtable_paddr) { - int cpu; - - cpu = smp_processor_id(); - *pgtable_paddr = cpu_get_ttbr1(); } +#ifdef CONFIG_AVZ +void mmu_get_current_domain_pgtable(addr_t *pgtable_paddr) +{ + *pgtable_paddr = cpu_get_vttbr(); +} +#endif + static void alloc_init_l3(u64 *l0pgtable, addr_t addr, addr_t end, addr_t phys, bool nocache, mmu_stage_t stage) { u64 *l1pte, *l2pte, *l3pte; diff --git a/so3/avz/include/avz/domain.h b/so3/avz/include/avz/domain.h index 00d772f62..86b242d32 100644 --- a/so3/avz/include/avz/domain.h +++ b/so3/avz/include/avz/domain.h @@ -19,6 +19,8 @@ #ifndef DOMAIN_H #define DOMAIN_H +#include + #ifndef __ASSEMBLY__ #ifdef CONFIG_SOO #include @@ -54,11 +56,9 @@ #include #define NR_GRANT_PFN 32 -#define NR_LONG_GRANT_PFN 8 typedef struct { addr_t pfn; - size_t page_count; bool free; } grant_pfn_t; @@ -121,8 +121,7 @@ struct domain { grant_pfn_t grant_pfn[NR_GRANT_PFN]; /* IPA reserved information for long mapping granted pages belonging to other domains */ - grant_pfn_t long_grant_pfn[NR_LONG_GRANT_PFN]; - addr_t long_grant_start_pfn; + addr_t fbdev_start_pfn; #endif /* CONFIG_SOO */ int processor; diff --git a/so3/avz/include/avz/fbdev_gnt.h b/so3/avz/include/avz/fbdev_gnt.h new file mode 100644 index 000000000..6485eef06 --- /dev/null +++ b/so3/avz/include/avz/fbdev_gnt.h @@ -0,0 +1,11 @@ +#ifndef FBDEV_GNT_H +#define FBDEV_GNT_H + +#include + +void fbdev_set_pgtable(struct domain *d, int slotID); +void fbdev_set_info(fbdev_info_t *fbdev, addr_t fake_pfn); +void fbdev_change_focus(int new_slotID); +addr_t fbdev_get_addr(void); + +#endif /* FBDEV_GNT_H */ diff --git a/so3/avz/include/avz/injector.h b/so3/avz/include/avz/injector.h index f9ffeb45d..96bad8af6 100644 --- a/so3/avz/include/avz/injector.h +++ b/so3/avz/include/avz/injector.h @@ -56,8 +56,7 @@ struct dom_context { grant_pfn_t grant_pfn[NR_GRANT_PFN]; /* IPA reserved page frame numbers for long granted pages */ - grant_pfn_t long_grant_pfn[NR_LONG_GRANT_PFN]; - addr_t long_grant_start_pfn; + addr_t fbdev_start_pfn; /* Stack frame of this domain */ struct cpu_regs stack_frame; diff --git a/so3/avz/kernel/Makefile b/so3/avz/kernel/Makefile index 02d2777c4..164cdf801 100644 --- a/so3/avz/kernel/Makefile +++ b/so3/avz/kernel/Makefile @@ -16,6 +16,7 @@ obj-y += sched_flip.o obj-y += schedule.o obj-y += hypercalls.o obj-${CONFIG_SOO} += gnttab.o +obj-${CONFIG_SOO} += fbdev_gnt.o obj-y += image-fit.o obj-y += domain_utils.o diff --git a/so3/avz/kernel/fbdev_gnt.c b/so3/avz/kernel/fbdev_gnt.c new file mode 100644 index 000000000..53ef40435 --- /dev/null +++ b/so3/avz/kernel/fbdev_gnt.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include + +#define MAX_FBDEV_PFN 8 + +typedef struct { + fbdev_info_t fbdev; + addr_t fake_pfn; + int current_slotID; +} fbdev_priv_t; + +static fbdev_priv_t priv = {}; + +static void __map_fbdev(struct domain *d, const fbdev_info_t *pfn_info) +{ + size_t i; + addr_t phys_addr; + addr_t ipa_addr; + size_t size; + void *pgtable; + + pgtable = (void *)d->pagetable_vaddr; + ipa_addr = d->fbdev_start_pfn << PAGE_SHIFT; + + for (i = 0; i < pfn_info->count; i++) { + phys_addr = pfn_info->pfn[i] << PAGE_SHIFT; + size = pfn_info->page_count[i] << PAGE_SHIFT; + + __create_mapping(pgtable, ipa_addr, phys_addr, size, true, S2); + + ipa_addr += size; + } +} + +static void __map_fake_fbdev(struct domain *d, addr_t fake_pfn, + const fbdev_info_t *real_fb) +{ + size_t i, j; + addr_t phys_addr; + addr_t ipa_addr; + void *pgtable; + + pgtable = (void *)d->pagetable_vaddr; + ipa_addr = d->fbdev_start_pfn << PAGE_SHIFT; + phys_addr = fake_pfn << PAGE_SHIFT; + + for (i = 0; i < real_fb->count; i++) { + for (j = 0; j < real_fb->page_count[i]; j++) { + __create_mapping(pgtable, ipa_addr, phys_addr, PAGE_SIZE, + true, S2); + + ipa_addr += PAGE_SIZE; + } + } +} + +void fbdev_set_pgtable(struct domain *d, int slotID) +{ + if (slotID <= 1) { + return; + } + + if (slotID == priv.current_slotID) { + __map_fbdev(d, &priv.fbdev); + } else { + __map_fake_fbdev(d, priv.fake_pfn, &priv.fbdev); + } +} + +void fbdev_set_info(fbdev_info_t *fbdev, addr_t fake_pfn) +{ + memcpy(&priv.fbdev, fbdev, sizeof(*fbdev)); + priv.fake_pfn = fake_pfn; + + // TODO: check already existing capsule +} + +void fbdev_change_focus(int new_slotID) +{ + if ((priv.current_slotID > 1) && memslot[priv.current_slotID].busy) { + __map_fake_fbdev(domains[priv.current_slotID], priv.fake_pfn, + &priv.fbdev); + } + + if ((new_slotID > 1) && memslot[new_slotID].busy) { + __map_fbdev(domains[new_slotID], &priv.fbdev); + } + + priv.current_slotID = new_slotID; +} + +addr_t fbdev_get_addr(void) +{ + return current_domain->fbdev_start_pfn << PAGE_SHIFT; +} diff --git a/so3/avz/kernel/gnttab.c b/so3/avz/kernel/gnttab.c index 7fed9cf0c..1de3539e0 100644 --- a/so3/avz/kernel/gnttab.c +++ b/so3/avz/kernel/gnttab.c @@ -85,9 +85,8 @@ gnttab_t *pick_granted_entry(grant_ref_t ref, domid_t origin_domid) * @param d The domain containing the grant table * @param target_domid The domain concerned by this grant * @param pfn The real frame number of the page to be granted - * @param page_count The number of page to grant */ -gnttab_t *new_gnttab_entry(struct domain *d, domid_t target_domid, addr_t pfn, size_t page_count) +gnttab_t *new_gnttab_entry(struct domain *d, domid_t target_domid, addr_t pfn) { gnttab_t *gnttab; @@ -97,7 +96,6 @@ gnttab_t *new_gnttab_entry(struct domain *d, domid_t target_domid, addr_t pfn, s gnttab->origin_domid = d->avz_shared->domID; gnttab->target_domid = target_domid; gnttab->pfn = pfn; - gnttab->page_count = page_count; /* Determine the ref number for this entry */ gnttab->ref = get_ref_max(&d->gnttab) + 1; @@ -144,31 +142,6 @@ addr_t allocate_grant_pfn(struct domain *d) return 0; /* Make gcc happy :-) */ } -/** - * @brief Find a free long grant pfn - * - * @param d Domain to search for the free pfn - * @return grant pfn object to be used for mapping the granted pages - */ -grant_pfn_t *allocate_long_grant_pfn(struct domain *d) -{ - int i; - addr_t start_pfn = d->long_grant_start_pfn; - - for (i = 0; i < NR_LONG_GRANT_PFN; i++) { - if (d->long_grant_pfn[i].free) { - d->long_grant_pfn[i].free = false; - d->long_grant_pfn[i].pfn = start_pfn; - return &d->long_grant_pfn[i]; - } - - start_pfn += d->long_grant_pfn[i].page_count; - } - - BUG(); - return NULL; -} - /** * @brief Map the grant page associated to vbstore in the IPA domain of the ME * @@ -220,9 +193,7 @@ void do_gnttab(gnttab_op_t *args) { struct domain *d; addr_t paddr, grant_paddr; - size_t page_count; gnttab_t *gnttab; - grant_pfn_t *grant_pfn; spin_lock(&gnttab_lock); @@ -234,9 +205,8 @@ void do_gnttab(gnttab_op_t *args) /* Create a new entry in the list of gnttab page */ paddr = ipa_to_pa(DOM_TO_MEMSLOT(d->avz_shared->domID), pfn_to_phys(args->pfn)); - page_count = args->page_count == 0 ? 1 : args->page_count; - gnttab = new_gnttab_entry(d, args->domid, phys_to_pfn(paddr), page_count); + gnttab = new_gnttab_entry(d, args->domid, phys_to_pfn(paddr)); args->ref = gnttab->ref; @@ -252,23 +222,13 @@ void do_gnttab(gnttab_op_t *args) gnttab = pick_granted_entry(args->ref, args->domid); BUG_ON(!gnttab); - page_count = gnttab->page_count; - if (page_count == 1) { - /* Here, we get an IPA address corresponding to the grant page */ - grant_paddr = pfn_to_phys(allocate_grant_pfn(d)); - } else { - grant_pfn = allocate_long_grant_pfn(d); - - grant_pfn->page_count = page_count; - grant_paddr = pfn_to_phys(grant_pfn->pfn); - } + /* Here, we get an IPA address corresponding to the grant page */ + grant_paddr = pfn_to_phys(allocate_grant_pfn(d)); /* This pfn will be exported to the domain */ args->pfn = phys_to_pfn(grant_paddr); - args->page_count = page_count; - __create_mapping((addr_t *) d->pagetable_vaddr, grant_paddr, pfn_to_phys(gnttab->pfn), PAGE_SIZE * page_count, - true, S2); + __create_mapping((addr_t *) d->pagetable_vaddr, grant_paddr, pfn_to_phys(gnttab->pfn), PAGE_SIZE, true, S2); break; diff --git a/so3/avz/kernel/hypercalls.c b/so3/avz/kernel/hypercalls.c index 263b11f07..ece13db70 100644 --- a/so3/avz/kernel/hypercalls.c +++ b/so3/avz/kernel/hypercalls.c @@ -41,6 +41,7 @@ #ifdef CONFIG_SOO #include +#include /** * Return the state of the ME corresponding to the ME_slotID. @@ -201,6 +202,18 @@ void do_avz_hypercall(void *__args) break; } + case AVZ_FBDEV_SET_INFO: + fbdev_set_info(&args->u.avz_fbdev_info_args.fbdev, args->u.avz_fbdev_info_args.fake_pfn); + break; + + case AVZ_FBDEV_CHANGE_FOCUS: + fbdev_change_focus(args->u.avz_fbdev_focus_args.new_slotID); + break; + + case AVZ_FBDEV_GET_ADDR: + args->u.avz_fbdev_addr_args.paddr = fbdev_get_addr(); + break; + #endif /* CONFIG_SOO */ default: diff --git a/so3/avz/kernel/injector.c b/so3/avz/kernel/injector.c index f951127ae..93c12b6fa 100644 --- a/so3/avz/kernel/injector.c +++ b/so3/avz/kernel/injector.c @@ -165,8 +165,7 @@ static void build_domain_context(unsigned int ME_slotID, struct domain *me, stru domctxt->pause_flags = me->pause_flags; memcpy(&domctxt->grant_pfn, &me->grant_pfn, sizeof(me->grant_pfn)); - memcpy(&domctxt->long_grant_pfn, &me->long_grant_pfn, sizeof(me->long_grant_pfn)); - memcpy(&domctxt->long_grant_start_pfn, &me->long_grant_start_pfn, sizeof(me->long_grant_start_pfn)); + memcpy(&domctxt->fbdev_start_pfn, &me->fbdev_start_pfn, sizeof(me->fbdev_start_pfn)); memcpy(&(domctxt->pause_count), &(me->pause_count), sizeof(me->pause_count)); @@ -283,8 +282,7 @@ void restore_domain_context(unsigned int ME_slotID, struct domain *me, struct do me->pause_flags = domctxt->pause_flags; memcpy(&me->grant_pfn, &domctxt->grant_pfn, sizeof(me->grant_pfn)); - memcpy(&me->long_grant_pfn, &domctxt->long_grant_pfn, sizeof(me->long_grant_pfn)); - memcpy(&me->long_grant_start_pfn, &domctxt->long_grant_start_pfn, sizeof(me->long_grant_start_pfn)); + memcpy(&me->fbdev_start_pfn, &domctxt->fbdev_start_pfn, sizeof(me->fbdev_start_pfn)); memcpy(&(me->pause_count), &(domctxt->pause_count), sizeof(me->pause_count)); diff --git a/so3/avz/mm/memory.c b/so3/avz/mm/memory.c index e54c0abbc..32c5af8f3 100644 --- a/so3/avz/mm/memory.c +++ b/so3/avz/mm/memory.c @@ -101,7 +101,7 @@ void switch_mm_domain(struct domain *d) { addr_t current_pgtable_paddr; - mmu_get_current_pgtable(¤t_pgtable_paddr); + mmu_get_current_domain_pgtable(¤t_pgtable_paddr); if (current_pgtable_paddr == d->pagetable_paddr) /* Check if the current page table is identical to the next one. */ diff --git a/so3/soo/include/soo/uapi/soo.h b/so3/soo/include/soo/uapi/soo.h index f5ae7caf2..967ddbd9f 100644 --- a/so3/soo/include/soo/uapi/soo.h +++ b/so3/soo/include/soo/uapi/soo.h @@ -73,6 +73,14 @@ typedef struct gnttab_op gnttab_op_t; void do_gnttab(gnttab_op_t *args); +#define MAX_FBDEV_PFN 8 + +typedef struct fbdev_info { + size_t count; + addr_t pfn[MAX_FBDEV_PFN]; + size_t page_count[MAX_FBDEV_PFN]; +} fbdev_info_t; + #define AVZ_SCHEDULER_FLIP 0 /* @@ -302,6 +310,9 @@ typedef struct agency_ioctl_args { #define AVZ_SET_ME_STATE 11 #define AVZ_GET_DOM_DESC 12 #define AVZ_GRANT_TABLE_OP 13 +#define AVZ_FBDEV_SET_INFO 14 +#define AVZ_FBDEV_CHANGE_FOCUS 15 +#define AVZ_FBDEV_GET_ADDR 16 /* AVZ_INJECT_CAPSULE */ typedef struct { @@ -364,6 +375,22 @@ typedef struct { gnttab_op_t gnttab_op; } avz_gnttab_t; +/* AVZ_FBDEV_SET_INFO */ +typedef struct { + fbdev_info_t fbdev; + addr_t fake_pfn; +} avz_fbdev_info_t; + +/* AVZ_FBDEV_CHANGE_FOCUS */ +typedef struct { + int new_slotID; +} avz_fbdev_focus_t; + +/* AVZ_FBDEV_GET_ADDR */ +typedef struct { + addr_t paddr; +} avz_fbdev_addr_t; + /* * AVZ hypercall argument */ @@ -383,6 +410,9 @@ typedef struct { avz_console_io_t avz_console_io_args; avz_domctl_t avz_domctl_args; avz_gnttab_t avz_gnttab_args; + avz_fbdev_info_t avz_fbdev_info_args; + avz_fbdev_focus_t avz_fbdev_focus_args; + avz_fbdev_addr_t avz_fbdev_addr_args; } u; } avz_hyp_t; From bc1e5db12e5c91c56c834971e9e1217135768484 Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Thu, 19 Mar 2026 09:11:47 +0100 Subject: [PATCH 3/8] update vfbdev to account for new fbdev address retriving --- so3/arch/arm64/thread.c | 1 + so3/soo/drivers/vfbdevfront/vfbdev.c | 29 +++++++--------------------- so3/soo/include/soo/dev/vfbdev.h | 4 ---- 3 files changed, 8 insertions(+), 26 deletions(-) diff --git a/so3/arch/arm64/thread.c b/so3/arch/arm64/thread.c index 9ad64bae3..ca4730ea3 100644 --- a/so3/arch/arm64/thread.c +++ b/so3/arch/arm64/thread.c @@ -18,6 +18,7 @@ #include #include +#include /** * Set the CPU registers with thread related information diff --git a/so3/soo/drivers/vfbdevfront/vfbdev.c b/so3/soo/drivers/vfbdevfront/vfbdev.c index 99f42e2e1..538c2deca 100644 --- a/so3/soo/drivers/vfbdevfront/vfbdev.c +++ b/so3/soo/drivers/vfbdevfront/vfbdev.c @@ -31,11 +31,8 @@ typedef struct { uint32_t hres; uint32_t vres; size_t size; - addr_t gnt_paddr[VFBDEV_MAX_REF]; - size_t page_count[VFBDEV_MAX_REF]; + addr_t fb_paddr; - uint64_t count_ref; - grant_ref_t fb_ref[VFBDEV_MAX_REF]; } vfbdev_priv_t; /* Our unique uart instance. */ @@ -199,9 +196,9 @@ static int retrieve_data(vfbdev_priv_t *priv) { vfbdev_request_t *ring_req; vfbdev_response_t *ring_rsp; - size_t i; + avz_hyp_t hyp_args; - if (priv->count_ref != 0) { + if (priv->size != 0) { return 1; } @@ -225,18 +222,12 @@ static int retrieve_data(vfbdev_priv_t *priv) priv->hres = ring_rsp->hres; priv->vres = ring_rsp->vres; priv->size = ring_rsp->size; - priv->count_ref = ring_rsp->count_ref; - memcpy(priv->fb_ref, ring_rsp->fb_ref, sizeof(ring_rsp->fb_ref)); vdevfront_processing_end(vfbdev_dev); - if (priv->count_ref == 0) { - return 0; - } - - for (i = 0; i < priv->count_ref; i++) { - gnttab_long_get(vfbdev_dev->otherend_id, priv->fb_ref[i], (void*)&priv->gnt_paddr[i], &priv->page_count[i]); - } + hyp_args.cmd = AVZ_FBDEV_GET_ADDR; + avz_hypercall(&hyp_args); + priv->fb_paddr = hyp_args.u.avz_fbdev_addr_args.paddr; return 1; } @@ -246,8 +237,6 @@ static int vfbdev_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offs pcb_t *pcb = current()->pcb; struct devclass *dev; vfbdev_priv_t *priv; - size_t i; - size_t next_page; dev = devclass_by_fd(fd); priv = devclass_get_priv(dev); @@ -260,11 +249,7 @@ static int vfbdev_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offs return -1; } - next_page = 0; - for (i = 0; i < priv->count_ref; i++) { - create_mapping(pcb->pgtable, virt_addr + offset, priv->gnt_paddr[i], priv->page_count[i] * PAGE_SIZE, false); - offset += priv->page_count[i] * PAGE_SIZE; - } + create_mapping(pcb->pgtable, virt_addr, priv->fb_paddr, priv->size, true); return 0; } diff --git a/so3/soo/include/soo/dev/vfbdev.h b/so3/soo/include/soo/dev/vfbdev.h index 3c86cb594..05f7d2068 100644 --- a/so3/soo/include/soo/dev/vfbdev.h +++ b/so3/soo/include/soo/dev/vfbdev.h @@ -8,8 +8,6 @@ #define VFBDEV_NAME "vfbdev" #define VFBDEV_PREFIX "[" VFBDEV_NAME "] " -#define VFBDEV_MAX_REF 8 - typedef struct { /* Nothing */ } vfbdev_request_t; @@ -18,8 +16,6 @@ typedef struct { uint32_t hres; uint32_t vres; uint64_t size; - uint64_t count_ref; - grant_ref_t fb_ref[VFBDEV_MAX_REF]; } vfbdev_response_t; DEFINE_RING_TYPES(vfbdev, vfbdev_request_t, vfbdev_response_t); From 8152eb7bdebcdcdde45398c03d307adcf6dc7336 Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Tue, 7 Apr 2026 11:33:41 +0200 Subject: [PATCH 4/8] cleanup --- so3/arch/arm64/exception.S | 4 +- so3/arch/arm64/virt64/include/mach/ipamap.h | 8 +-- so3/avz/include/avz/fbdev_gnt.h | 2 +- so3/avz/include/avz/gnttab.h | 5 -- so3/avz/include/avz/injector.h | 2 +- so3/avz/kernel/fbdev_gnt.c | 62 ++++++++++++--------- so3/avz/kernel/hypercalls.c | 2 +- so3/dts/virt64_capsule.dts | 1 + so3/soo/drivers/vfbdevfront/vfbdev.c | 57 +++++++++++++------ so3/soo/include/soo/dev/vfbdev.h | 20 ++++++- so3/soo/include/soo/gnttab.h | 2 - so3/soo/include/soo/uapi/soo.h | 11 ++-- so3/soo/kernel/gnttab.c | 30 ---------- 13 files changed, 110 insertions(+), 96 deletions(-) diff --git a/so3/arch/arm64/exception.S b/so3/arch/arm64/exception.S index 9377e4f89..d250d3b4b 100644 --- a/so3/arch/arm64/exception.S +++ b/so3/arch/arm64/exception.S @@ -314,7 +314,7 @@ ENTRY(pre_ret_to_el1) mrs x0, spsr_el2 str x0, [sp, #OFFSET_PSTATE] - // Save userspace register. Use OFFSET_SP as it is not used on the stack frame. + // Save EL0 register. Use OFFSET_SP as it is not used on the stack frame. mrs x0, sp_el0 str x0, [sp, #OFFSET_SP] mrs x0, tpidr_el0 @@ -340,7 +340,7 @@ ENTRY(pre_ret_to_el1) ldr x0, [sp, #OFFSET_PSTATE] msr spsr_el2, x0 - // Restore userspace register + // Restore EL0 register ldr x0, [sp, #OFFSET_SP] msr sp_el0, x0 ldr x0, [sp, #OFFSET_TLS_USR] diff --git a/so3/arch/arm64/virt64/include/mach/ipamap.h b/so3/arch/arm64/virt64/include/mach/ipamap.h index 87862289e..64edf3fb3 100644 --- a/so3/arch/arm64/virt64/include/mach/ipamap.h +++ b/so3/arch/arm64/virt64/include/mach/ipamap.h @@ -28,19 +28,19 @@ ipamap_t agency_ipamap[] = { .size = 0x3000000, }, { - /* PCIe mapping */ + /* PCIe configuration ranges */ .ipa_addr = 0x4010000000, .phys_addr = 0x4010000000, .size = 0x10000000 }, { - /* PCIe mapping */ + /* PCIe devices IO and 32 bits memory ranges */ .ipa_addr = 0x10000000, .phys_addr = 0x10000000, - .size = 0x40000000 + .size = 0x2f000000 }, { - /* PCIe mapping */ + /* PCIe devices 64 bits memory ranges */ .ipa_addr = 0x8000000000, .phys_addr = 0x8000000000, .size = 0x8000000000 diff --git a/so3/avz/include/avz/fbdev_gnt.h b/so3/avz/include/avz/fbdev_gnt.h index 6485eef06..133c8e30b 100644 --- a/so3/avz/include/avz/fbdev_gnt.h +++ b/so3/avz/include/avz/fbdev_gnt.h @@ -4,7 +4,7 @@ #include void fbdev_set_pgtable(struct domain *d, int slotID); -void fbdev_set_info(fbdev_info_t *fbdev, addr_t fake_pfn); +void fbdev_set_info(fbdev_info_t *fbdev); void fbdev_change_focus(int new_slotID); addr_t fbdev_get_addr(void); diff --git a/so3/avz/include/avz/gnttab.h b/so3/avz/include/avz/gnttab.h index 80b439e50..dbfa64d49 100644 --- a/so3/avz/include/avz/gnttab.h +++ b/so3/avz/include/avz/gnttab.h @@ -32,11 +32,6 @@ struct gnttab { /* (Real) physical frame number to be granted */ addr_t pfn; - /* Page count to be granted, if set to 0 then normal granting is used - * mapping one page. - */ - size_t page_count; - /* Unique ref ID used by the domain which refers to this page */ grant_ref_t ref; }; diff --git a/so3/avz/include/avz/injector.h b/so3/avz/include/avz/injector.h index 96bad8af6..809360b1b 100644 --- a/so3/avz/include/avz/injector.h +++ b/so3/avz/include/avz/injector.h @@ -55,7 +55,7 @@ struct dom_context { /* IPA reserved page frame numbers for granted pages */ grant_pfn_t grant_pfn[NR_GRANT_PFN]; - /* IPA reserved page frame numbers for long granted pages */ + /* IPA reserved start frame number for framebuffer */ addr_t fbdev_start_pfn; /* Stack frame of this domain */ diff --git a/so3/avz/kernel/fbdev_gnt.c b/so3/avz/kernel/fbdev_gnt.c index 53ef40435..ae9518756 100644 --- a/so3/avz/kernel/fbdev_gnt.c +++ b/so3/avz/kernel/fbdev_gnt.c @@ -1,13 +1,12 @@ +#include #include #include #include #include -#define MAX_FBDEV_PFN 8 - typedef struct { fbdev_info_t fbdev; - addr_t fake_pfn; + void *fake_fbdev; int current_slotID; } fbdev_priv_t; @@ -24,9 +23,10 @@ static void __map_fbdev(struct domain *d, const fbdev_info_t *pfn_info) pgtable = (void *)d->pagetable_vaddr; ipa_addr = d->fbdev_start_pfn << PAGE_SHIFT; - for (i = 0; i < pfn_info->count; i++) { - phys_addr = pfn_info->pfn[i] << PAGE_SHIFT; - size = pfn_info->page_count[i] << PAGE_SHIFT; + /* Map all distincts ranges of the framebuffer to the capsule */ + for (i = 0; i < pfn_info->pfn_count; i++) { + phys_addr = pfn_to_phys(pfn_info->pfn[i]); + size = pfn_info->page_count[i] * PAGE_SIZE; __create_mapping(pgtable, ipa_addr, phys_addr, size, true, S2); @@ -34,19 +34,25 @@ static void __map_fbdev(struct domain *d, const fbdev_info_t *pfn_info) } } -static void __map_fake_fbdev(struct domain *d, addr_t fake_pfn, - const fbdev_info_t *real_fb) +static void __map_fake_fbdev(struct domain *d, const fbdev_info_t *real_fb) { size_t i, j; addr_t phys_addr; addr_t ipa_addr; void *pgtable; + /* One time malloc of fake framebuffer page */ + if (priv.fake_fbdev == NULL) { + priv.fake_fbdev = malloc(PAGE_SIZE); + BUG_ON(!priv.fake_fbdev); + } + pgtable = (void *)d->pagetable_vaddr; - ipa_addr = d->fbdev_start_pfn << PAGE_SHIFT; - phys_addr = fake_pfn << PAGE_SHIFT; + ipa_addr = pfn_to_phys(d->fbdev_start_pfn); + phys_addr = __pa(priv.fake_fbdev); - for (i = 0; i < real_fb->count; i++) { + /* Map the capsule framebuffer to the fake one */ + for (i = 0; i < real_fb->pfn_count; i++) { for (j = 0; j < real_fb->page_count[i]; j++) { __create_mapping(pgtable, ipa_addr, phys_addr, PAGE_SIZE, true, S2); @@ -58,40 +64,42 @@ static void __map_fake_fbdev(struct domain *d, addr_t fake_pfn, void fbdev_set_pgtable(struct domain *d, int slotID) { - if (slotID <= 1) { + /* Only capsules have virtual framebuffer */ + if ((slotID < MEMSLOT_BASE) && !memslot[slotID].busy) return; - } - if (slotID == priv.current_slotID) { + if (slotID == priv.current_slotID) __map_fbdev(d, &priv.fbdev); - } else { - __map_fake_fbdev(d, priv.fake_pfn, &priv.fbdev); - } + else + __map_fake_fbdev(d, &priv.fbdev); } -void fbdev_set_info(fbdev_info_t *fbdev, addr_t fake_pfn) +void fbdev_set_info(fbdev_info_t *fbdev) { + int slotID; + memcpy(&priv.fbdev, fbdev, sizeof(*fbdev)); - priv.fake_pfn = fake_pfn; - // TODO: check already existing capsule + /* Map framebuffer to all capsules. */ + for (slotID = MEMSLOT_BASE; slotID < MEMSLOT_NR; slotID++) + if (memslot[slotID].busy) + fbdev_set_pgtable(domains[slotID], slotID); } void fbdev_change_focus(int new_slotID) { - if ((priv.current_slotID > 1) && memslot[priv.current_slotID].busy) { - __map_fake_fbdev(domains[priv.current_slotID], priv.fake_pfn, - &priv.fbdev); - } + /* Remap old capsule to fake framebuffer */ + if ((priv.current_slotID >= MEMSLOT_BASE) && memslot[priv.current_slotID].busy) + __map_fake_fbdev(domains[priv.current_slotID], &priv.fbdev); - if ((new_slotID > 1) && memslot[new_slotID].busy) { + /* Map the new capsule to the framebuffer */ + if ((new_slotID >= MEMSLOT_BASE) && memslot[new_slotID].busy) __map_fbdev(domains[new_slotID], &priv.fbdev); - } priv.current_slotID = new_slotID; } addr_t fbdev_get_addr(void) { - return current_domain->fbdev_start_pfn << PAGE_SHIFT; + return pfn_to_phys(current_domain->fbdev_start_pfn); } diff --git a/so3/avz/kernel/hypercalls.c b/so3/avz/kernel/hypercalls.c index ece13db70..824d5f40c 100644 --- a/so3/avz/kernel/hypercalls.c +++ b/so3/avz/kernel/hypercalls.c @@ -203,7 +203,7 @@ void do_avz_hypercall(void *__args) } case AVZ_FBDEV_SET_INFO: - fbdev_set_info(&args->u.avz_fbdev_info_args.fbdev, args->u.avz_fbdev_info_args.fake_pfn); + fbdev_set_info(&args->u.avz_fbdev_info_args.fbdev); break; case AVZ_FBDEV_CHANGE_FOCUS: diff --git a/so3/dts/virt64_capsule.dts b/so3/dts/virt64_capsule.dts index 60c1cd60f..b90966b6e 100644 --- a/so3/dts/virt64_capsule.dts +++ b/so3/dts/virt64_capsule.dts @@ -115,6 +115,7 @@ status = "ok"; }; + /* Enabling framebuffer support */ vfbdev { compatible = "vfbdev,frontend"; status = "ok"; diff --git a/so3/soo/drivers/vfbdevfront/vfbdev.c b/so3/soo/drivers/vfbdevfront/vfbdev.c index 538c2deca..1fce0a7de 100644 --- a/so3/soo/drivers/vfbdevfront/vfbdev.c +++ b/so3/soo/drivers/vfbdevfront/vfbdev.c @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2026 Clément Dieperink + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + #if 0 #define DEBUG #endif @@ -30,12 +48,12 @@ typedef struct { uint32_t hres; uint32_t vres; - size_t size; + size_t memory_size; addr_t fb_paddr; } vfbdev_priv_t; -/* Our unique uart instance. */ +/* Our unique vfbdev instance. */ static struct vbus_device *vfbdev_dev = NULL; irq_return_t vfbdev_interrupt(int irq, void *dev_id) @@ -192,14 +210,14 @@ vdrvfront_t vfbdevdrv = { .probe = vfbdev_probe, .resume = vfbdev_resume, .connected = vfbdev_connected }; -static int retrieve_data(vfbdev_priv_t *priv) +static void retrieve_data(vfbdev_priv_t *priv) { vfbdev_request_t *ring_req; vfbdev_response_t *ring_rsp; avz_hyp_t hyp_args; - if (priv->size != 0) { - return 1; + if ((priv->memory_size != 0) && (priv->fb_paddr != 0)) { + return; } vdevfront_processing_begin(vfbdev_dev); @@ -221,15 +239,13 @@ static int retrieve_data(vfbdev_priv_t *priv) priv->hres = ring_rsp->hres; priv->vres = ring_rsp->vres; - priv->size = ring_rsp->size; + priv->memory_size = ring_rsp->memory_size; vdevfront_processing_end(vfbdev_dev); hyp_args.cmd = AVZ_FBDEV_GET_ADDR; avz_hypercall(&hyp_args); priv->fb_paddr = hyp_args.u.avz_fbdev_addr_args.paddr; - - return 1; } static int vfbdev_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offset) @@ -239,17 +255,23 @@ static int vfbdev_mmap(int fd, addr_t virt_addr, uint32_t page_count, off_t offs vfbdev_priv_t *priv; dev = devclass_by_fd(fd); + BUG_ON(!dev); priv = devclass_get_priv(dev); + BUG_ON(!priv); - if (!retrieve_data(priv)) { - return -1; + retrieve_data(priv); + + /* Ensure that we got a framebuffer */ + if ((priv->memory_size == 0) || (priv->fb_paddr == 0)) { + return -ENODEV; } - if (page_count > (priv->size / PAGE_SIZE)) { - return -1; + /* Ensure requested mapping size doesn't overflow actual framebuffer size */ + if (page_count > (priv->memory_size / PAGE_SIZE)) { + return -EINVAL; } - create_mapping(pcb->pgtable, virt_addr, priv->fb_paddr, priv->size, true); + create_mapping(pcb->pgtable, virt_addr, priv->fb_paddr, page_count * PAGE_SIZE, true); return 0; } @@ -260,11 +282,11 @@ static int vfbdev_ioctl(int fd, unsigned long cmd, unsigned long args) vfbdev_priv_t *priv; dev = devclass_by_fd(fd); + BUG_ON(!dev); priv = devclass_get_priv(dev); + BUG_ON(!priv); - if (!retrieve_data(priv)) { - return -EINVAL; - } + retrieve_data(priv); switch (cmd) { case IOCTL_FB_HRES: @@ -276,7 +298,7 @@ static int vfbdev_ioctl(int fd, unsigned long cmd, unsigned long args) return 0; case IOCTL_FB_SIZE: - *((uint32_t *) args) = priv->size; + *((uint32_t *) args) = priv->memory_size; return 0; default: @@ -301,7 +323,6 @@ static int vfbdev_init(dev_t *dev, int fdt_offset) { vfbdev_priv_t *vfbdev_priv; - vfbdev_priv = malloc(sizeof(vfbdev_priv_t)); BUG_ON(!vfbdev_priv); diff --git a/so3/soo/include/soo/dev/vfbdev.h b/so3/soo/include/soo/dev/vfbdev.h index 05f7d2068..991cbf7b1 100644 --- a/so3/soo/include/soo/dev/vfbdev.h +++ b/so3/soo/include/soo/dev/vfbdev.h @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2026 Clément Dieperink + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + #ifndef VFBDEV_H #define VFBDEV_H @@ -15,7 +33,7 @@ typedef struct { typedef struct { uint32_t hres; uint32_t vres; - uint64_t size; + uint64_t memory_size; } vfbdev_response_t; DEFINE_RING_TYPES(vfbdev, vfbdev_request_t, vfbdev_response_t); diff --git a/so3/soo/include/soo/gnttab.h b/so3/soo/include/soo/gnttab.h index eff2e8fb6..df9ad40d1 100644 --- a/so3/soo/include/soo/gnttab.h +++ b/so3/soo/include/soo/gnttab.h @@ -27,7 +27,6 @@ int gnttab_suspend(void); int gnttab_resume(void); int gnttab_grant_foreign_access(domid_t domid, unsigned long frame); -int gnttab_long_grant_foreign_access(domid_t domid, unsigned long frame, size_t page_count); /* * Eventually end access through the given grant reference, and once that @@ -38,7 +37,6 @@ int gnttab_long_grant_foreign_access(domid_t domid, unsigned long frame, size_t void gnttab_end_foreign_access(grant_ref_t ref); void gnttab_map(domid_t domid, grant_ref_t grant_ref, void **vaddr); -void gnttab_long_get(domid_t domid, grant_ref_t grant_ref, void **paddr, size_t *page_count); void postmig_gnttab_update(void); diff --git a/so3/soo/include/soo/uapi/soo.h b/so3/soo/include/soo/uapi/soo.h index 967ddbd9f..a6f069525 100644 --- a/so3/soo/include/soo/uapi/soo.h +++ b/so3/soo/include/soo/uapi/soo.h @@ -64,7 +64,6 @@ struct gnttab_op { /* pfn to be granted or pfn associated to an existing ref */ addr_t pfn; - size_t page_count; /* Grant reference */ grant_ref_t ref; @@ -73,10 +72,15 @@ typedef struct gnttab_op gnttab_op_t; void do_gnttab(gnttab_op_t *args); -#define MAX_FBDEV_PFN 8 +/* + * Framebuffer to set the framebuffer addresses. + * The physical addresses may be splitted in multiple parts, which requires to have + * multiple set of strating page frame and page count + */ +#define MAX_FBDEV_PFN 8 typedef struct fbdev_info { - size_t count; + size_t pfn_count; addr_t pfn[MAX_FBDEV_PFN]; size_t page_count[MAX_FBDEV_PFN]; } fbdev_info_t; @@ -378,7 +382,6 @@ typedef struct { /* AVZ_FBDEV_SET_INFO */ typedef struct { fbdev_info_t fbdev; - addr_t fake_pfn; } avz_fbdev_info_t; /* AVZ_FBDEV_CHANGE_FOCUS */ diff --git a/so3/soo/kernel/gnttab.c b/so3/soo/kernel/gnttab.c index 7a0653932..d970e4e53 100644 --- a/so3/soo/kernel/gnttab.c +++ b/so3/soo/kernel/gnttab.c @@ -52,21 +52,6 @@ int gnttab_grant_foreign_access(domid_t domid, unsigned long pfn) return gnttab_op.ref; } -int gnttab_long_grant_foreign_access(domid_t domid, unsigned long pfn, size_t page_count) -{ - gnttab_op_t gnttab_op; - - /* Invoke the hypercall to grant access to domid */ - gnttab_op.cmd = GNTTAB_grant_page; - gnttab_op.domid = domid; - gnttab_op.pfn = pfn; - gnttab_op.page_count = page_count; - - avz_gnttab(&gnttab_op); - - return gnttab_op.ref; -} - /** * @brief Query the hypervisor to retrieve a pfn from a grant reference and * do a mapping and return a vaddr @@ -89,21 +74,6 @@ void gnttab_map(domid_t domid, grant_ref_t grant_ref, void **vaddr) BUG_ON(!*vaddr); } -void gnttab_long_get(domid_t domid, grant_ref_t grant_ref, void **paddr, size_t *page_count) -{ - gnttab_op_t gnttab_op; - - gnttab_op.cmd = GNTTAB_map_page; - gnttab_op.domid = domid; - gnttab_op.ref = grant_ref; - - avz_gnttab(&gnttab_op); - - *paddr = (void *) pfn_to_phys(gnttab_op.pfn); - *page_count = gnttab_op.page_count; - BUG_ON(!*paddr); -} - void gnttab_end_foreign_access(grant_ref_t ref) { gnttab_op_t gnttab_op; From cef71bb4505faf001129d1bf5abd153203eea02a Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Tue, 7 Apr 2026 12:54:26 +0200 Subject: [PATCH 5/8] renaming and cleanup --- so3/arch/arm64/domain.c | 3 +- so3/arch/arm64/include/asm/processor.h | 1 + so3/avz/include/avz/domain.h | 4 +-- so3/avz/include/avz/fbdev_gnt.h | 48 ++++++++++++++++++++++++-- so3/avz/kernel/fbdev_gnt.c | 16 ++++----- so3/avz/kernel/gnttab.c | 4 +-- so3/avz/kernel/hypercalls.c | 8 ++--- so3/soo/drivers/vfbdevfront/vfbdev.c | 2 +- so3/soo/include/soo/uapi/soo.h | 18 +++++----- 9 files changed, 73 insertions(+), 31 deletions(-) diff --git a/so3/arch/arm64/domain.c b/so3/arch/arm64/domain.c index 9d7916e60..e5ca38cd2 100644 --- a/so3/arch/arm64/domain.c +++ b/so3/arch/arm64/domain.c @@ -136,8 +136,9 @@ void __setup_dom_pgtable(struct domain *d, addr_t paddr_start, unsigned long map d->grant_pfn[i].free = true; } + /* Set IPA framebuffer starting address after the grant pfn area */ d->fbdev_start_pfn = phys_to_pfn(memslot[slotID].ipa_addr + map_size + 2 * PAGE_SIZE) + NR_GRANT_PFN; - fbdev_set_pgtable(d, slotID); + fbdev_ipamap_domain(d, slotID); #endif /* CONFIG_SOO */ } diff --git a/so3/arch/arm64/include/asm/processor.h b/so3/arch/arm64/include/asm/processor.h index 58375b2ec..fa63a3c64 100644 --- a/so3/arch/arm64/include/asm/processor.h +++ b/so3/arch/arm64/include/asm/processor.h @@ -1129,6 +1129,7 @@ typedef struct __attribute__((packed, aligned(8))) cpu_regs { u64 tls_usr; #ifdef CONFIG_AVZ + /* Used to keep track of EL1 exception registers in case they haven't been saved by the domain yet */ u64 elr_el1; u64 spsr_el1; #endif diff --git a/so3/avz/include/avz/domain.h b/so3/avz/include/avz/domain.h index 86b242d32..b9908e8d3 100644 --- a/so3/avz/include/avz/domain.h +++ b/so3/avz/include/avz/domain.h @@ -19,8 +19,6 @@ #ifndef DOMAIN_H #define DOMAIN_H -#include - #ifndef __ASSEMBLY__ #ifdef CONFIG_SOO #include @@ -120,7 +118,7 @@ struct domain { /* IPA reserved page frame numbers for mapping granted pages belonging to other domains */ grant_pfn_t grant_pfn[NR_GRANT_PFN]; - /* IPA reserved information for long mapping granted pages belonging to other domains */ + /* IPA reserved starting address for framebuffer mapping */ addr_t fbdev_start_pfn; #endif /* CONFIG_SOO */ diff --git a/so3/avz/include/avz/fbdev_gnt.h b/so3/avz/include/avz/fbdev_gnt.h index 133c8e30b..4947a5066 100644 --- a/so3/avz/include/avz/fbdev_gnt.h +++ b/so3/avz/include/avz/fbdev_gnt.h @@ -1,11 +1,53 @@ +/* + * Copyright (C) 2026 Clément Dieperink + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + #ifndef FBDEV_GNT_H #define FBDEV_GNT_H #include -void fbdev_set_pgtable(struct domain *d, int slotID); -void fbdev_set_info(fbdev_info_t *fbdev); +/** + * IPA map for the framebuffer for the given domain, either on actual buffer + * or the fake one depending on currently shown slot. + * + * @param d pointer to the domain to map + * @param slotID Slot ID of the domain + */ +void fbdev_ipamap_domain(struct domain *d, int slotID); + +/** + * Set the actual framebuffer physical pages ranges for + * futur mapping. + * + * @param fbdev Framebuffer pfns informations. + */ +void fbdev_set_pfns(fbdev_pfns_t *fbdev); + +/** + * Change the currently shown slot ID by remapping corresponding ipa. + * + * @param new_slotID to be shown. + */ void fbdev_change_focus(int new_slotID); -addr_t fbdev_get_addr(void); + +/** + * Get the frambuffer starting ipa for the current domain. + */ +addr_t fbdev_get_domain_ipa(void); #endif /* FBDEV_GNT_H */ diff --git a/so3/avz/kernel/fbdev_gnt.c b/so3/avz/kernel/fbdev_gnt.c index ae9518756..7c392faa7 100644 --- a/so3/avz/kernel/fbdev_gnt.c +++ b/so3/avz/kernel/fbdev_gnt.c @@ -5,14 +5,14 @@ #include typedef struct { - fbdev_info_t fbdev; + fbdev_pfns_t fbdev; void *fake_fbdev; int current_slotID; } fbdev_priv_t; static fbdev_priv_t priv = {}; -static void __map_fbdev(struct domain *d, const fbdev_info_t *pfn_info) +static void __map_fbdev(struct domain *d, const fbdev_pfns_t *pfn_info) { size_t i; addr_t phys_addr; @@ -21,7 +21,7 @@ static void __map_fbdev(struct domain *d, const fbdev_info_t *pfn_info) void *pgtable; pgtable = (void *)d->pagetable_vaddr; - ipa_addr = d->fbdev_start_pfn << PAGE_SHIFT; + ipa_addr = pfn_to_phys(d->fbdev_start_pfn); /* Map all distincts ranges of the framebuffer to the capsule */ for (i = 0; i < pfn_info->pfn_count; i++) { @@ -34,7 +34,7 @@ static void __map_fbdev(struct domain *d, const fbdev_info_t *pfn_info) } } -static void __map_fake_fbdev(struct domain *d, const fbdev_info_t *real_fb) +static void __map_fake_fbdev(struct domain *d, const fbdev_pfns_t *real_fb) { size_t i, j; addr_t phys_addr; @@ -62,7 +62,7 @@ static void __map_fake_fbdev(struct domain *d, const fbdev_info_t *real_fb) } } -void fbdev_set_pgtable(struct domain *d, int slotID) +void fbdev_ipamap_domain(struct domain *d, int slotID) { /* Only capsules have virtual framebuffer */ if ((slotID < MEMSLOT_BASE) && !memslot[slotID].busy) @@ -74,7 +74,7 @@ void fbdev_set_pgtable(struct domain *d, int slotID) __map_fake_fbdev(d, &priv.fbdev); } -void fbdev_set_info(fbdev_info_t *fbdev) +void fbdev_set_pfns(fbdev_pfns_t *fbdev) { int slotID; @@ -83,7 +83,7 @@ void fbdev_set_info(fbdev_info_t *fbdev) /* Map framebuffer to all capsules. */ for (slotID = MEMSLOT_BASE; slotID < MEMSLOT_NR; slotID++) if (memslot[slotID].busy) - fbdev_set_pgtable(domains[slotID], slotID); + fbdev_ipamap_domain(domains[slotID], slotID); } void fbdev_change_focus(int new_slotID) @@ -99,7 +99,7 @@ void fbdev_change_focus(int new_slotID) priv.current_slotID = new_slotID; } -addr_t fbdev_get_addr(void) +addr_t fbdev_get_domain_ipa(void) { return pfn_to_phys(current_domain->fbdev_start_pfn); } diff --git a/so3/avz/kernel/gnttab.c b/so3/avz/kernel/gnttab.c index 1de3539e0..333694cbf 100644 --- a/so3/avz/kernel/gnttab.c +++ b/so3/avz/kernel/gnttab.c @@ -81,7 +81,7 @@ gnttab_t *pick_granted_entry(grant_ref_t ref, domid_t origin_domid) /** * @brief Create a new grant table entry in the gnttab of a domain - * + * * @param d The domain containing the grant table * @param target_domid The domain concerned by this grant * @param pfn The real frame number of the page to be granted @@ -186,7 +186,7 @@ addr_t map_vbstore_pfn(int target_domid, int pfn) /** * @brief Hypercall entry for grant table related operations. - * + * * @param args gnttab detail structure */ void do_gnttab(gnttab_op_t *args) diff --git a/so3/avz/kernel/hypercalls.c b/so3/avz/kernel/hypercalls.c index 824d5f40c..30af35cf8 100644 --- a/so3/avz/kernel/hypercalls.c +++ b/so3/avz/kernel/hypercalls.c @@ -202,16 +202,16 @@ void do_avz_hypercall(void *__args) break; } - case AVZ_FBDEV_SET_INFO: - fbdev_set_info(&args->u.avz_fbdev_info_args.fbdev); + case AVZ_FBDEV_SET_PFNS: + fbdev_set_pfns(&args->u.avz_fbdev_pfns_args.fbdev); break; case AVZ_FBDEV_CHANGE_FOCUS: fbdev_change_focus(args->u.avz_fbdev_focus_args.new_slotID); break; - case AVZ_FBDEV_GET_ADDR: - args->u.avz_fbdev_addr_args.paddr = fbdev_get_addr(); + case AVZ_FBDEV_GET_ME_ADDR: + args->u.avz_fbdev_addr_args.paddr = fbdev_get_domain_ipa(); break; #endif /* CONFIG_SOO */ diff --git a/so3/soo/drivers/vfbdevfront/vfbdev.c b/so3/soo/drivers/vfbdevfront/vfbdev.c index 1fce0a7de..36db27dc0 100644 --- a/so3/soo/drivers/vfbdevfront/vfbdev.c +++ b/so3/soo/drivers/vfbdevfront/vfbdev.c @@ -243,7 +243,7 @@ static void retrieve_data(vfbdev_priv_t *priv) vdevfront_processing_end(vfbdev_dev); - hyp_args.cmd = AVZ_FBDEV_GET_ADDR; + hyp_args.cmd = AVZ_FBDEV_GET_ME_ADDR; avz_hypercall(&hyp_args); priv->fb_paddr = hyp_args.u.avz_fbdev_addr_args.paddr; } diff --git a/so3/soo/include/soo/uapi/soo.h b/so3/soo/include/soo/uapi/soo.h index a6f069525..39dd9031b 100644 --- a/so3/soo/include/soo/uapi/soo.h +++ b/so3/soo/include/soo/uapi/soo.h @@ -79,11 +79,11 @@ void do_gnttab(gnttab_op_t *args); */ #define MAX_FBDEV_PFN 8 -typedef struct fbdev_info { +typedef struct fbdev_pfns { size_t pfn_count; addr_t pfn[MAX_FBDEV_PFN]; size_t page_count[MAX_FBDEV_PFN]; -} fbdev_info_t; +} fbdev_pfns_t; #define AVZ_SCHEDULER_FLIP 0 @@ -314,9 +314,9 @@ typedef struct agency_ioctl_args { #define AVZ_SET_ME_STATE 11 #define AVZ_GET_DOM_DESC 12 #define AVZ_GRANT_TABLE_OP 13 -#define AVZ_FBDEV_SET_INFO 14 +#define AVZ_FBDEV_SET_PFNS 14 #define AVZ_FBDEV_CHANGE_FOCUS 15 -#define AVZ_FBDEV_GET_ADDR 16 +#define AVZ_FBDEV_GET_ME_ADDR 16 /* AVZ_INJECT_CAPSULE */ typedef struct { @@ -379,17 +379,17 @@ typedef struct { gnttab_op_t gnttab_op; } avz_gnttab_t; -/* AVZ_FBDEV_SET_INFO */ +/* AVZ_FBDEV_SET_PFNS */ typedef struct { - fbdev_info_t fbdev; -} avz_fbdev_info_t; + fbdev_pfns_t fbdev; +} avz_fbdev_pfns_t; /* AVZ_FBDEV_CHANGE_FOCUS */ typedef struct { int new_slotID; } avz_fbdev_focus_t; -/* AVZ_FBDEV_GET_ADDR */ +/* AVZ_FBDEV_GET_ME_ADDR */ typedef struct { addr_t paddr; } avz_fbdev_addr_t; @@ -413,7 +413,7 @@ typedef struct { avz_console_io_t avz_console_io_args; avz_domctl_t avz_domctl_args; avz_gnttab_t avz_gnttab_args; - avz_fbdev_info_t avz_fbdev_info_args; + avz_fbdev_pfns_t avz_fbdev_pfns_args; avz_fbdev_focus_t avz_fbdev_focus_args; avz_fbdev_addr_t avz_fbdev_addr_args; } u; From 3eccdfa5e91ebc4f86d52de3bb2554a305ea3dfa Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Tue, 7 Apr 2026 13:19:45 +0200 Subject: [PATCH 6/8] add missing header + cleanup --- so3/arch/arm64/domain.c | 2 +- so3/avz/include/avz/domain.h | 2 +- so3/avz/include/avz/fbdev_gnt.h | 1 - so3/avz/include/avz/injector.h | 2 +- so3/avz/kernel/fbdev_gnt.c | 29 ++++++++++++++++++++++------ so3/soo/drivers/vfbdevfront/vfbdev.c | 15 ++++++++++---- so3/soo/include/soo/uapi/soo.h | 2 +- 7 files changed, 38 insertions(+), 15 deletions(-) diff --git a/so3/arch/arm64/domain.c b/so3/arch/arm64/domain.c index e5ca38cd2..814fdb060 100644 --- a/so3/arch/arm64/domain.c +++ b/so3/arch/arm64/domain.c @@ -136,7 +136,7 @@ void __setup_dom_pgtable(struct domain *d, addr_t paddr_start, unsigned long map d->grant_pfn[i].free = true; } - /* Set IPA framebuffer starting address after the grant pfn area */ + /* Set staring framebuffer ipa address after the grant pfn area */ d->fbdev_start_pfn = phys_to_pfn(memslot[slotID].ipa_addr + map_size + 2 * PAGE_SIZE) + NR_GRANT_PFN; fbdev_ipamap_domain(d, slotID); #endif /* CONFIG_SOO */ diff --git a/so3/avz/include/avz/domain.h b/so3/avz/include/avz/domain.h index b9908e8d3..d7d333ecc 100644 --- a/so3/avz/include/avz/domain.h +++ b/so3/avz/include/avz/domain.h @@ -118,7 +118,7 @@ struct domain { /* IPA reserved page frame numbers for mapping granted pages belonging to other domains */ grant_pfn_t grant_pfn[NR_GRANT_PFN]; - /* IPA reserved starting address for framebuffer mapping */ + /* IPA reserved starting page frame number for framebuffer mapping */ addr_t fbdev_start_pfn; #endif /* CONFIG_SOO */ diff --git a/so3/avz/include/avz/fbdev_gnt.h b/so3/avz/include/avz/fbdev_gnt.h index 4947a5066..68a5a1457 100644 --- a/so3/avz/include/avz/fbdev_gnt.h +++ b/so3/avz/include/avz/fbdev_gnt.h @@ -13,7 +13,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * */ #ifndef FBDEV_GNT_H diff --git a/so3/avz/include/avz/injector.h b/so3/avz/include/avz/injector.h index 809360b1b..ea5a4a5e0 100644 --- a/so3/avz/include/avz/injector.h +++ b/so3/avz/include/avz/injector.h @@ -55,7 +55,7 @@ struct dom_context { /* IPA reserved page frame numbers for granted pages */ grant_pfn_t grant_pfn[NR_GRANT_PFN]; - /* IPA reserved start frame number for framebuffer */ + /* IPA reserved starting page frame number for framebuffer mapping */ addr_t fbdev_start_pfn; /* Stack frame of this domain */ diff --git a/so3/avz/kernel/fbdev_gnt.c b/so3/avz/kernel/fbdev_gnt.c index 7c392faa7..73fe11262 100644 --- a/so3/avz/kernel/fbdev_gnt.c +++ b/so3/avz/kernel/fbdev_gnt.c @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2026 Clément Dieperink + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include #include #include @@ -5,7 +22,7 @@ #include typedef struct { - fbdev_pfns_t fbdev; + fbdev_pfns_t fbdev_pfns; void *fake_fbdev; int current_slotID; } fbdev_priv_t; @@ -69,16 +86,16 @@ void fbdev_ipamap_domain(struct domain *d, int slotID) return; if (slotID == priv.current_slotID) - __map_fbdev(d, &priv.fbdev); + __map_fbdev(d, &priv.fbdev_pfns); else - __map_fake_fbdev(d, &priv.fbdev); + __map_fake_fbdev(d, &priv.fbdev_pfns); } void fbdev_set_pfns(fbdev_pfns_t *fbdev) { int slotID; - memcpy(&priv.fbdev, fbdev, sizeof(*fbdev)); + memcpy(&priv.fbdev_pfns, fbdev, sizeof(*fbdev)); /* Map framebuffer to all capsules. */ for (slotID = MEMSLOT_BASE; slotID < MEMSLOT_NR; slotID++) @@ -90,11 +107,11 @@ void fbdev_change_focus(int new_slotID) { /* Remap old capsule to fake framebuffer */ if ((priv.current_slotID >= MEMSLOT_BASE) && memslot[priv.current_slotID].busy) - __map_fake_fbdev(domains[priv.current_slotID], &priv.fbdev); + __map_fake_fbdev(domains[priv.current_slotID], &priv.fbdev_pfns); /* Map the new capsule to the framebuffer */ if ((new_slotID >= MEMSLOT_BASE) && memslot[new_slotID].busy) - __map_fbdev(domains[new_slotID], &priv.fbdev); + __map_fbdev(domains[new_slotID], &priv.fbdev_pfns); priv.current_slotID = new_slotID; } diff --git a/so3/soo/drivers/vfbdevfront/vfbdev.c b/so3/soo/drivers/vfbdevfront/vfbdev.c index 36db27dc0..d20e6b7eb 100644 --- a/so3/soo/drivers/vfbdevfront/vfbdev.c +++ b/so3/soo/drivers/vfbdevfront/vfbdev.c @@ -50,7 +50,6 @@ typedef struct { uint32_t vres; size_t memory_size; addr_t fb_paddr; - } vfbdev_priv_t; /* Our unique vfbdev instance. */ @@ -210,16 +209,22 @@ vdrvfront_t vfbdevdrv = { .probe = vfbdev_probe, .resume = vfbdev_resume, .connected = vfbdev_connected }; +/* Char device associated to the framebuffer */ + +/** + * Retrieve data (resolution, size, fb address) from peer and AVZ. + */ static void retrieve_data(vfbdev_priv_t *priv) { vfbdev_request_t *ring_req; vfbdev_response_t *ring_rsp; avz_hyp_t hyp_args; - if ((priv->memory_size != 0) && (priv->fb_paddr != 0)) { + /* Data have already been retrieved */ + if ((priv->memory_size != 0) && (priv->fb_paddr != 0)) return; - } + /* Retrieve resolution and size from peer */ vdevfront_processing_begin(vfbdev_dev); ring_req = vfbdev_new_ring_request(&priv->vfbdev.ring); @@ -243,6 +248,7 @@ static void retrieve_data(vfbdev_priv_t *priv) vdevfront_processing_end(vfbdev_dev); + /* Retrieve fb address from AVZ */ hyp_args.cmd = AVZ_FBDEV_GET_ME_ADDR; avz_hypercall(&hyp_args); priv->fb_paddr = hyp_args.u.avz_fbdev_addr_args.paddr; @@ -288,6 +294,7 @@ static int vfbdev_ioctl(int fd, unsigned long cmd, unsigned long args) retrieve_data(priv); + /* Set returned value accordingly to the command */ switch (cmd) { case IOCTL_FB_HRES: *((uint32_t *) args) = priv->hres; @@ -303,7 +310,7 @@ static int vfbdev_ioctl(int fd, unsigned long cmd, unsigned long args) default: /* Unknown command. */ - return -1; + return -EINVAL; } } diff --git a/so3/soo/include/soo/uapi/soo.h b/so3/soo/include/soo/uapi/soo.h index 39dd9031b..959906a81 100644 --- a/so3/soo/include/soo/uapi/soo.h +++ b/so3/soo/include/soo/uapi/soo.h @@ -73,7 +73,7 @@ typedef struct gnttab_op gnttab_op_t; void do_gnttab(gnttab_op_t *args); /* - * Framebuffer to set the framebuffer addresses. + * Page frame number to set the framebuffer addresses. * The physical addresses may be splitted in multiple parts, which requires to have * multiple set of strating page frame and page count */ From c85ec0174467f50eed21c93101a515799831ae82 Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Tue, 7 Apr 2026 13:28:53 +0200 Subject: [PATCH 7/8] fix clang-format --- so3/arch/arm64/virt64/include/mach/ipamap.h | 6 +++--- so3/avz/kernel/fbdev_gnt.c | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/so3/arch/arm64/virt64/include/mach/ipamap.h b/so3/arch/arm64/virt64/include/mach/ipamap.h index 64edf3fb3..6bdc9ae07 100644 --- a/so3/arch/arm64/virt64/include/mach/ipamap.h +++ b/so3/arch/arm64/virt64/include/mach/ipamap.h @@ -31,19 +31,19 @@ ipamap_t agency_ipamap[] = { /* PCIe configuration ranges */ .ipa_addr = 0x4010000000, .phys_addr = 0x4010000000, - .size = 0x10000000 + .size = 0x10000000, }, { /* PCIe devices IO and 32 bits memory ranges */ .ipa_addr = 0x10000000, .phys_addr = 0x10000000, - .size = 0x2f000000 + .size = 0x2f000000, }, { /* PCIe devices 64 bits memory ranges */ .ipa_addr = 0x8000000000, .phys_addr = 0x8000000000, - .size = 0x8000000000 + .size = 0x8000000000, }, }; diff --git a/so3/avz/kernel/fbdev_gnt.c b/so3/avz/kernel/fbdev_gnt.c index 73fe11262..24e031cf4 100644 --- a/so3/avz/kernel/fbdev_gnt.c +++ b/so3/avz/kernel/fbdev_gnt.c @@ -37,7 +37,7 @@ static void __map_fbdev(struct domain *d, const fbdev_pfns_t *pfn_info) size_t size; void *pgtable; - pgtable = (void *)d->pagetable_vaddr; + pgtable = (void *) d->pagetable_vaddr; ipa_addr = pfn_to_phys(d->fbdev_start_pfn); /* Map all distincts ranges of the framebuffer to the capsule */ @@ -64,15 +64,14 @@ static void __map_fake_fbdev(struct domain *d, const fbdev_pfns_t *real_fb) BUG_ON(!priv.fake_fbdev); } - pgtable = (void *)d->pagetable_vaddr; + pgtable = (void *) d->pagetable_vaddr; ipa_addr = pfn_to_phys(d->fbdev_start_pfn); phys_addr = __pa(priv.fake_fbdev); /* Map the capsule framebuffer to the fake one */ for (i = 0; i < real_fb->pfn_count; i++) { for (j = 0; j < real_fb->page_count[i]; j++) { - __create_mapping(pgtable, ipa_addr, phys_addr, PAGE_SIZE, - true, S2); + __create_mapping(pgtable, ipa_addr, phys_addr, PAGE_SIZE, true, S2); ipa_addr += PAGE_SIZE; } From b23c1a2013b1465c70dc47b902f19c8c5f00e9f5 Mon Sep 17 00:00:00 2001 From: Clement Dieperink Date: Tue, 7 Apr 2026 13:33:26 +0200 Subject: [PATCH 8/8] fix clang-format --- so3/soo/drivers/vfbdevfront/vfbdev.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/so3/soo/drivers/vfbdevfront/vfbdev.c b/so3/soo/drivers/vfbdevfront/vfbdev.c index d20e6b7eb..30fa11eaf 100644 --- a/so3/soo/drivers/vfbdevfront/vfbdev.c +++ b/so3/soo/drivers/vfbdevfront/vfbdev.c @@ -108,7 +108,8 @@ void vfbdev_probe(struct vbus_device *vdev) /* Prepare the shared to page to be visible on the other end */ - vfbdev_priv->vfbdev.ring_ref = vbus_grant_ring(vdev, phys_to_pfn(virt_to_phys_pt((addr_t) vfbdev_priv->vfbdev.ring.sring))); + vfbdev_priv->vfbdev.ring_ref = + vbus_grant_ring(vdev, phys_to_pfn(virt_to_phys_pt((addr_t) vfbdev_priv->vfbdev.ring.sring))); vbus_transaction_start(&vbt); @@ -201,13 +202,15 @@ void vfbdev_connected(struct vbus_device *vdev) DBG0("[vfbdev] Frontend connected\n"); } -vdrvfront_t vfbdevdrv = { .probe = vfbdev_probe, - .reconfiguring = vfbdev_reconfiguring, - .shutdown = vfbdev_shutdown, - .closed = vfbdev_closed, - .suspend = vfbdev_suspend, - .resume = vfbdev_resume, - .connected = vfbdev_connected }; +vdrvfront_t vfbdevdrv = { + .probe = vfbdev_probe, + .reconfiguring = vfbdev_reconfiguring, + .shutdown = vfbdev_shutdown, + .closed = vfbdev_closed, + .suspend = vfbdev_suspend, + .resume = vfbdev_resume, + .connected = vfbdev_connected, +}; /* Char device associated to the framebuffer */ @@ -314,7 +317,6 @@ static int vfbdev_ioctl(int fd, unsigned long cmd, unsigned long args) } } - static struct file_operations vfbdev_fops = { .mmap = vfbdev_mmap, .ioctl = vfbdev_ioctl,