Cleaned up host-linux.c.
Moved more logic into monitor-host, which is host neutral.
This commit is contained in:
parent
9ca28db2ab
commit
d4a8cf56d6
bochs/plex86/kernel
@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Compatibility macros for older kernels */
|
/* Compatibility macros & convenience functions for older kernels */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
#ifndef EXPORT_NO_SYMBOLS
|
#ifndef EXPORT_NO_SYMBOLS
|
||||||
@ -66,7 +66,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,0)
|
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,0)
|
||||||
static inline unsigned long copy_from_user(void *to, const void *from, unsigned long n)
|
static inline unsigned long
|
||||||
|
copy_from_user(void *to, const void *from, unsigned long n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if ( (i = verify_area(VERIFY_READ, from, n)) != 0 )
|
if ( (i = verify_area(VERIFY_READ, from, n)) != 0 )
|
||||||
@ -74,7 +75,8 @@ static inline unsigned long copy_from_user(void *to, const void *from, unsigned
|
|||||||
memcpy_fromfs(to, from, n);
|
memcpy_fromfs(to, from, n);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static inline unsigned long copy_to_user(void *to, const void *from, unsigned long n)
|
static inline unsigned long
|
||||||
|
copy_to_user(void *to, const void *from, unsigned long n)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if ( (i = verify_area(VERIFY_WRITE, to, n)) != 0 )
|
if ( (i = verify_area(VERIFY_WRITE, to, n)) != 0 )
|
||||||
@ -86,7 +88,8 @@ static inline unsigned long copy_to_user(void *to, const void *from, unsigned lo
|
|||||||
|
|
||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,18) && !defined(THIS_MODULE)
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,18) && !defined(THIS_MODULE)
|
||||||
/* Starting with version 2.1.18, the __this_module symbol is present,
|
/* Starting with version 2.1.18, the __this_module symbol is present,
|
||||||
but the THIS_MODULE #define was introduced much later ... */
|
* but the THIS_MODULE #define was introduced much later ...
|
||||||
|
*/
|
||||||
#define THIS_MODULE (&__this_module)
|
#define THIS_MODULE (&__this_module)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -103,7 +106,7 @@ MODULE_PARM(plex_major, "i");
|
|||||||
MODULE_PARM_DESC(plex_major, "major number (default " __MODULE_STRING(PLEX86_MAJOR) ")");
|
MODULE_PARM_DESC(plex_major, "major number (default " __MODULE_STRING(PLEX86_MAJOR) ")");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The kernel segment base */
|
/* The kernel segment base. */
|
||||||
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,0)
|
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,0)
|
||||||
# define KERNEL_OFFSET 0xc0000000
|
# define KERNEL_OFFSET 0xc0000000
|
||||||
#else
|
#else
|
||||||
@ -111,8 +114,9 @@ MODULE_PARM_DESC(plex_major, "major number (default " __MODULE_STRING(PLEX86_MAJ
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* File operations */
|
/* File operations. */
|
||||||
static int plex86_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
|
static int plex86_ioctl(struct inode *, struct file *, unsigned int,
|
||||||
|
unsigned long);
|
||||||
static int plex86_open(struct inode *, struct file *);
|
static int plex86_open(struct inode *, struct file *);
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,31)
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,31)
|
||||||
@ -124,13 +128,14 @@ static int plex86_open(struct inode *, struct file *);
|
|||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)
|
||||||
static int plex86_mmap(struct file * file, struct vm_area_struct * vma);
|
static int plex86_mmap(struct file * file, struct vm_area_struct * vma);
|
||||||
#else
|
#else
|
||||||
static int plex86_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma);
|
static int plex86_mmap(struct inode * inode, struct file * file,
|
||||||
|
struct vm_area_struct * vma);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
|
||||||
/* New License scheme */
|
/* New License scheme. */
|
||||||
#ifdef MODULE_LICENSE
|
#ifdef MODULE_LICENSE
|
||||||
MODULE_LICENSE("GPL"); /* Close enough. */
|
MODULE_LICENSE("GPL"); /* Close enough. Keeps kernel from complaining. */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -140,12 +145,12 @@ MODULE_LICENSE("GPL"); /* Close enough. */
|
|||||||
/* Structures / Variables */
|
/* Structures / Variables */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
static int retrieve_vm_pages(Bit32u *page, int max_pages, void *addr, unsigned size);
|
static int retrieve_vm_pages(Bit32u *page, int max_pages, void *addr,
|
||||||
static unsigned retrieve_phy_pages(Bit32u *page, int max_pages, void *addr, unsigned size);
|
unsigned size);
|
||||||
|
static unsigned retrieve_phy_pages(Bit32u *page, int max_pages, void *addr,
|
||||||
|
unsigned size);
|
||||||
static int retrieve_monitor_pages(void);
|
static int retrieve_monitor_pages(void);
|
||||||
|
|
||||||
monitor_pages_t monitor_pages;
|
|
||||||
extern unsigned intRedirCount[];
|
|
||||||
|
|
||||||
|
|
||||||
static struct file_operations plex86_fops = {
|
static struct file_operations plex86_fops = {
|
||||||
@ -193,10 +198,10 @@ init_module(void)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* clear uninitialised structures */
|
/* Clear uninitialised structures. */
|
||||||
memset(&monitor_pages, 0, sizeof(monitor_pages));
|
memset(&monitor_pages, 0, sizeof(monitor_pages));
|
||||||
|
|
||||||
/* register the device with the kernel */
|
/* Register the device with the kernel. */
|
||||||
err = register_chrdev(plex_major, "plex86", &plex86_fops);
|
err = register_chrdev(plex_major, "plex86", &plex86_fops);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk(KERN_WARNING "plex86: can't get major %d\n", plex_major);
|
printk(KERN_WARNING "plex86: can't get major %d\n", plex_major);
|
||||||
@ -208,7 +213,7 @@ init_module(void)
|
|||||||
if(!plex_major)
|
if(!plex_major)
|
||||||
plex_major = err;
|
plex_major = err;
|
||||||
|
|
||||||
/* register the /proc entry */
|
/* Register the /proc entry. */
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
||||||
if (!create_proc_info_entry("driver/plex86", 0, NULL, plex86_read_procmem))
|
if (!create_proc_info_entry("driver/plex86", 0, NULL, plex86_read_procmem))
|
||||||
@ -218,7 +223,7 @@ init_module(void)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* register /dev/misc/plex86 with devfs */
|
/* Register /dev/misc/plex86 with devfs. */
|
||||||
#ifdef CONFIG_DEVFS_FS
|
#ifdef CONFIG_DEVFS_FS
|
||||||
my_devfs_entry = devfs_register(NULL, "misc/plex86",
|
my_devfs_entry = devfs_register(NULL, "misc/plex86",
|
||||||
DEVFS_FL_DEFAULT,
|
DEVFS_FL_DEFAULT,
|
||||||
@ -229,7 +234,7 @@ init_module(void)
|
|||||||
printk(KERN_ERR "plex86: registering misc/plex86 devfs entry failed\n");
|
printk(KERN_ERR "plex86: registering misc/plex86 devfs entry failed\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* retrieve the monitor physical pages */
|
/* Retrieve the monitor physical pages. */
|
||||||
if ( !retrieve_monitor_pages() ) {
|
if ( !retrieve_monitor_pages() ) {
|
||||||
printk(KERN_ERR "plex86: retrieve_monitor_pages returned error\n");
|
printk(KERN_ERR "plex86: retrieve_monitor_pages returned error\n");
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
@ -243,13 +248,13 @@ init_module(void)
|
|||||||
goto fail_cpu_capabilities;
|
goto fail_cpu_capabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* success */
|
/* Success. */
|
||||||
EXPORT_NO_SYMBOLS;
|
EXPORT_NO_SYMBOLS;
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
fail_cpu_capabilities:
|
fail_cpu_capabilities:
|
||||||
fail_retrieve_pages:
|
fail_retrieve_pages:
|
||||||
/* unregister /proc entry */
|
/* Unregister /proc entry. */
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
||||||
remove_proc_entry("driver/plex86", NULL);
|
remove_proc_entry("driver/plex86", NULL);
|
||||||
@ -258,7 +263,7 @@ fail_retrieve_pages:
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* unregister device */
|
/* Unregister device. */
|
||||||
unregister_chrdev(plex_major, "plex86");
|
unregister_chrdev(plex_major, "plex86");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -266,10 +271,10 @@ fail_retrieve_pages:
|
|||||||
void
|
void
|
||||||
cleanup_module(void)
|
cleanup_module(void)
|
||||||
{
|
{
|
||||||
/* unregister device */
|
/* Unregister device. */
|
||||||
unregister_chrdev(plex_major, "plex86");
|
unregister_chrdev(plex_major, "plex86");
|
||||||
|
|
||||||
/* unregister /proc entry */
|
/* Unregister /proc entry. */
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
||||||
remove_proc_entry("driver/plex86", NULL);
|
remove_proc_entry("driver/plex86", NULL);
|
||||||
@ -298,7 +303,7 @@ plex86_open(struct inode *inode, struct file *filp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Allocate a VM structure. */
|
/* Allocate a VM structure. */
|
||||||
if ( (vm = vmalloc(sizeof(vm_t))) == NULL )
|
if ( (vm = hostAllocZeroedMem(sizeof(vm_t))) == NULL )
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
filp->private_data = vm;
|
filp->private_data = vm;
|
||||||
|
|
||||||
@ -320,7 +325,7 @@ plex86_release(struct inode *inode, struct file *filp)
|
|||||||
filp->private_data = NULL;
|
filp->private_data = NULL;
|
||||||
|
|
||||||
/* Free the virtual memory. */
|
/* Free the virtual memory. */
|
||||||
hostUnreserveGuestPages( vm );
|
unreserveGuestPhyPages(vm);
|
||||||
unallocVmPages( vm );
|
unallocVmPages( vm );
|
||||||
|
|
||||||
/* Free the VM structure. */
|
/* Free the VM structure. */
|
||||||
@ -337,7 +342,6 @@ plex86_release(struct inode *inode, struct file *filp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
plex86_ioctl(struct inode *inode, struct file *filp,
|
plex86_ioctl(struct inode *inode, struct file *filp,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
@ -367,15 +371,11 @@ plex86_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vm
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
vm_t *vm = (vm_t *)file->private_data;
|
vm_t *vm = (vm_t *)file->private_data;
|
||||||
int i, firstpage, nr_pages;
|
int firstpage, pagesN;
|
||||||
Bit32u *pagesArray;
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)
|
||||||
unsigned stateMask;
|
void *inode = NULL; /* Not used; for consistency of passing args. */
|
||||||
|
#endif
|
||||||
/* Must have memory allocated */
|
int ret;
|
||||||
if (!vm->pages.guest_n_pages) {
|
|
||||||
printk(KERN_WARNING "plex86: device not initialized\n");
|
|
||||||
return -EACCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Private mappings make no sense ... */
|
/* Private mappings make no sense ... */
|
||||||
if ( !(vma->vm_flags & VM_SHARED) ) {
|
if ( !(vma->vm_flags & VM_SHARED) ) {
|
||||||
@ -392,83 +392,69 @@ plex86_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vm
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Map all requested pages in ... */
|
|
||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
||||||
firstpage = vma->vm_pgoff;
|
firstpage = vma->vm_pgoff;
|
||||||
#else
|
#else
|
||||||
firstpage = vma->vm_offset >> PAGE_SHIFT;
|
firstpage = vma->vm_offset >> PAGE_SHIFT;
|
||||||
#endif
|
#endif
|
||||||
nr_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
|
pagesN = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
|
||||||
|
|
||||||
/* The memory map:
|
ret = genericMMap(vm, inode, file, vma, firstpage, pagesN);
|
||||||
* guest physical memory (guest_n_pages)
|
return( - hostConvertPlex86Errno(ret) );
|
||||||
* log_buffer (1)
|
}
|
||||||
* guest_cpu (1)
|
|
||||||
|
|
||||||
|
int
|
||||||
|
hostMMap(vm_t *vm, void *iV, void *fV, void *vmaV,
|
||||||
|
unsigned pagesN, Bit32u *pagesArray)
|
||||||
|
{
|
||||||
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,1,0)
|
||||||
|
void *inode = NULL;
|
||||||
|
#else
|
||||||
|
struct inode * inode = (struct inode *) iV;
|
||||||
|
#endif
|
||||||
|
struct file * file = (struct file *) fV;
|
||||||
|
struct vm_area_struct * vma = (struct vm_area_struct *) vmaV;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
UNUSED(file);
|
||||||
|
|
||||||
|
/* Note: this function returns Plex86Errno style errors, since
|
||||||
|
* it reports to the hostOS-independent logic.
|
||||||
*/
|
*/
|
||||||
if ( firstpage == 0 ) {
|
|
||||||
if (nr_pages != vm->pages.guest_n_pages) {
|
|
||||||
printk(KERN_WARNING "plex86: mmap of guest phy mem, "
|
|
||||||
"nr_pages of %u != guest_n_pages of %u\n",
|
|
||||||
nr_pages, vm->pages.guest_n_pages);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
/* printk(KERN_WARNING "plex86: found mmap of guest phy memory.\n"); */
|
|
||||||
pagesArray = &vm->pages.guest[0];
|
|
||||||
stateMask = VMStateMMapPhyMem;
|
|
||||||
}
|
|
||||||
else if ( firstpage == (vm->pages.guest_n_pages+0) ) {
|
|
||||||
if (nr_pages != 1) {
|
|
||||||
printk(KERN_WARNING "plex86: mmap of log_buffer, pages>1.\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
/* printk(KERN_WARNING "plex86: found mmap of log_buffer.\n"); */
|
|
||||||
pagesArray = &vm->pages.log_buffer[0];
|
|
||||||
stateMask = VMStateMMapPrintBuffer;
|
|
||||||
}
|
|
||||||
else if ( firstpage == (vm->pages.guest_n_pages+1) ) {
|
|
||||||
if (nr_pages != 1) {
|
|
||||||
printk(KERN_WARNING "plex86: mmap of guest_cpu, pages>1.\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
/* printk(KERN_WARNING "plex86: found mmap of guest_cpu.\n"); */
|
|
||||||
pagesArray = &vm->pages.guest_cpu;
|
|
||||||
stateMask = VMStateMMapGuestCPU;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printk(KERN_WARNING "plex86: mmap with firstpage of 0x%x.\n", firstpage);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check. */
|
||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,3,25)
|
||||||
if ( ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > nr_pages ) {
|
if ( ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) > pagesN ) {
|
||||||
printk(KERN_WARNING "plex86: mmap sanity checks failed.\n");
|
printk(KERN_WARNING "plex86: mmap sanity checks failed.\n");
|
||||||
return -EINVAL;
|
return Plex86ErrnoEINVAL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if ( (vma->vm_end - vma->vm_start) > (nr_pages << PAGE_SHIFT) ) {
|
if ( (vma->vm_end - vma->vm_start) > (pagesN << PAGE_SHIFT) ) {
|
||||||
printk(KERN_WARNING "plex86: mmap sanity checks failed.\n");
|
printk(KERN_WARNING "plex86: mmap sanity checks failed.\n");
|
||||||
return -EINVAL;
|
return Plex86ErrnoEINVAL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for ( i = 0; i < nr_pages; i++ ) {
|
for (i = 0; i < pagesN; i++) {
|
||||||
if ( remap_page_range(vma->vm_start + (i << PAGE_SHIFT),
|
if ( remap_page_range(vma->vm_start + (i << PAGE_SHIFT),
|
||||||
pagesArray[i] << 12,
|
pagesArray[i] << 12,
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
vma->vm_page_prot) )
|
vma->vm_page_prot) )
|
||||||
/* xxx What about fixing partial remaps? */
|
/* xxx What about fixing partial remaps? */
|
||||||
return -EAGAIN;
|
return Plex86ErrnoEAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,0)
|
#if LINUX_VERSION_CODE < VERSION_CODE(2,1,0)
|
||||||
/* Enter our inode into the VMA; no need to change the default ops */
|
/* Enter our inode into the VMA; no need to change the default ops. */
|
||||||
vma->vm_inode = inode;
|
vma->vm_inode = inode;
|
||||||
if (!inode->i_count)
|
if (!inode->i_count)
|
||||||
inode->i_count++;
|
inode->i_count++;
|
||||||
|
#else
|
||||||
|
UNUSED(inode);
|
||||||
#endif
|
#endif
|
||||||
vm->vmState |= stateMask;
|
|
||||||
return 0;
|
return 0; /* OK. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -497,6 +483,41 @@ plex86_read_procmem(char *buf, char **start, off_t offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#warning "Consolidate retrieve_XYZ() functions?"
|
||||||
|
int
|
||||||
|
retrieve_monitor_pages(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Retrieve start address and size of this module.
|
||||||
|
*
|
||||||
|
* Note that with old kernels, we cannot access the module info (size),
|
||||||
|
* hence we rely on the fact that Linux lets at least one page of
|
||||||
|
* virtual address space unused after the end of the module.
|
||||||
|
*/
|
||||||
|
#ifdef THIS_MODULE
|
||||||
|
void *start_addr = THIS_MODULE;
|
||||||
|
unsigned size = THIS_MODULE->size;
|
||||||
|
#else
|
||||||
|
void *start_addr = &mod_use_count_;
|
||||||
|
unsigned size = 0x10000000; /* Actual size determined below */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int n_pages;
|
||||||
|
|
||||||
|
n_pages = retrieve_vm_pages(monitor_pages.page, PLEX86_MAX_MONITOR_PAGES,
|
||||||
|
start_addr, size);
|
||||||
|
if (n_pages == 0) {
|
||||||
|
printk(KERN_ERR "plex86: retrieve_vm_pages returned error.\n");
|
||||||
|
return( 0 ); /* Error. */
|
||||||
|
}
|
||||||
|
printk(KERN_WARNING "plex86: %u monitor pages located\n", n_pages);
|
||||||
|
|
||||||
|
monitor_pages.startOffset = (Bit32u)start_addr;
|
||||||
|
monitor_pages.startOffsetPageAligned = monitor_pages.startOffset & 0xfffff000;
|
||||||
|
monitor_pages.n_pages = n_pages;
|
||||||
|
return( n_pages );
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
retrieve_vm_pages(Bit32u *page, int max_pages, void *addr, unsigned size)
|
retrieve_vm_pages(Bit32u *page, int max_pages, void *addr, unsigned size)
|
||||||
{
|
{
|
||||||
@ -529,23 +550,20 @@ retrieve_vm_pages(Bit32u *page, int max_pages, void *addr, unsigned size)
|
|||||||
asm volatile ("movl %%cr3, %0" : "=r" (host_cr3));
|
asm volatile ("movl %%cr3, %0" : "=r" (host_cr3));
|
||||||
host_pgd = (pageEntry_t *)(phys_to_virt(host_cr3 & ~0xfff));
|
host_pgd = (pageEntry_t *)(phys_to_virt(host_cr3 & ~0xfff));
|
||||||
|
|
||||||
for (i = 0; i < n_pages; i++)
|
for (i = 0; i < n_pages; i++) {
|
||||||
{
|
|
||||||
Bit32u virt_addr = start_addr + i*PAGESIZE + KERNEL_OFFSET;
|
Bit32u virt_addr = start_addr + i*PAGESIZE + KERNEL_OFFSET;
|
||||||
pageEntry_t *pde = host_pgd + (virt_addr >> 22);
|
pageEntry_t *pde = host_pgd + (virt_addr >> 22);
|
||||||
pageEntry_t *pte = (pageEntry_t *)phys_to_virt(pde->fields.base << 12)
|
pageEntry_t *pte = (pageEntry_t *)phys_to_virt(pde->fields.base << 12)
|
||||||
+ ((virt_addr >> 12) & 0x3ff);
|
+ ((virt_addr >> 12) & 0x3ff);
|
||||||
|
|
||||||
/* If page isn't present, assume end of area */
|
/* If page isn't present, assume end of area. */
|
||||||
if ( !pde->fields.P || ! pte->fields.P )
|
if ( !pde->fields.P || ! pte->fields.P ) {
|
||||||
{
|
|
||||||
n_pages = i;
|
n_pages = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Abort if our page list is too small */
|
/* Abort if our page list is too small */
|
||||||
if (i >= max_pages)
|
if (i >= max_pages) {
|
||||||
{
|
|
||||||
printk(KERN_WARNING "plex86: page list is too small!\n");
|
printk(KERN_WARNING "plex86: page list is too small!\n");
|
||||||
printk(KERN_WARNING "plex86: n_pages=%u, max_pages=%u\n",
|
printk(KERN_WARNING "plex86: n_pages=%u, max_pages=%u\n",
|
||||||
n_pages, max_pages);
|
n_pages, max_pages);
|
||||||
@ -558,91 +576,6 @@ retrieve_vm_pages(Bit32u *page, int max_pages, void *addr, unsigned size)
|
|||||||
return n_pages;
|
return n_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
retrieve_monitor_pages(void)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Retrieve start address and size of this module.
|
|
||||||
*
|
|
||||||
* Note that with old kernels, we cannot access the module info (size),
|
|
||||||
* hence we rely on the fact that Linux lets at least one page of
|
|
||||||
* virtual address space unused after the end of the module.
|
|
||||||
*/
|
|
||||||
#ifdef THIS_MODULE
|
|
||||||
void *start_addr = THIS_MODULE;
|
|
||||||
unsigned size = THIS_MODULE->size;
|
|
||||||
#else
|
|
||||||
void *start_addr = &mod_use_count_;
|
|
||||||
unsigned size = 0x10000000; /* Actual size determined below */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int n_pages;
|
|
||||||
|
|
||||||
n_pages = retrieve_vm_pages(monitor_pages.page, PLEX86_MAX_MONITOR_PAGES,
|
|
||||||
start_addr, size);
|
|
||||||
if (n_pages == 0) {
|
|
||||||
printk(KERN_ERR "plex86: retrieve_vm_pages returned error.\n");
|
|
||||||
return( 0 ); /* Error. */
|
|
||||||
}
|
|
||||||
printk(KERN_WARNING "plex86: %u monitor pages located\n", n_pages);
|
|
||||||
|
|
||||||
monitor_pages.startOffset = (Bit32u)start_addr;
|
|
||||||
monitor_pages.startOffsetPageAligned =
|
|
||||||
monitor_pages.startOffset & 0xfffff000;
|
|
||||||
monitor_pages.n_pages = n_pages;
|
|
||||||
return( n_pages );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
hostReserveGuestPages(vm_t *vm)
|
|
||||||
{
|
|
||||||
vm_pages_t *pg = &vm->pages;
|
|
||||||
unsigned p;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* As we want to map these pages to user space, we need to mark
|
|
||||||
* them as 'reserved' pages by setting the PG_reserved bit.
|
|
||||||
*
|
|
||||||
* This has the effect that:
|
|
||||||
* - remap_page_range accepts them as candidates for remapping
|
|
||||||
* - the swapper does *not* try to swap these pages out, even
|
|
||||||
* after they are mapped to user space
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,4,0)
|
|
||||||
for (p = 0; p < pg->guest_n_pages; p++)
|
|
||||||
set_bit(PG_reserved, &((mem_map + pg->guest[p])->flags));
|
|
||||||
set_bit(PG_reserved, &((mem_map + pg->log_buffer[0])->flags));
|
|
||||||
set_bit(PG_reserved, &((mem_map + pg->guest_cpu)->flags));
|
|
||||||
#else
|
|
||||||
for (p = 0; p < pg->guest_n_pages; p++)
|
|
||||||
mem_map_reserve(pg->guest[p]);
|
|
||||||
mem_map_reserve(pg->log_buffer[0]);
|
|
||||||
mem_map_reserve(pg->guest_cpu);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
hostUnreserveGuestPages(vm_t *vm)
|
|
||||||
{
|
|
||||||
vm_pages_t *pg = &vm->pages;
|
|
||||||
unsigned p;
|
|
||||||
|
|
||||||
/* Remove the PG_reserved flags before returning the pages */
|
|
||||||
#if LINUX_VERSION_CODE >= VERSION_CODE(2,4,0)
|
|
||||||
for (p = 0; p < pg->guest_n_pages; p++)
|
|
||||||
clear_bit(PG_reserved, &((mem_map + pg->guest[p])->flags));
|
|
||||||
clear_bit(PG_reserved, &((mem_map + pg->log_buffer[0])->flags));
|
|
||||||
clear_bit(PG_reserved, &((mem_map + pg->guest_cpu)->flags));
|
|
||||||
#else
|
|
||||||
for (p = 0; p < pg->guest_n_pages; p++)
|
|
||||||
mem_map_unreserve(pg->guest[p]);
|
|
||||||
mem_map_unreserve(pg->log_buffer[0]);
|
|
||||||
mem_map_unreserve(pg->guest_cpu);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
retrieve_phy_pages(Bit32u *page, int max_pages, void *addr_v, unsigned size)
|
retrieve_phy_pages(Bit32u *page, int max_pages, void *addr_v, unsigned size)
|
||||||
{
|
{
|
||||||
@ -689,13 +622,13 @@ retrieve_phy_pages(Bit32u *page, int max_pages, void *addr_v, unsigned size)
|
|||||||
pte = ((pageEntry_t *)phys_to_virt(pde->fields.base << 12))
|
pte = ((pageEntry_t *)phys_to_virt(pde->fields.base << 12))
|
||||||
+ ((laddr >> 12) & 0x3ff);
|
+ ((laddr >> 12) & 0x3ff);
|
||||||
if ( !pde->fields.P ) {
|
if ( !pde->fields.P ) {
|
||||||
printk(KERN_ERR "plex86: retrieve_phy_pages: PDE.P==0: i=%u, n=%u laddr=0x%x\n",
|
printk(KERN_ERR "plex86: retrieve_phy_pages: "
|
||||||
i, n_pages, laddr);
|
"PDE.P==0: i=%u, n=%u laddr=0x%x\n", i, n_pages, laddr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ( !pte->fields.P ) {
|
if ( !pte->fields.P ) {
|
||||||
printk(KERN_ERR "plex86: retrieve_phy_pages: PTE.P==0: i=%u, n=%u laddr=0x%x\n",
|
printk(KERN_ERR "plex86: retrieve_phy_pages: "
|
||||||
i, n_pages, laddr);
|
"PTE.P==0: i=%u, n=%u laddr=0x%x\n", i, n_pages, laddr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
page[i] = pte->fields.base;
|
page[i] = pte->fields.base;
|
||||||
@ -706,9 +639,47 @@ retrieve_phy_pages(Bit32u *page, int max_pages, void *addr_v, unsigned size)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************
|
||||||
/* The requisite host-specific functions. */
|
* The requisite host-specific functions. An implementation of each of
|
||||||
/************************************************************************/
|
* these functions needs to be offered for each host-XYZ.c file.
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
hostReservePhyPages(vm_t *vm, Bit32u *hostPhyPages, unsigned nPages)
|
||||||
|
{
|
||||||
|
unsigned p;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As we want to map these pages to user space, we need to mark
|
||||||
|
* them as 'reserved' pages by setting the PG_reserved bit.
|
||||||
|
*
|
||||||
|
* This has the effect that:
|
||||||
|
* - remap_page_range accepts them as candidates for remapping
|
||||||
|
* - the swapper does *not* try to swap these pages out, even
|
||||||
|
* after they are mapped to user space
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (p = 0; p < nPages; p++)
|
||||||
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,4,0)
|
||||||
|
set_bit(PG_reserved, &((mem_map + hostPhyPages[p])->flags));
|
||||||
|
#else
|
||||||
|
mem_map_reserve(hostPhyPages[p]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hostUnreservePhyPages(vm_t *vm, Bit32u *hostPhyPages, unsigned nPages)
|
||||||
|
{
|
||||||
|
unsigned p;
|
||||||
|
|
||||||
|
/* Remove the PG_reserved flags before returning the pages. */
|
||||||
|
for (p = 0; p < nPages; p++)
|
||||||
|
#if LINUX_VERSION_CODE >= VERSION_CODE(2,4,0)
|
||||||
|
clear_bit(PG_reserved, &((mem_map + hostPhyPages[p])->flags));
|
||||||
|
#else
|
||||||
|
mem_map_unreserve(hostPhyPages[p]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
hostIdle(void)
|
hostIdle(void)
|
||||||
@ -800,6 +771,8 @@ hostConvertPlex86Errno(unsigned ret)
|
|||||||
case Plex86ErrnoENOMEM: return(ENOMEM);
|
case Plex86ErrnoENOMEM: return(ENOMEM);
|
||||||
case Plex86ErrnoEFAULT: return(EFAULT);
|
case Plex86ErrnoEFAULT: return(EFAULT);
|
||||||
case Plex86ErrnoEINVAL: return(EINVAL);
|
case Plex86ErrnoEINVAL: return(EINVAL);
|
||||||
|
case Plex86ErrnoEACCES: return(EACCES);
|
||||||
|
case Plex86ErrnoEAGAIN: return(EAGAIN);
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "plex86: ioctlAllocVPhys: case %u\n", ret);
|
printk(KERN_ERR "plex86: ioctlAllocVPhys: case %u\n", ret);
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
|
@ -56,12 +56,12 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hostReserveGuestPages(vm_t *vm)
|
hostReservePhyPages(vm_t *vm, Bit32u *hostPhyPages, unsigned nPages)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hostUnreserveGuestPages(vm_t *vm)
|
hostUnreservePhyPages(vm_t *vm, Bit32u *hostPhyPages, unsigned nPages)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,11 @@
|
|||||||
#include "eflags.h"
|
#include "eflags.h"
|
||||||
#include "guest_context.h"
|
#include "guest_context.h"
|
||||||
|
|
||||||
|
#ifndef UNUSED
|
||||||
|
# define UNUSED(x) ((void)(x))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Method1: push event info (CPU pushes error code before) */
|
/* Method1: push event info (CPU pushes error code before) */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -481,6 +486,7 @@ typedef struct {
|
|||||||
|
|
||||||
extern monitor_pages_t monitor_pages;
|
extern monitor_pages_t monitor_pages;
|
||||||
extern cpuid_info_t cpuid_info;
|
extern cpuid_info_t cpuid_info;
|
||||||
|
extern unsigned intRedirCount[];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -566,6 +572,8 @@ vm_rdtsc(void) {
|
|||||||
#define Plex86ErrnoENOMEM 2
|
#define Plex86ErrnoENOMEM 2
|
||||||
#define Plex86ErrnoEFAULT 3
|
#define Plex86ErrnoEFAULT 3
|
||||||
#define Plex86ErrnoEINVAL 4
|
#define Plex86ErrnoEINVAL 4
|
||||||
|
#define Plex86ErrnoEACCES 5
|
||||||
|
#define Plex86ErrnoEAGAIN 6
|
||||||
|
|
||||||
#define vm_save_flags(x) \
|
#define vm_save_flags(x) \
|
||||||
asm volatile("pushfl ; popl %0": "=g" (x): :"memory")
|
asm volatile("pushfl ; popl %0": "=g" (x): :"memory")
|
||||||
@ -588,6 +596,10 @@ int ioctlGeneric(vm_t *vm, void *inode, void *filp,
|
|||||||
int ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg);
|
int ioctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg);
|
||||||
unsigned ioctlAllocVPhys(vm_t *vm, unsigned long arg);
|
unsigned ioctlAllocVPhys(vm_t *vm, unsigned long arg);
|
||||||
void copyGuestStateToUserSpace(vm_t *vm);
|
void copyGuestStateToUserSpace(vm_t *vm);
|
||||||
|
void unreserveGuestPhyPages(vm_t *vm);
|
||||||
|
void reserveGuestPhyPages(vm_t *vm);
|
||||||
|
int genericMMap(vm_t *vm, void *inode, void *file, void *vma,
|
||||||
|
unsigned firstPage, unsigned pagesN);
|
||||||
|
|
||||||
/* These are the functions that the host-OS-specific file of the
|
/* These are the functions that the host-OS-specific file of the
|
||||||
* plex86 device driver must define.
|
* plex86 device driver must define.
|
||||||
@ -602,13 +614,15 @@ unsigned hostGetAllocedMemPhyPages(Bit32u *page, int max_pages, void *ptr,
|
|||||||
Bit32u hostGetAllocedPagePhyPage(void *ptr);
|
Bit32u hostGetAllocedPagePhyPage(void *ptr);
|
||||||
void hostPrint(char *fmt, ...);
|
void hostPrint(char *fmt, ...);
|
||||||
Bit32u hostKernelOffset(void);
|
Bit32u hostKernelOffset(void);
|
||||||
void hostReserveGuestPages(vm_t *vm);
|
void hostReservePhyPages(vm_t *vm, Bit32u *hostPhyPages, unsigned nPages);
|
||||||
void hostUnreserveGuestPages(vm_t *vm);
|
void hostUnreservePhyPages(vm_t *vm, Bit32u *hostPhyPages, unsigned nPages);
|
||||||
int hostConvertPlex86Errno(unsigned ret);
|
int hostConvertPlex86Errno(unsigned ret);
|
||||||
unsigned hostMMapCheck(void *i, void *f);
|
unsigned hostMMapCheck(void *i, void *f);
|
||||||
void hostModuleCountReset(vm_t *vm, void *inode, void *filp);
|
void hostModuleCountReset(vm_t *vm, void *inode, void *filp);
|
||||||
unsigned long hostCopyFromUser(void *to, void *from, unsigned long len);
|
unsigned long hostCopyFromUser(void *to, void *from, unsigned long len);
|
||||||
unsigned long hostCopyToUser(void *to, void *from, unsigned long len);
|
unsigned long hostCopyToUser(void *to, void *from, unsigned long len);
|
||||||
|
int hostMMap(vm_t *vm, void *iV, void *fV, void *vmaV,
|
||||||
|
unsigned pagesN, Bit32u *pagesArray);
|
||||||
|
|
||||||
#endif /* HOST Space */
|
#endif /* HOST Space */
|
||||||
|
|
||||||
|
@ -25,14 +25,15 @@
|
|||||||
#define IN_HOST_SPACE
|
#define IN_HOST_SPACE
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
|
|
||||||
|
monitor_pages_t monitor_pages;
|
||||||
/* Instrumentation of how many hardware interrupts were redirected
|
/* Instrumentation of how many hardware interrupts were redirected
|
||||||
* to the host, while the VM was running.
|
* to the host, while the VM was running.
|
||||||
*/
|
*/
|
||||||
|
#warning "Check for SMP issues on these globals"
|
||||||
unsigned intRedirCount[256];
|
unsigned intRedirCount[256];
|
||||||
|
|
||||||
|
|
||||||
cpuid_info_t hostCpuIDInfo;
|
cpuid_info_t hostCpuIDInfo;
|
||||||
|
|
||||||
|
|
||||||
static int initIDTSlot(vm_t *vm, unsigned vec, int type);
|
static int initIDTSlot(vm_t *vm, unsigned vec, int type);
|
||||||
static void mapMonPages(vm_t *vm, Bit32u *, unsigned, Bit32u *, page_t *,
|
static void mapMonPages(vm_t *vm, Bit32u *, unsigned, Bit32u *, page_t *,
|
||||||
unsigned user, unsigned writable, char *name);
|
unsigned user, unsigned writable, char *name);
|
||||||
@ -744,7 +745,8 @@ ioctlGeneric(vm_t *vm, void *inode, void *filp,
|
|||||||
*/
|
*/
|
||||||
vm->vmState &= ~VMStateMMapAll;
|
vm->vmState &= ~VMStateMMapAll;
|
||||||
|
|
||||||
hostUnreserveGuestPages(vm);
|
#warning "Add check before calling unreserveGuestPhyPages()"
|
||||||
|
unreserveGuestPhyPages(vm);
|
||||||
unallocVmPages(vm);
|
unallocVmPages(vm);
|
||||||
|
|
||||||
/* Reset state to only FD opened. */
|
/* Reset state to only FD opened. */
|
||||||
@ -769,6 +771,7 @@ ioctlGeneric(vm_t *vm, void *inode, void *filp,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#warning "PLEX86_RESET should only conditionally compiled for debugging."
|
||||||
/*
|
/*
|
||||||
* For debugging, when the module gets hosed, this is a way
|
* For debugging, when the module gets hosed, this is a way
|
||||||
* to reset the in-use count, so we can rmmod it.
|
* to reset the in-use count, so we can rmmod it.
|
||||||
@ -1262,11 +1265,11 @@ hostPrint("plex86: vm_t size is %u\n", sizeof(vm_t));
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mark guest pages as reserved (for mmap()). */
|
/* Mark guest pages as reserved (for mmap()). */
|
||||||
hostReserveGuestPages( vm );
|
reserveGuestPhyPages(vm);
|
||||||
|
|
||||||
/* Initialize the guests physical memory. */
|
/* Initialize the guests physical memory. */
|
||||||
if ( initGuestPhyMem(vm) ) {
|
if ( initGuestPhyMem(vm) ) {
|
||||||
hostUnreserveGuestPages(vm);
|
unreserveGuestPhyPages(vm);
|
||||||
unallocVmPages(vm);
|
unallocVmPages(vm);
|
||||||
return -Plex86ErrnoEFAULT;
|
return -Plex86ErrnoEFAULT;
|
||||||
}
|
}
|
||||||
@ -1274,7 +1277,7 @@ hostPrint("plex86: vm_t size is %u\n", sizeof(vm_t));
|
|||||||
/* Initialize the monitor. */
|
/* Initialize the monitor. */
|
||||||
if ( !initMonitor(vm) ||
|
if ( !initMonitor(vm) ||
|
||||||
!mapMonitor(vm) ) {
|
!mapMonitor(vm) ) {
|
||||||
hostUnreserveGuestPages(vm);
|
unreserveGuestPhyPages(vm);
|
||||||
unallocVmPages(vm);
|
unallocVmPages(vm);
|
||||||
return -Plex86ErrnoEFAULT;
|
return -Plex86ErrnoEFAULT;
|
||||||
}
|
}
|
||||||
@ -1688,4 +1691,86 @@ initShadowPaging(vm_t *vm)
|
|||||||
xxxpanic(vm, "monPagingRemap: BadUsage4PDir\n");
|
xxxpanic(vm, "monPagingRemap: BadUsage4PDir\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reserveGuestPhyPages(vm_t *vm)
|
||||||
|
{
|
||||||
|
/* Mark guest pages as reserved (for mmap()). */
|
||||||
|
hostReservePhyPages(vm, vm->pages.guest, vm->pages.guest_n_pages);
|
||||||
|
hostReservePhyPages(vm, vm->pages.log_buffer, LOG_BUFF_PAGES);
|
||||||
|
hostReservePhyPages(vm, &vm->pages.guest_cpu, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unreserveGuestPhyPages(vm_t *vm)
|
||||||
|
{
|
||||||
|
hostUnreservePhyPages(vm, vm->pages.guest, vm->pages.guest_n_pages);
|
||||||
|
hostUnreservePhyPages(vm, vm->pages.log_buffer, LOG_BUFF_PAGES);
|
||||||
|
hostUnreservePhyPages(vm, &vm->pages.guest_cpu, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
genericMMap(vm_t *vm, void *inode, void *file, void *vma, unsigned firstPage,
|
||||||
|
unsigned pagesN)
|
||||||
|
{
|
||||||
|
unsigned stateMask;
|
||||||
|
Bit32u *pagesArray;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* The memory map:
|
||||||
|
* guest physical memory (guest_n_pages)
|
||||||
|
* log_buffer (1)
|
||||||
|
* guest_cpu (1)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Must have memory allocated. */
|
||||||
|
if (!vm->pages.guest_n_pages) {
|
||||||
|
hostPrint("plex86: genericMMap: device not initialized\n");
|
||||||
|
return Plex86ErrnoEACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( firstPage == 0 ) {
|
||||||
|
if (pagesN != vm->pages.guest_n_pages) {
|
||||||
|
hostPrint("plex86: mmap of guest phy mem, "
|
||||||
|
"pagesN of %u != guest_n_pages of %u\n",
|
||||||
|
pagesN, vm->pages.guest_n_pages);
|
||||||
|
return Plex86ErrnoEINVAL;
|
||||||
|
}
|
||||||
|
/* hostPrint("plex86: found mmap of guest phy memory.\n"); */
|
||||||
|
pagesArray = &vm->pages.guest[0];
|
||||||
|
stateMask = VMStateMMapPhyMem;
|
||||||
|
}
|
||||||
|
else if ( firstPage == (vm->pages.guest_n_pages+0) ) {
|
||||||
|
if (pagesN != 1) {
|
||||||
|
hostPrint("plex86: mmap of log_buffer, pages>1.\n");
|
||||||
|
return Plex86ErrnoEINVAL;
|
||||||
|
}
|
||||||
|
/* hostPrint("plex86: found mmap of log_buffer.\n"); */
|
||||||
|
pagesArray = &vm->pages.log_buffer[0];
|
||||||
|
stateMask = VMStateMMapPrintBuffer;
|
||||||
|
}
|
||||||
|
else if ( firstPage == (vm->pages.guest_n_pages+1) ) {
|
||||||
|
if (pagesN != 1) {
|
||||||
|
hostPrint("plex86: mmap of guest_cpu, pages>1.\n");
|
||||||
|
return Plex86ErrnoEINVAL;
|
||||||
|
}
|
||||||
|
/* hostPrint("plex86: found mmap of guest_cpu.\n"); */
|
||||||
|
pagesArray = &vm->pages.guest_cpu;
|
||||||
|
stateMask = VMStateMMapGuestCPU;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hostPrint("plex86: mmap with firstPage of 0x%x.\n", firstPage);
|
||||||
|
return Plex86ErrnoEINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call the hostOS-specific mmap code. */
|
||||||
|
ret = hostMMap(vm, inode, file, vma, pagesN, pagesArray);
|
||||||
|
if (ret != 0) {
|
||||||
|
/* Host-specific mmap code returned an error. Return that. */
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->vmState |= stateMask;
|
||||||
|
return 0; /* OK. */
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user