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

efficeon-agp.c (12501B)


      1/*
      2 * Transmeta's Efficeon AGPGART driver.
      3 *
      4 * Based upon a diff by Linus around November '02.
      5 *
      6 * Ported to the 2.6 kernel by Carlos Puchol <cpglinux@puchol.com>
      7 * and H. Peter Anvin <hpa@transmeta.com>.
      8 */
      9
     10/*
     11 * NOTE-cpg-040217:
     12 *
     13 *   - when compiled as a module, after loading the module,
     14 *     it will refuse to unload, indicating it is in use,
     15 *     when it is not.
     16 *   - no s3 (suspend to ram) testing.
     17 *   - tested on the efficeon integrated nothbridge for tens
     18 *     of iterations of starting x and glxgears.
     19 *   - tested with radeon 9000 and radeon mobility m9 cards
     20 *   - tested with c3/c4 enabled (with the mobility m9 card)
     21 */
     22
     23#include <linux/module.h>
     24#include <linux/pci.h>
     25#include <linux/init.h>
     26#include <linux/agp_backend.h>
     27#include <linux/gfp.h>
     28#include <linux/page-flags.h>
     29#include <linux/mm.h>
     30#include "agp.h"
     31#include "intel-agp.h"
     32
     33/*
     34 * The real differences to the generic AGP code is
     35 * in the GART mappings - a two-level setup with the
     36 * first level being an on-chip 64-entry table.
     37 *
     38 * The page array is filled through the ATTPAGE register
     39 * (Aperture Translation Table Page Register) at 0xB8. Bits:
     40 *  31:20: physical page address
     41 *   11:9: Page Attribute Table Index (PATI)
     42 *	   must match the PAT index for the
     43 *	   mapped pages (the 2nd level page table pages
     44 *	   themselves should be just regular WB-cacheable,
     45 *	   so this is normally zero.)
     46 *      8: Present
     47 *    7:6: reserved, write as zero
     48 *    5:0: GATT directory index: which 1st-level entry
     49 *
     50 * The Efficeon AGP spec requires pages to be WB-cacheable
     51 * but to be explicitly CLFLUSH'd after any changes.
     52 */
     53#define EFFICEON_ATTPAGE	0xb8
     54#define EFFICEON_L1_SIZE	64	/* Number of PDE pages */
     55
     56#define EFFICEON_PATI		(0 << 9)
     57#define EFFICEON_PRESENT	(1 << 8)
     58
     59static struct _efficeon_private {
     60	unsigned long l1_table[EFFICEON_L1_SIZE];
     61} efficeon_private;
     62
     63static const struct gatt_mask efficeon_generic_masks[] =
     64{
     65	{.mask = 0x00000001, .type = 0}
     66};
     67
     68/* This function does the same thing as mask_memory() for this chipset... */
     69static inline unsigned long efficeon_mask_memory(struct page *page)
     70{
     71	unsigned long addr = page_to_phys(page);
     72	return addr | 0x00000001;
     73}
     74
     75static const struct aper_size_info_lvl2 efficeon_generic_sizes[4] =
     76{
     77	{256, 65536, 0},
     78	{128, 32768, 32},
     79	{64, 16384, 48},
     80	{32, 8192, 56}
     81};
     82
     83/*
     84 * Control interfaces are largely identical to
     85 * the legacy Intel 440BX..
     86 */
     87
     88static int efficeon_fetch_size(void)
     89{
     90	int i;
     91	u16 temp;
     92	struct aper_size_info_lvl2 *values;
     93
     94	pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp);
     95	values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes);
     96
     97	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
     98		if (temp == values[i].size_value) {
     99			agp_bridge->previous_size =
    100			    agp_bridge->current_size = (void *) (values + i);
    101			agp_bridge->aperture_size_idx = i;
    102			return values[i].size;
    103		}
    104	}
    105
    106	return 0;
    107}
    108
    109static void efficeon_tlbflush(struct agp_memory * mem)
    110{
    111	printk(KERN_DEBUG PFX "efficeon_tlbflush()\n");
    112	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200);
    113	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
    114}
    115
    116static void efficeon_cleanup(void)
    117{
    118	u16 temp;
    119	struct aper_size_info_lvl2 *previous_size;
    120
    121	printk(KERN_DEBUG PFX "efficeon_cleanup()\n");
    122	previous_size = A_SIZE_LVL2(agp_bridge->previous_size);
    123	pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
    124	pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
    125	pci_write_config_word(agp_bridge->dev, INTEL_APSIZE,
    126			      previous_size->size_value);
    127}
    128
    129static int efficeon_configure(void)
    130{
    131	u16 temp2;
    132	struct aper_size_info_lvl2 *current_size;
    133
    134	printk(KERN_DEBUG PFX "efficeon_configure()\n");
    135
    136	current_size = A_SIZE_LVL2(agp_bridge->current_size);
    137
    138	/* aperture size */
    139	pci_write_config_word(agp_bridge->dev, INTEL_APSIZE,
    140			      current_size->size_value);
    141
    142	/* address to map to */
    143	agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
    144						    AGP_APERTURE_BAR);
    145
    146	/* agpctrl */
    147	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280);
    148
    149	/* paccfg/nbxcfg */
    150	pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2);
    151	pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG,
    152			      (temp2 & ~(1 << 10)) | (1 << 9) | (1 << 11));
    153	/* clear any possible error conditions */
    154	pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7);
    155	return 0;
    156}
    157
    158static int efficeon_free_gatt_table(struct agp_bridge_data *bridge)
    159{
    160	int index, freed = 0;
    161
    162	for (index = 0; index < EFFICEON_L1_SIZE; index++) {
    163		unsigned long page = efficeon_private.l1_table[index];
    164		if (page) {
    165			efficeon_private.l1_table[index] = 0;
    166			free_page(page);
    167			freed++;
    168		}
    169		printk(KERN_DEBUG PFX "efficeon_free_gatt_table(%p, %02x, %08x)\n",
    170			agp_bridge->dev, EFFICEON_ATTPAGE, index);
    171		pci_write_config_dword(agp_bridge->dev,
    172			EFFICEON_ATTPAGE, index);
    173	}
    174	printk(KERN_DEBUG PFX "efficeon_free_gatt_table() freed %d pages\n", freed);
    175	return 0;
    176}
    177
    178
    179/*
    180 * Since we don't need contiguous memory we just try
    181 * to get the gatt table once
    182 */
    183
    184#define GET_PAGE_DIR_OFF(addr) (addr >> 22)
    185#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
    186	GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr))
    187#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
    188#undef  GET_GATT
    189#define GET_GATT(addr) (efficeon_private.gatt_pages[\
    190	GET_PAGE_DIR_IDX(addr)]->remapped)
    191
    192static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
    193{
    194	int index;
    195	const int pati    = EFFICEON_PATI;
    196	const int present = EFFICEON_PRESENT;
    197	const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3;
    198	int num_entries, l1_pages;
    199
    200	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
    201
    202	printk(KERN_DEBUG PFX "efficeon_create_gatt_table(%d)\n", num_entries);
    203
    204	/* There are 2^10 PTE pages per PDE page */
    205	BUG_ON(num_entries & 0x3ff);
    206	l1_pages = num_entries >> 10;
    207
    208	for (index = 0 ; index < l1_pages ; index++) {
    209		int offset;
    210		unsigned long page;
    211		unsigned long value;
    212
    213		page = efficeon_private.l1_table[index];
    214		BUG_ON(page);
    215
    216		page = get_zeroed_page(GFP_KERNEL);
    217		if (!page) {
    218			efficeon_free_gatt_table(agp_bridge);
    219			return -ENOMEM;
    220		}
    221
    222		for (offset = 0; offset < PAGE_SIZE; offset += clflush_chunk)
    223			clflush((char *)page+offset);
    224
    225		efficeon_private.l1_table[index] = page;
    226
    227		value = virt_to_phys((unsigned long *)page) | pati | present | index;
    228
    229		pci_write_config_dword(agp_bridge->dev,
    230			EFFICEON_ATTPAGE, value);
    231	}
    232
    233	return 0;
    234}
    235
    236static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int type)
    237{
    238	int i, count = mem->page_count, num_entries;
    239	unsigned int *page, *last_page;
    240	const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3;
    241	const unsigned long clflush_mask = ~(clflush_chunk-1);
    242
    243	printk(KERN_DEBUG PFX "efficeon_insert_memory(%lx, %d)\n", pg_start, count);
    244
    245	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
    246	if ((pg_start + mem->page_count) > num_entries)
    247		return -EINVAL;
    248	if (type != 0 || mem->type != 0)
    249		return -EINVAL;
    250
    251	if (!mem->is_flushed) {
    252		global_cache_flush();
    253		mem->is_flushed = true;
    254	}
    255
    256	last_page = NULL;
    257	for (i = 0; i < count; i++) {
    258		int index = pg_start + i;
    259		unsigned long insert = efficeon_mask_memory(mem->pages[i]);
    260
    261		page = (unsigned int *) efficeon_private.l1_table[index >> 10];
    262
    263		if (!page)
    264			continue;
    265
    266		page += (index & 0x3ff);
    267		*page = insert;
    268
    269		/* clflush is slow, so don't clflush until we have to */
    270		if (last_page &&
    271		    (((unsigned long)page^(unsigned long)last_page) &
    272		     clflush_mask))
    273			clflush(last_page);
    274
    275		last_page = page;
    276	}
    277
    278	if ( last_page )
    279		clflush(last_page);
    280
    281	agp_bridge->driver->tlb_flush(mem);
    282	return 0;
    283}
    284
    285static int efficeon_remove_memory(struct agp_memory * mem, off_t pg_start, int type)
    286{
    287	int i, count = mem->page_count, num_entries;
    288
    289	printk(KERN_DEBUG PFX "efficeon_remove_memory(%lx, %d)\n", pg_start, count);
    290
    291	num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
    292
    293	if ((pg_start + mem->page_count) > num_entries)
    294		return -EINVAL;
    295	if (type != 0 || mem->type != 0)
    296		return -EINVAL;
    297
    298	for (i = 0; i < count; i++) {
    299		int index = pg_start + i;
    300		unsigned int *page = (unsigned int *) efficeon_private.l1_table[index >> 10];
    301
    302		if (!page)
    303			continue;
    304		page += (index & 0x3ff);
    305		*page = 0;
    306	}
    307	agp_bridge->driver->tlb_flush(mem);
    308	return 0;
    309}
    310
    311
    312static const struct agp_bridge_driver efficeon_driver = {
    313	.owner			= THIS_MODULE,
    314	.aperture_sizes		= efficeon_generic_sizes,
    315	.size_type		= LVL2_APER_SIZE,
    316	.num_aperture_sizes	= 4,
    317	.configure		= efficeon_configure,
    318	.fetch_size		= efficeon_fetch_size,
    319	.cleanup		= efficeon_cleanup,
    320	.tlb_flush		= efficeon_tlbflush,
    321	.mask_memory		= agp_generic_mask_memory,
    322	.masks			= efficeon_generic_masks,
    323	.agp_enable		= agp_generic_enable,
    324	.cache_flush		= global_cache_flush,
    325
    326	// Efficeon-specific GATT table setup / populate / teardown
    327	.create_gatt_table	= efficeon_create_gatt_table,
    328	.free_gatt_table	= efficeon_free_gatt_table,
    329	.insert_memory		= efficeon_insert_memory,
    330	.remove_memory		= efficeon_remove_memory,
    331	.cant_use_aperture	= false,	// true might be faster?
    332
    333	// Generic
    334	.alloc_by_type		= agp_generic_alloc_by_type,
    335	.free_by_type		= agp_generic_free_by_type,
    336	.agp_alloc_page		= agp_generic_alloc_page,
    337	.agp_alloc_pages	= agp_generic_alloc_pages,
    338	.agp_destroy_page	= agp_generic_destroy_page,
    339	.agp_destroy_pages	= agp_generic_destroy_pages,
    340	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
    341};
    342
    343static int agp_efficeon_probe(struct pci_dev *pdev,
    344			      const struct pci_device_id *ent)
    345{
    346	struct agp_bridge_data *bridge;
    347	u8 cap_ptr;
    348	struct resource *r;
    349
    350	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
    351	if (!cap_ptr)
    352		return -ENODEV;
    353
    354	/* Probe for Efficeon controller */
    355	if (pdev->device != PCI_DEVICE_ID_EFFICEON) {
    356		printk(KERN_ERR PFX "Unsupported Efficeon chipset (device id: %04x)\n",
    357		    pdev->device);
    358		return -ENODEV;
    359	}
    360
    361	printk(KERN_INFO PFX "Detected Transmeta Efficeon TM8000 series chipset\n");
    362
    363	bridge = agp_alloc_bridge();
    364	if (!bridge)
    365		return -ENOMEM;
    366
    367	bridge->driver = &efficeon_driver;
    368	bridge->dev = pdev;
    369	bridge->capndx = cap_ptr;
    370
    371	/*
    372	* If the device has not been properly setup, the following will catch
    373	* the problem and should stop the system from crashing.
    374	* 20030610 - hamish@zot.org
    375	*/
    376	if (pci_enable_device(pdev)) {
    377		printk(KERN_ERR PFX "Unable to Enable PCI device\n");
    378		agp_put_bridge(bridge);
    379		return -ENODEV;
    380	}
    381
    382	/*
    383	* The following fixes the case where the BIOS has "forgotten" to
    384	* provide an address range for the GART.
    385	* 20030610 - hamish@zot.org
    386	*/
    387	r = &pdev->resource[0];
    388	if (!r->start && r->end) {
    389		if (pci_assign_resource(pdev, 0)) {
    390			printk(KERN_ERR PFX "could not assign resource 0\n");
    391			agp_put_bridge(bridge);
    392			return -ENODEV;
    393		}
    394	}
    395
    396	/* Fill in the mode register */
    397	if (cap_ptr) {
    398		pci_read_config_dword(pdev,
    399				bridge->capndx+PCI_AGP_STATUS,
    400				&bridge->mode);
    401	}
    402
    403	pci_set_drvdata(pdev, bridge);
    404	return agp_add_bridge(bridge);
    405}
    406
    407static void agp_efficeon_remove(struct pci_dev *pdev)
    408{
    409	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
    410
    411	agp_remove_bridge(bridge);
    412	agp_put_bridge(bridge);
    413}
    414
    415#ifdef CONFIG_PM
    416static int agp_efficeon_suspend(struct pci_dev *dev, pm_message_t state)
    417{
    418	return 0;
    419}
    420
    421static int agp_efficeon_resume(struct pci_dev *pdev)
    422{
    423	printk(KERN_DEBUG PFX "agp_efficeon_resume()\n");
    424	return efficeon_configure();
    425}
    426#endif
    427
    428static const struct pci_device_id agp_efficeon_pci_table[] = {
    429	{
    430	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
    431	.class_mask	= ~0,
    432	.vendor		= PCI_VENDOR_ID_TRANSMETA,
    433	.device		= PCI_ANY_ID,
    434	.subvendor	= PCI_ANY_ID,
    435	.subdevice	= PCI_ANY_ID,
    436	},
    437	{ }
    438};
    439
    440MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table);
    441
    442static struct pci_driver agp_efficeon_pci_driver = {
    443	.name		= "agpgart-efficeon",
    444	.id_table	= agp_efficeon_pci_table,
    445	.probe		= agp_efficeon_probe,
    446	.remove		= agp_efficeon_remove,
    447#ifdef CONFIG_PM
    448	.suspend	= agp_efficeon_suspend,
    449	.resume		= agp_efficeon_resume,
    450#endif
    451};
    452
    453static int __init agp_efficeon_init(void)
    454{
    455	static int agp_initialised=0;
    456
    457	if (agp_off)
    458		return -EINVAL;
    459
    460	if (agp_initialised == 1)
    461		return 0;
    462	agp_initialised=1;
    463
    464	return pci_register_driver(&agp_efficeon_pci_driver);
    465}
    466
    467static void __exit agp_efficeon_cleanup(void)
    468{
    469	pci_unregister_driver(&agp_efficeon_pci_driver);
    470}
    471
    472module_init(agp_efficeon_init);
    473module_exit(agp_efficeon_cleanup);
    474
    475MODULE_AUTHOR("Carlos Puchol <cpglinux@puchol.com>");
    476MODULE_LICENSE("GPL and additional rights");