cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ali-agp.c (10282B)


      1/*
      2 * ALi AGPGART routines.
      3 */
      4
      5#include <linux/types.h>
      6#include <linux/module.h>
      7#include <linux/pci.h>
      8#include <linux/init.h>
      9#include <linux/agp_backend.h>
     10#include <asm/page.h>		/* PAGE_SIZE */
     11#include "agp.h"
     12
     13#define ALI_AGPCTRL	0xb8
     14#define ALI_ATTBASE	0xbc
     15#define ALI_TLBCTRL	0xc0
     16#define ALI_TAGCTRL	0xc4
     17#define ALI_CACHE_FLUSH_CTRL	0xD0
     18#define ALI_CACHE_FLUSH_ADDR_MASK	0xFFFFF000
     19#define ALI_CACHE_FLUSH_EN	0x100
     20
     21static int ali_fetch_size(void)
     22{
     23	int i;
     24	u32 temp;
     25	struct aper_size_info_32 *values;
     26
     27	pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp);
     28	temp &= ~(0xfffffff0);
     29	values = A_SIZE_32(agp_bridge->driver->aperture_sizes);
     30
     31	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
     32		if (temp == values[i].size_value) {
     33			agp_bridge->previous_size =
     34			    agp_bridge->current_size = (void *) (values + i);
     35			agp_bridge->aperture_size_idx = i;
     36			return values[i].size;
     37		}
     38	}
     39
     40	return 0;
     41}
     42
     43static void ali_tlbflush(struct agp_memory *mem)
     44{
     45	u32 temp;
     46
     47	pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp);
     48	temp &= 0xfffffff0;
     49	temp |= (1<<0 | 1<<1);
     50	pci_write_config_dword(agp_bridge->dev, ALI_TAGCTRL, temp);
     51}
     52
     53static void ali_cleanup(void)
     54{
     55	struct aper_size_info_32 *previous_size;
     56	u32 temp;
     57
     58	previous_size = A_SIZE_32(agp_bridge->previous_size);
     59
     60	pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp);
     61// clear tag
     62	pci_write_config_dword(agp_bridge->dev, ALI_TAGCTRL,
     63			((temp & 0xffffff00) | 0x00000001|0x00000002));
     64
     65	pci_read_config_dword(agp_bridge->dev,  ALI_ATTBASE, &temp);
     66	pci_write_config_dword(agp_bridge->dev, ALI_ATTBASE,
     67			((temp & 0x00000ff0) | previous_size->size_value));
     68}
     69
     70static int ali_configure(void)
     71{
     72	u32 temp;
     73	struct aper_size_info_32 *current_size;
     74
     75	current_size = A_SIZE_32(agp_bridge->current_size);
     76
     77	/* aperture size and gatt addr */
     78	pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp);
     79	temp = (((temp & 0x00000ff0) | (agp_bridge->gatt_bus_addr & 0xfffff000))
     80			| (current_size->size_value & 0xf));
     81	pci_write_config_dword(agp_bridge->dev, ALI_ATTBASE, temp);
     82
     83	/* tlb control */
     84	pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp);
     85	pci_write_config_dword(agp_bridge->dev, ALI_TLBCTRL, ((temp & 0xffffff00) | 0x00000010));
     86
     87	/* address to map to */
     88	agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
     89						    AGP_APERTURE_BAR);
     90
     91#if 0
     92	if (agp_bridge->type == ALI_M1541) {
     93		u32 nlvm_addr = 0;
     94
     95		switch (current_size->size_value) {
     96			case 0:  break;
     97			case 1:  nlvm_addr = 0x100000;break;
     98			case 2:  nlvm_addr = 0x200000;break;
     99			case 3:  nlvm_addr = 0x400000;break;
    100			case 4:  nlvm_addr = 0x800000;break;
    101			case 6:  nlvm_addr = 0x1000000;break;
    102			case 7:  nlvm_addr = 0x2000000;break;
    103			case 8:  nlvm_addr = 0x4000000;break;
    104			case 9:  nlvm_addr = 0x8000000;break;
    105			case 10: nlvm_addr = 0x10000000;break;
    106			default: break;
    107		}
    108		nlvm_addr--;
    109		nlvm_addr&=0xfff00000;
    110
    111		nlvm_addr+= agp_bridge->gart_bus_addr;
    112		nlvm_addr|=(agp_bridge->gart_bus_addr>>12);
    113		dev_info(&agp_bridge->dev->dev, "nlvm top &base = %8x\n",
    114			 nlvm_addr);
    115	}
    116#endif
    117
    118	pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp);
    119	temp &= 0xffffff7f;		//enable TLB
    120	pci_write_config_dword(agp_bridge->dev, ALI_TLBCTRL, temp);
    121
    122	return 0;
    123}
    124
    125
    126static void m1541_cache_flush(void)
    127{
    128	int i, page_count;
    129	u32 temp;
    130
    131	global_cache_flush();
    132
    133	page_count = 1 << A_SIZE_32(agp_bridge->current_size)->page_order;
    134	for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) {
    135		pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
    136				&temp);
    137		pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
    138				(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
    139				  (agp_bridge->gatt_bus_addr + i)) |
    140				 ALI_CACHE_FLUSH_EN));
    141	}
    142}
    143
    144static struct page *m1541_alloc_page(struct agp_bridge_data *bridge)
    145{
    146	struct page *page = agp_generic_alloc_page(agp_bridge);
    147	u32 temp;
    148
    149	if (!page)
    150		return NULL;
    151
    152	pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
    153	pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
    154			(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
    155			  page_to_phys(page)) | ALI_CACHE_FLUSH_EN ));
    156	return page;
    157}
    158
    159static void ali_destroy_page(struct page *page, int flags)
    160{
    161	if (page) {
    162		if (flags & AGP_PAGE_DESTROY_UNMAP) {
    163			global_cache_flush();	/* is this really needed?  --hch */
    164			agp_generic_destroy_page(page, flags);
    165		} else
    166			agp_generic_destroy_page(page, flags);
    167	}
    168}
    169
    170static void m1541_destroy_page(struct page *page, int flags)
    171{
    172	u32 temp;
    173
    174	if (page == NULL)
    175		return;
    176
    177	if (flags & AGP_PAGE_DESTROY_UNMAP) {
    178		global_cache_flush();
    179
    180		pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
    181		pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
    182				       (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
    183					 page_to_phys(page)) | ALI_CACHE_FLUSH_EN));
    184	}
    185	agp_generic_destroy_page(page, flags);
    186}
    187
    188
    189/* Setup function */
    190
    191static const struct aper_size_info_32 ali_generic_sizes[7] =
    192{
    193	{256, 65536, 6, 10},
    194	{128, 32768, 5, 9},
    195	{64, 16384, 4, 8},
    196	{32, 8192, 3, 7},
    197	{16, 4096, 2, 6},
    198	{8, 2048, 1, 4},
    199	{4, 1024, 0, 3}
    200};
    201
    202static const struct agp_bridge_driver ali_generic_bridge = {
    203	.owner			= THIS_MODULE,
    204	.aperture_sizes		= ali_generic_sizes,
    205	.size_type		= U32_APER_SIZE,
    206	.num_aperture_sizes	= 7,
    207	.needs_scratch_page	= true,
    208	.configure		= ali_configure,
    209	.fetch_size		= ali_fetch_size,
    210	.cleanup		= ali_cleanup,
    211	.tlb_flush		= ali_tlbflush,
    212	.mask_memory		= agp_generic_mask_memory,
    213	.masks			= NULL,
    214	.agp_enable		= agp_generic_enable,
    215	.cache_flush		= global_cache_flush,
    216	.create_gatt_table	= agp_generic_create_gatt_table,
    217	.free_gatt_table	= agp_generic_free_gatt_table,
    218	.insert_memory		= agp_generic_insert_memory,
    219	.remove_memory		= agp_generic_remove_memory,
    220	.alloc_by_type		= agp_generic_alloc_by_type,
    221	.free_by_type		= agp_generic_free_by_type,
    222	.agp_alloc_page		= agp_generic_alloc_page,
    223	.agp_destroy_page	= ali_destroy_page,
    224	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
    225};
    226
    227static const struct agp_bridge_driver ali_m1541_bridge = {
    228	.owner			= THIS_MODULE,
    229	.aperture_sizes		= ali_generic_sizes,
    230	.size_type		= U32_APER_SIZE,
    231	.num_aperture_sizes	= 7,
    232	.configure		= ali_configure,
    233	.fetch_size		= ali_fetch_size,
    234	.cleanup		= ali_cleanup,
    235	.tlb_flush		= ali_tlbflush,
    236	.mask_memory		= agp_generic_mask_memory,
    237	.masks			= NULL,
    238	.agp_enable		= agp_generic_enable,
    239	.cache_flush		= m1541_cache_flush,
    240	.create_gatt_table	= agp_generic_create_gatt_table,
    241	.free_gatt_table	= agp_generic_free_gatt_table,
    242	.insert_memory		= agp_generic_insert_memory,
    243	.remove_memory		= agp_generic_remove_memory,
    244	.alloc_by_type		= agp_generic_alloc_by_type,
    245	.free_by_type		= agp_generic_free_by_type,
    246	.agp_alloc_page		= m1541_alloc_page,
    247	.agp_destroy_page	= m1541_destroy_page,
    248	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
    249};
    250
    251
    252static struct agp_device_ids ali_agp_device_ids[] =
    253{
    254	{
    255		.device_id	= PCI_DEVICE_ID_AL_M1541,
    256		.chipset_name	= "M1541",
    257	},
    258	{
    259		.device_id	= PCI_DEVICE_ID_AL_M1621,
    260		.chipset_name	= "M1621",
    261	},
    262	{
    263		.device_id	= PCI_DEVICE_ID_AL_M1631,
    264		.chipset_name	= "M1631",
    265	},
    266	{
    267		.device_id	= PCI_DEVICE_ID_AL_M1632,
    268		.chipset_name	= "M1632",
    269	},
    270	{
    271		.device_id	= PCI_DEVICE_ID_AL_M1641,
    272		.chipset_name	= "M1641",
    273	},
    274	{
    275		.device_id	= PCI_DEVICE_ID_AL_M1644,
    276		.chipset_name	= "M1644",
    277	},
    278	{
    279		.device_id	= PCI_DEVICE_ID_AL_M1647,
    280		.chipset_name	= "M1647",
    281	},
    282	{
    283		.device_id	= PCI_DEVICE_ID_AL_M1651,
    284		.chipset_name	= "M1651",
    285	},
    286	{
    287		.device_id	= PCI_DEVICE_ID_AL_M1671,
    288		.chipset_name	= "M1671",
    289	},
    290	{
    291		.device_id	= PCI_DEVICE_ID_AL_M1681,
    292		.chipset_name	= "M1681",
    293	},
    294	{
    295		.device_id	= PCI_DEVICE_ID_AL_M1683,
    296		.chipset_name	= "M1683",
    297	},
    298
    299	{ }, /* dummy final entry, always present */
    300};
    301
    302static int agp_ali_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
    303{
    304	struct agp_device_ids *devs = ali_agp_device_ids;
    305	struct agp_bridge_data *bridge;
    306	u8 hidden_1621_id, cap_ptr;
    307	int j;
    308
    309	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
    310	if (!cap_ptr)
    311		return -ENODEV;
    312
    313	/* probe for known chipsets */
    314	for (j = 0; devs[j].chipset_name; j++) {
    315		if (pdev->device == devs[j].device_id)
    316			goto found;
    317	}
    318
    319	dev_err(&pdev->dev, "unsupported ALi chipset [%04x/%04x])\n",
    320		pdev->vendor, pdev->device);
    321	return -ENODEV;
    322
    323
    324found:
    325	bridge = agp_alloc_bridge();
    326	if (!bridge)
    327		return -ENOMEM;
    328
    329	bridge->dev = pdev;
    330	bridge->capndx = cap_ptr;
    331
    332	switch (pdev->device) {
    333	case PCI_DEVICE_ID_AL_M1541:
    334		bridge->driver = &ali_m1541_bridge;
    335		break;
    336	case PCI_DEVICE_ID_AL_M1621:
    337		pci_read_config_byte(pdev, 0xFB, &hidden_1621_id);
    338		switch (hidden_1621_id) {
    339		case 0x31:
    340			devs[j].chipset_name = "M1631";
    341			break;
    342		case 0x32:
    343			devs[j].chipset_name = "M1632";
    344			break;
    345		case 0x41:
    346			devs[j].chipset_name = "M1641";
    347			break;
    348		case 0x43:
    349			devs[j].chipset_name = "M1621";
    350			break;
    351		case 0x47:
    352			devs[j].chipset_name = "M1647";
    353			break;
    354		case 0x51:
    355			devs[j].chipset_name = "M1651";
    356			break;
    357		default:
    358			break;
    359		}
    360		fallthrough;
    361	default:
    362		bridge->driver = &ali_generic_bridge;
    363	}
    364
    365	dev_info(&pdev->dev, "ALi %s chipset\n", devs[j].chipset_name);
    366
    367	/* Fill in the mode register */
    368	pci_read_config_dword(pdev,
    369			bridge->capndx+PCI_AGP_STATUS,
    370			&bridge->mode);
    371
    372	pci_set_drvdata(pdev, bridge);
    373	return agp_add_bridge(bridge);
    374}
    375
    376static void agp_ali_remove(struct pci_dev *pdev)
    377{
    378	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
    379
    380	agp_remove_bridge(bridge);
    381	agp_put_bridge(bridge);
    382}
    383
    384static const struct pci_device_id agp_ali_pci_table[] = {
    385	{
    386	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
    387	.class_mask	= ~0,
    388	.vendor		= PCI_VENDOR_ID_AL,
    389	.device		= PCI_ANY_ID,
    390	.subvendor	= PCI_ANY_ID,
    391	.subdevice	= PCI_ANY_ID,
    392	},
    393	{ }
    394};
    395
    396MODULE_DEVICE_TABLE(pci, agp_ali_pci_table);
    397
    398static struct pci_driver agp_ali_pci_driver = {
    399	.name		= "agpgart-ali",
    400	.id_table	= agp_ali_pci_table,
    401	.probe		= agp_ali_probe,
    402	.remove		= agp_ali_remove,
    403};
    404
    405static int __init agp_ali_init(void)
    406{
    407	if (agp_off)
    408		return -EINVAL;
    409	return pci_register_driver(&agp_ali_pci_driver);
    410}
    411
    412static void __exit agp_ali_cleanup(void)
    413{
    414	pci_unregister_driver(&agp_ali_pci_driver);
    415}
    416
    417module_init(agp_ali_init);
    418module_exit(agp_ali_cleanup);
    419
    420MODULE_AUTHOR("Dave Jones");
    421MODULE_LICENSE("GPL and additional rights");
    422