started in on a bunch of memory management code

This commit is contained in:
Eric J. Bowersox 2013-04-14 03:38:48 -06:00
parent 3609cb2627
commit 54529bc017
23 changed files with 1741 additions and 41 deletions

View File

@ -0,0 +1,19 @@
import "comrogue/objectbase.idl";
/*-------------------
* IMalloc interface
*-------------------
*/
[object, uuid(00000002-0000-0000-C000-000000000046)]
interface IMalloc : IUnknown
{
[unique] typedef IMalloc *PMALLOC;
PVOID Alloc([in] SIZE_T cb);
PVOID Realloc([in] PVOID pv, [in] SIZE_T cb);
void Free([in] PVOID pv);
SIZE_T GetSize([in] PVOID pv);
INT32 DidAlloc([in] PVOID pv);
void HeapMinimize(void);
}

View File

@ -49,6 +49,9 @@ interface ICOMROGUETypes
typedef INT32 INT_PTR;
typedef UINT32 UINT_PTR;
typedef UINT_PTR SIZE_T;
typedef INT_PTR SSIZE_T;
/* Base pointer type definitions */
typedef INT16 *PINT16;
typedef UINT16 *PUINT16;

View File

@ -45,6 +45,19 @@ interface IUnknown
UINT32 Release();
}
/*-------------------------
* IClassFactory interface
*-------------------------
*/
[object, uuid(00000001-0000-0000-C000-000000000046), pointer_default(unique)]
interface IClassFactory : IUnknown
{
[unique] typedef IClassFactory *PCLASSFACTORY;
HRESULT CreateInstance([in, unique] IUnknown *punkOuter, [in] REFIID riid, [out, iid_is(riid)] PPVOID ppvObject);
HRESULT LockServer([in] BOOL fLock);
}
/*----------------------------
* IServiceProvider interface
*----------------------------

View File

@ -0,0 +1,61 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#ifndef __MEMMGR_H_INCLUDED
#define __MEMMGR_H_INCLUDED
#ifdef __COMROGUE_INTERNALS__
#ifndef __ASM__
#include <comrogue/types.h>
#include <comrogue/compiler_macros.h>
#include <comrogue/internals/mmu.h>
#include <comrogue/internals/startup.h>
CDECL_BEGIN
/* Page mapping functions */
extern PHYSADDR MmGetPhysAddr(PTTB pTTB, KERNADDR vma);
extern HRESULT MmDemapPages(PTTB pTTB, KERNADDR vmaBase, UINT32 cpg);
extern HRESULT MmMapPages(PTTB pTTB, PHYSADDR paBase, KERNADDR vmaBase, UINT32 cpg, UINT32 uiTableFlags,
UINT32 uiPageFlags);
/* Initialization functions only */
extern void _MmInit(PSTARTUP_INFO pstartup);
CDECL_END
#endif /* __ASM__ */
#endif /* __COMROGUE_INTERNALS__ */
#endif /* __MEMMGR_H_INCLUDED */

View File

@ -43,6 +43,7 @@
#define SYS_PAGE_SIZE 4096 /* standard page size for normal page */
#define SYS_PAGE_BITS 12 /* log2(SYS_PAGE_SIZE), number of bits in a page address */
#define SYS_TTB0_SIZE 8192 /* TTB0 must be located on this boundary and is this size */
#define SYS_TTB0_ENTRIES 2048 /* SYS_TTB0_SIZE/4, number of entries in TTB0 */
#define SYS_TTB1_SIZE 16384 /* TTB1 must be located on this boundary and is this size */
#define SYS_TTB1_ENTRIES 4096 /* SYS_TTB1_SIZE/4, number of entries in TTB1 */
#define SYS_TTB_BITS 12 /* log2(SYS_TTB1_SIZE/4), number of bits in a TTB address */
@ -124,6 +125,16 @@
#define PGQUERY_SM 0x00000002 /* small page (4K) */
#define PGQUERY_SM_XN 0x00000003 /* small page with Execute-Never set */
/* Combinations of flags we use regularly. */
#define TTBFLAGS_LIB_CODE TTBPGTBL_ALWAYS
#define PGTBLFLAGS_LIB_CODE (PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP10)
#define TTBFLAGS_KERNEL_CODE TTBPGTBL_ALWAYS
#define PGTBLFLAGS_KERNEL_CODE (PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01)
#define TTBFLAGS_KERNEL_DATA TTBPGTBL_ALWAYS
#define PGTBLFLAGS_KERNEL_DATA (PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01)
#define TTBFLAGS_MMIO TTBPGTBL_ALWAYS
#define PGTBLFLAGS_MMIO (PGTBLSM_ALWAYS | PGTBLSM_AP01)
#ifndef __ASM__
/*-------------------------------------------------------
@ -224,16 +235,21 @@ typedef struct tagPAGETAB {
/* internal structure of a MPDB entry */
typedef struct tagMPDB1 {
PHYSADDR paPTE; /* PA of page table entry for the page */
unsigned next : 20; /* index of "next" entry in list */
unsigned tag : 12; /* page tag */
} MPDB1;
/* The MPDB entry itself. */
typedef union tagMPDB {
UINT32 raw; /* raw data */
UINT64 raw; /* raw data */
MPDB1 d; /* structured data */
} MPDB, *PMPDB;
/* Page index macros */
#define mmPA2PageIndex(pa) ((pa) >> SYS_PAGE_BITS)
#define mmPageIndex2PA(ndx) ((ndx) << SYS_PAGE_BITS)
#endif /* __ASM__ */
#endif /* __COMROGUE_INTERNALS__ */

View File

