📄 monitor.h
字号:
#define CR0_PE (1<<0)#define CR0_MP (1<<1)#define CR0_EM (1<<2)#define CR0_TS (1<<3)#define CR0_ET (1<<4)#define CR0_NE (1<<5)#define CR0_WP (1<<16)#define CR0_AM (1<<18)#define CR0_NW (1<<29)#define CR0_CD (1<<30)#define CR0_PG (1<<31)/* * Complete state of the VM (Virtual Machine). */typedef struct { Bit32u guestPhyMemAddr; /* Ptr to malloced memory from user space. */ /* Store eflags values of the guest which are virtualized to * run in the monitor */ eflags_t veflags; unsigned executeMethod; unsigned vmState; unsigned mon_request; unsigned guestFaultNo; Bit32u pinReqPPI; unsigned redirect_vector; Bit32u kernel_offset;#define MonitorSpace 0#define UserSpace 1#define HostSpace 2 volatile unsigned inMonFault; /* Extra info on aborts, especially when a message can't * be printed out */ unsigned abort_code; struct { Bit64u t0; /* TSC before excecution of guest code */ Bit64u cyclesElapsed; /* Cycles of guest execution */ unsigned a20Enable; /* A20 line enabled? */ Bit32u a20AddrMask; /* mask to apply to phy address */ Bit32u a20IndexMask; /* mask to apply to phy address */ } system; cpuid_info_t guestCPUIDInfo;/* This macro yields a physical address after applying the A20 line * enable mask to the original physical address. */#define A20Addr(vm, paddr) ( (paddr) & ((vm)->system.a20AddrMask) )#define A20PageIndex(vm, pi) ( (pi) & ((vm)->system.a20IndexMask) ) /* Keep an index of the next available Page Table */ unsigned ptbl_laddr_map_i; Bit32u mon_pde_mask; /* Upper 10 bits of monitor lin addr space */ Bit32u mon_pdi; /* Same value shifted down 22 bits. */ Bit64u vpaging_tsc; /* time stamp of last page mappings flush */ /* We need to keep track of what each of the guest's physical */ /* pages contains, and maintain some additional attributes. */ /* We determine which kinds of information reside in the page, */ /* dynamically. */ phyPageInfo_t pageInfo[MAX_MON_GUEST_PAGES]; /* This is a hack for now. I need to store the "struct page *" * information returned by get_user_pages() in the Linux kernel. * Should clean this up. */ void *hostStructPagePtr[MAX_MON_GUEST_PAGES]; /* A revolving queue, which stores information on guest physical memory * pages which are currently pinned. Only a certain number of pages * may be pinned at any one time. This is a really simplistic * strategy - when the Q is full, the page which was pinned the * longest time ago is unpinned to make room. It's a * "least recently pinned" strategy. */#define MaxPhyPagesPinned 1024 /* 4Megs of pinned pages max per VM. */ struct { unsigned nEntries; /* Number of entries in table. */ unsigned tail; Bit32u ppi[MaxPhyPagesPinned]; /* Physical Page Index of pinned guest page. */ } guestPhyPagePinQueue; struct { volatile unsigned event; /* Any log event occurred. */ /* Inactive, OK to dump to host and change */ volatile unsigned locked; /* Number of times buffer wrapped since last print to kernel */ /* debug facility */ volatile unsigned offset; /* Current index within buffer */ volatile unsigned error; /* Error printing. (ex. string too long) */ } log_buffer_info; vm_pages_t pages; /* memory pages allocated by the host */ /* Host specific fields. These fields should NOT be accessed */ /* from code which may execute in either host or monitor/guest */ /* spaces, unless you need to _specifically_ manipulate a */ /* host-specific field. */ struct { vm_addr_t addr; /* addresses of data structures in host space */ void (*__host2mon)(void); /* Host to guest nexus entry point */ pageEntry_t nexus_pde; /* PDE pointing to nexus page table */ } host; /* Guest specific fields. These fields should NOT be accessed */ /* from code which may execute in either host or monitor/guest */ /* spaces, unless you need to _specifically_ manipulate a */ /* guest-specific field. */ struct { vm_addr_t addr; /* addresses of data structures in guest space */ void (*__mon2host)(void); /* monitor to host entry point */ } guest; } vm_t;extern char __nexus_start, __nexus_end, __mon_cs;extern char __host2mon, __mon2host, __handle_fault, __handle_int;extern char __ret_to_guest;/* * This structure describes the pages containing the code/data * of the monitor itself (inside the kernel module) */#define Plex86MaxKernelModulePages 128typedef struct { /* Virtual address space occupied by the kernel module. */ Bit32u startOffset; Bit32u startOffsetPageAligned; unsigned nPages; /* Number of pages. */ /* A list of the Physical Page Indeces of the pages comprising the * kernel module. A PPI is just the physical page address >> 12. */ Bit32u ppi[Plex86MaxKernelModulePages]; } kernelModulePages_t;extern kernelModulePages_t kernelModulePages;extern cpuid_info_t hostCpuIDInfo;#if !defined(IN_HOST_SPACE) && !defined(IN_MONITOR_SPACE)#error "No space defined for this file"#endif#if defined(IN_HOST_SPACE) || defined(IN_MONITOR_SPACE)void mon_memzero(void *ptr, int size);void mon_memcpy(void *dst, void *src, int size);void *mon_memset(void *s, unsigned c, unsigned n);/* * We need to set the monitor CS/DS base address so that the module pages, * which are mapped starting at linear address 'laddr' into the guest address * space, reside at the same offset relative to the monitor CS base as they * reside relative to the kernel CS base in the host address space. This way, * we can execute the (non-relocatable) module code within the guest address * space ... */#define MON_BASE_FROM_LADDR(laddr) \ ((laddr) - kernelModulePages.startOffsetPageAligned)/* ============================================================ * These are the functions which are available in either of the * host or monitor/guest spaces. *//* Access to label offsets in nexus.S... From the host address perspective */#define HOST_NEXUS_OFFSET(vm, field) \ ( ((Bit32u)vm->host.addr.nexus) + \ (((Bit32u) &field) - ((Bit32u) &__nexus_start)) )/* From the monitor/guest address perspective. */#define MON_NEXUS_OFFSET(vm, field) \ ( ((Bit32u)vm->guest.addr.nexus) + \ (((Bit32u) &field) - ((Bit32u) &__nexus_start)) ) static __inline__ Bit64uvm_rdtsc(void) { Bit64u ret; asm volatile ( "rdtsc" : "=A" (ret) ); return ret; }#endif /* {HOST, MONITOR} */#ifdef IN_HOST_SPACE/* ========================================================== * These are the functions which are available to the monitor * running in the host space. *//* * Generate a software interrupt */#define soft_int(n) \ asm volatile ( \ " movb %b0, __soft_int_vector \n\t" \ " jmp __soft_int_n \n\t" \ "__soft_int_n: \n\t" \ " sti \n\t" \ " .byte 0xcd \n\t" \ "__soft_int_vector: \n\t" \ " .byte 0x00 \n\t" \ : \ : "r" ((Bit8u) (n) ) \ : "memory" \ )#define Plex86ErrnoEBUSY 1#define Plex86ErrnoENOMEM 2#define Plex86ErrnoEFAULT 3#define Plex86ErrnoEINVAL 4#define Plex86ErrnoEACCES 5#define Plex86ErrnoEAGAIN 6#define vm_save_flags(x) \ asm volatile("pushfl ; popl %0": "=g" (x): :"memory")#define vm_restore_flags(x) \ asm volatile("pushl %0 ; popfl": :"g" (x): "memory", "cc")int hostInitMonitor(vm_t *);unsigned hostMapMonitor(vm_t *);unsigned hostInitGuestPhyMem(vm_t *);void hostUnallocVmPages(vm_t *);int hostAllocVmPages(vm_t *, plex86IoctlRegisterMem_t *registerMsg);void hostInitShadowPaging(vm_t *vm);void hostDeviceOpen(vm_t *);unsigned hostModuleInit(void);unsigned hostGetCpuCapabilities(void);int hostIoctlGeneric(vm_t *vm, void *inode, void *filp, unsigned int cmd, unsigned long arg);int hostIoctlExecute(vm_t *vm, plex86IoctlExecute_t *executeMsg);int hostIoctlRegisterMem(vm_t *vm, plex86IoctlRegisterMem_t *registerMsg);void hostCopyGuestStateToUserSpace(vm_t *vm);void hostReleasePinnedUserPages(vm_t *vm);unsigned hostHandlePagePinRequest(vm_t *vm, Bit32u reqPPI);/* These are the functions that the host-OS-specific file of the * plex86 device driver must define. */unsigned hostOSIdle(void);void *hostOSAllocZeroedMem(unsigned long size);void hostOSFreeMem(void *ptr);void *hostOSAllocZeroedPage(void);void hostOSFreePage(void *ptr);unsigned hostOSGetAllocedMemPhyPages(Bit32u *page, int max_pages, void *ptr, unsigned size);Bit32u hostOSGetAndPinUserPage(vm_t *vm, Bit32u userAddr, void **osSpecificPtr, Bit32u *ppi, Bit32u *kernelAddr);void hostOSUnpinUserPage(vm_t *vm, Bit32u userAddr, void *osSpecificPtr, Bit32u ppi, Bit32u *kernelAddr, unsigned dirty);Bit32u hostOSGetAllocedPagePhyPage(void *ptr);void hostOSPrint(char *fmt, ...);Bit32u hostOSKernelOffset(void);int hostOSConvertPlex86Errno(unsigned ret);void hostOSModuleCountReset(vm_t *vm, void *inode, void *filp);void hostOSInstrumentIntRedirCount(unsigned interruptVector);unsigned long hostOSCopyFromUser(void *to, void *from, unsigned long len);unsigned long hostOSCopyToUser(void *to, void *from, unsigned long len);#endif /* HOST Space */#ifdef IN_MONITOR_SPACE/* ========================================================== * These are the functions which are available to the monitor * running in the monitor/guest space. */void sysFlushPrintBuf(vm_t *);void sysRemapMonitor(vm_t *);int monprint(vm_t *, char *fmt, ...);int mon_vsnprintf(char *str, unsigned size, const char *fmt, va_list args);void resetPrintBuf(vm_t *);/* Translate from guest laddr to monitor laddr. */#define Guest2Monitor(vm, laddr) ( ((Bit32u) (laddr)) - \ vm->guest.addr.nexus->mon_base )void monpanic(vm_t *, char *fmt, ...) __attribute__ ((noreturn));void monpanic_nomess(vm_t *);void toHostGuestFault(vm_t *, unsigned fault);void toHostPinUserPage(vm_t *, Bit32u ppi);void guestPageFault(vm_t *, guest_context_t *context, Bit32u cr2);void *open_guest_phy_page(vm_t *, Bit32u ppage_index, Bit8u *mon_offset);void close_guest_phy_page(vm_t *, Bit32u ppage_index);#define MapLinOK 0#define MapLinMonConflict 1#define MapLinAlreadyMapped 2#define MapLinPPageOOB 3#define MapLinException 4#define MapLinEmulate 5unsigned mapGuestLinAddr(vm_t *, Bit32u guest_laddr, Bit32u *guest_ppage_index, unsigned us, unsigned rw, Bit32u attr, Bit32u *error);unsigned addPageAttributes(vm_t *, Bit32u ppi, Bit32u attr);phyPageInfo_t *getPageUsage(vm_t *, Bit32u ppage_index);void virtualize_lconstruct(vm_t *, Bit32u l0, Bit32u l1, unsigned perm);unsigned getMonPTi(vm_t *, unsigned pdi, unsigned source);#define invlpg_mon_offset(mon_offset) \ asm volatile ("invlpg (%0)": :"r" (mon_offset): "memory")/* For now nothing, but we should conditionally compile in code * to panic when the expression is not true. */#define VM_ASSERT(vm, expression) \ if ( !(expression) ) \ monpanic(vm, "Assertion (%s) failed at %s:%u", \ #expression, __FILE__, __LINE__)#define CLI() asm volatile ("cli": : : "memory")#define STI() asm volatile ("sti": : : "memory")#endif /* MONITOR Space. */#endif /* __MONITOR_H__ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -