Page 1 of 1

mtrr

Posted: Mon Feb 28, 2011 5:56 pm
by digo_rp
Could anyone help me again please?

Guys I´ve been trying to understand intel manual, chapter 11:11 that says about mtrr

I´m trying to set memory regions, like from 0 to 64 set as writeback,

from vesa memory set as writecombining,

but I expending to much time trying to understand

Caches 0-64 MByte as WB cache type.

IA32_MTRR_PHYSBASE0 = 0000 0000 0000 0006H <- this I understand, everyting ok!
IA32_MTRR_PHYSMASK0 = 0000 000F FC00 0800H <- this is odd to me, how to calc that mask, intel doen´t says that,
it just says that for that memory address that mask is need it..

this is an example from intel manual, chapter 11:11

could anyone help me please ?

Re: mtrr

Posted: Mon Feb 28, 2011 6:14 pm
by Tosi
In case others didn't know which volume he is talking about, it is 3A (Systems Programming). Check out figure 11-7 in section 11.11.2.3, which describes the structure of the IA32_MTRR_PHYSBASEn and IA32_MTRR_PHYSMASKn registers. In brief, bits 0-10 of the PHYSMASK are reserved, bit 11 marks whether it is valid, bits 12 to MAXPHYSADDR set the range mask, and all other bits are reserved.

Re: mtrr

Posted: Mon Feb 28, 2011 6:24 pm
by digo_rp
this is kinda of how many memory I want to set ? " bits 12 to MAXPHYSADDR set the range mask "

something like

physbase = 0x200 = " 0x200000"
physmask = 0xfffe = " 1048575 kb"

is like that ? sorry if this question is kinda of stupid, I´m trying to learn reading reading, then asking asking for help, :D

Re: mtrr

Posted: Mon Feb 28, 2011 7:19 pm
by Tosi
I actually have no idea since I've never messed with the MTRRs. I just searched the manual for the relevant sections, and only glanced at it.
From looking at it again, the PHYSMASK field doesn't seem to set the amount of memory mapped per se, but rather the extent of the range. It allows for discontinuous ranges, although the manually specifically warns against using them. In the example mapping section, the important distinction of the PHYSMASK field is:
This mask is chosen so that when any address in the 200000H to 3FFFFFH range is AND’d with the mask
value, it will return the same value as when the base address is AND’d with the mask value (which is 200000H).
So let's say you have a memory location named "addr." Then the following equation holds:

Code: Select all

addr & PHYSMASK = PHYSBASE & PHYSMASK
I would go into detail on how to calculate PHYSMASK, but I am really tired right now and can't think straight.

Re: mtrr

Posted: Mon Feb 28, 2011 7:34 pm
by digo_rp
my big problem is my english, is so poor, this is why I have to much problem trying to understand some code.

example in the intel manual it says:

This mask is chosen so
that when any address in the 200000H to 3FFFFFH range is AND’d with the mask
value, it will return the same value as when the base address is AND’d with the mask
value (which is 200000H).

what this means ? "AND’d " ???

please

Re: mtrr

Posted: Mon Feb 28, 2011 7:49 pm
by bewing
AND is an assembly language instruction. "AND'd" is bad english, but it means "use AND".
In C, it is represented by &

(i & j) = i AND j

Re: mtrr

Posted: Tue Mar 01, 2011 2:13 am
by Combuster
It serves to make a verb of a noun: You have been Bewing'd (I prefer the 'd because the "regular" Bewinged can be ambiguously interpreted as be-winged rather than bewing-ed, and the same for some other cases)