@ -1,3 +1,34 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#ifndef __OBJECT_DEFINITION_MACROS_H_INCLUDED
#define __OBJECT_DEFINITION_MACROS_H_INCLUDED
@ -28,7 +59,7 @@
#else
#define DEFINE_UUID_TYPE(typ, name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C extern const typ GUIDATTR name
EXTERN_C extern const typ name
#endif /* INITGUID */
@ -61,11 +92,11 @@
#define INHERIT_METHODS(sym) sym
#define BEGIN_INTERFACE(typ) \
struct typ ## VTable; \
typedef interface tagIf ## typ { const struct typ ## VTable *pVTable; } typ; \
struct typ ## VTable {
#define BEGIN_INTERFACE_(typ, parent) \
struct typ ## VTable {
#define END_INTERFACE(typ) }; \
typedef interface typ { const struct typ ## VTable *pVTable; } typ;
#define BEGIN_INTERFACE_(typ, parent) BEGIN_INTERFACE(typ)
#define END_INTERFACE(typ) };
#else

View File

@ -0,0 +1,56 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#ifndef __OBJHELP_H_INCLUDED
#define __OBJHELP_H_INCLUDED
#ifndef __ASM__
#include <comrogue/compiler_macros.h>
#include <comrogue/objectbase.h>
#include <comrogue/allocator.h>
CDECL_BEGIN
/* QueryInterface helpers */
extern HRESULT ObjHlpStandardQueryInterface_IMalloc(IUnknown *pThis, REFIID riid, PPVOID ppvObject);
/* AddRef/Release helpers */
extern UINT32 ObjHlpStaticAddRefRelease(IUnknown *pThis);
/* Other helpers */
extern void ObjHlpDoNothingReturnVoid(IUnknown *pThis);
CDECL_END
#endif /* __ASM__ */
#endif /* __OBJHELP_H_INCLUDED */

View File

@ -58,6 +58,7 @@
#define FACILITY_ITF 4
#define FACILITY_COMROGUE 7
#define FACILITY_STRFORMAT 0x333
#define FACILITY_MEMMGR 0x601
#ifndef __ASM__
@ -79,19 +80,27 @@
#endif /* __ASM__ */
#define S_OK SCODE_CAST(0x00000000) /* OK return */
#define S_FALSE SCODE_CAST(0x00000001) /* "False" return */
/* Basic success codes */
#define S_OK SCODE_CAST(0x00000000) /* OK return */
#define S_FALSE SCODE_CAST(0x00000001) /* "False" return */
#define E_NOTIMPL SCODE_CAST(0x80000001) /* not implemented */
#define E_OUTOFMEMORY SCODE_CAST(0x80000002) /* out of memory */
#define E_INVALIDARG SCODE_CAST(0x80000003) /* invalid argument */
#define E_NOINTERFACE SCODE_CAST(0x80000004) /* no such interface */
#define E_POINTER SCODE_CAST(0x80000005) /* invalid pointer */
#define E_HANDLE SCODE_CAST(0x80000006) /* invalid handle */
#define E_ABORT SCODE_CAST(0x80000007) /* aborted operation */
#define E_FAIL SCODE_CAST(0x80000008) /* unspecified failure */
#define E_ACCESSDENIED SCODE_CAST(0x80000009) /* access denied */
#define E_PENDING SCODE_CAST(0x8000000A) /* data not yet available */
#define E_UNEXPECTED SCODE_CAST(0x8000FFFF) /* unexpected error */
/* Basic error codes */
#define E_NOTIMPL SCODE_CAST(0x80000001) /* not implemented */
#define E_OUTOFMEMORY SCODE_CAST(0x80000002) /* out of memory */
#define E_INVALIDARG SCODE_CAST(0x80000003) /* invalid argument */
#define E_NOINTERFACE SCODE_CAST(0x80000004) /* no such interface */
#define E_POINTER SCODE_CAST(0x80000005) /* invalid pointer */
#define E_HANDLE SCODE_CAST(0x80000006) /* invalid handle */
#define E_ABORT SCODE_CAST(0x80000007) /* aborted operation */
#define E_FAIL SCODE_CAST(0x80000008) /* unspecified failure */
#define E_ACCESSDENIED SCODE_CAST(0x80000009) /* access denied */
#define E_PENDING SCODE_CAST(0x8000000A) /* data not yet available */
#define E_UNEXPECTED SCODE_CAST(0x8000FFFF) /* unexpected error */
/* Memory manager error codes */
#define MEMMGR_E_NOPGTBL SCODE_CAST(0x86010001) /* no page tables available */
#define MEMMGR_E_BADTTBFLG SCODE_CAST(0x86010002) /* bad TTB flags encountered */
#define MEMMGR_E_COLLIDED SCODE_CAST(0x86010003) /* memory mapping collided */
#define MEMMGR_E_ENDTTB SCODE_CAST(0x86010004) /* tried to "walk off" end of TTB */
#endif /* __SCODE_H_INCLUDED */

51
include/comrogue/stdobj.h Normal file
View File

@ -0,0 +1,51 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#ifndef __STDOBJ_H_INCLUDED
#define __STDOBJ_H_INCLUDED
#ifndef __ASM__
#include <comrogue/compiler_macros.h>
#include <comrogue/object_types.h>
CDECL_BEGIN
extern BOOL IsEqualGUID(REFGUID guid1, REFGUID guid2);
CDECL_END
#define IsEqualIID(iid1, iid2) IsEqualGUID(iid1, iid2)
#define IsEqualCLSID(clsid1, clsid2) IsEqualGUID(clsid1, clsid2)
#endif /* __ASM__ */
#endif /* __STDOBJ_H_INCLUDED */

View File

@ -48,7 +48,9 @@ typedef HRESULT (*PFNFORMAT8)(PPVOID, PCCHAR, UINT32);
CDECL_BEGIN
extern PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, INT32 nBytes);
extern PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, SSIZE_T cb);
extern INT32 StrCompareMem(PCVOID pMem1, PCVOID pMem2, SSIZE_T cb);
extern PVOID StrSetMem(PVOID pMem, INT32 ch, SSIZE_T cb);
extern BOOL StrIsDigit8(CHAR ch);
extern INT32 StrLength8(PCSTR psz);

View File

@ -48,9 +48,9 @@ AFLAGS = -mcpu=arm1176jzf-s -mfloat-abi=hard
ASM_CPP_FLAGS = $(INCLUDES) $(DEFS) -D__ASM__
PRESTART_OBJS = prestart.o early_trace.o collect_startup.o early_mm.o
LIB_OBJS = divide.o qdivrem.o intlib.o str.o strcopymem.o
RES_OBJS = lowlevel.o trace.o
INIT_OBJS = start.o kistart.o
LIB_OBJS = divide.o qdivrem.o intlib.o objhelp.o str.o strcopymem.o strcomparemem.o strsetmem.o lib_guids.o
RES_OBJS = lowlevel.o trace.o memmgr.o vmmap.o pagealloc.o
INIT_OBJS = start.o kistart.o init_heap.o
all: kernel.img

View File

