[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] Re: Linux Stubdom Problem
2011/8/19 Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>: > On Mon, 15 Aug 2011, Jiageng Yu wrote: >> Hi Stefano, >> >> Â Â In the linux-pv xenfbfront driver, the vram is allocated by: >> Â Â xenfb_probe() >> Â Â Â Â ->info->fb = vmalloc(fb_size); >> >> Â Â In the linux-stubdom, the memory areas: (info->fb, >> info->fb+fb_size) in linux-pv kernel, (s->vram_offset, >> s->vram_offset+VGA_RAM_SIZE) in vga_common_init function, >> (s->vram_ptr, s->vram_ptr+VGA_RAM_SIZE) in stubdom. These memory areas >> should be mapped into the same machine memory region. >> >> Â Â But the (info->fb, info->fb+fb_size) in linux-pv kernel is >> allocated independently. I have two optional plans to slove the >> problem. >> >> 1. Modify linux-pv kernel. >> Â Â This plan is more closer to the minios stubdom. First, I delay the >> initial process of xenfbfront driver until qemu allocates s->vram_ptr. >> Then, I set info->fb = s->vram_ptr. >> >> 2. Modify libxc. >> Â Â The s->vram_ptr is generated by mmap() function in >> linux_privcmd_map_foreign_bulk(). Maybe I could replace the return >> value of mmap() with the info->fb, which is obtained from xenstore. > > you would also need to modify qemu_ram_alloc to make sure the same pages > are remapped into the guest as videoram > > >> Â Â Can these plans solve the problem? Or there is the better one? > > I think it is best to keep the memory allocation in xenfbfront as it is > and find a way to map the pages in qemu. Isn't possible to use a mmap on > the fbdev device to obtain a mapping of the vmalloc'ed area into qemu? > Once we have mapped the pages into qemu address space it is just a > matter of using them as videoram. ÂOtherwise you would have timing > issues because qemu is probably going to start after xenfbfront has > already allocated the buffer and enstablished a connection with the > backend. > > In any case why don't you try running a guest without a video card (the > qemu command line option for that is -vga none or -nographic) and see if > everything else works? > Hi Stefano, I am trying to fix the vram mapping issue. That is my new patch. It is still needed to debug. Please check it for me and make sure I am running on the right way. I define a new enmu type Stubdom_Vga_State which is used to notify xen_remap_bucket whether to map the vram memory. In fbdev_pv_display_prepare function, I map the xen_fbfront memory to qemu (fb_mem) and directly incoke ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) to map the vram of hvm guest. diff --git a/fbdev.c b/fbdev.c index a601b48..f7ff682 100644 --- a/fbdev.c +++ b/fbdev.c @@ -30,6 +30,12 @@ #include "sysemu.h" #include "pflib.h" +#include "hw/xen_backend.h" +#include <xen/hvm/params.h> +#include <sys/ioctl.h> +#include "xenctrlosdep.h" +#include <xen/privcmd.h> + /* -------------------------------------------------------------------- */ /* file handles */ @@ -541,29 +547,23 @@ static void fbdev_cleanup(void) } } -static int fbdev_init(const char *device) +static int fbdev_init(int prot, unsigned long size) { struct vt_stat vts; unsigned long page_mask; char ttyname[32]; /* open framebuffer */ - if (device == NULL) { - device = getenv("FRAMEBUFFER"); - } - if (device == NULL) { - device = "/dev/fb0"; - } - fb = open(device, O_RDWR); + fb = open("/dev/fb0", O_RDWR); if (fb == -1) { - fprintf(stderr, "open %s: %s\n", device, strerror(errno)); + fprintf(stderr, "open /dev/fb0: %s\n", strerror(errno)); return -1; } /* open virtual console */ tty = 0; if (ioctl(tty, VT_GETSTATE, &vts) < 0) { fprintf(stderr, "Not started from virtual terminal, trying to open one.\n"); snprintf(ttyname, sizeof(ttyname), "/dev/tty0"); tty = open(ttyname, O_RDWR); @@ -632,14 +632,14 @@ static int fbdev_init(const char *device) goto err; } page_mask = getpagesize()-1; fb_mem_offset = (unsigned long)(fb_fix.smem_start) & page_mask; - fb_mem = mmap(NULL,fb_fix.smem_len+fb_mem_offset, - PROT_READ|PROT_WRITE,MAP_SHARED,fb,0); + fb_mem = mmap(NULL, size << XC_PAGE_SHIFT, prot, MAP_SHARED, fb, 0); if (fb_mem == MAP_FAILED) { perror("mmap"); goto err; } + /* move viewport to upper left corner */ if (fb_var.xoffset != 0 || fb_var.yoffset != 0) { fb_var.xoffset = 0; @@ -930,3 +928,71 @@ void fbdev_display_uninit(void) qemu_remove_exit_notifier(&exit_notifier); uninit_mouse(); } + +int fbdev_pv_display_prepare(unsigned long domid, int prot, const unsigned long *arr, + int *err, unsigned int num) +{ + xen_pfn_t *pfn; + privcmd_mmapbatch_t ioctlx; + int fd,i,rc; + + if (fbdev_init(prot,num) != 0) { + exit(1); + } + + pfn = malloc(num * sizeof(*pfn)); + if(!pfn){ + errno = -ENOMEM; + rc = -1; + return rc; + } + memcpy(pfn, arr, num*sizeof(*arr)); + + fd = open("/proc/xen/privcmd", O_RDWR); + if(fd == -1){ + fprintf(stderr,"Could not obtain handle on privcmd device\n"); + exit(1); + } + + ioctlx.num = num; + ioctlx.dom = domid; + ioctlx.addr = (unsigned long)fb_mem; + ioctlx.arr = pfn; + + rc = ioctl(fd, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx); + + for(i=0; i<num; i++) + { + switch(pfn[i] ^ arr[i]) + { + case 0: + err[i] = rc != -ENOENT ? rc:0; + continue; + default: + err[i] = -EINVAL; + continue; + } + break; + } + + free(pfn); + + if (rc == -ENOENT && i == num) + rc=0; + else if(rc) + { + errno = -rc; + rc = -1; + } + + if(rc < 0) + { + fprintf(stderr,"privcmd ioctl failed\n"); + munmap(fb_mem, num << XC_PAGE_SHIFT); + return NULL; + } + + close(fd); + + return fb_mem; +} diff --git a/hw/vga.c b/hw/vga.c index 0f54734..de7dd85 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -28,6 +28,7 @@ #include "vga_int.h" #include "pixel_ops.h" #include "qemu-timer.h" +#include "xen_backend.h" //#define DEBUG_VGA //#define DEBUG_VGA_MEM @@ -2237,7 +2238,12 @@ void vga_common_init(VGACommonState *s, int vga_ram_size) s->is_vbe_vmstate = 0; #endif s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size); +#ifdef CONFIG_STUBDOM + stubdom_vga_state = VGA_INIT_READY; +#endif s->vram_ptr = qemu_get_ram_ptr(s->vram_offset); s->vram_size = vga_ram_size; s->get_bpp = vga_get_bpp; s->get_offsets = vga_get_offsets; diff --git a/hw/xen_backend.c b/hw/xen_backend.c index c506dfe..f4ecce4 100644 --- a/hw/xen_backend.c +++ b/hw/xen_backend.c @@ -48,6 +48,10 @@ XenGnttab xen_xcg = XC_HANDLER_INITIAL_VALUE; struct xs_handle *xenstore = NULL; const char *xen_protocol; +#ifdef CONFIG_STUBDOM +enum Stubdom_Vga_State stubdom_vga_state=0; +#endif + /* private */ static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = QTAILQ_HEAD_INITIALIZER(xendevs); static int debug = 0; diff --git a/hw/xen_backend.h b/hw/xen_backend.h index 3305630..36167d1 100644 --- a/hw/xen_backend.h +++ b/hw/xen_backend.h @@ -60,6 +60,16 @@ extern XenXC xen_xc; extern struct xs_handle *xenstore; extern const char *xen_protocol; +#ifdef CONFIG_STUBDOM +/* linux stubdom vga initialization*/ +enum Stubdom_Vga_State{ + VGA_INIT_WAIT = 0, + VGA_INIT_READY, + VGA_INIT_COMPLETE +}; +extern enum Stubdom_Vga_State stubdom_vga_state; +#endif + /* xenstore helper functions */ int xenstore_write_str(const char *base, const char *node, const char *val); int xenstore_write_int(const char *base, const char *node, int ival); diff --git a/xen-mapcache.c b/xen-mapcache.c index 007136a..e615f98 100644 --- a/xen-mapcache.c +++ b/xen-mapcache.c @@ -20,6 +20,7 @@ #include "xen-mapcache.h" #include "trace.h" +#include "hw/xen.h" //#define MAPCACHE_DEBUG @@ -144,8 +145,19 @@ static void xen_remap_bucket(MapCacheEntry *entry, pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i; } +#ifdef CONFIG_STUBDOM + if(stubdom_vga_state == VGA_INIT_READY){ + fprintf(stderr,"xen_remap_bucket: start linux stubdom vga\n"); + vaddr_base = fbdev_pv_display_prepare(xen_domid, PROT_READ|PROT_WRITE, + pfns, err, nb_pfn); + stubdom_vga_state = VGA_INIT_COMPLETE; + }else + vaddr_base = xc_map_foreign_bulk(xen_xc, xen_domid, PROT_READ|PROT_WRITE, + pfns, err, nb_pfn); +#else vaddr_base = xc_map_foreign_bulk(xen_xc, xen_domid, PROT_READ|PROT_WRITE, pfns, err, nb_pfn); +#endif if (vaddr_base == NULL) { perror("xc_map_foreign_bulk"); exit(-1); Through I try to avoid modifing any code of linux-pv kernel, I still have to commente out some code to make it run. diff --git a/drivers/xen/xenfs/privcmd.c b/drivers/xen/xenfs/privcmd.c index f80be7f..420f3b1 100644 --- a/drivers/xen/xenfs/privcmd.c +++ b/drivers/xen/xenfs/privcmd.c @@ -303,11 +309,10 @@ static long privcmd_ioctl_mmap_batch(void __user *udata) vma = find_vma(mm, m.addr); ret = -EINVAL; + if (!vma || - vma->vm_ops != &privcmd_vm_ops || (m.addr != vma->vm_start) || - ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) || - !privcmd_enforce_singleshot_mapping(vma)) { + ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end)) { up_write(&mm->mmap_sem); goto out; } The debug dump of qemu is: (XEN) mm.c:945:d51 Error getting mfn 8ed68 (pfn 18000) from L1 entry 800000008ed68625 for l1e_owner=51, pg_owner=51 (XEN) mm.c:5044:d51 ptwr_emulate: fixing up invalid PAE PTE 800000008ed68625 (XEN) mm.c:945:d51 Error getting mfn 8ed68 (pfn 18000) from L1 entry 800000008ed68667 for l1e_owner=51, pg_owner=51 (XEN) mm.c:5049:d51 ptwr_emulate: could not get_page_from_l1e() <1>BUG: unable to handle kernel <c>paging request<c> at c1f1b8f8 <1>IP: [<c011a7f0>] ptep_set_access_flags+0x40/0x80 *pdpt = 0000000001ee2001 <c>*pde = 0000000000008067 *pte = 8000000001f1b061 <0>Oops: 0003 [#1] <0>last sysfs file: /sys/devices/virtual/vc/vcsa1/dev Pid: 283, comm: qemu Not tainted (2.6.32.41 #6) EIP: 0061:[<c011a7f0>] EFLAGS: 00010202 CPU: 0 EIP is at ptep_set_access_flags+0x40/0x80 That seems the mapping is failed. (pfn 18000) is the first vram page in hvm guest. Jiageng Yu. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |