powerpc fixes for 5.16 #2
Fix a bug in copying of sigset_t for 32-bit systems, which caused X to not start. Fix handling of shared LSIs (rare) with the xive interrupt controller (Power9/10). Fix missing TOC setup in some KVM code, which could result in oopses depending on kernel data layout. Fix DMA mapping when we have persistent memory and only one DMA window available. Fix further problems with STRICT_KERNEL_RWX on 8xx, exposed by a recent fix. A couple of other minor fixes. Thanks to: Alexey Kardashevskiy, Aneesh Kumar K.V, Cédric Le Goater, Christian Zigotzky, Christophe Leroy, Daniel Axtens, Finn Thain, Greg Kurz, Masahiro Yamada, Nicholas Piggin, Uwe Kleine-König. -----BEGIN PGP SIGNATURE----- iQJHBAABCAAxFiEEJFGtCPCthwEv2Y/bUevqPMjhpYAFAmGZzGMTHG1wZUBlbGxl cm1hbi5pZC5hdQAKCRBR6+o8yOGlgBrRD/4qE1A3+nXe+uZRJM3H5F8C/Ui2I/1G JPekyfW9aZklsv8SMlz8BotDTlK8vNwiEtkAuwqLOfPXPi1p/Y1do4sPtXAjUpuX mXZP3G9K2xXmALLedXMjJNO6YJjTT5LE7OT42QziSfY1ScS7iqfGNANg1zRjkCRW yf2cpBbMRnWdDhCgWyE/V/V4xdPyOTTnnWn3d4F3qNshV0luKgTJl/9yo0OmQrGe /T4Cw8jG5p+pSblNyFaACnYlKWF4bYTQIl5NWsvJY0A2cg3I5ah6+hexdGRN/JdI K3PWpJ8rx5RjICkTFE4cADI6xIF1bHhjMh3ytcaMH5USBMmW3fTUUfcFwjRkRDHa b8Z6V631mgK1v3L0RlrAn+PZ9R212wpupvQT6YOf4pFb5+BzOyaCQCzyQv+BnwoI Fwran0HEO6NUODq4off9MADEpNTjwhV2mDFojxiCJ9eb1oCIilLbs8BOUWRSHYe0 1S22pdj9XSR7yxXt5DnjQBwhR47ZS7D3jXf9gjbmJ/qn6cRPAFzt/m/woSY2Vv7T UrZVjz5lb+skjij7vxw+L9jUIwLBd99cvBiHzJpWUNc0RTQeBlAh4QBK/1MNixCP 93LTN7tsRdGknLRTJ5yfRhEhwuhTTH8SEPp3H+qOZj9sXwq3Bftl4Nm40AgoATHO G4kPlgrCMQBcRQ== =Ss4y -----END PGP SIGNATURE----- Merge tag 'powerpc-5.16-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux Pull more powerpc fixes from Michael Ellerman: - Fix a bug in copying of sigset_t for 32-bit systems, which caused X to not start. - Fix handling of shared LSIs (rare) with the xive interrupt controller (Power9/10). - Fix missing TOC setup in some KVM code, which could result in oopses depending on kernel data layout. - Fix DMA mapping when we have persistent memory and only one DMA window available. - Fix further problems with STRICT_KERNEL_RWX on 8xx, exposed by a recent fix. - A couple of other minor fixes. Thanks to Alexey Kardashevskiy, Aneesh Kumar K.V, Cédric Le Goater, Christian Zigotzky, Christophe Leroy, Daniel Axtens, Finn Thain, Greg Kurz, Masahiro Yamada, Nicholas Piggin, and Uwe Kleine-König. * tag 'powerpc-5.16-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/xive: Change IRQ domain to a tree domain powerpc/8xx: Fix pinned TLBs with CONFIG_STRICT_KERNEL_RWX powerpc/signal32: Fix sigset_t copy powerpc/book3e: Fix TLBCAM preset at boot powerpc/pseries/ddw: Do not try direct mapping with persistent memory and one window powerpc/pseries/ddw: simplify enable_ddw() powerpc/pseries/ddw: Revert "Extend upper limit for huge DMA window for persistent memory" powerpc/pseries: Fix numa FORM2 parsing fallback code powerpc/pseries: rename numa_dist_table to form2_distances powerpc: clean vdso32 and vdso64 directories powerpc/83xx/mpc8349emitx: Drop unused variable KVM: PPC: Book3S HV: Use GLOBAL_TOC for kvmppc_h_set_dabr/xdabr()
This commit is contained in:
commit
75603b14ed
@ -196,3 +196,6 @@ clean-files := vmlinux.lds
|
||||
# Force dependency (incbin is bad)
|
||||
$(obj)/vdso32_wrapper.o : $(obj)/vdso32/vdso32.so.dbg
|
||||
$(obj)/vdso64_wrapper.o : $(obj)/vdso64/vdso64.so.dbg
|
||||
|
||||
# for cleaning
|
||||
subdir- += vdso32 vdso64
|
||||
|
@ -733,6 +733,7 @@ _GLOBAL(mmu_pin_tlb)
|
||||
#ifdef CONFIG_PIN_TLB_DATA
|
||||
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
|
||||
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
|
||||
li r8, 0
|
||||
#ifdef CONFIG_PIN_TLB_IMMR
|
||||
li r0, 3
|
||||
#else
|
||||
@ -741,26 +742,26 @@ _GLOBAL(mmu_pin_tlb)
|
||||
mtctr r0
|
||||
cmpwi r4, 0
|
||||
beq 4f
|
||||
LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
|
||||
LOAD_REG_ADDR(r9, _sinittext)
|
||||
|
||||
2: ori r0, r6, MD_EVALID
|
||||
ori r12, r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT
|
||||
mtspr SPRN_MD_CTR, r5
|
||||
mtspr SPRN_MD_EPN, r0
|
||||
mtspr SPRN_MD_TWC, r7
|
||||
mtspr SPRN_MD_RPN, r8
|
||||
mtspr SPRN_MD_RPN, r12
|
||||
addi r5, r5, 0x100
|
||||
addis r6, r6, SZ_8M@h
|
||||
addis r8, r8, SZ_8M@h
|
||||
cmplw r6, r9
|
||||
bdnzt lt, 2b
|
||||
|
||||
4: LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
|
||||
4:
|
||||
2: ori r0, r6, MD_EVALID
|
||||
ori r12, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT
|
||||
mtspr SPRN_MD_CTR, r5
|
||||
mtspr SPRN_MD_EPN, r0
|
||||
mtspr SPRN_MD_TWC, r7
|
||||
mtspr SPRN_MD_RPN, r8
|
||||
mtspr SPRN_MD_RPN, r12
|
||||
addi r5, r5, 0x100
|
||||
addis r6, r6, SZ_8M@h
|
||||
addis r8, r8, SZ_8M@h
|
||||
@ -781,7 +782,7 @@ _GLOBAL(mmu_pin_tlb)
|
||||
#endif
|
||||
#if defined(CONFIG_PIN_TLB_IMMR) || defined(CONFIG_PIN_TLB_DATA)
|
||||
lis r0, (MD_RSV4I | MD_TWAM)@h
|
||||
mtspr SPRN_MI_CTR, r0
|
||||
mtspr SPRN_MD_CTR, r0
|
||||
#endif
|
||||
mtspr SPRN_SRR1, r10
|
||||
mtspr SPRN_SRR0, r11
|
||||
|
@ -25,8 +25,14 @@ static inline int __get_user_sigset(sigset_t *dst, const sigset_t __user *src)
|
||||
|
||||
return __get_user(dst->sig[0], (u64 __user *)&src->sig[0]);
|
||||
}
|
||||
#define unsafe_get_user_sigset(dst, src, label) \
|
||||
unsafe_get_user((dst)->sig[0], (u64 __user *)&(src)->sig[0], label)
|
||||
#define unsafe_get_user_sigset(dst, src, label) do { \
|
||||
sigset_t *__dst = dst; \
|
||||
const sigset_t __user *__src = src; \
|
||||
int i; \
|
||||
\
|
||||
for (i = 0; i < _NSIG_WORDS; i++) \
|
||||
unsafe_get_user(__dst->sig[i], &__src->sig[i], label); \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_VSX
|
||||
extern unsigned long copy_vsx_to_user(void __user *to,
|
||||
|
@ -2005,7 +2005,7 @@ hcall_real_table:
|
||||
.globl hcall_real_table_end
|
||||
hcall_real_table_end:
|
||||
|
||||
_GLOBAL(kvmppc_h_set_xdabr)
|
||||
_GLOBAL_TOC(kvmppc_h_set_xdabr)
|
||||
EXPORT_SYMBOL_GPL(kvmppc_h_set_xdabr)
|
||||
andi. r0, r5, DABRX_USER | DABRX_KERNEL
|
||||
beq 6f
|
||||
@ -2015,7 +2015,7 @@ EXPORT_SYMBOL_GPL(kvmppc_h_set_xdabr)
|
||||
6: li r3, H_PARAMETER
|
||||
blr
|
||||
|
||||
_GLOBAL(kvmppc_h_set_dabr)
|
||||
_GLOBAL_TOC(kvmppc_h_set_dabr)
|
||||
EXPORT_SYMBOL_GPL(kvmppc_h_set_dabr)
|
||||
li r5, DABRX_USER | DABRX_KERNEL
|
||||
3:
|
||||
|
@ -314,7 +314,7 @@ static unsigned long __init kaslr_choose_location(void *dt_ptr, phys_addr_t size
|
||||
pr_warn("KASLR: No safe seed for randomizing the kernel base.\n");
|
||||
|
||||
ram = min_t(phys_addr_t, __max_low_memory, size);
|
||||
ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true, false);
|
||||
ram = map_mem_in_cams(ram, CONFIG_LOWMEM_CAM_NUM, true, true);
|
||||
linear_sz = min_t(unsigned long, ram, SZ_512M);
|
||||
|
||||
/* If the linear size is smaller than 64M, do not randmize */
|
||||
|
@ -645,7 +645,7 @@ static void early_init_this_mmu(void)
|
||||
|
||||
if (map)
|
||||
linear_map_top = map_mem_in_cams(linear_map_top,
|
||||
num_cams, true, true);
|
||||
num_cams, false, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -766,7 +766,7 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
|
||||
num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4;
|
||||
|
||||
linear_sz = map_mem_in_cams(first_memblock_size, num_cams,
|
||||
false, true);
|
||||
true, true);
|
||||
|
||||
ppc64_rma_size = min_t(u64, linear_sz, 0x40000000);
|
||||
} else
|
||||
|
@ -376,9 +376,9 @@ static void initialize_form2_numa_distance_lookup_table(void)
|
||||
{
|
||||
int i, j;
|
||||
struct device_node *root;
|
||||
const __u8 *numa_dist_table;
|
||||
const __u8 *form2_distances;
|
||||
const __be32 *numa_lookup_index;
|
||||
int numa_dist_table_length;
|
||||
int form2_distances_length;
|
||||
int max_numa_index, distance_index;
|
||||
|
||||
if (firmware_has_feature(FW_FEATURE_OPAL))
|
||||
@ -392,45 +392,41 @@ static void initialize_form2_numa_distance_lookup_table(void)
|
||||
max_numa_index = of_read_number(&numa_lookup_index[0], 1);
|
||||
|
||||
/* first element of the array is the size and is encode-int */
|
||||
numa_dist_table = of_get_property(root, "ibm,numa-distance-table", NULL);
|
||||
numa_dist_table_length = of_read_number((const __be32 *)&numa_dist_table[0], 1);
|
||||
form2_distances = of_get_property(root, "ibm,numa-distance-table", NULL);
|
||||
form2_distances_length = of_read_number((const __be32 *)&form2_distances[0], 1);
|
||||
/* Skip the size which is encoded int */
|
||||
numa_dist_table += sizeof(__be32);
|
||||
form2_distances += sizeof(__be32);
|
||||
|
||||
pr_debug("numa_dist_table_len = %d, numa_dist_indexes_len = %d\n",
|
||||
numa_dist_table_length, max_numa_index);
|
||||
pr_debug("form2_distances_len = %d, numa_dist_indexes_len = %d\n",
|
||||
form2_distances_length, max_numa_index);
|
||||
|
||||
for (i = 0; i < max_numa_index; i++)
|
||||
/* +1 skip the max_numa_index in the property */
|
||||
numa_id_index_table[i] = of_read_number(&numa_lookup_index[i + 1], 1);
|
||||
|
||||
|
||||
if (numa_dist_table_length != max_numa_index * max_numa_index) {
|
||||
if (form2_distances_length != max_numa_index * max_numa_index) {
|
||||
WARN(1, "Wrong NUMA distance information\n");
|
||||
/* consider everybody else just remote. */
|
||||
for (i = 0; i < max_numa_index; i++) {
|
||||
for (j = 0; j < max_numa_index; j++) {
|
||||
int nodeA = numa_id_index_table[i];
|
||||
int nodeB = numa_id_index_table[j];
|
||||
|
||||
if (nodeA == nodeB)
|
||||
numa_distance_table[nodeA][nodeB] = LOCAL_DISTANCE;
|
||||
else
|
||||
numa_distance_table[nodeA][nodeB] = REMOTE_DISTANCE;
|
||||
}
|
||||
}
|
||||
form2_distances = NULL; // don't use it
|
||||
}
|
||||
|
||||
distance_index = 0;
|
||||
for (i = 0; i < max_numa_index; i++) {
|
||||
for (j = 0; j < max_numa_index; j++) {
|
||||
int nodeA = numa_id_index_table[i];
|
||||
int nodeB = numa_id_index_table[j];
|
||||
int dist;
|
||||
|
||||
numa_distance_table[nodeA][nodeB] = numa_dist_table[distance_index++];
|
||||
pr_debug("dist[%d][%d]=%d ", nodeA, nodeB, numa_distance_table[nodeA][nodeB]);
|
||||
if (form2_distances)
|
||||
dist = form2_distances[distance_index++];
|
||||
else if (nodeA == nodeB)
|
||||
dist = LOCAL_DISTANCE;
|
||||
else
|
||||
dist = REMOTE_DISTANCE;
|
||||
numa_distance_table[nodeA][nodeB] = dist;
|
||||
pr_debug("dist[%d][%d]=%d ", nodeA, nodeB, dist);
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(root);
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,6 @@ err:
|
||||
static int mcu_remove(struct i2c_client *client)
|
||||
{
|
||||
struct mcu *mcu = i2c_get_clientdata(client);
|
||||
int ret;
|
||||
|
||||
kthread_stop(shutdown_thread);
|
||||
|
||||
|
@ -1094,15 +1094,6 @@ static phys_addr_t ddw_memory_hotplug_max(void)
|
||||
phys_addr_t max_addr = memory_hotplug_max();
|
||||
struct device_node *memory;
|
||||
|
||||
/*
|
||||
* The "ibm,pmemory" can appear anywhere in the address space.
|
||||
* Assuming it is still backed by page structs, set the upper limit
|
||||
* for the huge DMA window as MAX_PHYSMEM_BITS.
|
||||
*/
|
||||
if (of_find_node_by_type(NULL, "ibm,pmemory"))
|
||||
return (sizeof(phys_addr_t) * 8 <= MAX_PHYSMEM_BITS) ?
|
||||
(phys_addr_t) -1 : (1ULL << MAX_PHYSMEM_BITS);
|
||||
|
||||
for_each_node_by_type(memory, "memory") {
|
||||
unsigned long start, size;
|
||||
int n_mem_addr_cells, n_mem_size_cells, len;
|
||||
@ -1238,7 +1229,6 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
|
||||
u32 ddw_avail[DDW_APPLICABLE_SIZE];
|
||||
struct dma_win *window;
|
||||
struct property *win64;
|
||||
bool ddw_enabled = false;
|
||||
struct failed_ddw_pdn *fpdn;
|
||||
bool default_win_removed = false, direct_mapping = false;
|
||||
bool pmem_present;
|
||||
@ -1253,7 +1243,6 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
|
||||
|
||||
if (find_existing_ddw(pdn, &dev->dev.archdata.dma_offset, &len)) {
|
||||
direct_mapping = (len >= max_ram_len);
|
||||
ddw_enabled = true;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
@ -1367,8 +1356,10 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
|
||||
len = order_base_2(query.largest_available_block << page_shift);
|
||||
win_name = DMA64_PROPNAME;
|
||||
} else {
|
||||
direct_mapping = true;
|
||||
win_name = DIRECT64_PROPNAME;
|
||||
direct_mapping = !default_win_removed ||
|
||||
(len == MAX_PHYSMEM_BITS) ||
|
||||
(!pmem_present && (len == max_ram_len));
|
||||
win_name = direct_mapping ? DIRECT64_PROPNAME : DMA64_PROPNAME;
|
||||
}
|
||||
|
||||
ret = create_ddw(dev, ddw_avail, &create, page_shift, len);
|
||||
@ -1406,8 +1397,8 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
|
||||
dev_info(&dev->dev, "failed to map DMA window for %pOF: %d\n",
|
||||
dn, ret);
|
||||
|
||||
/* Make sure to clean DDW if any TCE was set*/
|
||||
clean_dma_window(pdn, win64->value);
|
||||
/* Make sure to clean DDW if any TCE was set*/
|
||||
clean_dma_window(pdn, win64->value);
|
||||
goto out_del_list;
|
||||
}
|
||||
} else {
|
||||
@ -1454,7 +1445,6 @@ static bool enable_ddw(struct pci_dev *dev, struct device_node *pdn)
|
||||
spin_unlock(&dma_win_list_lock);
|
||||
|
||||
dev->dev.archdata.dma_offset = win_addr;
|
||||
ddw_enabled = true;
|
||||
goto out_unlock;
|
||||
|
||||
out_del_list:
|
||||
@ -1490,10 +1480,10 @@ out_unlock:
|
||||
* as RAM, then we failed to create a window to cover persistent
|
||||
* memory and need to set the DMA limit.
|
||||
*/
|
||||
if (pmem_present && ddw_enabled && direct_mapping && len == max_ram_len)
|
||||
if (pmem_present && direct_mapping && len == max_ram_len)
|
||||
dev->dev.bus_dma_limit = dev->dev.archdata.dma_offset + (1ULL << len);
|
||||
|
||||
return ddw_enabled && direct_mapping;
|
||||
return direct_mapping;
|
||||
}
|
||||
|
||||
static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
|
||||
|
@ -3,7 +3,6 @@ config PPC_XIVE
|
||||
bool
|
||||
select PPC_SMP_MUXED_IPI
|
||||
select HARDIRQS_SW_RESEND
|
||||
select IRQ_DOMAIN_NOMAP
|
||||
|
||||
config PPC_XIVE_NATIVE
|
||||
bool
|
||||
|
@ -1443,8 +1443,7 @@ static const struct irq_domain_ops xive_irq_domain_ops = {
|
||||
|
||||
static void __init xive_init_host(struct device_node *np)
|
||||
{
|
||||
xive_irq_domain = irq_domain_add_nomap(np, XIVE_MAX_IRQ,
|
||||
&xive_irq_domain_ops, NULL);
|
||||
xive_irq_domain = irq_domain_add_tree(np, &xive_irq_domain_ops, NULL);
|
||||
if (WARN_ON(xive_irq_domain == NULL))
|
||||
return;
|
||||
irq_set_default_host(xive_irq_domain);
|
||||
|
Loading…
Reference in New Issue
Block a user