For Xen, setup paging the way the kernel wants it and transfer control to the kernel Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.h Added: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386mem.h Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/mb.S Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenboot.c Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenmem.c _____
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c 2005-05-20 08:06:27 UTC (rev 15429) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c 2005-05-20 10:33:27 UTC (rev 15430) @@ -14,33 +14,22 @@
#include <debug.h>
#include "i386boot.h" +#include "i386mem.h"
-/* Bits to shift to convert a Virtual Address into an Offset in the Page Table */ -#define PFN_SHIFT 12 - -/* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */ -#define PDE_SHIFT 20 -#define PDE_SHIFT_PAE 18 - - -/* Converts a Phsyical Address Pointer into a Page Frame Number */ -#define PaPtrToPfn(p) \ - (((ULONG_PTR)&p) >> PFN_SHIFT) - -/* Converts a Phsyical Address into a Page Frame Number */ -#define PaToPfn(p) \ - ((p) >> PFN_SHIFT) - #define STARTUP_BASE 0xF0000000 #define HYPERSPACE_BASE 0xF0800000 #define APIC_BASE 0xFEC00000 +#ifdef XEN_VER +#define KPCR_BASE 0xFB000000 +#else #define KPCR_BASE 0xFF000000 +#endif
#define LowMemPageTableIndex 0 -#define StartupPageTableIndex (STARTUP_BASE >> 20) / sizeof(HARDWARE_PTE_X86) -#define HyperspacePageTableIndex (HYPERSPACE_BASE >> 20) / sizeof(HARDWARE_PTE_X86) -#define KpcrPageTableIndex (KPCR_BASE >> 20) / sizeof(HARDWARE_PTE_X86) -#define ApicPageTableIndex (APIC_BASE >> 20) / sizeof(HARDWARE_PTE_X86) +#define StartupPageTableIndex (STARTUP_BASE >> PDN_SHIFT) +#define HyperspacePageTableIndex (HYPERSPACE_BASE >> PDN_SHIFT) +#define KpcrPageTableIndex (KPCR_BASE >> PDN_SHIFT) +#define ApicPageTableIndex (APIC_BASE >> PDN_SHIFT)
#define LowMemPageTableIndexPae 0 #define StartupPageTableIndexPae (STARTUP_BASE >> 21) @@ -48,83 +37,32 @@ #define KpcrPageTableIndexPae (KPCR_BASE >> 21) #define ApicPageTableIndexPae (APIC_BASE >> 21)
- -#define KernelEntryPoint (KernelEntry - KERNEL_BASE_PHYS) + KernelBase - -/* Unrelocated Kernel Base in Virtual Memory */ -extern ULONG_PTR KernelBase; - -/* Kernel Entrypoint in Physical Memory */ -extern ULONG_PTR KernelEntry; - -/* Page Directory and Tables for non-PAE Systems */ -extern ULONG_PTR startup_pagedirectory; -extern ULONG_PTR lowmem_pagetable; -extern ULONG_PTR kernel_pagetable; -extern ULONG_PTR hyperspace_pagetable; -extern ULONG_PTR _pae_pagedirtable; -extern ULONG_PTR apic_pagetable; -extern ULONG_PTR kpcr_pagetable; - -/* Page Directory and Tables for PAE Systems */ -extern ULONG_PTR startup_pagedirectorytable_pae; -extern ULONG_PTR startup_pagedirectory_pae; -extern ULONG_PTR lowmem_pagetable_pae; -extern ULONG_PTR kernel_pagetable_pae; -extern ULONG_PTR hyperspace_pagetable_pae; -extern ULONG_PTR pagedirtable_pae; -extern ULONG_PTR apic_pagetable_pae; -extern ULONG_PTR kpcr_pagetable_pae; - -typedef struct _HARDWARE_PTE_X86 { - ULONG Valid : 1; - ULONG Write : 1; - ULONG Owner : 1; - ULONG WriteThrough : 1; - ULONG CacheDisable : 1; - ULONG Accessed : 1; - ULONG Dirty : 1; - ULONG LargePage : 1; - ULONG Global : 1; - ULONG CopyOnWrite : 1; - ULONG Prototype : 1; - ULONG reserved : 1; - ULONG PageFrameNumber : 20; -} HARDWARE_PTE_X86, *PHARDWARE_PTE_X86; - -typedef struct _HARDWARE_PTE_X64 { - ULONG Valid : 1; - ULONG Write : 1; - ULONG Owner : 1; - ULONG WriteThrough : 1; - ULONG CacheDisable : 1; - ULONG Accessed : 1; - ULONG Dirty : 1; - ULONG LargePage : 1; - ULONG Global : 1; - ULONG CopyOnWrite : 1; - ULONG Prototype : 1; - ULONG reserved : 1; - ULONG PageFrameNumber : 20; - ULONG reserved2 : 31; - ULONG NoExecute : 1; -} HARDWARE_PTE_X64, *PHARDWARE_PTE_X64; - -typedef struct _PAGE_DIRECTORY_X86 { - HARDWARE_PTE_X86 Pde[1024]; -} PAGE_DIRECTORY_x86, *PPAGE_DIRECTORY_X86; - -typedef struct _PAGE_DIRECTORY_X64 { - HARDWARE_PTE_X64 Pde[2048]; -} PAGE_DIRECTORY_X64, *PPAGE_DIRECTORY_X64; - -typedef struct _PAGE_DIRECTORY_TABLE_X64 { - HARDWARE_PTE_X64 Pde[4]; -} PAGE_DIRECTORY_TABLE_X64, *PPAGE_DIRECTORY_TABLE_X64; - /* FUNCTIONS *****************************************************************/
/*++ + * i386BootAddrToPfn + * INTERNAL + * + * Translate an address to a page frame number + * + * Params: + * Addr - address to translate + * + * Returns: + * Frame number. + * + * Remarks: + * None. + * + *--*/ +ULONG +STDCALL +i386BootAddrToPfn(ULONG_PTR Addr) +{ + return PaToPfn(Addr); +} + +/*++ * i386BootStartup * INTERNAL * @@ -156,7 +94,7 @@ PaeModeEnabled = i386BootGetPaeMode();
/* Initialize the page directory */ - i386BootSetupPageDirectory(PaeModeEnabled); + i386BootSetupPageDirectory(PaeModeEnabled, TRUE, i386BootAddrToPfn);
/* Initialize Paging, Write-Protection and Load NTOSKRNL */ i386BootSetupPae(PaeModeEnabled, Magic); @@ -257,7 +195,8 @@ *--*/ VOID FASTCALL -i386BootSetupPageDirectory(BOOLEAN PaeModeEnabled) +i386BootSetupPageDirectory(BOOLEAN PaeModeEnabled, BOOLEAN SetupApic, + ULONG (STDCALL *AddrToPfn)(ULONG_PTR Addr)) { PPAGE_DIRECTORY_X86 PageDir; PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae; @@ -369,7 +308,7 @@ } else {
/* Get the Kernel Table Index */ - KernelPageTableIndex = (KernelBase >> PDE_SHIFT) / sizeof(HARDWARE_PTE_X86); + KernelPageTableIndex = KernelBase >> PDN_SHIFT;
/* Get the Startup Page Directory */ PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory; @@ -377,35 +316,37 @@ /* Set up the Low Memory PDE */ PageDir->Pde[LowMemPageTableIndex].Valid = 1; PageDir->Pde[LowMemPageTableIndex].Write = 1; - PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable); + PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = (*AddrToPfn)((ULONG_PTR) &lowmem_pagetable);
/* Set up the Kernel PDEs */ PageDir->Pde[KernelPageTableIndex].Valid = 1; PageDir->Pde[KernelPageTableIndex].Write = 1; - PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable); + PageDir->Pde[KernelPageTableIndex].PageFrameNumber = (*AddrToPfn)((ULONG_PTR) &kernel_pagetable); PageDir->Pde[KernelPageTableIndex + 1].Valid = 1; PageDir->Pde[KernelPageTableIndex + 1].Write = 1; - PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096); + PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = (*AddrToPfn)((ULONG_PTR) &kernel_pagetable + 4096);
/* Set up the Startup PDE */ PageDir->Pde[StartupPageTableIndex].Valid = 1; PageDir->Pde[StartupPageTableIndex].Write = 1; - PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory); + PageDir->Pde[StartupPageTableIndex].PageFrameNumber = (*AddrToPfn)((LONG_PTR) &startup_pagedirectory);
/* Set up the Hyperspace PDE */ PageDir->Pde[HyperspacePageTableIndex].Valid = 1; PageDir->Pde[HyperspacePageTableIndex].Write = 1; - PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable); + PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = (*AddrToPfn)((LONG_PTR) &hyperspace_pagetable);
/* Set up the Apic PDE */ - PageDir->Pde[ApicPageTableIndex].Valid = 1; - PageDir->Pde[ApicPageTableIndex].Write = 1; - PageDir->Pde[ApicPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable); + if (SetupApic) { + PageDir->Pde[ApicPageTableIndex].Valid = 1; + PageDir->Pde[ApicPageTableIndex].Write = 1; + PageDir->Pde[ApicPageTableIndex].PageFrameNumber = (*AddrToPfn)((LONG_PTR) &apic_pagetable); + }
/* Set up the KPCR PDE */ PageDir->Pde[KpcrPageTableIndex].Valid = 1; PageDir->Pde[KpcrPageTableIndex].Write = 1; - PageDir->Pde[KpcrPageTableIndex].PageFrameNumber = PaPtrToPfn(kpcr_pagetable); + PageDir->Pde[KpcrPageTableIndex].PageFrameNumber = (*AddrToPfn)((LONG_PTR) &kpcr_pagetable);
/* Set up Low Memory PTEs */ PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable; @@ -414,7 +355,7 @@ PageDir->Pde[i].Valid = 1; PageDir->Pde[i].Write = 1; PageDir->Pde[i].Owner = 1; - PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE); + PageDir->Pde[i].PageFrameNumber = (*AddrToPfn)(i * PAGE_SIZE); }
/* Set up Kernel PTEs */ @@ -423,27 +364,29 @@
PageDir->Pde[i].Valid = 1; PageDir->Pde[i].Write = 1; - PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE); + PageDir->Pde[i].PageFrameNumber = (*AddrToPfn)(KERNEL_BASE_PHYS + i * PAGE_SIZE); }
/* Set up APIC PTEs */ - PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable; - PageDir->Pde[0].Valid = 1; - PageDir->Pde[0].Write = 1; - PageDir->Pde[0].CacheDisable = 1; - PageDir->Pde[0].WriteThrough = 1; - PageDir->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE); - PageDir->Pde[0x200].Valid = 1; - PageDir->Pde[0x200].Write = 1; - PageDir->Pde[0x200].CacheDisable = 1; - PageDir->Pde[0x200].WriteThrough = 1; - PageDir->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS); + if (SetupApic) { + PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable; + PageDir->Pde[0].Valid = 1; + PageDir->Pde[0].Write = 1; + PageDir->Pde[0].CacheDisable = 1; + PageDir->Pde[0].WriteThrough = 1; + PageDir->Pde[0].PageFrameNumber = (*AddrToPfn)(APIC_BASE); + PageDir->Pde[0x200].Valid = 1; + PageDir->Pde[0x200].Write = 1; + PageDir->Pde[0x200].CacheDisable = 1; + PageDir->Pde[0x200].WriteThrough = 1; + PageDir->Pde[0x200].PageFrameNumber = (*AddrToPfn)(APIC_BASE + KERNEL_BASE_PHYS); + }
/* Set up KPCR PTEs */ PageDir = (PPAGE_DIRECTORY_X86)&kpcr_pagetable; PageDir->Pde[0].Valid = 1; PageDir->Pde[0].Write = 1; - PageDir->Pde[0].PageFrameNumber = 1; + PageDir->Pde[0].PageFrameNumber = (*AddrToPfn)(PAGE_SIZE); } return; } _____
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.h --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.h 2005-05-20 08:06:27 UTC (rev 15429) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.h 2005-05-20 10:33:27 UTC (rev 15430) @@ -1,6 +1,33 @@
#ifndef I386BOOT_H_INCLUDED #define I386BOOT_H_INCLUDED
+#define KernelEntryPoint (KernelEntry - KERNEL_BASE_PHYS) + KernelBase + +/* Unrelocated Kernel Base in Virtual Memory */ +extern ULONG_PTR KernelBase; + +/* Kernel Entrypoint in Physical Memory */ +extern ULONG_PTR KernelEntry; + +/* Page Directory and Tables for non-PAE Systems */ +extern ULONG_PTR startup_pagedirectory; +extern ULONG_PTR lowmem_pagetable; +extern ULONG_PTR kernel_pagetable; +extern ULONG_PTR hyperspace_pagetable; +extern ULONG_PTR _pae_pagedirtable; +extern ULONG_PTR apic_pagetable; +extern ULONG_PTR kpcr_pagetable; + +/* Page Directory and Tables for PAE Systems */ +extern ULONG_PTR startup_pagedirectorytable_pae; +extern ULONG_PTR startup_pagedirectory_pae; +extern ULONG_PTR lowmem_pagetable_pae; +extern ULONG_PTR kernel_pagetable_pae; +extern ULONG_PTR hyperspace_pagetable_pae; +extern ULONG_PTR pagedirtable_pae; +extern ULONG_PTR apic_pagetable_pae; +extern ULONG_PTR kpcr_pagetable_pae; + VOID STDCALL i386BootStartup(ULONG Magic); @@ -15,6 +42,7 @@
VOID FASTCALL -i386BootSetupPageDirectory(BOOLEAN PaeModeEnabled); +i386BootSetupPageDirectory(BOOLEAN PaeModeEnabled, BOOLEAN SetupApic, + ULONG (STDCALL *AddrToPfn)(ULONG_PTR Addr));
#endif /* ! defined I386BOOT_H_INCLUDED */ _____
Copied: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386mem.h (from rev 15391, branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c) --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386boot.c 2005-05-17 22:15:18 UTC (rev 15391) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/i386mem.h 2005-05-20 10:33:27 UTC (rev 15430) @@ -0,0 +1,84 @@
+#ifndef I386MEM_H_INCLUDED +#define I386MEM_H_INCLUDED + +/* Bits to shift to convert a Virtual Address into an Offset in the Page Table */ +#define PFN_SHIFT 12 + +/* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */ +#define PDN_SHIFT 22 + + +/* Converts a Phsyical Address Pointer into a Page Frame Number */ +#define PaPtrToPfn(p) \ + (((ULONG_PTR)&p) >> PFN_SHIFT) + +/* Converts a Phsyical Address into a Page Frame Number */ +#define PaToPfn(p) \ + ((p) >> PFN_SHIFT) + +typedef struct _HARDWARE_PTE_X86 { + union { + struct { + ULONG Valid : 1; + ULONG Write : 1; + ULONG Owner : 1; + ULONG WriteThrough : 1; + ULONG CacheDisable : 1; + ULONG Accessed : 1; + ULONG Dirty : 1; + ULONG LargePage : 1; + ULONG Global : 1; + ULONG CopyOnWrite : 1; + ULONG Prototype : 1; + ULONG reserved : 1; + ULONG PageFrameNumber : 20; + }; + ULONG Val; + }; +} HARDWARE_PTE_X86, *PHARDWARE_PTE_X86, HARDWARE_PDE_X86, *PHARDWARE_PDE_X86; + +typedef struct _HARDWARE_PTE_X64 { + ULONG Valid : 1; + ULONG Write : 1; + ULONG Owner : 1; + ULONG WriteThrough : 1; + ULONG CacheDisable : 1; + ULONG Accessed : 1; + ULONG Dirty : 1; + ULONG LargePage : 1; + ULONG Global : 1; + ULONG CopyOnWrite : 1; + ULONG Prototype : 1; + ULONG reserved : 1; + ULONG PageFrameNumber : 20; + ULONG reserved2 : 31; + ULONG NoExecute : 1; +} HARDWARE_PTE_X64, *PHARDWARE_PTE_X64; + +#define PTRS_PER_PD_X86 (PAGE_SIZE / sizeof(HARDWARE_PDE_X86)) +#define PTRS_PER_PT_X86 (PAGE_SIZE / sizeof(HARDWARE_PTE_X86)) + +/* Page Directory Index of a given virtual address */ +#define PD_IDX(Va) ((((ULONG_PTR) Va) >> PDN_SHIFT) & (PTRS_PER_PD_X86 - 1)) +/* Page Table Index of a give virtual address */ +#define PT_IDX(Va) ((((ULONG_PTR) Va) >> PFN_SHIFT) & (PTRS_PER_PT_X86 - 1)) +/* Convert a Page Directory or Page Table entry to a (machine) address */ +#define PAGE_MASK (~(PAGE_SIZE-1)) + +typedef struct _PAGE_DIRECTORY_X86 { + HARDWARE_PDE_X86 Pde[PTRS_PER_PD_X86]; +} PAGE_DIRECTORY_X86, *PPAGE_DIRECTORY_X86; + +typedef struct _PAGE_TABLE_X86 { + HARDWARE_PTE_X86 Pte[PTRS_PER_PT_X86]; +} PAGE_TABLE_X86, *PPAGE_TABLE_X86; + +typedef struct _PAGE_DIRECTORY_X64 { + HARDWARE_PTE_X64 Pde[2048]; +} PAGE_DIRECTORY_X64, *PPAGE_DIRECTORY_X64; + +typedef struct _PAGE_DIRECTORY_TABLE_X64 { + HARDWARE_PTE_X64 Pde[4]; +} PAGE_DIRECTORY_TABLE_X64, *PPAGE_DIRECTORY_TABLE_X64; + +#endif /* ! defined I386MEM_H_INCLUDED */ _____
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h 2005-05-20 08:06:27 UTC (rev 15429) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/machxen.h 2005-05-20 10:33:27 UTC (rev 15430) @@ -21,9 +21,8 @@
#ifndef __I386_MACHXEN_H_ #define __I386_MACHXEN_H_
-#ifndef __MEMORY_H +#include "i386mem.h" #include "mm.h" -#endif
#include <rosxen.h> #include <xen.h> @@ -74,6 +73,7 @@ VOID XenMemInit(start_info_t *StartInfo); u32 XenMemVirtualToMachine(void *VirtualAddress); int XenMemGrantForeignAccess(domid_t DomId, void *VirtAddr, BOOL ReadOnly); +VOID XenMemInstallPageDir(PPAGE_DIRECTORY_X86 NewPageDir);
BOOL XenDiskReadLogicalSectors(ULONG DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); BOOL XenDiskGetPartitionEntry(ULONG DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); _____
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/mb.S --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/mb.S 2005-05-20 08:06:27 UTC (rev 15429) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/mb.S 2005-05-20 10:33:27 UTC (rev 15430) @@ -61,6 +61,7 @@
.endr
.bss + .align 4096 PageDirectoryStart: startup_pagedirectory: .fill 4096, 1, 0 _____
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenboot.c --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenboot.c 2005-05-20 08:06:27 UTC (rev 15429) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenboot.c 2005-05-20 10:33:27 UTC (rev 15430) @@ -22,17 +22,24 @@
#include "machine.h" #include "machxen.h"
+static ULONG STDCALL +XenBootAddrToPfn(ULONG_PTR Addr) +{ + return (ULONG) XenMemVirtualToMachine((void *) Addr) >> PAGE_SHIFT; +} + VOID XenBootReactOS(VOID) - { +{ BOOLEAN PaeModeEnabled; + ASMCODE PagedJump;
+ /* Clear screen and make sure all console output is written */ XenVideoClearScreen(0x07); + XenConsFlushWait();
/* Disable events */ -#ifdef TODO XenEvtchnDisableEvents(); -#endif
/* Re-initalize EFLAGS */ Ke386EraseFlags(); @@ -41,10 +48,14 @@ PaeModeEnabled = FALSE;
/* Initialize the page directory */ - i386BootSetupPageDirectory(PaeModeEnabled); + i386BootSetupPageDirectory(PaeModeEnabled, FALSE, XenBootAddrToPfn);
- /* Initialize Paging, Write-Protection and Load NTOSKRNL */ - i386BootSetupPae(PaeModeEnabled, 0x2badb002); - } + /* Switch to the new page directory */ + XenMemInstallPageDir((PPAGE_DIRECTORY_X86) &startup_pagedirectory);
+ /* Jump to Kernel */ + PagedJump = (ASMCODE)KernelEntryPoint; + PagedJump(0x2badb002, &LoaderBlock); +} + /* EOF */ _____
Modified: branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenmem.c --- branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenmem.c 2005-05-20 08:06:27 UTC (rev 15429) +++ branches/xen/reactos/boot/freeldr/freeldr/arch/i386/xenmem.c 2005-05-20 10:33:27 UTC (rev 15430) @@ -17,6 +17,8 @@
*/
#include "freeldr.h" +#include "i386boot.h" +#include "i386mem.h" #include "machxen.h"
#include <rosxen.h> @@ -27,53 +29,10 @@ #include <grant_table.h> #endif /* CONFIG_XEN_BLKDEV_GRANT */
-/* Page Directory Entry */ -typedef struct _PDE -{ - u32 Pde; -} PDE, *PPDE; - -/* Page Table Entry */ -typedef struct _PTE -{ - u32 Pte; -} PTE, *PPTE; - -#define PGDIR_SHIFT 22 -#define PTRS_PER_PD (PAGE_SIZE / sizeof(PDE)) -#define PTRS_PER_PT (PAGE_SIZE / sizeof(PTE)) - -/* Page Directory Index of a given virtual address */ -#define PD_IDX(Va) ((((ULONG_PTR) Va) >> PGDIR_SHIFT) & (PTRS_PER_PD - 1)) -/* Page Table Index of a give virtual address */ -#define PT_IDX(Va) ((((ULONG_PTR) Va) >> PAGE_SHIFT) & (PTRS_PER_PT - 1)) -/* Convert a Page Directory or Page Table entry to a (machine) address */ -#define PAGE_MASK (~(PAGE_SIZE-1)) - -/* The PA_* definitions below were copied from ntoskrnl/mm/i386/page.c, maybe - we need a public header for them?? */ -#define PA_BIT_PRESENT (0) -#define PA_BIT_READWRITE (1) -#define PA_BIT_USER (2) -#define PA_BIT_WT (3) -#define PA_BIT_CD (4) -#define PA_BIT_ACCESSED (5) -#define PA_BIT_DIRTY (6) -#define PA_BIT_GLOBAL (8) - -#define PA_PRESENT (1 << PA_BIT_PRESENT) -#define PA_READWRITE (1 << PA_BIT_READWRITE) -#define PA_USER (1 << PA_BIT_USER) -#define PA_DIRTY (1 << PA_BIT_DIRTY) -#define PA_WT (1 << PA_BIT_WT) -#define PA_CD (1 << PA_BIT_CD) -#define PA_ACCESSED (1 << PA_BIT_ACCESSED) -#define PA_GLOBAL (1 << PA_BIT_GLOBAL) - start_info_t *XenStartInfo; shared_info_t *XenSharedInfo;
-static PPDE XenPageDir; +static PPAGE_DIRECTORY_X86 XenPageDir;
#if 2 == XEN_VER #define XEN_MMU_UPDATE(req, count, success, domid) \ @@ -169,8 +128,8 @@ static char ErrMsg[] = "XenMemInit failed\n"; unsigned long StartPfn; /* (Virtual) page frame number of beginning of freeldr */ - PPDE PageDir; /* Virtual address of page directory */ - PPTE PageTableForPageDir; /* Virtual address of page table which + PPAGE_DIRECTORY_X86 PageDir; /* Virtual address of page directory */ + PPAGE_TABLE_X86 PageTableForPageDir; /* Virtual address of page table which contains entry for the page directory */ unsigned long PageDirMachineAddr; /* Machine address of page directory */ unsigned PageTablesRequired; /* Number of page tables we require */ @@ -180,16 +139,18 @@ unsigned long HighAddr; /* Virtual address after reloc to high memory */ unsigned long PageNumber; /* Index of current page */ - PPTE PageTable; /* Page table containing current page */ + PPAGE_TABLE_X86 PageTable; /* Page table containing current page */ + HARDWARE_PTE_X86 Pte; /* Page table entry */ #ifdef CONFIG_XEN_BLKDEV_GRANT gnttab_setup_table_t Setup; /* Grant table setup request */ unsigned long Frame; /* Grant table frame */ #endif /* CONFIG_XEN_BLKDEV_GRANT */
- PageDir = (PPDE) StartInfo->pt_base; - PageTableForPageDir = (PPTE)((char *) StartInfo->pt_base - + PAGE_SIZE * (PD_IDX(StartInfo->pt_base) + 1)); - PageDirMachineAddr = PageTableForPageDir[PT_IDX(StartInfo->pt_base)].Pte + PageDir = (PPAGE_DIRECTORY_X86) StartInfo->pt_base; + PageTableForPageDir = (PPAGE_TABLE_X86)((char *) StartInfo->pt_base + + PAGE_SIZE + * (PD_IDX(StartInfo->pt_base) + 1)); + PageDirMachineAddr = PageTableForPageDir->Pte[PT_IDX(StartInfo->pt_base)].Val & PAGE_MASK;
/* Determine pfn of first allocated memory */ @@ -197,20 +158,21 @@
/* First, lets connect all our page tables */ #ifdef CONFIG_XEN_BLKDEV_GRANT - PageTablesRequired = ROUND_UP(StartInfo->nr_pages + 2, PTRS_PER_PT) - / PTRS_PER_PT; + PageTablesRequired = ROUND_UP(StartInfo->nr_pages + 2, PTRS_PER_PT_X86) + / PTRS_PER_PT_X86; #else /* CONFIG_XEN_BLKDEV_GRANT */ - PageTablesRequired = ROUND_UP(StartInfo->nr_pages + 1, PTRS_PER_PT) - / PTRS_PER_PT; + PageTablesRequired = ROUND_UP(StartInfo->nr_pages + 1, PTRS_PER_PT_X86) + / PTRS_PER_PT_X86; #endif /* CONFIG_XEN_BLKDEV_GRANT */ for (PageTableNumber = 0; PageTableNumber < PageTablesRequired; PageTableNumber++) { MfnIndex = StartInfo->nr_pages - (StartPfn + PageTablesRequired) + PageTableNumber; - if (0 == PageDir[PageTableNumber].Pde) + if (0 == PageDir->Pde[PageTableNumber].Val) { - MmuReq.ptr = PageDirMachineAddr + PageTableNumber * sizeof(PTE); + MmuReq.ptr = PageDirMachineAddr + + PageTableNumber * sizeof(HARDWARE_PTE_X86); } else { @@ -218,14 +180,18 @@ * means that it's also mapped in the area following pt_base. We * don't want it there, so let's map another page at that pos. * This page table will be mapped near the top of memory later */ - PageTable = (PPTE)((char *) PageDir - + (PageTableNumber + 1) * PAGE_SIZE); - MmuReq.ptr = (PageDir[PD_IDX((unsigned long) PageTable)].Pde + PageTable = (PPAGE_TABLE_X86)((char *) PageDir + + (PageTableNumber + 1) * PAGE_SIZE); + MmuReq.ptr = (PageDir->Pde[PD_IDX(PageTable)].Val & PAGE_MASK) + - PT_IDX((unsigned long) PageTable) * sizeof(PTE); + PT_IDX(PageTable) * sizeof(HARDWARE_PTE_X86); } - MmuReq.val = (((u32*)StartInfo->mfn_list)[MfnIndex] << PAGE_SHIFT) - | (PA_PRESENT | PA_READWRITE | PA_USER); + Pte.Val = 0; + Pte.PageFrameNumber = ((u32*)StartInfo->mfn_list)[MfnIndex]; + Pte.Valid = 1; + Pte.Write = 1; + Pte.Owner = 1; + MmuReq.val = Pte.Val; if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF)) { HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg); @@ -235,24 +201,31 @@
/* Now, let's make the page directory visible near the top of mem */ HighAddr = (StartInfo->nr_pages - (PageTablesRequired + 1)) * PAGE_SIZE; - MmuReq.ptr = (PageDir[PD_IDX(HighAddr)].Pde & PAGE_MASK) - + PT_IDX(HighAddr) * sizeof(PTE); - MmuReq.val = PageDirMachineAddr - | (PA_PRESENT | PA_USER); + MmuReq.ptr = (PageDir->Pde[PD_IDX(HighAddr)].Val & PAGE_MASK) + + PT_IDX(HighAddr) * sizeof(HARDWARE_PTE_X86); + Pte.Val = 0; + Pte.PageFrameNumber = PageDirMachineAddr >> PFN_SHIFT; + Pte.Valid = 1; + Pte.Owner = 1; + MmuReq.val = Pte.Val; if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF)) { HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg); XenDie(); } - XenPageDir = (PPDE) HighAddr; + XenPageDir = (PPAGE_DIRECTORY_X86) HighAddr;
/* We don't need the page directory mapped at the low address (pt_base) * anymore, so we'll map another page there */ - MmuReq.ptr = (PageDir[PD_IDX((unsigned long) PageDir)].Pde & PAGE_MASK) - + PT_IDX((unsigned long) PageDir) * sizeof(PTE); + MmuReq.ptr = (PageDir->Pde[PD_IDX((unsigned long) PageDir)].Val & PAGE_MASK) + + PT_IDX((unsigned long) PageDir) * sizeof(HARDWARE_PTE_X86); MfnIndex = StartInfo->nr_pages - (StartPfn + PageTablesRequired + 1); - MmuReq.val = (((u32*)StartInfo->mfn_list)[MfnIndex] << PAGE_SHIFT) - | (PA_PRESENT | PA_READWRITE | PA_USER); + Pte.Val = 0; + Pte.PageFrameNumber = ((u32*)StartInfo->mfn_list)[MfnIndex]; + Pte.Valid = 1; + Pte.Write = 1; + Pte.Owner = 1; + MmuReq.val = Pte.Val; if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF)) { HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg); @@ -265,10 +238,13 @@ { HighAddr = (StartInfo->nr_pages - PageTablesRequired + PageTableNumber) * PAGE_SIZE; - MmuReq.ptr = (XenPageDir[PD_IDX(HighAddr)].Pde & PAGE_MASK) - + PT_IDX(HighAddr) * sizeof(PTE); - MmuReq.val = (XenPageDir[PageTableNumber].Pde & PAGE_MASK) - | (PA_PRESENT | PA_USER); + MmuReq.ptr = (XenPageDir->Pde[PD_IDX(HighAddr)].Val & PAGE_MASK) + + PT_IDX(HighAddr) * sizeof(HARDWARE_PTE_X86); + Pte.Val = 0; + Pte.PageFrameNumber = XenPageDir->Pde[PageTableNumber].Val >> PFN_SHIFT; + Pte.Valid = 1; + Pte.Owner = 1; + MmuReq.val = Pte.Val; if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF)) { HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg); @@ -281,9 +257,10 @@ PageNumber < StartInfo->nr_pages - (PageTablesRequired + 1); PageNumber++) { - PageTable = (PPTE)((char *) XenPageDir + - (PD_IDX(PageNumber * PAGE_SIZE) + 1) * PAGE_SIZE); - if (0 == PageTable[PT_IDX(PageNumber * PAGE_SIZE)].Pte) + PageTable = (PPAGE_TABLE_X86)((char *) XenPageDir + + (PD_IDX(PageNumber * PAGE_SIZE) + 1) + * PAGE_SIZE); + if (0 == PageTable->Pte[PT_IDX(PageNumber * PAGE_SIZE)].Val) { if (PageNumber < StartPfn) { @@ -293,11 +270,16 @@ { MfnIndex = PageNumber - StartPfn; } - MmuReq.ptr = (XenPageDir[PD_IDX(PageNumber * PAGE_SIZE)].Pde + MmuReq.ptr = (XenPageDir->Pde[PD_IDX(PageNumber * PAGE_SIZE)].Val & PAGE_MASK) - + PT_IDX(PageNumber * PAGE_SIZE) * sizeof(PTE); - MmuReq.val = (((u32 *) StartInfo->mfn_list)[MfnIndex] << PAGE_SHIFT) - | (PA_PRESENT | PA_READWRITE | PA_USER); + + PT_IDX(PageNumber * PAGE_SIZE) + * sizeof(HARDWARE_PTE_X86); + Pte.Val = 0; + Pte.PageFrameNumber = ((u32 *) StartInfo->mfn_list)[MfnIndex]; + Pte.Valid = 1; + Pte.Write = 1; + Pte.Owner = 1; + MmuReq.val = Pte.Val; if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF)) { HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg); @@ -313,11 +295,16 @@ /* We don't own the shared_info page, map it as an extra page just after * our "normal" memory */ XenSharedInfo = (shared_info_t *)(XenStartInfo->nr_pages * PAGE_SIZE); - MmuReq.ptr = (XenPageDir[PD_IDX(XenStartInfo->nr_pages * PAGE_SIZE)].Pde + MmuReq.ptr = (XenPageDir->Pde[PD_IDX(XenStartInfo->nr_pages * PAGE_SIZE)].Val & PAGE_MASK) - + PT_IDX(XenStartInfo->nr_pages * PAGE_SIZE) * sizeof(PTE); - MmuReq.val = XenStartInfo->shared_info - | (PA_PRESENT | PA_READWRITE | PA_USER); + + PT_IDX(XenStartInfo->nr_pages * PAGE_SIZE) + * sizeof(HARDWARE_PTE_X86); + Pte.Val = 0; + Pte.PageFrameNumber = XenStartInfo->shared_info >> PFN_SHIFT; + Pte.Valid = 1; + Pte.Write = 1; + Pte.Owner = 1; + MmuReq.val = Pte.Val; if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF)) { HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg); @@ -339,11 +326,15 @@ } XenMemBlkdevGrantShared = (grant_entry_t *)((XenStartInfo->nr_pages + 1) * PAGE_SIZE); - MmuReq.ptr = (XenPageDir[PD_IDX(XenMemBlkdevGrantShared)].Pde + MmuReq.ptr = (XenPageDir->Pde[PD_IDX(XenMemBlkdevGrantShared)].Val & PAGE_MASK) - + PT_IDX(XenMemBlkdevGrantShared) * sizeof(PTE); - MmuReq.val = (Frame << PAGE_SHIFT) - | (PA_PRESENT | PA_READWRITE | PA_USER); + + PT_IDX(XenMemBlkdevGrantShared) * sizeof(HARDWARE_PTE_X86); + Pte.Val = 0; + Pte.PageFrameNumber = Frame; + Pte.Valid = 1; + Pte.Write = 1; + Pte.Owner = 1; + MmuReq.val = Pte.Val; if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF)) { HYPERVISOR_console_io(CONSOLEIO_write, sizeof(ErrMsg), ErrMsg); @@ -355,14 +346,32 @@ u32 XenMemVirtualToMachine(void *VirtualAddress) { - PPTE PageTable; + PPAGE_TABLE_X86 PageTable;
- PageTable = (PPTE)((char *) XenPageDir + - (PD_IDX((ULONG_PTR) VirtualAddress) + 1) * PAGE_SIZE); - return PageTable[PT_IDX((ULONG_PTR) VirtualAddress)].Pte - & PAGE_MASK; + PageTable = (PPAGE_TABLE_X86)((char *) XenPageDir + + (PD_IDX((ULONG_PTR) VirtualAddress) + 1) + * PAGE_SIZE); + return PageTable->Pte[PT_IDX(VirtualAddress)].Val & PAGE_MASK; }
+static void * +XenMemMachineToVirtual(ULONG Mfn) +{ + PPAGE_TABLE_X86 PageTable; + ULONG Index; + + PageTable = (PPAGE_TABLE_X86)(XenPageDir + 1); + Index = 0; + while (TRUE) + { + if ((PageTable->Pte[Index].PageFrameNumber) == Mfn) + { + return (void *)(Index * PAGE_SIZE); + } + Index++; + } +} + #ifdef CONFIG_XEN_BLKDEV_GRANT int XenMemGrantForeignAccess(domid_t DomId, void *VirtualAddress, BOOL ReadOnly) @@ -370,7 +379,7 @@ int Ref = 0; /* We only do 1 page at the moment */
XenMemBlkdevGrantShared[Ref].frame = (XenMemVirtualToMachine(VirtualAddress) - >> PAGE_SHIFT); + >> PFN_SHIFT); XenMemBlkdevGrantShared[Ref].domid = DomId; wmb(); XenMemBlkdevGrantShared[Ref].flags = GTF_permit_access @@ -380,4 +389,111 @@ } #endif /* CONFIG_XEN_BLKDEV_GRANT */
+static VOID +XenMemSetNewPageReadonly(PPAGE_DIRECTORY_X86 NewPageDir, ULONG Mfn) +{ + PPAGE_TABLE_X86 PageTable; + unsigned PdIndex; + unsigned PtIndex; + + for (PdIndex = 0; PdIndex < PTRS_PER_PD_X86; PdIndex++) + { + if (NewPageDir->Pde[PdIndex].Valid) + { + PageTable = (PPAGE_TABLE_X86) + XenMemMachineToVirtual(NewPageDir->Pde[PdIndex].PageFrameNumber); + for (PtIndex = 0; PtIndex < PTRS_PER_PT_X86; PtIndex++) + { + if (PageTable->Pte[PtIndex].PageFrameNumber == Mfn) + { + PageTable->Pte[PtIndex].Write = 0; + } + } + } + } +} + +static VOID +XenMemSetOldPageReadonly(ULONG Mfn) +{ + PPAGE_TABLE_X86 PageTable; + ULONG Index; + mmu_update_t MmuReq; + ULONG_PTR Address; + HARDWARE_PTE_X86 Pte; + + PageTable = (PPAGE_TABLE_X86)(XenPageDir + 1); + Index = 0; + while (TRUE) + { + if ((PageTable->Pte[Index].PageFrameNumber) == Mfn) + { + Address = Index * PAGE_SIZE; + MmuReq.ptr = (XenPageDir->Pde[PD_IDX(Address)].Val & PAGE_MASK) + + PT_IDX(Address) * sizeof(HARDWARE_PTE_X86); + Pte.Val = PageTable->Pte[Index].Val; + Pte.Write = 0; + MmuReq.val = Pte.Val; + if (0 != XEN_MMU_UPDATE(&MmuReq, 1, NULL, DOMID_SELF)) + { + printf("Failed to map new page dir/table read-only\n"); + XenDie(); + } + return; + } + Index++; + } +} + +VOID +XenMemInstallPageDir(PPAGE_DIRECTORY_X86 NewPageDir) +{ + struct mmuext_op MmuExtReq; + ULONG NewPageDirMfn; + ULONG PageIndex; + + NewPageDirMfn = PaToPfn(XenMemVirtualToMachine((void *) NewPageDir)); + + for (PageIndex = PTRS_PER_PD_X86; 0 < PageIndex; PageIndex--) + { + if (NewPageDir->Pde[PageIndex - 1].PageFrameNumber == NewPageDirMfn) + { + /* A machine page cannot be a page directory and a page table at + the same time. We're trying to map the page dir as page table here, + undo the mapping and deal with it later. */ + NewPageDir->Pde[PageIndex - 1].Val = 0; + } + } + + XenMemSetNewPageReadonly(NewPageDir, NewPageDirMfn); + for (PageIndex = PTRS_PER_PD_X86; 0 < PageIndex; PageIndex--) + { + if (NewPageDir->Pde[PageIndex - 1].Valid) + { + XenMemSetNewPageReadonly(NewPageDir, + NewPageDir->Pde[PageIndex - 1].Val + >> PFN_SHIFT); + } + } + + XenMemSetOldPageReadonly(NewPageDirMfn); + for (PageIndex = PTRS_PER_PD_X86; 0 < PageIndex; PageIndex--) + { + if (NewPageDir->Pde[PageIndex - 1].Valid) + { + XenMemSetOldPageReadonly(NewPageDir->Pde[PageIndex - 1].Val + >> PFN_SHIFT); + } + } + + /* Set the PDBR */ + MmuExtReq.cmd = MMUEXT_NEW_BASEPTR; + MmuExtReq.mfn = NewPageDirMfn; + if (0 != HYPERVISOR_mmuext_op(&MmuExtReq, 1, NULL, DOMID_SELF)) + { + printf("Failed to set new page dir\n"); + XenDie(); + } +} + /* EOF */