But I consider it rather elementary English to strip the past or perfect tense from a regular verb (A kiss, to kiss, I kissed; The Rickroll, to Rickroll, I was Rickroll'd)

Re: mtrr

Posted: Tue Mar 01, 2011 2:14 pm
by Tosi
It refers to the bitwise AND operation: for example, 0xF0 AND 0x0F would be 0, while 0x82 AND 0x02 would be 0x02. The x86 assembly mnemonic is "and", and the C operator is &.

Re: mtrr

Posted: Tue Mar 01, 2011 3:11 pm
by digo_rp
thank so much guys,

but you see ?, the intel 3A manual doesn´t says how to calculate that mask, :( I´m confused!

Re: mtrr

Posted: Tue Mar 01, 2011 7:15 pm
by Brendan
Hi,
digo_rp wrote:example in the intel manual it says:

This mask is chosen so
that when any address in the 200000H to 3FFFFFH range is AND’d with the mask
value, it will return the same value as when the base address is AND’d with the mask
value (which is 200000H).
You could convert that paragraph directly into C code:

Code: Select all

    if(  (address & MTTR_MASK) == MTTR_BASE) { /* MTRR effects this access */ }
It's worth noting here that it is impossible to cover some address ranges with a single variable MTTR. To be able to cover an address range with one variable MTTR, the base address of that range must be on a "size of the range" boundary and the size of the range must be a power of 2. For example, a 2 MiB address range would have to be on a 2 MiB boundary, a 4 KiB address range would have to be on a 4 KiB boundary, etc.

If the size of the range is a power of 2 and the base address of the range is on a "size of the range" boundary; then the calculation is simple:

Code: Select all

    MTRR_MASK = ~(size_of_range)
If the size of the range is not a power of 2, or if the base address of the range is not on a "size of the range" boundary; then you have to split it up into multiple ranges that are. This can be tricky.

For an example, imagine you've got 56 KiB area at 0xA8642000. To start with the size of the area isn't a power of 2, so you need to split it up into smaller areas that are a power of 2. The largest area would be 32 KiB (which leaves you with 24 KiB that still needs splitting up), the next area would be 16 KiB and the last area would be 8 KiB. The 32 KiB area can't use "base address 0xA8642000" because it's not aligned, and neither can the 16 KiB area. The 8 KiB area can though. If the 16 KiB area placed directly above that, and the 32 KiB area is directly above that, then it all works. You end up with:

1st: 8 KiB from 0xA8642000 to 0xA8643FFF (MTRR_base = 0xA8642000, MTTR_mask = 0xFFFFE000)
2nd: 16 KiB from 0xA8644000 to 0xA8647FFF (MTRR_base = 0xA8644000, MTTR_mask = 0xFFFFC000)
3rd: 32 KiB from 0xA8648000 to 0xA864FFFF (MTRR_base = 0xA8648000, MTTR_mask = 0xFFFF8000)

What if there's a 56 KiB area at 0xE0000000? In that case you'd still need to split it into 3 areas, but the largest area can go first, and you'd end up with:
1st: 32 KiB from 0xE0000000 to 0xE0007FFF (MTRR_base = 0xE0000000, MTTR_mask = 0xFFFF8000)
2nd: 16 KiB from 0xE0008000 to 0xE000BFFF (MTRR_base = 0xE0008000, MTTR_mask = 0xFFFFC000)
3rd: 8 KiB from 0xE000C000 to 0xA8643FFF (MTRR_base = 0xE000C000, MTTR_mask = 0xFFFFE000)

However, this is a special case; where you may be able to do it more efficiently by having one area that is "too large" and another area to correct the wrong part. For the area that is too large, you'd round up to the nearest power of 2 and get a 64 KiB area. This is 8 KiB larger than it should be, so you can create a second area that says "ignore the first MTTR, this 8 KiB is uncachable". The result might look like this:

1st: 64 KiB from 0xE0000000 to 0xE000FFFF (MTRR_base = 0xE0000000, MTTR_mask = 0xFFFF0000) - "write through"
2nd: 8 KiB from 0xE000E000 to 0xE000FFFF (MTRR_base = 0xE000E000, MTTR_mask = 0xFFFFE000) - "uncachable"

This only works in some cases though - that second area must be "uncachable", and (if I remember right) the first area can't be "write combining". It'd be best to look up the details in Intel's manual if you're considering this.. ;)

Fortunately, the PCI specifications have restrictions that device manufacturers have to follow for memory mapped IO areas; and these restrictions happen to be virtually the same as the MTRR restrictions. This means that for memory mapped PCI areas you'll only need one MTTR; and the only case where you need to use more than one is for RAM (which the firmware would've already done for you).


Cheers,

Brendan

Re: mtrr

Posted: Wed Mar 02, 2011 5:08 am
by digo_rp
Brendan, for example:

I want to set as write-combining the vesa frame buffer that is at this case 0xC0000000

how do I get mask for that address? so sorry for this question again, some cases I have some problem

understanding some explanations in english... I´m learning english too :-D

please could you help me ?

Re: mtrr

Posted: Wed Mar 02, 2011 8:06 am
by Combuster
Do you know what happens when you subtract 1 from a power of two? Try a few cases and write down the results in binary.

Re: mtrr

Posted: Fri Mar 04, 2011 6:04 pm
by digo_rp
Guys I found a good way to calculate the physmask this I found from google

PhysMask and PhysBase Values. Software can calculate the PhysMask value using the following procedure:

1. Substract the memory-range physical base-address from the upper physical-address of the memory range.

2. Substract the value calculated in Step 1 from the physical memory size.

3. Truncate the lower 12 bits of the result in Step 2 to create the PhysMask value to be loaded into the MTRRphysMaskn register.
Truncation is performed by right-shifting the value 12 bits.

For example, assume a 32-Mbyte memory range is specified within the 52-bit physical address space, starting at address 200_0000h.
The upper address of the range is 3FF_FFFFh.
Following the process outlined above yields:

1. 3FF_FFFFh-200_0000h = 1FF_FFFFh
2. F_FFFF_FFFF_FFFFh-1_FF_FFFFh = F_FFFF_FE00_0000h
3. Right shift (F_FFFF_FE00_0000h) by 12 = FF_FFFF_E000h

In this example, the 40-bit value loaded into the PhysMask field is FF_FFFF_E000h.

Software must also truncate the lower 12 bits of the physical base address before loading it into the PhysBase field.
In the example above, the 40-bit PhysBase field is 00_0000_2000h

Re: mtrr

Posted: Fri Mar 04, 2011 9:05 pm
by Gigasoft
This mask is chosen so
that when any address in the 200000H to 3FFFFFH range is logically conjugated with the mask
value, it will return the same value as when the base address is logically conjugated with the mask
value (which is 200000H).
FTFY.