MODULE MemCache;
IMPORT SYSTEM, Machine;
CONST
UC* = 0; WC* = 1; WT* = 4; WP* = 5; WB* = 6;
PS = 4096;
M = 100000H;
Ok = 0;
TYPE
SetCacheMessage = POINTER TO RECORD (Machine.Message)
physAdr: SYSTEM.ADDRESS; size, type: LONGINT;
res: ARRAY Machine.MaxCPU OF LONGINT
END;
PROCEDURE -GetMTTRcapLow(): SET;
CODE {SYSTEM.AMD64, SYSTEM.Privileged}
MOV ECX, 0FEH ; MTTRcap
RDMSR
END GetMTTRcapLow;
PROCEDURE -GetMTTRphysBaseLow(n: SYSTEM.ADDRESS): SET;
CODE {SYSTEM.AMD64, SYSTEM.Privileged}
XOR RAX, RAX
POP RCX
SHL RCX, 1
ADD RCX, 200H ; MTTRphysBase0
RDMSR
END GetMTTRphysBaseLow;
PROCEDURE -GetMTTRphysMaskLow(n: SYSTEM.ADDRESS): SET;
CODE {SYSTEM.AMD64, SYSTEM.Privileged}
XOR RAX, RAX
POP RCX
SHL RCX, 1
ADD RCX, 201H ; MTTRphysMask0
RDMSR
END GetMTTRphysMaskLow;
PROCEDURE -SetMTTRphysBase(n: SYSTEM.ADDRESS; high, low: SET);
CODE {SYSTEM.AMD64, SYSTEM.Privileged}
POP RAX
POP RDX
POP RCX
SHL RCX, 1
ADD RCX, 200H ; MTTRphysBase0
WRMSR
END SetMTTRphysBase;
PROCEDURE -SetMTTRphysMask(n: SYSTEM.ADDRESS; high, low: SET);
CODE {SYSTEM.AMD64, SYSTEM.Privileged}
POP RAX
POP RDX
POP RCX
SHL RCX, 1
ADD RCX, 201H ; MTTRphysMask0
WRMSR
END SetMTTRphysMask;
PROCEDURE LocalSetCacheProperties*(physAdr: SYSTEM.ADDRESS; size, type: LONGINT; VAR res: LONGINT);
VAR i, n, f: LONGINT; mask, base: SET; j, k: SYSTEM.ADDRESS;
BEGIN
ASSERT((physAdr MOD PS = 0) & (size MOD PS = 0) & (size # 0));
IF (physAdr >= M) OR (physAdr < 0) THEN
k := size; WHILE k > 0 DO k := ASH(k, 1) END;
IF k = 80000000H THEN
IF physAdr MOD size = 0 THEN
Machine.Acquire(Machine.Memory);
IF Machine.MTTR IN Machine.features THEN
mask := GetMTTRcapLow();
IF (type # WC) OR (10 IN mask) THEN
n := SYSTEM.VAL(LONGINT, mask * {0..7});
i := 0; f := -1; res := Ok;
WHILE (i # n) & (res = Ok) DO
mask := GetMTTRphysMaskLow(i);
IF 11 IN mask THEN
mask := mask * {12..MAX(SET)};
base := GetMTTRphysBaseLow(i) * mask;
j := physAdr; k := physAdr+size;
WHILE (j # k) & (SYSTEM.VAL(SET, j) * mask # base) DO INC(j, PS) END;
IF j # k THEN res := 1508 END
ELSE
IF f = -1 THEN f := i END
END;
INC(i)
END;
IF res = Ok THEN
IF f # -1 THEN
SetMTTRphysBase(f, {}, SYSTEM.VAL(SET, physAdr) * {12..31} + SYSTEM.VAL(SET, type) * {0..7});
SetMTTRphysMask(f, {0..3}, (-SYSTEM.VAL(SET, size-1)) * {12..31} + {11})
ELSE
res := 1506
END
ELSE
END
ELSE
res := 1511
END
ELSE
res := 1505
END;
Machine.Release(Machine.Memory)
ELSE
res := 1510
END
ELSE
res := 1509
END
ELSE
res := 1507
END
END LocalSetCacheProperties;
PROCEDURE HandleSetCacheProperties(id: LONGINT; CONST state: Machine.State; msg: Machine.Message);
BEGIN
WITH msg: SetCacheMessage DO
LocalSetCacheProperties(msg.physAdr, msg.size, msg.type, msg.res[id])
END
END HandleSetCacheProperties;
PROCEDURE GlobalSetCacheProperties*(physAdr: SYSTEM.ADDRESS; size, type: LONGINT; VAR res: LONGINT);
VAR i: LONGINT; msg: SetCacheMessage;
BEGIN
NEW(msg); msg.physAdr := physAdr; msg.size := size; msg.type := type;
FOR i := 0 TO Machine.MaxCPU-1 DO msg.res[i] := 2304 END;
Machine.Broadcast(HandleSetCacheProperties, msg, {Machine.Self, Machine.FrontBarrier, Machine.BackBarrier});
res := 0;
FOR i := 0 TO Machine.MaxCPU-1 DO
IF (res = 0) & (msg.res[i] # 0) THEN res := msg.res[i] END
END
END GlobalSetCacheProperties;
PROCEDURE LocalDisableCaching*;
CODE {SYSTEM.Pentium, SYSTEM.Privileged}
PUSHFD
CLI
MOV EAX, CR0
OR EAX, 40000000H
AND EAX, 0DFFFFFFFH
MOV CR0, EAX
WBINVD
MOV EAX, CR4
AND EAX, 0FFFFFF7FH
MOV CR4, EAX
MOV EAX, CR3
MOV CR3, EAX
MOV ECX, 2FFH ; MTTRdefType
MOV EAX, 0
MOV EDX, 0
WRMSR
WBINVD
MOV EAX, CR3
MOV CR3, EAX
MOV EAX, CR0
OR EAX, 60000000H
MOV CR0, EAX
POPFD
END LocalDisableCaching;
PROCEDURE HandleDisableCaching(id: LONGINT; CONST state: Machine.State; msg: Machine.Message);
BEGIN
LocalDisableCaching
END HandleDisableCaching;
PROCEDURE GlobalDisableCaching*;
BEGIN
Machine.Broadcast(HandleDisableCaching, NIL, {Machine.Self, Machine.FrontBarrier, Machine.BackBarrier})
END GlobalDisableCaching;
END MemCache.
(*
to do:
o change error codes
*)