1*16c0b05fSPeter Xu /* 2*16c0b05fSPeter Xu * Intel IOMMU APIs 3*16c0b05fSPeter Xu * 4*16c0b05fSPeter Xu * Copyright (C) 2016 Red Hat, Inc. 5*16c0b05fSPeter Xu * 6*16c0b05fSPeter Xu * Authors: 7*16c0b05fSPeter Xu * Peter Xu <peterx@redhat.com>, 8*16c0b05fSPeter Xu * 9*16c0b05fSPeter Xu * This work is licensed under the terms of the GNU LGPL, version 2 or 10*16c0b05fSPeter Xu * later. 11*16c0b05fSPeter Xu */ 12*16c0b05fSPeter Xu 13*16c0b05fSPeter Xu #include "intel-iommu.h" 14*16c0b05fSPeter Xu 15*16c0b05fSPeter Xu #define VTD_RTA_MASK (PAGE_MASK) 16*16c0b05fSPeter Xu #define VTD_IRTA_MASK (PAGE_MASK) 17*16c0b05fSPeter Xu 18*16c0b05fSPeter Xu void *vtd_reg_base; 19*16c0b05fSPeter Xu 20*16c0b05fSPeter Xu static uint64_t vtd_root_table(void) 21*16c0b05fSPeter Xu { 22*16c0b05fSPeter Xu /* No extend root table support yet */ 23*16c0b05fSPeter Xu return vtd_readq(DMAR_RTADDR_REG) & VTD_RTA_MASK; 24*16c0b05fSPeter Xu } 25*16c0b05fSPeter Xu 26*16c0b05fSPeter Xu static uint64_t vtd_ir_table(void) 27*16c0b05fSPeter Xu { 28*16c0b05fSPeter Xu return vtd_readq(DMAR_IRTA_REG) & VTD_IRTA_MASK; 29*16c0b05fSPeter Xu } 30*16c0b05fSPeter Xu 31*16c0b05fSPeter Xu static void vtd_gcmd_or(uint32_t cmd) 32*16c0b05fSPeter Xu { 33*16c0b05fSPeter Xu uint32_t status; 34*16c0b05fSPeter Xu 35*16c0b05fSPeter Xu /* We only allow set one bit for each time */ 36*16c0b05fSPeter Xu assert(is_power_of_2(cmd)); 37*16c0b05fSPeter Xu 38*16c0b05fSPeter Xu status = vtd_readl(DMAR_GSTS_REG); 39*16c0b05fSPeter Xu vtd_writel(DMAR_GCMD_REG, status | cmd); 40*16c0b05fSPeter Xu 41*16c0b05fSPeter Xu if (cmd & VTD_GCMD_ONE_SHOT_BITS) { 42*16c0b05fSPeter Xu /* One-shot bits are taking effect immediately */ 43*16c0b05fSPeter Xu return; 44*16c0b05fSPeter Xu } 45*16c0b05fSPeter Xu 46*16c0b05fSPeter Xu /* Make sure IOMMU handled our command request */ 47*16c0b05fSPeter Xu while (!(vtd_readl(DMAR_GSTS_REG) & cmd)) 48*16c0b05fSPeter Xu cpu_relax(); 49*16c0b05fSPeter Xu } 50*16c0b05fSPeter Xu 51*16c0b05fSPeter Xu static void vtd_dump_init_info(void) 52*16c0b05fSPeter Xu { 53*16c0b05fSPeter Xu uint32_t version; 54*16c0b05fSPeter Xu 55*16c0b05fSPeter Xu version = vtd_readl(DMAR_VER_REG); 56*16c0b05fSPeter Xu 57*16c0b05fSPeter Xu /* Major version >= 1 */ 58*16c0b05fSPeter Xu assert(((version >> 3) & 0xf) >= 1); 59*16c0b05fSPeter Xu 60*16c0b05fSPeter Xu printf("VT-d version: 0x%x\n", version); 61*16c0b05fSPeter Xu printf(" cap: 0x%016lx\n", vtd_readq(DMAR_CAP_REG)); 62*16c0b05fSPeter Xu printf(" ecap: 0x%016lx\n", vtd_readq(DMAR_ECAP_REG)); 63*16c0b05fSPeter Xu } 64*16c0b05fSPeter Xu 65*16c0b05fSPeter Xu static void vtd_setup_root_table(void) 66*16c0b05fSPeter Xu { 67*16c0b05fSPeter Xu void *root = alloc_page(); 68*16c0b05fSPeter Xu 69*16c0b05fSPeter Xu memset(root, 0, PAGE_SIZE); 70*16c0b05fSPeter Xu vtd_writeq(DMAR_RTADDR_REG, virt_to_phys(root)); 71*16c0b05fSPeter Xu vtd_gcmd_or(VTD_GCMD_ROOT); 72*16c0b05fSPeter Xu printf("DMAR table address: 0x%016lx\n", vtd_root_table()); 73*16c0b05fSPeter Xu } 74*16c0b05fSPeter Xu 75*16c0b05fSPeter Xu static void vtd_setup_ir_table(void) 76*16c0b05fSPeter Xu { 77*16c0b05fSPeter Xu void *root = alloc_page(); 78*16c0b05fSPeter Xu 79*16c0b05fSPeter Xu memset(root, 0, PAGE_SIZE); 80*16c0b05fSPeter Xu /* 0xf stands for table size (2^(0xf+1) == 65536) */ 81*16c0b05fSPeter Xu vtd_writeq(DMAR_IRTA_REG, virt_to_phys(root) | 0xf); 82*16c0b05fSPeter Xu vtd_gcmd_or(VTD_GCMD_IR_TABLE); 83*16c0b05fSPeter Xu printf("IR table address: 0x%016lx\n", vtd_ir_table()); 84*16c0b05fSPeter Xu } 85*16c0b05fSPeter Xu 86*16c0b05fSPeter Xu void vtd_init(void) 87*16c0b05fSPeter Xu { 88*16c0b05fSPeter Xu setup_vm(); 89*16c0b05fSPeter Xu smp_init(); 90*16c0b05fSPeter Xu 91*16c0b05fSPeter Xu vtd_reg_base = ioremap(Q35_HOST_BRIDGE_IOMMU_ADDR, PAGE_SIZE); 92*16c0b05fSPeter Xu 93*16c0b05fSPeter Xu vtd_dump_init_info(); 94*16c0b05fSPeter Xu vtd_gcmd_or(VTD_GCMD_QI); /* Enable QI */ 95*16c0b05fSPeter Xu vtd_setup_root_table(); 96*16c0b05fSPeter Xu vtd_setup_ir_table(); 97*16c0b05fSPeter Xu vtd_gcmd_or(VTD_GCMD_DMAR); /* Enable DMAR */ 98*16c0b05fSPeter Xu vtd_gcmd_or(VTD_GCMD_IR); /* Enable IR */ 99*16c0b05fSPeter Xu } 100