0001
0002 #include <linux/init.h>
0003 #include <linux/mm.h>
0004 #include <asm/mtrr.h>
0005 #include <asm/msr.h>
0006
0007 #include "mtrr.h"
0008
0009 static void
0010 amd_get_mtrr(unsigned int reg, unsigned long *base,
0011 unsigned long *size, mtrr_type *type)
0012 {
0013 unsigned long low, high;
0014
0015 rdmsr(MSR_K6_UWCCR, low, high);
0016
0017 if (reg == 1)
0018 low = high;
0019
0020 *base = (low & 0xFFFE0000) >> PAGE_SHIFT;
0021 *type = 0;
0022 if (low & 1)
0023 *type = MTRR_TYPE_UNCACHABLE;
0024 if (low & 2)
0025 *type = MTRR_TYPE_WRCOMB;
0026 if (!(low & 3)) {
0027 *size = 0;
0028 return;
0029 }
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 low = (~low) & 0x1FFFC;
0046 *size = (low + 4) << (15 - PAGE_SHIFT);
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 static void
0060 amd_set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type type)
0061 {
0062 u32 regs[2];
0063
0064
0065
0066
0067 rdmsr(MSR_K6_UWCCR, regs[0], regs[1]);
0068
0069
0070
0071 if (size == 0) {
0072 regs[reg] = 0;
0073 } else {
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 regs[reg] = (-size >> (15 - PAGE_SHIFT) & 0x0001FFFC)
0084 | (base << PAGE_SHIFT) | (type + 1);
0085 }
0086
0087
0088
0089
0090
0091 wbinvd();
0092 wrmsr(MSR_K6_UWCCR, regs[0], regs[1]);
0093 }
0094
0095 static int
0096 amd_validate_add_page(unsigned long base, unsigned long size, unsigned int type)
0097 {
0098
0099
0100
0101
0102
0103
0104
0105
0106 if (type > MTRR_TYPE_WRCOMB || size < (1 << (17 - PAGE_SHIFT))
0107 || (size & ~(size - 1)) - size || (base & (size - 1)))
0108 return -EINVAL;
0109 return 0;
0110 }
0111
0112 static const struct mtrr_ops amd_mtrr_ops = {
0113 .vendor = X86_VENDOR_AMD,
0114 .set = amd_set_mtrr,
0115 .get = amd_get_mtrr,
0116 .get_free_region = generic_get_free_region,
0117 .validate_add_page = amd_validate_add_page,
0118 .have_wrcomb = positive_have_wrcomb,
0119 };
0120
0121 int __init amd_init_mtrr(void)
0122 {
0123 set_mtrr_ops(&amd_mtrr_ops);
0124 return 0;
0125 }