forked from 0ad/0ad
fix error path for acpi/mahaf failures (attempt#2)
prevent using mahaf if it's going to fail anyway module_init: add ModuleIsError (allows acpi and mahaf init routines to pass failure notification on to their second and later callers) counter: safer memory management This was SVN commit r5333.
This commit is contained in:
parent
b853a47c8e
commit
f039e1ce76
@ -66,3 +66,9 @@ void ModuleSetError(volatile ModuleInitState* pInitState)
|
||||
{
|
||||
*pInitState = MODULE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
bool ModuleIsError(volatile ModuleInitState* pInitState)
|
||||
{
|
||||
return (*pInitState == MODULE_ERROR);
|
||||
}
|
||||
|
@ -44,4 +44,13 @@ extern bool ModuleShouldShutdown(volatile ModuleInitState* initState);
|
||||
**/
|
||||
extern void ModuleSetError(volatile ModuleInitState* initState);
|
||||
|
||||
/**
|
||||
* @return whether the module is in the failure state, i.e. ModuleSetError
|
||||
* was previously called on the same initState.
|
||||
*
|
||||
* this function is provided so that modules can report init failure to
|
||||
* the second or later caller.
|
||||
**/
|
||||
extern bool ModuleIsError(volatile ModuleInitState* initState);
|
||||
|
||||
#endif // #ifndef INCLUDED_MODULE_INIT
|
||||
|
@ -310,14 +310,15 @@ static ModuleInitState initState;
|
||||
|
||||
bool acpi_Init()
|
||||
{
|
||||
if(ModuleIsError(&initState))
|
||||
return false;
|
||||
if(!ModuleShouldInitialize(&initState))
|
||||
return true;
|
||||
|
||||
if(!mahaf_Init())
|
||||
goto fail;
|
||||
|
||||
if(mahaf_IsPhysicalMappingDangerous())
|
||||
goto fail;
|
||||
if(!mahaf_Init())
|
||||
goto fail;
|
||||
|
||||
if(!LatchAllTables())
|
||||
goto fail;
|
||||
|
@ -278,6 +278,8 @@ static ModuleInitState initState;
|
||||
|
||||
bool mahaf_Init()
|
||||
{
|
||||
if(ModuleIsError(&initState))
|
||||
return false;
|
||||
if(!ModuleShouldInitialize(&initState))
|
||||
return true;
|
||||
|
||||
|
@ -14,6 +14,18 @@
|
||||
#ifndef INCLUDED_MAHAF
|
||||
#define INCLUDED_MAHAF
|
||||
|
||||
/**
|
||||
* @return whether mapping physical memory is known to be dangerous
|
||||
* on this platform.
|
||||
*
|
||||
* callable before or after mahaf_Init.
|
||||
*
|
||||
* note: mahaf_MapPhysicalMemory will complain if it
|
||||
* is called despite this function having returned true.
|
||||
**/
|
||||
extern bool mahaf_IsPhysicalMappingDangerous();
|
||||
|
||||
|
||||
extern bool mahaf_Init();
|
||||
extern void mahaf_Shutdown();
|
||||
|
||||
@ -24,15 +36,6 @@ extern void mahaf_WritePort8 (u16 port, u8 value);
|
||||
extern void mahaf_WritePort16(u16 port, u16 value);
|
||||
extern void mahaf_WritePort32(u16 port, u32 value);
|
||||
|
||||
/**
|
||||
* @return whether mapping physical memory is known to be dangerous
|
||||
* on this platform.
|
||||
*
|
||||
* note: mahaf_MapPhysicalMemory will warn if it is called despite this
|
||||
* function having returned true.
|
||||
**/
|
||||
extern bool mahaf_IsPhysicalMappingDangerous();
|
||||
|
||||
extern volatile void* mahaf_MapPhysicalMemory(uintptr_t physicalAddress, size_t numBytes);
|
||||
extern void mahaf_UnmapPhysicalMemory(volatile void* virtualAddress);
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "counter.h"
|
||||
|
||||
#include "lib/bits.h"
|
||||
#include "lib/allocators.h"
|
||||
|
||||
#include "tsc.h"
|
||||
#include "hpet.h"
|
||||
@ -28,14 +29,11 @@
|
||||
/**
|
||||
* @return pointer to a newly constructed ICounter subclass of type <id> at
|
||||
* the given address, or 0 iff the ID is invalid.
|
||||
* @param size receives the size [bytes] of the created instance.
|
||||
* @param size maximum allowable size [bytes] of the subclass instance
|
||||
**/
|
||||
static ICounter* ConstructCounterAt(uint id, void* address, size_t& size)
|
||||
static ICounter* ConstructCounterAt(uint id, void* address, size_t size)
|
||||
{
|
||||
// rationale for placement new: see call site.
|
||||
#define CREATE(impl)\
|
||||
size = sizeof(Counter##impl);\
|
||||
return new(address) Counter##impl();
|
||||
|
||||
#include "lib/nommgr.h" // MMGR interferes with placement new
|
||||
|
||||
@ -48,25 +46,30 @@ static ICounter* ConstructCounterAt(uint id, void* address, size_t& size)
|
||||
switch(id)
|
||||
{
|
||||
case 0:
|
||||
CREATE(HPET)
|
||||
debug_assert(sizeof(CounterHPET) <= size);
|
||||
return new(address) CounterHPET();
|
||||
case 1:
|
||||
CREATE(TSC)
|
||||
debug_assert(sizeof(CounterTSC) <= size);
|
||||
return new(address) CounterTSC();
|
||||
case 2:
|
||||
CREATE(QPC)
|
||||
debug_assert(sizeof(CounterQPC) <= size);
|
||||
return new(address) CounterQPC();
|
||||
case 3:
|
||||
CREATE(PMT)
|
||||
debug_assert(sizeof(CounterPMT) <= size);
|
||||
return new(address) CounterPMT();
|
||||
case 4:
|
||||
CREATE(TGT)
|
||||
debug_assert(sizeof(CounterTGT) <= size);
|
||||
return new(address) CounterTGT();
|
||||
default:
|
||||
size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "lib/mmgr.h"
|
||||
|
||||
#undef CREATE
|
||||
}
|
||||
|
||||
|
||||
static volatile uintptr_t isCounterAllocated;
|
||||
|
||||
ICounter* CreateCounter(uint id)
|
||||
{
|
||||
// we placement-new the Counter classes in a static buffer.
|
||||
@ -80,16 +83,15 @@ ICounter* CreateCounter(uint id)
|
||||
// first use of them.
|
||||
// - using static_calloc isn't possible because we don't know the
|
||||
// size until after the alloc / placement new.
|
||||
static const size_t MEM_SIZE = 200; // checked below
|
||||
static u8 mem[MEM_SIZE];
|
||||
static u8* nextMem = mem;
|
||||
|
||||
u8* addr = (u8*)round_up((uintptr_t)nextMem, 16);
|
||||
size_t size;
|
||||
ICounter* counter = ConstructCounterAt(id, addr, size);
|
||||
if(!CAS(&isCounterAllocated, 0, 1))
|
||||
debug_warn("static counter memory is already in use!");
|
||||
|
||||
nextMem = addr+size;
|
||||
debug_assert(nextMem < mem+MEM_SIZE); // had enough room?
|
||||
static const size_t memSize = 200;
|
||||
static u8 mem[memSize];
|
||||
u8* alignedMem = (u8*)round_up((uintptr_t)mem, 16);
|
||||
const size_t bytesLeft = mem+memSize - alignedMem;
|
||||
ICounter* counter = ConstructCounterAt(id, alignedMem, bytesLeft);
|
||||
|
||||
return counter;
|
||||
}
|
||||
@ -97,10 +99,10 @@ ICounter* CreateCounter(uint id)
|
||||
|
||||
void DestroyCounter(ICounter*& counter)
|
||||
{
|
||||
if(!counter)
|
||||
return;
|
||||
|
||||
debug_assert(counter);
|
||||
counter->Shutdown();
|
||||
counter->~ICounter(); // must be called due to placement new
|
||||
counter = 0;
|
||||
|
||||
isCounterAllocated = 0;
|
||||
}
|
||||
|
@ -64,6 +64,9 @@ public:
|
||||
/**
|
||||
* @return a newly created ICounter of type <id> or 0 iff the ID is invalid.
|
||||
* @param id integer ID (0..N-1)
|
||||
*
|
||||
* there can only be one active counter at a time; the previous one must
|
||||
* have been destroyed before creating another!
|
||||
**/
|
||||
extern ICounter* CreateCounter(uint id);
|
||||
|
||||
|
@ -53,10 +53,12 @@ static const u64 CONFIG_ENABLE = BIT64(0);
|
||||
|
||||
LibError CounterHPET::Activate()
|
||||
{
|
||||
if(mahaf_IsPhysicalMappingDangerous())
|
||||
return ERR::FAIL; // NOWARN (happens on Win2k)
|
||||
if(!mahaf_Init())
|
||||
return ERR::FAIL; // NOWARN (no Administrator privileges)
|
||||
if(!acpi_Init())
|
||||
return ERR::FAIL; // NOWARN (happens on Win2k; see mahaf_IsPhysicalMappingDangerous)
|
||||
WARN_RETURN(ERR::FAIL); // shouldn't fail, since we've checked mahaf_IsPhysicalMappingDangerous
|
||||
const HpetDescriptionTable* hpet = (const HpetDescriptionTable*)acpi_GetTable("HPET");
|
||||
if(!hpet)
|
||||
return ERR::NO_SYS; // NOWARN (HPET not reported by BIOS)
|
||||
|
@ -33,6 +33,7 @@ static const u32 TMR_VAL_EXT = BIT(8);
|
||||
|
||||
LibError CounterPMT::Activate()
|
||||
{
|
||||
// mahaf is needed for port I/O.
|
||||
if(!mahaf_Init())
|
||||
return ERR::FAIL; // NOWARN (no Administrator privileges)
|
||||
if(!acpi_Init())
|
||||
|
Loading…
Reference in New Issue
Block a user