@ -99,7 +99,7 @@ SEG_INIT_CODE static UINT32 make_section_flags(UINT32 uiTableFlags, UINT32 uiPag
* The number of pages that were actually mapped by this function call, or -1 if there was an error in the mapping.
*
* Side effects:
* May modify the ndxTTB'th entry in the TTB, if it was not previously allocated. May modify the current page
* May modify the TTB entry we point to, if it was not previously allocated. May modify the current page
* table that the TTB entry points to, where applicable. If we need to allocate a new page table, may modify the
* global variables g_cpgForPageTables, g_ctblFreeonLastPage, and g_ptblNext.
*/
@ -334,7 +334,7 @@ SEG_INIT_CODE PHYSADDR EMmInit(PSTARTUP_INFO pstartup)
/* Allocate space for the Master Page Database but do not initialize it. */
pstartup->paMPDB = paTTB + SYS_TTB1_SIZE;
cbMPDB = pstartup->cpgSystemTotal << 2;
cbMPDB = pstartup->cpgSystemTotal << 3; /* 8 bytes per entry */
pstartup->cpgMPDB = cbMPDB >> SYS_PAGE_BITS;
if (cbMPDB & (SYS_PAGE_SIZE - 1))
{
@ -349,34 +349,32 @@ SEG_INIT_CODE PHYSADDR EMmInit(PSTARTUP_INFO pstartup)
/* Map the "prestart" area (everything below load address, plus prestart code & data) as identity. */
VERIFY(map_pages(0, 0, (INT32)(&cpgPrestartTotal), TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_AP01));
/* Map the IO area as identity. */
VERIFY(map_pages(PHYSADDR_IO_BASE, PHYSADDR_IO_BASE, PAGE_COUNT_IO, TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_AP01));
VERIFY(map_pages(PHYSADDR_IO_BASE, PHYSADDR_IO_BASE, PAGE_COUNT_IO, TTBFLAGS_MMIO, PGTBLFLAGS_MMIO));
/* Map the library area. */
VERIFY(map_pages((PHYSADDR)(&paLibraryCode), (KERNADDR)(&vmaLibraryCode), (INT32)(&cpgLibraryCode),
TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP10));
TTBFLAGS_LIB_CODE, PGTBLFLAGS_LIB_CODE));
/* Map the kernel code area. */
VERIFY(map_pages((PHYSADDR)(&paKernelCode), (KERNADDR)(&vmaKernelCode), (INT32)(&cpgKernelCode),
TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
TTBFLAGS_KERNEL_CODE, PGTBLFLAGS_KERNEL_CODE));
/* Map the kernel data/BSS area. */
VERIFY(map_pages((PHYSADDR)(&paKernelData), (KERNADDR)(&vmaKernelData),
(INT32)(&cpgKernelData) + (INT32)(&cpgKernelBss),
TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
(INT32)(&cpgKernelData) + (INT32)(&cpgKernelBss), TTBFLAGS_KERNEL_DATA, PGTBLFLAGS_KERNEL_DATA));
/* Map the kernel init code area. */
VERIFY(map_pages((PHYSADDR)(&paInitCode), (KERNADDR)(&vmaInitCode), (INT32)(&cpgInitCode),
TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
TTBFLAGS_KERNEL_CODE, PGTBLFLAGS_KERNEL_CODE));
/* Map the kernel init data/BSS area. */
VERIFY(map_pages((PHYSADDR)(&paInitData), (KERNADDR)(&vmaInitData),
(INT32)(&cpgInitData) + (INT32)(&cpgInitBss),
TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
(INT32)(&cpgInitData) + (INT32)(&cpgInitBss), TTBFLAGS_KERNEL_DATA, PGTBLFLAGS_KERNEL_DATA));
/* Map the TTB itself. */
pstartup->kaTTB = (KERNADDR)(&vmaFirstFree);
VERIFY(map_pages(paTTB, pstartup->kaTTB, SYS_TTB1_SIZE / SYS_PAGE_SIZE,
TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
VERIFY(map_pages(paTTB, pstartup->kaTTB, SYS_TTB1_SIZE / SYS_PAGE_SIZE, TTBFLAGS_KERNEL_DATA,
PGTBLFLAGS_KERNEL_DATA));
/* Map the Master Page Database. */
pstartup->kaMPDB = pstartup->kaTTB + SYS_TTB1_SIZE;
VERIFY(map_pages(pstartup->paMPDB, pstartup->kaTTB + SYS_TTB1_SIZE, pstartup->cpgMPDB,
TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
VERIFY(map_pages(pstartup->paMPDB, pstartup->kaTTB + SYS_TTB1_SIZE, pstartup->cpgMPDB, TTBFLAGS_KERNEL_DATA,
PGTBLFLAGS_KERNEL_DATA));
/* Map the IO area into high memory as well. */
VERIFY(map_pages(PHYSADDR_IO_BASE, VMADDR_IO_BASE, PAGE_COUNT_IO, TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_AP01));
VERIFY(map_pages(PHYSADDR_IO_BASE, VMADDR_IO_BASE, PAGE_COUNT_IO, TTBFLAGS_MMIO, PGTBLFLAGS_MMIO));
#if 0
/* Dump the TTB and page tables to trace output. */

308
kernel/init_heap.c Normal file
View File

@ -0,0 +1,308 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#include <comrogue/types.h>
#include <comrogue/str.h>
#include <comrogue/allocator.h>
#include <comrogue/objhelp.h>
#include <comrogue/internals/seg.h>
#include "sizes.h"
/*-------------------------------------------------------------------------------------------------------------
* Initial heap implementation. Since this will only be used by initializer code and freed with the rest
* of the initializer code and data, it doesn't need to be very efficient. The implementation is adapted from
* the original K&R storage allocator, with modifications to implement the full IMalloc interface.
*-------------------------------------------------------------------------------------------------------------
*/
extern PCHAR g_pInitHeapBlock; /* pointer to heap init block defined in assembly code */
typedef union tagBLOCK
{
struct
{
union tagBLOCK *pNextFree; /* pointer to next free block */
SIZE_T cblk; /* size of this free block (in blocks) */
} data;
INT64 x; /* to force alignment */
} BLOCK, *PBLOCK;
typedef struct tagINITHEAP
{
IMalloc hdr; /* object header must be first */
BLOCK blkBase; /* base "zero" block */
PBLOCK pblkLastAlloc; /* last allocated block */
} INITHEAP, *PINITHEAP;
/*
* Allocates a block of memory.
*
* Parameters:
* - pThis = Base interface pointer.
* - cb = Size of the memory block to be allocated, in bytes.
*
* Returns:
* A pointer to the allocated block of memory, or NULL if memory could not be allocated.
*/
SEG_INIT_CODE static PVOID init_heap_Alloc(IMalloc *pThis, SIZE_T cb)
{
PINITHEAP pih = (PINITHEAP)pThis;
register PBLOCK p, q;
register SIZE_T nBlocks = 1 + (cb + sizeof(BLOCK) - 1) / sizeof(BLOCK);
q = pih->pblkLastAlloc;
for (p = q->data.pNextFree; ; q = p, p = p->data.pNextFree)
{
if (p->data.cblk >= nBlocks)
{
if (p->data.cblk == nBlocks)
q->data.pNextFree = p->data.pNextFree;
else
{
p->data.cblk -= nBlocks;
p += p->data.cblk;
p->data.cblk = nBlocks;
}
pih->pblkLastAlloc = q;
return (PVOID)(p + 1);
}
if (p == pih->pblkLastAlloc)
break;
}
return NULL;
}
/*
* Determines whether this allocator was used to allocate a block of memory.
*
* Parameters:
* - pThis = Base interface pointer.
* - pv = Pointer to the memory block to test. If this parameter is NULL, -1 is returned.
*
* Returns:
* - 1 = If the memory block was allocated by this allocator.
* - 0 = If the memory block was not allocated by this allocator.
* - -1 = If this method cannot determine whether the allocator allocated the memory block.
*/
SEG_INIT_CODE static INT32 init_heap_DidAlloc(IMalloc *pThis, PVOID pv)
{
register PCHAR p = (PCHAR)pv;
if (!pv)
return -1; /* not our business */
return ((p >= g_pInitHeapBlock) && (p < g_pInitHeapBlock + SIZE_INIT_HEAP)) ? 1 : 0;
}
/*
* Frees a previously allocated block of memory.
*
* Parameters:
* - pThis = Base interface pointer.
* - pv = Pointer to the memory block to be freed. If this parameter is NULL, this method has no effect.
*
* Returns:
* Nothing.
*
* Side effects:
* After this call, the memory pointed to by pv is invalid and should not be used.
*/
SEG_INIT_CODE static void init_heap_Free(IMalloc *pThis, PVOID pv)
{
PINITHEAP pih = (PINITHEAP)pThis;
register PBLOCK p, q;
if (init_heap_DidAlloc(pThis, pv) != 1)
return; /* not our business */
p = ((PBLOCK)pv) - 1;
for (q = pih->pblkLastAlloc; !((p > q) && (p < q->data.pNextFree)); q = q->data.pNextFree)
if ((q >= q->data.pNextFree) && ((p > q) || (p < q->data.pNextFree)))
break; /* at one end or another */
if (p + p->data.cblk == q->data.pNextFree)
{
/* coalesce block with next (free) block */
p->data.cblk += q->data.pNextFree->data.cblk;
p->data.pNextFree = q->data.pNextFree->data.pNextFree;
}
else
p->data.pNextFree = q->data.pNextFree; /* chain to next free block */
if (q + q->data.cblk == p)
{
/* coalesce free block with previous (free) block */
q->data.cblk += p->data.cblk;
q->data.pNextFree = p->data.pNextFree;
}
else
q->data.pNextFree = p; /* chain to previous free block */
pih->pblkLastAlloc = q;
}
/*
* Changes the size of a previously allocated block.
*
* Parameters:
* - pThis = Base interface pointer.
* - pv = Pointer to the block of memory to be reallocated. If this parameter is NULL, a block of memory
* of size cb is allocated and returned.
* - cb = The new size of the memory block to be reallocated, in bytes. If this parameter is 0 and pv is
* not NULL, the block of memory pointed to by pv is freed and NULL is returned.
*
* Returns:
* If pv is not NULL and cb is 0, NULL is always returned. Otherwise, NULL is returned if the block of memory
* could not be reallocated, or the pointer to the reallocated block of memory is returned.
*/
SEG_INIT_CODE static PVOID init_heap_Realloc(IMalloc *pThis, PVOID pv, SIZE_T cb)
{
PINITHEAP pih = (PINITHEAP)pThis;
SIZE_T nBlocksNew, nBlocksExtra;
PVOID pNew;
register PBLOCK p, pNext, q, qp;
/* Handle degenerate cases */
if (!pv)
return init_heap_Alloc(pThis, cb);
if (cb == 0)
{
init_heap_Free(pThis, pv);
return NULL;
}
if (init_heap_DidAlloc(pThis, pv) != 1)
return NULL; /* not our business */
p = ((PBLOCK)pv) - 1;
nBlocksNew = 1 + (cb + sizeof(BLOCK) - 1) / sizeof(BLOCK);
if (nBlocksNew == p->data.cblk)
return pv; /* nothing to do! */
if (nBlocksNew < p->data.cblk)
{ /* shrinking block - chop block in middle and free the upper end */
pNext = p + nBlocksNew;
pNext->data.cblk = p->data.cblk - nBlocksNew;
p->data.cblk = nBlocksNew;
init_heap_Free(pThis, (PVOID)(pNext + 1));
return pv;
}
/* see if next block is free so we can expand in place */
nBlocksExtra = nBlocksNew - p->data.cblk;
pNext = p + p->data.cblk;
qp = pih->pblkLastAlloc;
for (q = qp->data.pNextFree; ; qp = q, q = q->data.pNextFree)
{
if (q == pNext)
{
if (q->data.cblk < nBlocksExtra)
break; /* cannot get enough blocks by combining next free block */
qp->data.pNextFree = q->data.pNextFree; /* remove block from free list */
if (q->data.cblk == nBlocksExtra)
{ /* take it all */
pih->pblkLastAlloc = qp->data.pNextFree;
}
else
{ /* chop in two, add first block to existing, free second block */
pNext += nBlocksExtra;
pNext->data.cblk = q->data.cblk - nBlocksExtra;
init_heap_Free(pThis, (PVOID)(pNext + 1));
}
p->data.cblk = nBlocksNew;
return pv;
}
if (q == pih->pblkLastAlloc)
break; /* not found */
}
/* last ditch effort: allocate new block and copy old contents in */
pNew = init_heap_Alloc(pThis, cb);
if (!pNew)
return NULL; /* cannot reallocate */
StrCopyMem(pv, pNew, (p->data.cblk - 1) * sizeof(BLOCK));
init_heap_Free(pThis, pv);
return pNew;
}
/*
* Returns the size of a previously-allocated block of memory.
*
* Parameters:
* - pThis = Base interface pointer.
* - pv = Pointer to the block of memory.
*
* Returns:
* The size of the allocated block of memory in bytes, which may be greater than the size requested when
* it was allocated.
*/
SEG_INIT_CODE static SIZE_T init_heap_GetSize(IMalloc *pThis, PVOID pv)
{
register PBLOCK p;
if (init_heap_DidAlloc(pThis, pv) != 1)
return (SIZE_T)(-1); /* not our business */
p = ((PBLOCK)pv) - 1;
return (p->data.cblk - 1) * sizeof(BLOCK);
}
static const SEG_INIT_RODATA struct IMallocVTable vtblInitHeap =
{
.QueryInterface = ObjHlpStandardQueryInterface_IMalloc,
.AddRef = ObjHlpStaticAddRefRelease,
.Release = ObjHlpStaticAddRefRelease,
.Alloc = init_heap_Alloc,
.Realloc = init_heap_Realloc,
.Free = init_heap_Free,
.GetSize = init_heap_GetSize,
.DidAlloc = init_heap_DidAlloc,
.HeapMinimize = (void (*)(IMalloc *))ObjHlpDoNothingReturnVoid
};
/*
* Returns a reference to the initial heap.
*
* Parameters:
* None.
*
* Returns:
* A reference to the initial heap, in the form of a pointer to its IMalloc interface.
*/
SEG_INIT_CODE IMalloc *_MmGetInitHeap(void)
{
static SEG_INIT_DATA INITHEAP initheap = { .pblkLastAlloc = NULL };
register PBLOCK p;
if (!(initheap.pblkLastAlloc))
{ /* initialize fields of initheap */
initheap.hdr.pVTable = &vtblInitHeap;
initheap.pblkLastAlloc = initheap.blkBase.data.pNextFree = &(initheap.blkBase);
initheap.blkBase.data.cblk = 0;
/* add g_pInitHeapBlock as the free block in the heap */
p = (PBLOCK)g_pInitHeapBlock;
p->data.cblk = SIZE_INIT_HEAP / sizeof(BLOCK);
init_heap_Free((IMalloc *)(&initheap), (PVOID)(p + 1));
}
return (IMalloc *)(&initheap);
}

50
kernel/lib_guids.c Normal file
View File

@ -0,0 +1,50 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
/*------------------------------------------------------------------------------------------------------
* This module defines all the GUIDs as static data that goes into the library segment (i.e. accessible
* from both supervisor and user modes). The following definitions MUST be first in this source file,
* AND in this order.
*------------------------------------------------------------------------------------------------------
*/
#include <comrogue/internals/seg.h>
#define GUIDATTR SEG_LIB_RODATA
#define INITGUID
#include <comrogue/object_definition_macros.h>
/*-------------------------------------------------------------------------------------------------
* Now include all the header files generated from IDL. Try to include them in the order in which
* interfaces are defined.
*-------------------------------------------------------------------------------------------------
*/
#include <comrogue/object_types.h>
#include <comrogue/objectbase.h>
#include <comrogue/allocator.h>

49
kernel/memmgr.c Normal file
View File

@ -0,0 +1,49 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#include <comrogue/types.h>
#include <comrogue/internals/seg.h>
#include <comrogue/internals/memmgr.h>
#include <comrogue/internals/startup.h>
/*---------------------
* Initialization code
*---------------------
*/
extern void _MmInitVMMap(PSTARTUP_INFO pstartup);
extern void _MmInitPageAlloc(PSTARTUP_INFO pstartup);
SEG_INIT_CODE void _MmInit(PSTARTUP_INFO pstartup)
{
_MmInitVMMap(pstartup);
_MmInitPageAlloc(pstartup);
}

93
kernel/objhelp.c Normal file
View File

@ -0,0 +1,93 @@
#include <comrogue/types.h>
#include <comrogue/scode.h>
#include <comrogue/str.h>
#include <comrogue/object_types.h>
#include <comrogue/objectbase.h>
#include <comrogue/allocator.h>
#include <comrogue/stdobj.h>
#include <comrogue/objhelp.h>
#include <comrogue/internals/seg.h>
/*--------------------------------------------
* Standard object functions (API-type calls)
*--------------------------------------------
*/
/*
* Determines whether two GUID references are equal.
*
* Parameters:
* - guid1 = First GUID to compare.
* - guid2 = Second GUID to compare.
*
* Returns:
* TRUE if the GUIDs are equal, FALSE otherwise.
*/
SEG_LIB_CODE BOOL IsEqualGUID(REFGUID guid1, REFGUID guid2)
{
return MAKEBOOL(StrCompareMem(guid1, guid2, sizeof(GUID)) == 0);
}
/*-----------------------------------------------------------------
* Functions to be used in the construction of C interface vtables
*-----------------------------------------------------------------
*/
/*
* Retrieves pointers to the supported interfaces on an object. Any pointer returned by this method
* has AddRef called on it before it returns.
*
* Parameters:
* - pThis = Base interface pointer.
* - riid = The identifier of the interface being requested.
* - ppvObject = Address of a pointer variable that receives the interface pointer requested by riid.
* On return, *ppvObject contains the requested interface pointer, or NULL if the interface
* is not supported.
*
* Returns:
* - S_OK = If the interface is supported. *ppvObject contains the pointer to the interface.
* - E_NOINTERFACE = If the interface is not supported. *ppvObject contains NULL.
* - E_POINTER = If ppvObject is NULL.
*/
/* This macro makes a ObjHlpStandardQueryInterface_IXXX function for any interface directly derived from IUnknown */
#define MAKE_BASE_QI(iface) \
SEG_LIB_CODE HRESULT ObjHlpStandardQueryInterface_ ## iface (IUnknown *pThis, REFIID riid, PPVOID ppvObject) \
{ \
if (!ppvObject) return E_POINTER; \
*ppvObject = NULL; \
if (!IsEqualIID(riid, &IID_ ## iface) && !IsEqualIID(riid, &IID_IUnknown)) \
return E_NOINTERFACE; \
IUnknown_AddRef(pThis); \
*ppvObject = (PVOID)pThis; \
return S_OK; \
}
MAKE_BASE_QI(IMalloc)
/*
* "Dummy" version of AddRef/Release used for static objects.
*
* Parameters:
* - pThis = Base interface pointer.
*
* Returns:
* 1.
*/
SEG_LIB_CODE UINT32 ObjHlpStaticAddRefRelease(IUnknown *pThis)
{
return 1;
}
/*
* Method returning void that does nothing.
*
* Parameters:
* - pThis = Base interface pointer.
*
* Returns:
* Nothing.
*/
SEG_LIB_CODE void ObjHlpDoNothingReturnVoid(IUnknown *pThis)
{
/* do nothing */
}

58
kernel/pagealloc.c Normal file
View File

@ -0,0 +1,58 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#include <comrogue/types.h>
#include <comrogue/internals/seg.h>
#include <comrogue/internals/mmu.h>
#include <comrogue/internals/startup.h>
/* Lists we keep track of various pages on. */
typedef struct tagPAGELIST {
UINT32 ndxLast; /* index of last page in list */
UINT32 cpg; /* count of pages in list */
} PAGELIST, *PPAGELIST;
/* The Master Page Database */
static PMPDB g_pMasterPageDB = NULL;
/* Individual page lists. */
//static PAGELIST g_pglFree = { 0, 0 }; /* pages that are free */
//static PAGELIST g_pglZeroed = { 0, 0 }; /* pages that are free and zeroed */
//static PAGELIST g_pglStandby = { 0, 0 }; /* pages removed but "in transition" */
//static PAGELIST g_pglModified = { 0, 0 }; /* pages removed but "in transition" and modified */
//static PAGELIST g_pglBad = { 0, 0 }; /* bad pages */
SEG_INIT_CODE void _MmInitPageAlloc(PSTARTUP_INFO pstartup)
{
g_pMasterPageDB = (PMPDB)(pstartup->kaMPDB);
}

43
kernel/sizes.h Normal file
View File

@ -0,0 +1,43 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#ifndef __SIZES_H_INCLUDED
#define __SIZES_H_INCLUDED
/*-----------------------------------
* Sizes of internal data structures
*-----------------------------------
*/
#define SIZE_INIT_STACK 4096 /* size of the initial stack */
#define SIZE_INIT_HEAP 16384 /* size of the initial heap */
#endif /* __SIZES_H_INCLUDED */

View File

@ -31,6 +31,7 @@
*/
#include <comrogue/internals/layout.h>
#include <comrogue/internals/sctlr.h>
#include "sizes.h"
.section ".initHEAD.text"
@ -112,6 +113,10 @@ COMROGUEStart:
#endif
.section ".init.bss"
.balign 8
.globl g_pInitHeapBlock
g_pInitHeapBlock:
.space SIZE_INIT_HEAP
.balign 4
.space 4096
.space SIZE_INIT_STACK
.initstack:

187
kernel/strcomparemem.S Normal file
View File

@ -0,0 +1,187 @@
/*
* Copyright 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Steve C. Woodford for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2002 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Taken from FreeBSD memcmp.S, munged by Erbo to COMROGUE standards */
.section ".lib.text"
/* Func: INT32 StrCompareMem(PCVOID pMem1, PCVOID pMem2, SSIZE_T cb); */
/*
* Compares two memory blocks as bytes, returning a value for comparison between the two.
*
* Parameters:
* - pMem1 = First block of memory to compare.
* - pMem2 = Second block of memory to compare.
* - cb = Size of the two memory blocks in bytes.
*
* Returns:
* 0 if the two memory blocks are the same; a value less than 0 if the memory block pointed to by pMem1 is
* less than the one pointed to by pMem2; a value greater than 0 if the memory block pointed to by pMem1 is
* greater than the one pointed to by pMem2.
*/
.globl StrCompareMem
StrCompareMem:
mov ip, r0
cmp r2, #0x06 /* optimized version for 6-byte compares */
beq .Lmemcmp_6bytes
mov r0, #0x00
/* Are both addresses aligned the same way? */
cmp r2, #0x00
eornes r3, ip, r1
bxeq lr /* len == 0, or same addresses! */
tst r3, #0x03
subne r2, r2, #0x01
bne .Lmemcmp_bytewise2 /* Badly aligned. Do it the slow way */
/* Word-align the addresses, if necessary */
sub r3, r1, #0x05
ands r3, r3, #0x03
add r3, r3, r3, lsl #1
addne pc, pc, r3, lsl #3
nop
/* Compare up to 3 bytes */
ldrb r0, [ip], #0x01
ldrb r3, [r1], #0x01
subs r0, r0, r3
bxne lr
subs r2, r2, #0x01
bxeq lr
/* Compare up to 2 bytes */
ldrb r0, [ip], #0x01
ldrb r3, [r1], #0x01
subs r0, r0, r3
bxne lr
subs r2, r2, #0x01
bxeq lr
/* Compare 1 byte */
ldrb r0, [ip], #0x01
ldrb r3, [r1], #0x01
subs r0, r0, r3
bxne lr
subs r2, r2, #0x01
bxeq lr
/* Compare 4 bytes at a time, if possible */
subs r2, r2, #0x04
bcc .Lmemcmp_bytewise
.Lmemcmp_word_aligned:
ldr r0, [ip], #0x04
ldr r3, [r1], #0x04
subs r2, r2, #0x04
cmpcs r0, r3
beq .Lmemcmp_word_aligned
sub r0, r0, r3
/* Correct for extra subtraction, and check if done */
adds r2, r2, #0x04
cmpeq r0, #0x00 /* If done, did all bytes match? */
bxeq lr /* Yup. Just return */
/* Re-do the final word byte-wise */
sub ip, ip, #0x04
sub r1, r1, #0x04
.Lmemcmp_bytewise:
add r2, r2, #0x03
.Lmemcmp_bytewise2:
ldrb r0, [ip], #0x01
ldrb r3, [r1], #0x01
subs r2, r2, #0x01
cmpcs r0, r3
beq .Lmemcmp_bytewise2
sub r0, r0, r3
bx lr
/*
* 6 byte compares are very common, thanks to the network stack.
* This code is hand-scheduled to reduce the number of stalls for
* load results. Everything else being equal, this will be ~32%
* faster than a byte-wise memcmp.
*/
.align 5
.Lmemcmp_6bytes:
ldrb r3, [r1, #0x00] /* r3 = b2#0 */
ldrb r0, [ip, #0x00] /* r0 = b1#0 */
ldrb r2, [r1, #0x01] /* r2 = b2#1 */
subs r0, r0, r3 /* r0 = b1#0 - b2#0 */
ldreqb r3, [ip, #0x01] /* r3 = b1#1 */
bxne lr /* Return if mismatch on #0 */
subs r0, r3, r2 /* r0 = b1#1 - b2#1 */
ldreqb r3, [r1, #0x02] /* r3 = b2#2 */
ldreqb r0, [ip, #0x02] /* r0 = b1#2 */
bxne lr /* Return if mismatch on #1 */
ldrb r2, [r1, #0x03] /* r2 = b2#3 */
subs r0, r0, r3 /* r0 = b1#2 - b2#2 */
ldreqb r3, [ip, #0x03] /* r3 = b1#3 */
bxne lr /* Return if mismatch on #2 */
subs r0, r3, r2 /* r0 = b1#3 - b2#3 */
ldreqb r3, [r1, #0x04] /* r3 = b2#4 */
ldreqb r0, [ip, #0x04] /* r0 = b1#4 */
bxne lr /* Return if mismatch on #3 */
ldrb r2, [r1, #0x05] /* r2 = b2#5 */
subs r0, r0, r3 /* r0 = b1#4 - b2#4 */
ldreqb r3, [ip, #0x05] /* r3 = b1#5 */
bxne lr /* Return if mismatch on #4 */
sub r0, r3, r2 /* r0 = b1#5 - b2#5 */
bx lr

View File

@ -58,14 +58,14 @@
*
* Apologies for the state of the comments ;-)
*/
/* Func: PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, INT32 nBytes); */
/* Func: PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, SSIZE_T cb); */
/*
* Copies memory data from one block of memory to another. Assumes the memory blocks do NOT overlap.
*
* Parameters:
* - pDest = Destination for the copy operation.
* - pSrc = Source for the copy operation.
* - nBytes = Number of bytes to be copied.
* - cb = Number of bytes to be copied.
*
* Returns:
* pDest.

183
kernel/strsetmem.S Normal file
View File

@ -0,0 +1,183 @@
/*
* Copyright 2003 Wasabi Systems, Inc.
* All rights reserved.
*
* Written by Steve C. Woodford for Wasabi Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed for the NetBSD Project by
* Wasabi Systems, Inc.
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1995 Mark Brinicombe.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Mark Brinicombe.
* 4. The name of the company nor the name of the author may be used to
* endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* Taken from FreeBSD memset.S, munged by Erbo to COMROGUE standards */
.section ".lib.text"
/* FUNC: PVOID StrSetMem(PVOID pMem, INT32 ch, SSIZE_T cb); */
/*
* Fills a block of memory with a constant byte value.
*
* Parameters:
* - pMem = Pointer to the memory block to be filled.
* - ch = The constant byte (character) to fill that memory with.
* - cb = The size in bytes of the memory block to be filled.
*
* Returns:
* pMem.
*/
.globl StrSetMem
StrSetMem:
and r3, r1, #0xff /* We deal with bytes */
mov r1, r2
cmp r1, #0x04 /* Do we have less than 4 bytes */
mov ip, r0
blt .Lmemset_lessthanfour
/* Ok first we will word align the address */
ands r2, ip, #0x03 /* Get the bottom two bits */
bne .Lmemset_wordunaligned /* The address is not word aligned */
/* We are now word aligned */
.Lmemset_wordaligned:
orr r3, r3, r3, lsl #8 /* Extend value to 16-bits */
tst ip, #0x04 /* Quad-align for armv5e */
orr r3, r3, r3, lsl #16 /* Extend value to 32-bits */
subne r1, r1, #0x04 /* Quad-align if necessary */
strne r3, [ip], #0x04
cmp r1, #0x10
blt .Lmemset_loop4 /* If less than 16 then use words */
mov r2, r3 /* Duplicate data */
cmp r1, #0x80 /* If < 128 then skip the big loop */
blt .Lmemset_loop32
/* Do 128 bytes at a time */
.Lmemset_loop128:
subs r1, r1, #0x80
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
bgt .Lmemset_loop128
bxeq lr /* Zero length so just exit */
add r1, r1, #0x80 /* Adjust for extra sub */
/* Do 32 bytes at a time */
.Lmemset_loop32:
subs r1, r1, #0x20
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
strged r2, [ip], #0x08
bgt .Lmemset_loop32
bxeq lr /* Zero length so just exit */
adds r1, r1, #0x10 /* Partially adjust for extra sub */
/* Deal with 16 bytes or more */
strged r2, [ip], #0x08
strged r2, [ip], #0x08
bxeq lr /* Zero length so just exit */
addlt r1, r1, #0x10 /* Possibly adjust for extra sub */
/* We have at least 4 bytes so copy as words */
.Lmemset_loop4:
subs r1, r1, #0x04
strge r3, [ip], #0x04
bgt .Lmemset_loop4
bxeq lr /* Zero length so just exit */
/* Compensate for 64-bit alignment check */
adds r1, r1, #0x04
bxeq lr
cmp r1, #2
strb r3, [ip], #0x01 /* Set 1 byte */
strgeb r3, [ip], #0x01 /* Set another byte */
strgtb r3, [ip] /* and a third */
bx lr /* Exit */
.Lmemset_wordunaligned:
rsb r2, r2, #0x004
strb r3, [ip], #0x01 /* Set 1 byte */
cmp r2, #0x02
strgeb r3, [ip], #0x01 /* Set another byte */
sub r1, r1, r2
strgtb r3, [ip], #0x01 /* and a third */
cmp r1, #0x04 /* More than 4 bytes left? */
bge .Lmemset_wordaligned /* Yup */
.Lmemset_lessthanfour:
cmp r1, #0x00
bxeq lr /* Zero length so exit */
strb r3, [ip], #0x01 /* Set 1 byte */
cmp r1, #0x02
strgeb r3, [ip], #0x01 /* Set another byte */
strgtb r3, [ip] /* and a third */
bx lr /* Exit */

465
kernel/vmmap.c Normal file
View File

@ -0,0 +1,465 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#include <comrogue/types.h>
#include <comrogue/scode.h>
#include <comrogue/internals/seg.h>
#include <comrogue/internals/mmu.h>
#include <comrogue/internals/memmgr.h>
#include <comrogue/internals/startup.h>
#define NMAPFRAMES 4 /* number of frame mappings */
static PTTB g_pttb1 = NULL; /* pointer to TTB1 */
static KERNADDR g_kaEndFence = 0; /* end fence in kernel addresses, after we reserve some */
static KERNADDR g_kaTableMap[NMAPFRAMES] = { 0 }; /* kernel addresses for page table mappings */
static PHYSADDR g_paTableMap[NMAPFRAMES] = { 0 }; /* physical addresses for page table mappings */
static UINT32 g_refTableMap[NMAPFRAMES] = { 0 }; /* reference counts for table mappings */
/*
* Maps a page table's page into kernel memory space where we can examine it.
*
* Parameters:
* - paPageTable = Physical address of the page table to map.
*
* Returns:
* Pointer to the pagetable in kernel memory, or NULL if we weren't able to map it.
*
* Side effects:
* May modify g_paTableMap and g_refTableMap, and may modify TTB1 if we map a page into memory.
*/
static PPAGETAB map_pagetable(PHYSADDR paPageTable)
{
PHYSADDR paOfPage = paPageTable & ~(SYS_PAGE_SIZE - 1); /* actual page table page's PA */
register UINT32 i; /* loop counter */
for (i = 0; i < NMAPFRAMES; i++)
{
if (g_paTableMap[i] == paOfPage)
{
g_refTableMap[i]++; /* already mapped, return it */
goto returnOK;
}
}
for (i = 0; i < NMAPFRAMES; i++)
{
if (!(g_paTableMap[i]))
{
g_paTableMap[i] = paOfPage; /* claim slot and map into it */
g_refTableMap[i] = 1;
if (FAILED(MmMapPages(g_pttb1, g_paTableMap[i], g_kaTableMap[i], 1, TTBFLAGS_KERNEL_DATA,
PGTBLFLAGS_KERNEL_DATA)))
{
g_refTableMap[i] = 0;
g_paTableMap[i] = 0;
return NULL;
}
break;
}
}
if (i == NMAPFRAMES)
return NULL;
returnOK:
return (PPAGETAB)(g_kaTableMap[i] | (paPageTable & (SYS_PAGE_SIZE - 1)));
}
/*
* Demaps a page table's page from kernel memory space.
*
* Parameters:
* - ppgtbl = Pointer to the page table.
*
* Returns:
* Nothing.
*
* Side effects:
* May modify g_paTableMap and g_refTableMap, and may modify TTB1 if we unmap a page from memory.
*/
static void demap_pagetable(PPAGETAB ppgtbl)
{
KERNADDR kaOfPage = ((KERNADDR)ppgtbl) & ~(SYS_PAGE_SIZE - 1);
register UINT32 i; /* loop counter */
for (i = 0; i < NMAPFRAMES; i++)
{
if (g_kaTableMap[i] == kaOfPage)
{
if (--g_refTableMap[i] == 0)
{
MmDemapPages(g_pttb1, g_kaTableMap[i], 1);
g_paTableMap[i] = 0;
}
break;
}
}
}
/*
* Resolves a specified TTB to either itself or the global TTB1, depending on whether one was specified
* and on the virtual address to be worked with.
*
* Parameters:
* - pTTB = The specified TTB pointer.
* - vma = The base virtual address we're working with.
*
* Returns:
* The pointer to the selected TTB, which may be the global variable g_pttb1.
*/
static PTTB resolve_ttb(PTTB pTTB, KERNADDR vma)
{
if (!pTTB || (vma & 0x80000000))
return g_pttb1; /* if no TTB specified or address is out of range for TTB0, use TTB1 */
return pTTB;
}
/*
* Returns the physical address corresponding to a virtual memory address.
*
* Parameters:
* - pTTB = The TTB to resolve the VM address against. If this is NULL or if the address specified
* is outside the TTB0 range, the system TTB is used.
*
* Returns:
* The physical address corresponding to the virtual memory address, or NULL if the address could
* not be resolved (is not mapped, or page table could not be mapped).
*/
PHYSADDR MmGetPhysAddr(PTTB pTTB, KERNADDR vma)
{
PTTB pTTBEntry = resolve_ttb(pTTB, vma) + mmVMA2TTBIndex(vma);
PPAGETAB pTab;
PHYSADDR rc;
if ((pTTBEntry->data & TTBQUERY_MASK) == TTBQUERY_FAULT)
return NULL; /* we're not allocated */
if (pTTBEntry->data & TTBSEC_ALWAYS)
return (pTTBEntry->data & TTBSEC_BASE) | (vma & ~TTBSEC_BASE); /* resolve section address */
pTab = map_pagetable(pTTBEntry->data & TTBPGTBL_BASE);
if (!pTab)
return NULL; /* could not map the page table */
rc = (pTab->pgtbl[mmVMA2PGTBLIndex(vma)].pg.pgaddr << SYS_PAGE_BITS) | (vma & (SYS_PAGE_SIZE - 1));
demap_pagetable(pTab);
return rc;
}
/*
* Deallocates page mapping entries within a single current entry in the TTB.
*
* Parameters:
* - pTTBEntry = Pointer to the TTB entry to deallocate in.
* - ndxPage = Starting index in the page table of the first entry to deallocate.
* - cpg = Count of the number of pages to deallocate. Note that this function will not deallocate more
* page mapping entries than remain on the page, as indicated by ndxPage.
*
* Returns:
* Standard HRESULT success/failure. If the result is successful, the SCODE_CODE of the result will
* indicate the number of pages actually deallocated.
*
* Side effects:
* May modify the TTB entry pointed to, and the page table it points to, where applicable. If the
* page table is empty after we finish demapping entries, it may be deallocated.
*/
static HRESULT demap_pages1(PTTB pTTBEntry, UINT32 ndxPage, UINT32 cpg)
{
UINT32 cpgCurrent; /* number of pages we're mapping */
PPAGETAB pTab = NULL; /* pointer to current or new page table */
HRESULT hr; /* return from this function */
register INT32 i; /* loop counter */
/* Figure out how many entries we're going to demap. */
cpgCurrent = SYS_PGTBL_ENTRIES - ndxPage; /* total free slots on page */
if (cpg < cpgCurrent)
cpgCurrent = cpg; /* only map up to max requested */
hr = MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_MEMMGR, cpgCurrent);
if ((pTTBEntry->data & TTBSEC_ALWAYS) && (cpgCurrent == SYS_PGTBL_ENTRIES) && (ndxPage == 0))
{ /* we can kill off the whole section */
pTTBEntry->data = 0;
/* TODO: handle TLB and cache */
}
else if (pTTBEntry->data & TTBPGTBL_ALWAYS)
{
pTab = map_pagetable(pTTBEntry->data & TTBPGTBL_BASE);
if (!pTab)
return MEMMGR_E_NOPGTBL;
for (i = 0; i<cpgCurrent; i++)
{
pTab->pgtbl[ndxPage + i].data = 0;
pTab->pgaux[ndxPage + i].data = 0;
/* TODO: handle TLB and cache */
}
/* TODO: check to see if page table can be deallocated */
demap_pagetable(pTab);
}
return hr;
}
HRESULT MmDemapPages(PTTB pTTB, KERNADDR vmaBase, UINT32 cpg)
{
PTTB pMyTTB = resolve_ttb(pTTB, vmaBase); /* the TTB we use */
UINT32 ndxTTBMax = (pMyTTB == g_pttb1) ? SYS_TTB1_ENTRIES : SYS_TTB0_ENTRIES;
UINT32 ndxTTB = mmVMA2TTBIndex(vmaBase); /* TTB entry index */
UINT32 ndxPage = mmVMA2PGTBLIndex(vmaBase); /* starting page entry index */
UINT32 cpgRemaining = cpg; /* number of pages remaining to demap */
HRESULT hr; /* temporary result */
if ((cpgRemaining > 0) && (ndxPage > 0))
{
/* We are starting in the middle of a VM page. Demap to the end of the VM page. */
hr = demap_pages1(pMyTTB + ndxTTB, ndxPage, cpgRemaining);
if (FAILED(hr))
return hr;
cpgRemaining -= SCODE_CODE(hr);
if (++ndxTTB == ndxTTBMax)
return MEMMGR_E_ENDTTB;
}
while (cpgRemaining > 0)
{
hr = demap_pages1(pMyTTB + ndxTTB, 0, cpgRemaining);
if (FAILED(hr))
return hr;
cpgRemaining -= SCODE_CODE(hr);
if (++ndxTTB == ndxTTBMax)
return MEMMGR_E_ENDTTB;
}
return S_OK;
}
/*
* Morphs the "flags" bits used for a page table entry in the TTB and for a page entry in the page table
* into the "flags" bits used for a section entry in the TTB.
*
* Parameters:
* - uiTableFlags = Flag bits that would be used for a page table entry in the TTB.
* - uiPageFlags = Flag bits that would be used for a page entry in the page table.
*
* Returns:
* The flag bits that would be used for a section entry in the TTB. If a bit or option is set
* in either uiTableFlags or uiPageFlags, it will be set in the appropriate place in the result.
*/
static UINT32 make_section_flags(UINT32 uiTableFlags, UINT32 uiPageFlags)
{
register UINT32 rc = TTBSEC_ALWAYS;
rc |= ((uiTableFlags & TTBPGTBL_PXN) >> 2);
rc |= ((uiTableFlags & TTBPGTBL_NS) << 16);
rc |= (uiTableFlags & TTBPGTBL_DOM_MASK);
rc |= (uiTableFlags & TTBPGTBL_P);
rc |= ((uiPageFlags & PGTBLSM_XN) << 4);
rc |= (uiPageFlags & PGTBLSM_B);
rc |= (uiPageFlags & PGTBLSM_C);
rc |= ((uiPageFlags & PGTBLSM_AP) << 6);
rc |= ((uiPageFlags & PGTBLSM_TEX) << 6);
rc |= ((uiPageFlags & PGTBLSM_APX) << 6);
rc |= ((uiPageFlags & PGTBLSM_S) << 6);
rc |= ((uiPageFlags & PGTBLSM_NG) << 6);
return rc;
}
static HRESULT map_pages1(PTTB pttbEntry, PHYSADDR paBase, UINT32 ndxPage, UINT32 cpg, UINT32 uiTableFlags,
UINT32 uiPageFlags)
{
UINT32 cpgCurrent; /* number of pages we're mapping */
PPAGETAB pTab = NULL; /* pointer to current or new page table */
HRESULT hr; /* return from this function */
register INT32 i; /* loop counter */
switch (pttbEntry->data & TTBQUERY_MASK)
{
case TTBQUERY_FAULT: /* not allocated, allocate a new page table for the slot */
/* TODO: allocate something into pTab */
if (!pTab)
return MEMMGR_E_NOPGTBL;
for (i=0; i<SYS_PGTBL_ENTRIES; i++)
{
pTab->pgtbl[i].data = 0; /* blank out the new page table */
pTab->pgaux[i].data = 0;
}
/* TODO: use physical address of page here */
pttbEntry->data = MmGetPhysAddr(g_pttb1, (KERNADDR)pTab) | uiTableFlags; /* poke new entry */
break;
case TTBQUERY_PGTBL: /* existing page table */
if ((pttbEntry->data & TTBPGTBL_ALLFLAGS) != uiTableFlags)
return MEMMGR_E_BADTTBFLG; /* table flags not compatible */
pTab = map_pagetable(pttbEntry->data & TTBPGTBL_BASE);
if (!pTab)
return MEMMGR_E_NOPGTBL; /* could not map the page table */
break;
case TTBQUERY_SEC:
case TTBQUERY_PXNSEC:
/* this is a section, make sure its base address covers this mapping and its flags are compatible */
if ((pttbEntry->data & TTBSEC_ALLFLAGS) != make_section_flags(uiTableFlags, uiPageFlags))
return MEMMGR_E_BADTTBFLG;
if ((pttbEntry->data & TTBSEC_BASE) != (paBase & TTBSEC_BASE))
return MEMMGR_E_COLLIDED;
break;
}
/* Figure out how many entries we're going to map. */
cpgCurrent = SYS_PGTBL_ENTRIES - ndxPage; /* total free slots on page */
if (cpg < cpgCurrent)
cpgCurrent = cpg; /* only map up to max requested */
hr = MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_MEMMGR, cpgCurrent);
if (!(pttbEntry->data & TTBSEC_ALWAYS))
{
/* fill in entries in the page table */
for (i=0; i < cpgCurrent; i++)
{
if ((pTab->pgtbl[ndxPage + i].data & PGQUERY_MASK) != PGQUERY_FAULT)
{
while (--i >= 0)
{ /* reverse any mapping we've done in this function */
pTab->pgtbl[ndxPage + i].data = 0;
pTab->pgaux[ndxPage + i].data = 0;
}
hr = MEMMGR_E_COLLIDED; /* stepping on existing mapping */
goto exit;
}
pTab->pgtbl[ndxPage + i].data = paBase | uiPageFlags;
pTab->pgaux[ndxPage + i].data = 0; /* TODO */
paBase += SYS_PAGE_SIZE;
}
}
exit:
demap_pagetable(pTab);
return hr;
}
HRESULT MmMapPages(PTTB pTTB, PHYSADDR paBase, KERNADDR vmaBase, UINT32 cpg, UINT32 uiTableFlags,
UINT32 uiPageFlags)
{
PTTB pMyTTB = resolve_ttb(pTTB, vmaBase); /* the TTB we use */
UINT32 ndxTTBMax = (pMyTTB == g_pttb1) ? SYS_TTB1_ENTRIES : SYS_TTB0_ENTRIES;
UINT32 ndxTTB = mmVMA2TTBIndex(vmaBase); /* TTB entry index */
UINT32 ndxPage = mmVMA2PGTBLIndex(vmaBase); /* starting page entry index */
UINT32 cpgRemaining = cpg; /* number of pages remaining to map */
HRESULT hr; /* temporary result */
if ((cpgRemaining > 0) && (ndxPage > 0))
{
/* We are starting in the middle of a VM page. Map to the end of the VM page. */
hr = map_pages1(pMyTTB + ndxTTB, paBase, ndxPage, cpgRemaining, uiTableFlags, uiPageFlags);
if (FAILED(hr))
return hr;
cpgRemaining -= SCODE_CODE(hr);
paBase += (SCODE_CODE(hr) << SYS_PAGE_BITS);
if (++ndxTTB == ndxTTBMax)
{
hr = MEMMGR_E_ENDTTB;
goto errorExit;
}
}
while (cpgRemaining >= SYS_PGTBL_ENTRIES)
{
/* try to map a whole section's worth at a time */
if ((paBase & TTBSEC_BASE) == paBase)
{
/* paBase is section-aligned now as well, we can use a direct 1Mb section mapping */
switch (pMyTTB[ndxTTB].data & TTBQUERY_MASK)
{
case TTBQUERY_FAULT: /* unmapped - map the section */
pMyTTB[ndxTTB].data = paBase | make_section_flags(uiTableFlags, uiPageFlags);
break;
case TTBQUERY_PGTBL: /* collided with a page table */
hr = MEMMGR_E_COLLIDED;
goto errorExit;
case TTBQUERY_SEC: /* test existing section */
case TTBQUERY_PXNSEC:
if ((pMyTTB[ndxTTB].data & TTBSEC_ALLFLAGS) != make_section_flags(uiTableFlags, uiPageFlags))
{
hr = MEMMGR_E_BADTTBFLG;
goto errorExit;
}
if ((pMyTTB[ndxTTB].data & TTBSEC_BASE) != paBase)
{
hr = MEMMGR_E_COLLIDED;
goto errorExit;
}
break;
}
/* we mapped a whole section worth */
hr = MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_MEMMGR, SYS_PGTBL_ENTRIES);
}
else
{
/* just map 256 individual pages */
hr = map_pages1(pMyTTB + ndxTTB, paBase, 0, cpgRemaining, uiTableFlags, uiPageFlags);
if (FAILED(hr))
goto errorExit;
}
/* adjust base physical address, page count, and TTB index */
paBase += (SCODE_CODE(hr) << SYS_PAGE_BITS);
cpgRemaining -= SCODE_CODE(hr);
if (++ndxTTB == ndxTTBMax)
{
hr = MEMMGR_E_ENDTTB;
goto errorExit;
}
}
if (cpgRemaining > 0)
{
/* map the "tail end" onto the next TTB */
hr = map_pages1(pMyTTB + ndxTTB, paBase, 0, cpgRemaining, uiTableFlags, uiPageFlags);
if (FAILED(hr))
goto errorExit;
}
return S_OK;
errorExit:
/* demap everything we've managed to map thusfar */
MmDemapPages(pMyTTB, vmaBase, cpg - cpgRemaining);
return hr;
}
/*---------------------
* Initialization code
*---------------------
*/
SEG_INIT_CODE void _MmInitVMMap(PSTARTUP_INFO pstartup)
{
UINT32 i; /* loop counter */
g_pttb1 = (PTTB)(pstartup->kaTTB);
g_kaEndFence = pstartup->vmaFirstFree;
for (i=0; i<NMAPFRAMES; i++)
{
g_kaTableMap[i] = g_kaEndFence;
g_kaEndFence += SYS_PAGE_SIZE;
}
}