Merge 4.19-rc6 into usb-next

We want the USB fixes in here as well.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Greg Kroah-Hartman 2018-09-30 08:09:14 -07:00
commit 29f79155b9
453 changed files with 4145 additions and 2280 deletions

View File

@ -1,4 +1,4 @@
Device-Tree bindings for input/gpio_keys.c keyboard driver Device-Tree bindings for input/keyboard/gpio_keys.c keyboard driver
Required properties: Required properties:
- compatible = "gpio-keys"; - compatible = "gpio-keys";

View File

@ -10,6 +10,7 @@ Required properties:
Use "cdns,pc302-gem" for Picochip picoXcell pc302 and later devices based on Use "cdns,pc302-gem" for Picochip picoXcell pc302 and later devices based on
the Cadence GEM, or the generic form: "cdns,gem". the Cadence GEM, or the generic form: "cdns,gem".
Use "atmel,sama5d2-gem" for the GEM IP (10/100) available on Atmel sama5d2 SoCs. Use "atmel,sama5d2-gem" for the GEM IP (10/100) available on Atmel sama5d2 SoCs.
Use "atmel,sama5d3-macb" for the 10/100Mbit IP available on Atmel sama5d3 SoCs.
Use "atmel,sama5d3-gem" for the Gigabit IP available on Atmel sama5d3 SoCs. Use "atmel,sama5d3-gem" for the Gigabit IP available on Atmel sama5d3 SoCs.
Use "atmel,sama5d4-gem" for the GEM IP (10/100) available on Atmel sama5d4 SoCs. Use "atmel,sama5d4-gem" for the GEM IP (10/100) available on Atmel sama5d4 SoCs.
Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC. Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.

View File

@ -33,4 +33,3 @@ Video Function Calls
video-clear-buffer video-clear-buffer
video-set-streamtype video-set-streamtype
video-set-format video-set-format
video-set-attributes

View File

@ -4510,7 +4510,8 @@ Do not enable KVM_FEATURE_PV_UNHALT if you disable HLT exits.
Architectures: s390 Architectures: s390
Parameters: none Parameters: none
Returns: 0 on success, -EINVAL if hpage module parameter was not set Returns: 0 on success, -EINVAL if hpage module parameter was not set
or cmma is enabled or cmma is enabled, or the VM has the KVM_VM_S390_UCONTROL
flag set
With this capability the KVM support for memory backing with 1m pages With this capability the KVM support for memory backing with 1m pages
through hugetlbfs can be enabled for a VM. After the capability is through hugetlbfs can be enabled for a VM. After the capability is
@ -4521,6 +4522,15 @@ hpage module parameter is not set to 1, -EINVAL is returned.
While it is generally possible to create a huge page backed VM without While it is generally possible to create a huge page backed VM without
this capability, the VM will not be able to run. this capability, the VM will not be able to run.
7.14 KVM_CAP_MSR_PLATFORM_INFO
Architectures: x86
Parameters: args[0] whether feature should be enabled or not
With this capability, a guest may read the MSR_PLATFORM_INFO MSR. Otherwise,
a #GP would be raised when the guest tries to access. Currently, this
capability does not enable write permissions of this MSR for the guest.
8. Other capabilities. 8. Other capabilities.
---------------------- ----------------------

View File

@ -9716,13 +9716,6 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/
S: Maintained S: Maintained
F: drivers/media/dvb-frontends/mn88473* F: drivers/media/dvb-frontends/mn88473*
PCI DRIVER FOR MOBIVEIL PCIE IP
M: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt
F: drivers/pci/controller/pcie-mobiveil.c
MODULE SUPPORT MODULE SUPPORT
M: Jessica Yu <jeyu@kernel.org> M: Jessica Yu <jeyu@kernel.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux.git modules-next T: git git://git.kernel.org/pub/scm/linux/kernel/git/jeyu/linux.git modules-next
@ -10949,7 +10942,7 @@ M: Willy Tarreau <willy@haproxy.com>
M: Ksenija Stanojevic <ksenija.stanojevic@gmail.com> M: Ksenija Stanojevic <ksenija.stanojevic@gmail.com>
S: Odd Fixes S: Odd Fixes
F: Documentation/auxdisplay/lcd-panel-cgram.txt F: Documentation/auxdisplay/lcd-panel-cgram.txt
F: drivers/misc/panel.c F: drivers/auxdisplay/panel.c
PARALLEL PORT SUBSYSTEM PARALLEL PORT SUBSYSTEM
M: Sudip Mukherjee <sudipm.mukherjee@gmail.com> M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
@ -11137,6 +11130,13 @@ F: include/uapi/linux/switchtec_ioctl.h
F: include/linux/switchtec.h F: include/linux/switchtec.h
F: drivers/ntb/hw/mscc/ F: drivers/ntb/hw/mscc/
PCI DRIVER FOR MOBIVEIL PCIE IP
M: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt
F: drivers/pci/controller/pcie-mobiveil.c
PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support) PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
M: Jason Cooper <jason@lakedaemon.net> M: Jason Cooper <jason@lakedaemon.net>
@ -11203,8 +11203,14 @@ F: tools/pci/
PCI ENHANCED ERROR HANDLING (EEH) FOR POWERPC PCI ENHANCED ERROR HANDLING (EEH) FOR POWERPC
M: Russell Currey <ruscur@russell.cc> M: Russell Currey <ruscur@russell.cc>
M: Sam Bobroff <sbobroff@linux.ibm.com>
M: Oliver O'Halloran <oohall@gmail.com>
L: linuxppc-dev@lists.ozlabs.org L: linuxppc-dev@lists.ozlabs.org
S: Supported S: Supported
F: Documentation/PCI/pci-error-recovery.txt
F: drivers/pci/pcie/aer.c
F: drivers/pci/pcie/dpc.c
F: drivers/pci/pcie/err.c
F: Documentation/powerpc/eeh-pci-error-recovery.txt F: Documentation/powerpc/eeh-pci-error-recovery.txt
F: arch/powerpc/kernel/eeh*.c F: arch/powerpc/kernel/eeh*.c
F: arch/powerpc/platforms/*/eeh*.c F: arch/powerpc/platforms/*/eeh*.c
@ -12260,6 +12266,7 @@ F: Documentation/networking/rds.txt
RDT - RESOURCE ALLOCATION RDT - RESOURCE ALLOCATION
M: Fenghua Yu <fenghua.yu@intel.com> M: Fenghua Yu <fenghua.yu@intel.com>
M: Reinette Chatre <reinette.chatre@intel.com>
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
S: Supported S: Supported
F: arch/x86/kernel/cpu/intel_rdt* F: arch/x86/kernel/cpu/intel_rdt*
@ -13449,9 +13456,8 @@ F: drivers/i2c/busses/i2c-synquacer.c
F: Documentation/devicetree/bindings/i2c/i2c-synquacer.txt F: Documentation/devicetree/bindings/i2c/i2c-synquacer.txt
SOCIONEXT UNIPHIER SOUND DRIVER SOCIONEXT UNIPHIER SOUND DRIVER
M: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Maintained S: Orphan
F: sound/soc/uniphier/ F: sound/soc/uniphier/
SOEKRIS NET48XX LED SUPPORT SOEKRIS NET48XX LED SUPPORT
@ -15919,6 +15925,7 @@ F: net/x25/
X86 ARCHITECTURE (32-BIT AND 64-BIT) X86 ARCHITECTURE (32-BIT AND 64-BIT)
M: Thomas Gleixner <tglx@linutronix.de> M: Thomas Gleixner <tglx@linutronix.de>
M: Ingo Molnar <mingo@redhat.com> M: Ingo Molnar <mingo@redhat.com>
M: Borislav Petkov <bp@alien8.de>
R: "H. Peter Anvin" <hpa@zytor.com> R: "H. Peter Anvin" <hpa@zytor.com>
M: x86@kernel.org M: x86@kernel.org
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
@ -15947,6 +15954,15 @@ M: Borislav Petkov <bp@alien8.de>
S: Maintained S: Maintained
F: arch/x86/kernel/cpu/microcode/* F: arch/x86/kernel/cpu/microcode/*
X86 MM
M: Dave Hansen <dave.hansen@linux.intel.com>
M: Andy Lutomirski <luto@kernel.org>
M: Peter Zijlstra <peterz@infradead.org>
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/mm
S: Maintained
F: arch/x86/mm/
X86 PLATFORM DRIVERS X86 PLATFORM DRIVERS
M: Darren Hart <dvhart@infradead.org> M: Darren Hart <dvhart@infradead.org>
M: Andy Shevchenko <andy@infradead.org> M: Andy Shevchenko <andy@infradead.org>

View File

@ -2,7 +2,7 @@
VERSION = 4 VERSION = 4
PATCHLEVEL = 19 PATCHLEVEL = 19
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -rc4 EXTRAVERSION = -rc6
NAME = Merciless Moray NAME = Merciless Moray
# *DOCUMENTATION* # *DOCUMENTATION*
@ -299,19 +299,7 @@ KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
# SUBARCH tells the usermode build what the underlying arch is. That is set include scripts/subarch.include
# first, and if a usermode build is happening, the "ARCH=um" on the command
# line overrides the setting of ARCH below. If a native build is happening,
# then ARCH is assigned, getting whatever value it gets normally, and
# SUBARCH is subsequently ignored.
SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
-e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
-e s/riscv.*/riscv/)
# Cross compiling and selecting different set of gcc/bin-utils # Cross compiling and selecting different set of gcc/bin-utils
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@ -41,7 +41,7 @@ macb1_clk: macb1_clk {
}; };
macb1: ethernet@f802c000 { macb1: ethernet@f802c000 {
compatible = "cdns,at91sam9260-macb", "cdns,macb"; compatible = "atmel,sama5d3-macb", "cdns,at91sam9260-macb", "cdns,macb";
reg = <0xf802c000 0x100>; reg = <0xf802c000 0x100>;
interrupts = <35 IRQ_TYPE_LEVEL_HIGH 3>; interrupts = <35 IRQ_TYPE_LEVEL_HIGH 3>;
pinctrl-names = "default"; pinctrl-names = "default";

View File

@ -1051,7 +1051,6 @@ static inline void vmemmap_remove_mapping(unsigned long start,
return hash__vmemmap_remove_mapping(start, page_size); return hash__vmemmap_remove_mapping(start, page_size);
} }
#endif #endif
struct page *realmode_pfn_to_page(unsigned long pfn);
static inline pte_t pmd_pte(pmd_t pmd) static inline pte_t pmd_pte(pmd_t pmd)
{ {

View File

@ -220,8 +220,6 @@ extern void iommu_del_device(struct device *dev);
extern int __init tce_iommu_bus_notifier_init(void); extern int __init tce_iommu_bus_notifier_init(void);
extern long iommu_tce_xchg(struct iommu_table *tbl, unsigned long entry, extern long iommu_tce_xchg(struct iommu_table *tbl, unsigned long entry,
unsigned long *hpa, enum dma_data_direction *direction); unsigned long *hpa, enum dma_data_direction *direction);
extern long iommu_tce_xchg_rm(struct iommu_table *tbl, unsigned long entry,
unsigned long *hpa, enum dma_data_direction *direction);
#else #else
static inline void iommu_register_group(struct iommu_table_group *table_group, static inline void iommu_register_group(struct iommu_table_group *table_group,
int pci_domain_number, int pci_domain_number,

View File

@ -38,6 +38,7 @@ extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
unsigned long ua, unsigned int pageshift, unsigned long *hpa); unsigned long ua, unsigned int pageshift, unsigned long *hpa);
extern long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem, extern long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
unsigned long ua, unsigned int pageshift, unsigned long *hpa); unsigned long ua, unsigned int pageshift, unsigned long *hpa);
extern void mm_iommu_ua_mark_dirty_rm(struct mm_struct *mm, unsigned long ua);
extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem); extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem);
extern void mm_iommu_mapped_dec(struct mm_iommu_table_group_mem_t *mem); extern void mm_iommu_mapped_dec(struct mm_iommu_table_group_mem_t *mem);
#endif #endif

View File

@ -9,6 +9,7 @@ extern void ppc_printk_progress(char *s, unsigned short hex);
extern unsigned int rtas_data; extern unsigned int rtas_data;
extern unsigned long long memory_limit; extern unsigned long long memory_limit;
extern bool init_mem_is_free;
extern unsigned long klimit; extern unsigned long klimit;
extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);

View File

@ -1314,9 +1314,7 @@ EXC_REAL_BEGIN(denorm_exception_hv, 0x1500, 0x100)
#ifdef CONFIG_PPC_DENORMALISATION #ifdef CONFIG_PPC_DENORMALISATION
mfspr r10,SPRN_HSRR1 mfspr r10,SPRN_HSRR1
mfspr r11,SPRN_HSRR0 /* save HSRR0 */
andis. r10,r10,(HSRR1_DENORM)@h /* denorm? */ andis. r10,r10,(HSRR1_DENORM)@h /* denorm? */
addi r11,r11,-4 /* HSRR0 is next instruction */
bne+ denorm_assist bne+ denorm_assist
#endif #endif
@ -1382,6 +1380,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
*/ */
XVCPSGNDP32(32) XVCPSGNDP32(32)
denorm_done: denorm_done:
mfspr r11,SPRN_HSRR0
subi r11,r11,4
mtspr SPRN_HSRR0,r11 mtspr SPRN_HSRR0,r11
mtcrf 0x80,r9 mtcrf 0x80,r9
ld r9,PACA_EXGEN+EX_R9(r13) ld r9,PACA_EXGEN+EX_R9(r13)

View File

@ -1013,31 +1013,6 @@ long iommu_tce_xchg(struct iommu_table *tbl, unsigned long entry,
} }
EXPORT_SYMBOL_GPL(iommu_tce_xchg); EXPORT_SYMBOL_GPL(iommu_tce_xchg);
#ifdef CONFIG_PPC_BOOK3S_64
long iommu_tce_xchg_rm(struct iommu_table *tbl, unsigned long entry,
unsigned long *hpa, enum dma_data_direction *direction)
{
long ret;
ret = tbl->it_ops->exchange_rm(tbl, entry, hpa, direction);
if (!ret && ((*direction == DMA_FROM_DEVICE) ||
(*direction == DMA_BIDIRECTIONAL))) {
struct page *pg = realmode_pfn_to_page(*hpa >> PAGE_SHIFT);
if (likely(pg)) {
SetPageDirty(pg);
} else {
tbl->it_ops->exchange_rm(tbl, entry, hpa, direction);
ret = -EFAULT;
}
}
return ret;
}
EXPORT_SYMBOL_GPL(iommu_tce_xchg_rm);
#endif
int iommu_take_ownership(struct iommu_table *tbl) int iommu_take_ownership(struct iommu_table *tbl)
{ {
unsigned long flags, i, sz = (tbl->it_size + 7) >> 3; unsigned long flags, i, sz = (tbl->it_size + 7) >> 3;

View File

@ -176,13 +176,27 @@ _GLOBAL(tm_reclaim)
std r1, PACATMSCRATCH(r13) std r1, PACATMSCRATCH(r13)
ld r1, PACAR1(r13) ld r1, PACAR1(r13)
/* Store the PPR in r11 and reset to decent value */
std r11, GPR11(r1) /* Temporary stash */ std r11, GPR11(r1) /* Temporary stash */
/*
* Move the saved user r1 to the kernel stack in case PACATMSCRATCH is
* clobbered by an exception once we turn on MSR_RI below.
*/
ld r11, PACATMSCRATCH(r13)
std r11, GPR1(r1)
/*
* Store r13 away so we can free up the scratch SPR for the SLB fault
* handler (needed once we start accessing the thread_struct).
*/
GET_SCRATCH0(r11)
std r11, GPR13(r1)
/* Reset MSR RI so we can take SLB faults again */ /* Reset MSR RI so we can take SLB faults again */
li r11, MSR_RI li r11, MSR_RI
mtmsrd r11, 1 mtmsrd r11, 1
/* Store the PPR in r11 and reset to decent value */
mfspr r11, SPRN_PPR mfspr r11, SPRN_PPR
HMT_MEDIUM HMT_MEDIUM
@ -207,11 +221,11 @@ _GLOBAL(tm_reclaim)
SAVE_GPR(8, r7) /* user r8 */ SAVE_GPR(8, r7) /* user r8 */
SAVE_GPR(9, r7) /* user r9 */ SAVE_GPR(9, r7) /* user r9 */
SAVE_GPR(10, r7) /* user r10 */ SAVE_GPR(10, r7) /* user r10 */
ld r3, PACATMSCRATCH(r13) /* user r1 */ ld r3, GPR1(r1) /* user r1 */
ld r4, GPR7(r1) /* user r7 */ ld r4, GPR7(r1) /* user r7 */
ld r5, GPR11(r1) /* user r11 */ ld r5, GPR11(r1) /* user r11 */
ld r6, GPR12(r1) /* user r12 */ ld r6, GPR12(r1) /* user r12 */
GET_SCRATCH0(8) /* user r13 */ ld r8, GPR13(r1) /* user r13 */
std r3, GPR1(r7) std r3, GPR1(r7)
std r4, GPR7(r7) std r4, GPR7(r7)
std r5, GPR11(r7) std r5, GPR11(r7)

View File

@ -525,8 +525,8 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned long ea, unsigned long dsisr) unsigned long ea, unsigned long dsisr)
{ {
struct kvm *kvm = vcpu->kvm; struct kvm *kvm = vcpu->kvm;
unsigned long mmu_seq, pte_size; unsigned long mmu_seq;
unsigned long gpa, gfn, hva, pfn; unsigned long gpa, gfn, hva;
struct kvm_memory_slot *memslot; struct kvm_memory_slot *memslot;
struct page *page = NULL; struct page *page = NULL;
long ret; long ret;
@ -623,9 +623,10 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
*/ */
hva = gfn_to_hva_memslot(memslot, gfn); hva = gfn_to_hva_memslot(memslot, gfn);
if (upgrade_p && __get_user_pages_fast(hva, 1, 1, &page) == 1) { if (upgrade_p && __get_user_pages_fast(hva, 1, 1, &page) == 1) {
pfn = page_to_pfn(page);
upgrade_write = true; upgrade_write = true;
} else { } else {
unsigned long pfn;
/* Call KVM generic code to do the slow-path check */ /* Call KVM generic code to do the slow-path check */
pfn = __gfn_to_pfn_memslot(memslot, gfn, false, NULL, pfn = __gfn_to_pfn_memslot(memslot, gfn, false, NULL,
writing, upgrade_p); writing, upgrade_p);
@ -639,61 +640,43 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
} }
} }
/* See if we can insert a 1GB or 2MB large PTE here */ /*
level = 0; * Read the PTE from the process' radix tree and use that
if (page && PageCompound(page)) { * so we get the shift and attribute bits.
pte_size = PAGE_SIZE << compound_order(compound_head(page)); */
if (pte_size >= PUD_SIZE && local_irq_disable();
(gpa & (PUD_SIZE - PAGE_SIZE)) == ptep = __find_linux_pte(vcpu->arch.pgdir, hva, NULL, &shift);
(hva & (PUD_SIZE - PAGE_SIZE))) { pte = *ptep;
level = 2; local_irq_enable();
pfn &= ~((PUD_SIZE >> PAGE_SHIFT) - 1);
} else if (pte_size >= PMD_SIZE && /* Get pte level from shift/size */
(gpa & (PMD_SIZE - PAGE_SIZE)) == if (shift == PUD_SHIFT &&
(hva & (PMD_SIZE - PAGE_SIZE))) { (gpa & (PUD_SIZE - PAGE_SIZE)) ==
level = 1; (hva & (PUD_SIZE - PAGE_SIZE))) {
pfn &= ~((PMD_SIZE >> PAGE_SHIFT) - 1); level = 2;
} else if (shift == PMD_SHIFT &&
(gpa & (PMD_SIZE - PAGE_SIZE)) ==
(hva & (PMD_SIZE - PAGE_SIZE))) {
level = 1;
} else {
level = 0;
if (shift > PAGE_SHIFT) {
/*
* If the pte maps more than one page, bring over
* bits from the virtual address to get the real
* address of the specific single page we want.
*/
unsigned long rpnmask = (1ul << shift) - PAGE_SIZE;
pte = __pte(pte_val(pte) | (hva & rpnmask));
} }
} }
/* pte = __pte(pte_val(pte) | _PAGE_EXEC | _PAGE_ACCESSED);
* Compute the PTE value that we need to insert. if (writing || upgrade_write) {
*/ if (pte_val(pte) & _PAGE_WRITE)
if (page) { pte = __pte(pte_val(pte) | _PAGE_DIRTY);
pgflags = _PAGE_READ | _PAGE_EXEC | _PAGE_PRESENT | _PAGE_PTE |
_PAGE_ACCESSED;
if (writing || upgrade_write)
pgflags |= _PAGE_WRITE | _PAGE_DIRTY;
pte = pfn_pte(pfn, __pgprot(pgflags));
} else { } else {
/* pte = __pte(pte_val(pte) & ~(_PAGE_WRITE | _PAGE_DIRTY));
* Read the PTE from the process' radix tree and use that
* so we get the attribute bits.
*/
local_irq_disable();
ptep = __find_linux_pte(vcpu->arch.pgdir, hva, NULL, &shift);
pte = *ptep;
local_irq_enable();
if (shift == PUD_SHIFT &&
(gpa & (PUD_SIZE - PAGE_SIZE)) ==
(hva & (PUD_SIZE - PAGE_SIZE))) {
level = 2;
} else if (shift == PMD_SHIFT &&
(gpa & (PMD_SIZE - PAGE_SIZE)) ==
(hva & (PMD_SIZE - PAGE_SIZE))) {
level = 1;
} else if (shift && shift != PAGE_SHIFT) {
/* Adjust PFN */
unsigned long mask = (1ul << shift) - PAGE_SIZE;
pte = __pte(pte_val(pte) | (hva & mask));
}
pte = __pte(pte_val(pte) | _PAGE_EXEC | _PAGE_ACCESSED);
if (writing || upgrade_write) {
if (pte_val(pte) & _PAGE_WRITE)
pte = __pte(pte_val(pte) | _PAGE_DIRTY);
} else {
pte = __pte(pte_val(pte) & ~(_PAGE_WRITE | _PAGE_DIRTY));
}
} }
/* Allocate space in the tree and write the PTE */ /* Allocate space in the tree and write the PTE */

View File

@ -187,12 +187,35 @@ long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa,
EXPORT_SYMBOL_GPL(kvmppc_gpa_to_ua); EXPORT_SYMBOL_GPL(kvmppc_gpa_to_ua);
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
static void kvmppc_rm_clear_tce(struct iommu_table *tbl, unsigned long entry) static long iommu_tce_xchg_rm(struct mm_struct *mm, struct iommu_table *tbl,
unsigned long entry, unsigned long *hpa,
enum dma_data_direction *direction)
{
long ret;
ret = tbl->it_ops->exchange_rm(tbl, entry, hpa, direction);
if (!ret && ((*direction == DMA_FROM_DEVICE) ||
(*direction == DMA_BIDIRECTIONAL))) {
__be64 *pua = IOMMU_TABLE_USERSPACE_ENTRY_RM(tbl, entry);
/*
* kvmppc_rm_tce_iommu_do_map() updates the UA cache after
* calling this so we still get here a valid UA.
*/
if (pua && *pua)
mm_iommu_ua_mark_dirty_rm(mm, be64_to_cpu(*pua));
}
return ret;
}
static void kvmppc_rm_clear_tce(struct kvm *kvm, struct iommu_table *tbl,
unsigned long entry)
{ {
unsigned long hpa = 0; unsigned long hpa = 0;
enum dma_data_direction dir = DMA_NONE; enum dma_data_direction dir = DMA_NONE;
iommu_tce_xchg_rm(tbl, entry, &hpa, &dir); iommu_tce_xchg_rm(kvm->mm, tbl, entry, &hpa, &dir);
} }
static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm, static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm,
@ -224,7 +247,7 @@ static long kvmppc_rm_tce_iommu_do_unmap(struct kvm *kvm,
unsigned long hpa = 0; unsigned long hpa = 0;
long ret; long ret;
if (iommu_tce_xchg_rm(tbl, entry, &hpa, &dir)) if (iommu_tce_xchg_rm(kvm->mm, tbl, entry, &hpa, &dir))
/* /*
* real mode xchg can fail if struct page crosses * real mode xchg can fail if struct page crosses
* a page boundary * a page boundary
@ -236,7 +259,7 @@ static long kvmppc_rm_tce_iommu_do_unmap(struct kvm *kvm,
ret = kvmppc_rm_tce_iommu_mapped_dec(kvm, tbl, entry); ret = kvmppc_rm_tce_iommu_mapped_dec(kvm, tbl, entry);
if (ret) if (ret)
iommu_tce_xchg_rm(tbl, entry, &hpa, &dir); iommu_tce_xchg_rm(kvm->mm, tbl, entry, &hpa, &dir);
return ret; return ret;
} }
@ -282,7 +305,7 @@ static long kvmppc_rm_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl,
if (WARN_ON_ONCE_RM(mm_iommu_mapped_inc(mem))) if (WARN_ON_ONCE_RM(mm_iommu_mapped_inc(mem)))
return H_CLOSED; return H_CLOSED;
ret = iommu_tce_xchg_rm(tbl, entry, &hpa, &dir); ret = iommu_tce_xchg_rm(kvm->mm, tbl, entry, &hpa, &dir);
if (ret) { if (ret) {
mm_iommu_mapped_dec(mem); mm_iommu_mapped_dec(mem);
/* /*
@ -371,7 +394,7 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
return ret; return ret;
WARN_ON_ONCE_RM(1); WARN_ON_ONCE_RM(1);
kvmppc_rm_clear_tce(stit->tbl, entry); kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
} }
kvmppc_tce_put(stt, entry, tce); kvmppc_tce_put(stt, entry, tce);
@ -520,7 +543,7 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
goto unlock_exit; goto unlock_exit;
WARN_ON_ONCE_RM(1); WARN_ON_ONCE_RM(1);
kvmppc_rm_clear_tce(stit->tbl, entry); kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
} }
kvmppc_tce_put(stt, entry + i, tce); kvmppc_tce_put(stt, entry + i, tce);
@ -571,7 +594,7 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
return ret; return ret;
WARN_ON_ONCE_RM(1); WARN_ON_ONCE_RM(1);
kvmppc_rm_clear_tce(stit->tbl, entry); kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
} }
} }

View File

@ -443,6 +443,9 @@ _GLOBAL(csum_ipv6_magic)
addc r0, r8, r9 addc r0, r8, r9
ld r10, 0(r4) ld r10, 0(r4)
ld r11, 8(r4) ld r11, 8(r4)
#ifdef CONFIG_CPU_LITTLE_ENDIAN
rotldi r5, r5, 8
#endif
adde r0, r0, r10 adde r0, r0, r10
add r5, r5, r7 add r5, r5, r7
adde r0, r0, r11 adde r0, r0, r11

View File

@ -28,6 +28,12 @@ static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
{ {
int err; int err;
/* Make sure we aren't patching a freed init section */
if (init_mem_is_free && init_section_contains(exec_addr, 4)) {
pr_debug("Skipping init section patching addr: 0x%px\n", exec_addr);
return 0;
}
__put_user_size(instr, patch_addr, 4, err); __put_user_size(instr, patch_addr, 4, err);
if (err) if (err)
return err; return err;

View File

@ -308,55 +308,6 @@ void register_page_bootmem_memmap(unsigned long section_nr,
{ {
} }
/*
* We do not have access to the sparsemem vmemmap, so we fallback to
* walking the list of sparsemem blocks which we already maintain for
* the sake of crashdump. In the long run, we might want to maintain
* a tree if performance of that linear walk becomes a problem.
*
* realmode_pfn_to_page functions can fail due to:
* 1) As real sparsemem blocks do not lay in RAM continously (they
* are in virtual address space which is not available in the real mode),
* the requested page struct can be split between blocks so get_page/put_page
* may fail.
* 2) When huge pages are used, the get_page/put_page API will fail
* in real mode as the linked addresses in the page struct are virtual
* too.
*/
struct page *realmode_pfn_to_page(unsigned long pfn)
{
struct vmemmap_backing *vmem_back;
struct page *page;
unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift;
unsigned long pg_va = (unsigned long) pfn_to_page(pfn);
for (vmem_back = vmemmap_list; vmem_back; vmem_back = vmem_back->list) {
if (pg_va < vmem_back->virt_addr)
continue;
/* After vmemmap_list entry free is possible, need check all */
if ((pg_va + sizeof(struct page)) <=
(vmem_back->virt_addr + page_size)) {
page = (struct page *) (vmem_back->phys + pg_va -
vmem_back->virt_addr);
return page;
}
}
/* Probably that page struct is split between real pages */
return NULL;
}
EXPORT_SYMBOL_GPL(realmode_pfn_to_page);
#else
struct page *realmode_pfn_to_page(unsigned long pfn)
{
struct page *page = pfn_to_page(pfn);
return page;
}
EXPORT_SYMBOL_GPL(realmode_pfn_to_page);
#endif /* CONFIG_SPARSEMEM_VMEMMAP */ #endif /* CONFIG_SPARSEMEM_VMEMMAP */
#ifdef CONFIG_PPC_BOOK3S_64 #ifdef CONFIG_PPC_BOOK3S_64

View File

@ -63,6 +63,7 @@
#endif #endif
unsigned long long memory_limit; unsigned long long memory_limit;
bool init_mem_is_free;
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
pte_t *kmap_pte; pte_t *kmap_pte;
@ -396,6 +397,7 @@ void free_initmem(void)
{ {
ppc_md.progress = ppc_printk_progress; ppc_md.progress = ppc_printk_progress;
mark_initmem_nx(); mark_initmem_nx();
init_mem_is_free = true;
free_initmem_default(POISON_FREE_INITMEM); free_initmem_default(POISON_FREE_INITMEM);
} }

View File

@ -18,11 +18,15 @@
#include <linux/migrate.h> #include <linux/migrate.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/sizes.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/pte-walk.h> #include <asm/pte-walk.h>
static DEFINE_MUTEX(mem_list_mutex); static DEFINE_MUTEX(mem_list_mutex);
#define MM_IOMMU_TABLE_GROUP_PAGE_DIRTY 0x1
#define MM_IOMMU_TABLE_GROUP_PAGE_MASK ~(SZ_4K - 1)
struct mm_iommu_table_group_mem_t { struct mm_iommu_table_group_mem_t {
struct list_head next; struct list_head next;
struct rcu_head rcu; struct rcu_head rcu;
@ -263,6 +267,9 @@ static void mm_iommu_unpin(struct mm_iommu_table_group_mem_t *mem)
if (!page) if (!page)
continue; continue;
if (mem->hpas[i] & MM_IOMMU_TABLE_GROUP_PAGE_DIRTY)
SetPageDirty(page);
put_page(page); put_page(page);
mem->hpas[i] = 0; mem->hpas[i] = 0;
} }
@ -360,7 +367,6 @@ struct mm_iommu_table_group_mem_t *mm_iommu_lookup_rm(struct mm_struct *mm,
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(mm_iommu_lookup_rm);
struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm, struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
unsigned long ua, unsigned long entries) unsigned long ua, unsigned long entries)
@ -390,7 +396,7 @@ long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
if (pageshift > mem->pageshift) if (pageshift > mem->pageshift)
return -EFAULT; return -EFAULT;
*hpa = *va | (ua & ~PAGE_MASK); *hpa = (*va & MM_IOMMU_TABLE_GROUP_PAGE_MASK) | (ua & ~PAGE_MASK);
return 0; return 0;
} }
@ -413,11 +419,31 @@ long mm_iommu_ua_to_hpa_rm(struct mm_iommu_table_group_mem_t *mem,
if (!pa) if (!pa)
return -EFAULT; return -EFAULT;
*hpa = *pa | (ua & ~PAGE_MASK); *hpa = (*pa & MM_IOMMU_TABLE_GROUP_PAGE_MASK) | (ua & ~PAGE_MASK);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(mm_iommu_ua_to_hpa_rm);
extern void mm_iommu_ua_mark_dirty_rm(struct mm_struct *mm, unsigned long ua)
{
struct mm_iommu_table_group_mem_t *mem;
long entry;
void *va;
unsigned long *pa;
mem = mm_iommu_lookup_rm(mm, ua, PAGE_SIZE);
if (!mem)
return;
entry = (ua - mem->ua) >> PAGE_SHIFT;
va = &mem->hpas[entry];
pa = (void *) vmalloc_to_phys(va);
if (!pa)
return;
*pa |= MM_IOMMU_TABLE_GROUP_PAGE_DIRTY;
}
long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem) long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem)
{ {

View File

@ -1204,7 +1204,9 @@ int find_and_online_cpu_nid(int cpu)
int new_nid; int new_nid;
/* Use associativity from first thread for all siblings */ /* Use associativity from first thread for all siblings */
vphn_get_associativity(cpu, associativity); if (vphn_get_associativity(cpu, associativity))
return cpu_to_node(cpu);
new_nid = associativity_to_nid(associativity); new_nid = associativity_to_nid(associativity);
if (new_nid < 0 || !node_possible(new_nid)) if (new_nid < 0 || !node_possible(new_nid))
new_nid = first_online_node; new_nid = first_online_node;
@ -1452,7 +1454,8 @@ static struct timer_list topology_timer;
static void reset_topology_timer(void) static void reset_topology_timer(void)
{ {
mod_timer(&topology_timer, jiffies + topology_timer_secs * HZ); if (vphn_enabled)
mod_timer(&topology_timer, jiffies + topology_timer_secs * HZ);
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP

View File

@ -45,7 +45,7 @@ static void scan_pkey_feature(void)
* Since any pkey can be used for data or execute, we will just treat * Since any pkey can be used for data or execute, we will just treat
* all keys as equal and track them as one entity. * all keys as equal and track them as one entity.
*/ */
pkeys_total = be32_to_cpu(vals[0]); pkeys_total = vals[0];
pkeys_devtree_defined = true; pkeys_devtree_defined = true;
} }

View File

@ -276,7 +276,7 @@ long pnv_pci_ioda2_table_alloc_pages(int nid, __u64 bus_offset,
level_shift = entries_shift + 3; level_shift = entries_shift + 3;
level_shift = max_t(unsigned int, level_shift, PAGE_SHIFT); level_shift = max_t(unsigned int, level_shift, PAGE_SHIFT);
if ((level_shift - 3) * levels + page_shift >= 60) if ((level_shift - 3) * levels + page_shift >= 55)
return -EINVAL; return -EINVAL;
/* Allocate TCE table */ /* Allocate TCE table */

View File

@ -0,0 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_RISCV_PROTOTYPES_H
#include <linux/ftrace.h>
#include <asm-generic/asm-prototypes.h>
#endif /* _ASM_RISCV_PROTOTYPES_H */

View File

@ -481,7 +481,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
break; break;
case KVM_CAP_S390_HPAGE_1M: case KVM_CAP_S390_HPAGE_1M:
r = 0; r = 0;
if (hpage) if (hpage && !kvm_is_ucontrol(kvm))
r = 1; r = 1;
break; break;
case KVM_CAP_S390_MEM_OP: case KVM_CAP_S390_MEM_OP:
@ -691,7 +691,7 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
mutex_lock(&kvm->lock); mutex_lock(&kvm->lock);
if (kvm->created_vcpus) if (kvm->created_vcpus)
r = -EBUSY; r = -EBUSY;
else if (!hpage || kvm->arch.use_cmma) else if (!hpage || kvm->arch.use_cmma || kvm_is_ucontrol(kvm))
r = -EINVAL; r = -EINVAL;
else { else {
r = 0; r = 0;

View File

@ -708,11 +708,13 @@ void gmap_discard(struct gmap *gmap, unsigned long from, unsigned long to)
vmaddr |= gaddr & ~PMD_MASK; vmaddr |= gaddr & ~PMD_MASK;
/* Find vma in the parent mm */ /* Find vma in the parent mm */
vma = find_vma(gmap->mm, vmaddr); vma = find_vma(gmap->mm, vmaddr);
if (!vma)
continue;
/* /*
* We do not discard pages that are backed by * We do not discard pages that are backed by
* hugetlbfs, so we don't have to refault them. * hugetlbfs, so we don't have to refault them.
*/ */
if (vma && is_vm_hugetlb_page(vma)) if (is_vm_hugetlb_page(vma))
continue; continue;
size = min(to - gaddr, PMD_SIZE - (gaddr & ~PMD_MASK)); size = min(to - gaddr, PMD_SIZE - (gaddr & ~PMD_MASK));
zap_page_range(vma, vmaddr, size); zap_page_range(vma, vmaddr, size);

View File

@ -25,20 +25,6 @@ ENTRY(get_sev_encryption_bit)
push %ebx push %ebx
push %ecx push %ecx
push %edx push %edx
push %edi
/*
* RIP-relative addressing is needed to access the encryption bit
* variable. Since we are running in 32-bit mode we need this call/pop
* sequence to get the proper relative addressing.
*/
call 1f
1: popl %edi
subl $1b, %edi
movl enc_bit(%edi), %eax
cmpl $0, %eax
jge .Lsev_exit
/* Check if running under a hypervisor */ /* Check if running under a hypervisor */
movl $1, %eax movl $1, %eax
@ -69,15 +55,12 @@ ENTRY(get_sev_encryption_bit)
movl %ebx, %eax movl %ebx, %eax
andl $0x3f, %eax /* Return the encryption bit location */ andl $0x3f, %eax /* Return the encryption bit location */
movl %eax, enc_bit(%edi)
jmp .Lsev_exit jmp .Lsev_exit
.Lno_sev: .Lno_sev:
xor %eax, %eax xor %eax, %eax
movl %eax, enc_bit(%edi)
.Lsev_exit: .Lsev_exit:
pop %edi
pop %edx pop %edx
pop %ecx pop %ecx
pop %ebx pop %ebx
@ -113,8 +96,6 @@ ENTRY(set_sev_encryption_mask)
ENDPROC(set_sev_encryption_mask) ENDPROC(set_sev_encryption_mask)
.data .data
enc_bit:
.int 0xffffffff
#ifdef CONFIG_AMD_MEM_ENCRYPT #ifdef CONFIG_AMD_MEM_ENCRYPT
.balign 8 .balign 8

View File

@ -379,7 +379,6 @@ static int __init crypto_aegis128_aesni_module_init(void)
{ {
if (!boot_cpu_has(X86_FEATURE_XMM2) || if (!boot_cpu_has(X86_FEATURE_XMM2) ||
!boot_cpu_has(X86_FEATURE_AES) || !boot_cpu_has(X86_FEATURE_AES) ||
!boot_cpu_has(X86_FEATURE_OSXSAVE) ||
!cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL))
return -ENODEV; return -ENODEV;

View File

@ -379,7 +379,6 @@ static int __init crypto_aegis128l_aesni_module_init(void)
{ {
if (!boot_cpu_has(X86_FEATURE_XMM2) || if (!boot_cpu_has(X86_FEATURE_XMM2) ||
!boot_cpu_has(X86_FEATURE_AES) || !boot_cpu_has(X86_FEATURE_AES) ||
!boot_cpu_has(X86_FEATURE_OSXSAVE) ||
!cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL))
return -ENODEV; return -ENODEV;

View File

@ -379,7 +379,6 @@ static int __init crypto_aegis256_aesni_module_init(void)
{ {
if (!boot_cpu_has(X86_FEATURE_XMM2) || if (!boot_cpu_has(X86_FEATURE_XMM2) ||
!boot_cpu_has(X86_FEATURE_AES) || !boot_cpu_has(X86_FEATURE_AES) ||
!boot_cpu_has(X86_FEATURE_OSXSAVE) ||
!cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL))
return -ENODEV; return -ENODEV;

View File

@ -40,7 +40,6 @@ MORUS1280_DECLARE_ALGS(sse2, "morus1280-sse2", 350);
static int __init crypto_morus1280_sse2_module_init(void) static int __init crypto_morus1280_sse2_module_init(void)
{ {
if (!boot_cpu_has(X86_FEATURE_XMM2) || if (!boot_cpu_has(X86_FEATURE_XMM2) ||
!boot_cpu_has(X86_FEATURE_OSXSAVE) ||
!cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL))
return -ENODEV; return -ENODEV;

View File

@ -40,7 +40,6 @@ MORUS640_DECLARE_ALGS(sse2, "morus640-sse2", 400);
static int __init crypto_morus640_sse2_module_init(void) static int __init crypto_morus640_sse2_module_init(void)
{ {
if (!boot_cpu_has(X86_FEATURE_XMM2) || if (!boot_cpu_has(X86_FEATURE_XMM2) ||
!boot_cpu_has(X86_FEATURE_OSXSAVE) ||
!cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL)) !cpu_has_xfeatures(XFEATURE_MASK_SSE, NULL))
return -ENODEV; return -ENODEV;

View File

@ -95,8 +95,8 @@ static void hv_apic_eoi_write(u32 reg, u32 val)
*/ */
static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector) static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector)
{ {
struct ipi_arg_ex **arg; struct hv_send_ipi_ex **arg;
struct ipi_arg_ex *ipi_arg; struct hv_send_ipi_ex *ipi_arg;
unsigned long flags; unsigned long flags;
int nr_bank = 0; int nr_bank = 0;
int ret = 1; int ret = 1;
@ -105,7 +105,7 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector)
return false; return false;
local_irq_save(flags); local_irq_save(flags);
arg = (struct ipi_arg_ex **)this_cpu_ptr(hyperv_pcpu_input_arg); arg = (struct hv_send_ipi_ex **)this_cpu_ptr(hyperv_pcpu_input_arg);
ipi_arg = *arg; ipi_arg = *arg;
if (unlikely(!ipi_arg)) if (unlikely(!ipi_arg))
@ -135,7 +135,7 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector)
static bool __send_ipi_mask(const struct cpumask *mask, int vector) static bool __send_ipi_mask(const struct cpumask *mask, int vector)
{ {
int cur_cpu, vcpu; int cur_cpu, vcpu;
struct ipi_arg_non_ex ipi_arg; struct hv_send_ipi ipi_arg;
int ret = 1; int ret = 1;
trace_hyperv_send_ipi_mask(mask, vector); trace_hyperv_send_ipi_mask(mask, vector);

View File

@ -14,6 +14,16 @@
#ifndef _ASM_X86_FIXMAP_H #ifndef _ASM_X86_FIXMAP_H
#define _ASM_X86_FIXMAP_H #define _ASM_X86_FIXMAP_H
/*
* Exposed to assembly code for setting up initial page tables. Cannot be
* calculated in assembly code (fixmap entries are an enum), but is sanity
* checked in the actual fixmap C code to make sure that the fixmap is
* covered fully.
*/
#define FIXMAP_PMD_NUM 2
/* fixmap starts downwards from the 507th entry in level2_fixmap_pgt */
#define FIXMAP_PMD_TOP 507
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/acpi.h> #include <asm/acpi.h>

View File

@ -726,19 +726,21 @@ struct hv_enlightened_vmcs {
#define HV_STIMER_AUTOENABLE (1ULL << 3) #define HV_STIMER_AUTOENABLE (1ULL << 3)
#define HV_STIMER_SINT(config) (__u8)(((config) >> 16) & 0x0F) #define HV_STIMER_SINT(config) (__u8)(((config) >> 16) & 0x0F)
struct ipi_arg_non_ex {
u32 vector;
u32 reserved;
u64 cpu_mask;
};
struct hv_vpset { struct hv_vpset {
u64 format; u64 format;
u64 valid_bank_mask; u64 valid_bank_mask;
u64 bank_contents[]; u64 bank_contents[];
}; };
struct ipi_arg_ex { /* HvCallSendSyntheticClusterIpi hypercall */
struct hv_send_ipi {
u32 vector;
u32 reserved;
u64 cpu_mask;
};
/* HvCallSendSyntheticClusterIpiEx hypercall */
struct hv_send_ipi_ex {
u32 vector; u32 vector;
u32 reserved; u32 reserved;
struct hv_vpset vp_set; struct hv_vpset vp_set;

View File

@ -869,6 +869,8 @@ struct kvm_arch {
bool x2apic_format; bool x2apic_format;
bool x2apic_broadcast_quirk_disabled; bool x2apic_broadcast_quirk_disabled;
bool guest_can_read_msr_platform_info;
}; };
struct kvm_vm_stat { struct kvm_vm_stat {
@ -1022,6 +1024,7 @@ struct kvm_x86_ops {
void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu); void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr); void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr); void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
bool (*guest_apic_has_interrupt)(struct kvm_vcpu *vcpu);
void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap); void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu); void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa); void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
@ -1055,6 +1058,7 @@ struct kvm_x86_ops {
bool (*umip_emulated)(void); bool (*umip_emulated)(void);
int (*check_nested_events)(struct kvm_vcpu *vcpu, bool external_intr); int (*check_nested_events)(struct kvm_vcpu *vcpu, bool external_intr);
void (*request_immediate_exit)(struct kvm_vcpu *vcpu);
void (*sched_in)(struct kvm_vcpu *kvm, int cpu); void (*sched_in)(struct kvm_vcpu *kvm, int cpu);
@ -1482,6 +1486,7 @@ extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu); int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu);
int kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err); int kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err);
void __kvm_request_immediate_exit(struct kvm_vcpu *vcpu);
int kvm_is_in_guest(void); int kvm_is_in_guest(void);

View File

@ -48,10 +48,13 @@ int __init early_set_memory_encrypted(unsigned long vaddr, unsigned long size);
/* Architecture __weak replacement functions */ /* Architecture __weak replacement functions */
void __init mem_encrypt_init(void); void __init mem_encrypt_init(void);
void __init mem_encrypt_free_decrypted_mem(void);
bool sme_active(void); bool sme_active(void);
bool sev_active(void); bool sev_active(void);
#define __bss_decrypted __attribute__((__section__(".bss..decrypted")))
#else /* !CONFIG_AMD_MEM_ENCRYPT */ #else /* !CONFIG_AMD_MEM_ENCRYPT */
#define sme_me_mask 0ULL #define sme_me_mask 0ULL
@ -77,6 +80,8 @@ early_set_memory_decrypted(unsigned long vaddr, unsigned long size) { return 0;
static inline int __init static inline int __init
early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 0; } early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 0; }
#define __bss_decrypted
#endif /* CONFIG_AMD_MEM_ENCRYPT */ #endif /* CONFIG_AMD_MEM_ENCRYPT */
/* /*
@ -88,6 +93,8 @@ early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 0;
#define __sme_pa(x) (__pa(x) | sme_me_mask) #define __sme_pa(x) (__pa(x) | sme_me_mask)
#define __sme_pa_nodebug(x) (__pa_nodebug(x) | sme_me_mask) #define __sme_pa_nodebug(x) (__pa_nodebug(x) | sme_me_mask)
extern char __start_bss_decrypted[], __end_bss_decrypted[], __start_bss_decrypted_unused[];
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __X86_MEM_ENCRYPT_H__ */ #endif /* __X86_MEM_ENCRYPT_H__ */

View File

@ -14,6 +14,7 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/fixmap.h>
extern p4d_t level4_kernel_pgt[512]; extern p4d_t level4_kernel_pgt[512];
extern p4d_t level4_ident_pgt[512]; extern p4d_t level4_ident_pgt[512];
@ -22,7 +23,7 @@ extern pud_t level3_ident_pgt[512];
extern pmd_t level2_kernel_pgt[512]; extern pmd_t level2_kernel_pgt[512];
extern pmd_t level2_fixmap_pgt[512]; extern pmd_t level2_fixmap_pgt[512];
extern pmd_t level2_ident_pgt[512]; extern pmd_t level2_ident_pgt[512];
extern pte_t level1_fixmap_pgt[512]; extern pte_t level1_fixmap_pgt[512 * FIXMAP_PMD_NUM];
extern pgd_t init_top_pgt[]; extern pgd_t init_top_pgt[];
#define swapper_pg_dir init_top_pgt #define swapper_pg_dir init_top_pgt

View File

@ -377,6 +377,7 @@ struct kvm_sync_regs {
#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) #define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1)
#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
#define KVM_STATE_NESTED_GUEST_MODE 0x00000001 #define KVM_STATE_NESTED_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_RUN_PENDING 0x00000002 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002

View File

@ -382,6 +382,11 @@ static inline bool is_mbm_event(int e)
e <= QOS_L3_MBM_LOCAL_EVENT_ID); e <= QOS_L3_MBM_LOCAL_EVENT_ID);
} }
struct rdt_parse_data {
struct rdtgroup *rdtgrp;
char *buf;
};
/** /**
* struct rdt_resource - attributes of an RDT resource * struct rdt_resource - attributes of an RDT resource
* @rid: The index of the resource * @rid: The index of the resource
@ -423,16 +428,19 @@ struct rdt_resource {
struct rdt_cache cache; struct rdt_cache cache;
struct rdt_membw membw; struct rdt_membw membw;
const char *format_str; const char *format_str;
int (*parse_ctrlval) (void *data, struct rdt_resource *r, int (*parse_ctrlval)(struct rdt_parse_data *data,
struct rdt_domain *d); struct rdt_resource *r,
struct rdt_domain *d);
struct list_head evt_list; struct list_head evt_list;
int num_rmid; int num_rmid;
unsigned int mon_scale; unsigned int mon_scale;
unsigned long fflags; unsigned long fflags;
}; };
int parse_cbm(void *_data, struct rdt_resource *r, struct rdt_domain *d); int parse_cbm(struct rdt_parse_data *data, struct rdt_resource *r,
int parse_bw(void *_buf, struct rdt_resource *r, struct rdt_domain *d); struct rdt_domain *d);
int parse_bw(struct rdt_parse_data *data, struct rdt_resource *r,
struct rdt_domain *d);
extern struct mutex rdtgroup_mutex; extern struct mutex rdtgroup_mutex;
@ -536,6 +544,7 @@ int rdtgroup_pseudo_lock_create(struct rdtgroup *rdtgrp);
void rdtgroup_pseudo_lock_remove(struct rdtgroup *rdtgrp); void rdtgroup_pseudo_lock_remove(struct rdtgroup *rdtgrp);
struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r); struct rdt_domain *get_domain_from_cpu(int cpu, struct rdt_resource *r);
int update_domains(struct rdt_resource *r, int closid); int update_domains(struct rdt_resource *r, int closid);
int closids_supported(void);
void closid_free(int closid); void closid_free(int closid);
int alloc_rmid(void); int alloc_rmid(void);
void free_rmid(u32 rmid); void free_rmid(u32 rmid);

View File

@ -64,19 +64,19 @@ static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r)
return true; return true;
} }
int parse_bw(void *_buf, struct rdt_resource *r, struct rdt_domain *d) int parse_bw(struct rdt_parse_data *data, struct rdt_resource *r,
struct rdt_domain *d)
{ {
unsigned long data; unsigned long bw_val;
char *buf = _buf;
if (d->have_new_ctrl) { if (d->have_new_ctrl) {
rdt_last_cmd_printf("duplicate domain %d\n", d->id); rdt_last_cmd_printf("duplicate domain %d\n", d->id);
return -EINVAL; return -EINVAL;
} }
if (!bw_validate(buf, &data, r)) if (!bw_validate(data->buf, &bw_val, r))
return -EINVAL; return -EINVAL;
d->new_ctrl = data; d->new_ctrl = bw_val;
d->have_new_ctrl = true; d->have_new_ctrl = true;
return 0; return 0;
@ -123,18 +123,13 @@ static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
return true; return true;
} }
struct rdt_cbm_parse_data {
struct rdtgroup *rdtgrp;
char *buf;
};
/* /*
* Read one cache bit mask (hex). Check that it is valid for the current * Read one cache bit mask (hex). Check that it is valid for the current
* resource type. * resource type.
*/ */
int parse_cbm(void *_data, struct rdt_resource *r, struct rdt_domain *d) int parse_cbm(struct rdt_parse_data *data, struct rdt_resource *r,
struct rdt_domain *d)
{ {
struct rdt_cbm_parse_data *data = _data;
struct rdtgroup *rdtgrp = data->rdtgrp; struct rdtgroup *rdtgrp = data->rdtgrp;
u32 cbm_val; u32 cbm_val;
@ -195,11 +190,17 @@ int parse_cbm(void *_data, struct rdt_resource *r, struct rdt_domain *d)
static int parse_line(char *line, struct rdt_resource *r, static int parse_line(char *line, struct rdt_resource *r,
struct rdtgroup *rdtgrp) struct rdtgroup *rdtgrp)
{ {
struct rdt_cbm_parse_data data; struct rdt_parse_data data;
char *dom = NULL, *id; char *dom = NULL, *id;
struct rdt_domain *d; struct rdt_domain *d;
unsigned long dom_id; unsigned long dom_id;
if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP &&
r->rid == RDT_RESOURCE_MBA) {
rdt_last_cmd_puts("Cannot pseudo-lock MBA resource\n");
return -EINVAL;
}
next: next:
if (!line || line[0] == '\0') if (!line || line[0] == '\0')
return 0; return 0;

View File

@ -97,6 +97,12 @@ void rdt_last_cmd_printf(const char *fmt, ...)
* limited as the number of resources grows. * limited as the number of resources grows.
*/ */
static int closid_free_map; static int closid_free_map;
static int closid_free_map_len;
int closids_supported(void)
{
return closid_free_map_len;
}
static void closid_init(void) static void closid_init(void)
{ {
@ -111,6 +117,7 @@ static void closid_init(void)
/* CLOSID 0 is always reserved for the default group */ /* CLOSID 0 is always reserved for the default group */
closid_free_map &= ~1; closid_free_map &= ~1;
closid_free_map_len = rdt_min_closid;
} }
static int closid_alloc(void) static int closid_alloc(void)
@ -802,7 +809,7 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of,
sw_shareable = 0; sw_shareable = 0;
exclusive = 0; exclusive = 0;
seq_printf(seq, "%d=", dom->id); seq_printf(seq, "%d=", dom->id);
for (i = 0; i < r->num_closid; i++, ctrl++) { for (i = 0; i < closids_supported(); i++, ctrl++) {
if (!closid_allocated(i)) if (!closid_allocated(i))
continue; continue;
mode = rdtgroup_mode_by_closid(i); mode = rdtgroup_mode_by_closid(i);
@ -989,7 +996,7 @@ bool rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d,
/* Check for overlap with other resource groups */ /* Check for overlap with other resource groups */
ctrl = d->ctrl_val; ctrl = d->ctrl_val;
for (i = 0; i < r->num_closid; i++, ctrl++) { for (i = 0; i < closids_supported(); i++, ctrl++) {
ctrl_b = (unsigned long *)ctrl; ctrl_b = (unsigned long *)ctrl;
mode = rdtgroup_mode_by_closid(i); mode = rdtgroup_mode_by_closid(i);
if (closid_allocated(i) && i != closid && if (closid_allocated(i) && i != closid &&
@ -1024,16 +1031,27 @@ static bool rdtgroup_mode_test_exclusive(struct rdtgroup *rdtgrp)
{ {
int closid = rdtgrp->closid; int closid = rdtgrp->closid;
struct rdt_resource *r; struct rdt_resource *r;
bool has_cache = false;
struct rdt_domain *d; struct rdt_domain *d;
for_each_alloc_enabled_rdt_resource(r) { for_each_alloc_enabled_rdt_resource(r) {
if (r->rid == RDT_RESOURCE_MBA)
continue;
has_cache = true;
list_for_each_entry(d, &r->domains, list) { list_for_each_entry(d, &r->domains, list) {
if (rdtgroup_cbm_overlaps(r, d, d->ctrl_val[closid], if (rdtgroup_cbm_overlaps(r, d, d->ctrl_val[closid],
rdtgrp->closid, false)) rdtgrp->closid, false)) {
rdt_last_cmd_puts("schemata overlaps\n");
return false; return false;
}
} }
} }
if (!has_cache) {
rdt_last_cmd_puts("cannot be exclusive without CAT/CDP\n");
return false;
}
return true; return true;
} }
@ -1085,7 +1103,6 @@ static ssize_t rdtgroup_mode_write(struct kernfs_open_file *of,
rdtgrp->mode = RDT_MODE_SHAREABLE; rdtgrp->mode = RDT_MODE_SHAREABLE;
} else if (!strcmp(buf, "exclusive")) { } else if (!strcmp(buf, "exclusive")) {
if (!rdtgroup_mode_test_exclusive(rdtgrp)) { if (!rdtgroup_mode_test_exclusive(rdtgrp)) {
rdt_last_cmd_printf("schemata overlaps\n");
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
@ -1155,8 +1172,8 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
struct rdt_resource *r; struct rdt_resource *r;
struct rdt_domain *d; struct rdt_domain *d;
unsigned int size; unsigned int size;
bool sep = false; bool sep;
u32 cbm; u32 ctrl;
rdtgrp = rdtgroup_kn_lock_live(of->kn); rdtgrp = rdtgroup_kn_lock_live(of->kn);
if (!rdtgrp) { if (!rdtgrp) {
@ -1174,6 +1191,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
} }
for_each_alloc_enabled_rdt_resource(r) { for_each_alloc_enabled_rdt_resource(r) {
sep = false;
seq_printf(s, "%*s:", max_name_width, r->name); seq_printf(s, "%*s:", max_name_width, r->name);
list_for_each_entry(d, &r->domains, list) { list_for_each_entry(d, &r->domains, list) {
if (sep) if (sep)
@ -1181,8 +1199,13 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) { if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) {
size = 0; size = 0;
} else { } else {
cbm = d->ctrl_val[rdtgrp->closid]; ctrl = (!is_mba_sc(r) ?
size = rdtgroup_cbm_to_size(r, d, cbm); d->ctrl_val[rdtgrp->closid] :
d->mbps_val[rdtgrp->closid]);
if (r->rid == RDT_RESOURCE_MBA)
size = ctrl;
else
size = rdtgroup_cbm_to_size(r, d, ctrl);
} }
seq_printf(s, "%d=%u", d->id, size); seq_printf(s, "%d=%u", d->id, size);
sep = true; sep = true;
@ -2336,12 +2359,18 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
u32 *ctrl; u32 *ctrl;
for_each_alloc_enabled_rdt_resource(r) { for_each_alloc_enabled_rdt_resource(r) {
/*
* Only initialize default allocations for CBM cache
* resources
*/
if (r->rid == RDT_RESOURCE_MBA)
continue;
list_for_each_entry(d, &r->domains, list) { list_for_each_entry(d, &r->domains, list) {
d->have_new_ctrl = false; d->have_new_ctrl = false;
d->new_ctrl = r->cache.shareable_bits; d->new_ctrl = r->cache.shareable_bits;
used_b = r->cache.shareable_bits; used_b = r->cache.shareable_bits;
ctrl = d->ctrl_val; ctrl = d->ctrl_val;
for (i = 0; i < r->num_closid; i++, ctrl++) { for (i = 0; i < closids_supported(); i++, ctrl++) {
if (closid_allocated(i) && i != closid) { if (closid_allocated(i) && i != closid) {
mode = rdtgroup_mode_by_closid(i); mode = rdtgroup_mode_by_closid(i);
if (mode == RDT_MODE_PSEUDO_LOCKSETUP) if (mode == RDT_MODE_PSEUDO_LOCKSETUP)
@ -2373,6 +2402,12 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
} }
for_each_alloc_enabled_rdt_resource(r) { for_each_alloc_enabled_rdt_resource(r) {
/*
* Only initialize default allocations for CBM cache
* resources
*/
if (r->rid == RDT_RESOURCE_MBA)
continue;
ret = update_domains(r, rdtgrp->closid); ret = update_domains(r, rdtgrp->closid);
if (ret < 0) { if (ret < 0) {
rdt_last_cmd_puts("failed to initialize allocations\n"); rdt_last_cmd_puts("failed to initialize allocations\n");

View File

@ -35,6 +35,7 @@
#include <asm/bootparam_utils.h> #include <asm/bootparam_utils.h>
#include <asm/microcode.h> #include <asm/microcode.h>
#include <asm/kasan.h> #include <asm/kasan.h>
#include <asm/fixmap.h>
/* /*
* Manage page tables very early on. * Manage page tables very early on.
@ -112,6 +113,7 @@ static bool __head check_la57_support(unsigned long physaddr)
unsigned long __head __startup_64(unsigned long physaddr, unsigned long __head __startup_64(unsigned long physaddr,
struct boot_params *bp) struct boot_params *bp)
{ {
unsigned long vaddr, vaddr_end;
unsigned long load_delta, *p; unsigned long load_delta, *p;
unsigned long pgtable_flags; unsigned long pgtable_flags;
pgdval_t *pgd; pgdval_t *pgd;
@ -165,7 +167,8 @@ unsigned long __head __startup_64(unsigned long physaddr,
pud[511] += load_delta; pud[511] += load_delta;
pmd = fixup_pointer(level2_fixmap_pgt, physaddr); pmd = fixup_pointer(level2_fixmap_pgt, physaddr);
pmd[506] += load_delta; for (i = FIXMAP_PMD_TOP; i > FIXMAP_PMD_TOP - FIXMAP_PMD_NUM; i--)
pmd[i] += load_delta;
/* /*
* Set up the identity mapping for the switchover. These * Set up the identity mapping for the switchover. These
@ -234,6 +237,21 @@ unsigned long __head __startup_64(unsigned long physaddr,
/* Encrypt the kernel and related (if SME is active) */ /* Encrypt the kernel and related (if SME is active) */
sme_encrypt_kernel(bp); sme_encrypt_kernel(bp);
/*
* Clear the memory encryption mask from the .bss..decrypted section.
* The bss section will be memset to zero later in the initialization so
* there is no need to zero it after changing the memory encryption
* attribute.
*/
if (mem_encrypt_active()) {
vaddr = (unsigned long)__start_bss_decrypted;
vaddr_end = (unsigned long)__end_bss_decrypted;
for (; vaddr < vaddr_end; vaddr += PMD_SIZE) {
i = pmd_index(vaddr);
pmd[i] -= sme_get_me_mask();
}
}
/* /*
* Return the SME encryption mask (if SME is active) to be used as a * Return the SME encryption mask (if SME is active) to be used as a
* modifier for the initial pgdir entry programmed into CR3. * modifier for the initial pgdir entry programmed into CR3.

View File

@ -24,6 +24,7 @@
#include "../entry/calling.h" #include "../entry/calling.h"
#include <asm/export.h> #include <asm/export.h>
#include <asm/nospec-branch.h> #include <asm/nospec-branch.h>
#include <asm/fixmap.h>
#ifdef CONFIG_PARAVIRT #ifdef CONFIG_PARAVIRT
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
@ -445,13 +446,20 @@ NEXT_PAGE(level2_kernel_pgt)
KERNEL_IMAGE_SIZE/PMD_SIZE) KERNEL_IMAGE_SIZE/PMD_SIZE)
NEXT_PAGE(level2_fixmap_pgt) NEXT_PAGE(level2_fixmap_pgt)
.fill 506,8,0 .fill (512 - 4 - FIXMAP_PMD_NUM),8,0
.quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE_NOENC pgtno = 0
/* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */ .rept (FIXMAP_PMD_NUM)
.fill 5,8,0 .quad level1_fixmap_pgt + (pgtno << PAGE_SHIFT) - __START_KERNEL_map \
+ _PAGE_TABLE_NOENC;
pgtno = pgtno + 1
.endr
/* 6 MB reserved space + a 2MB hole */
.fill 4,8,0
NEXT_PAGE(level1_fixmap_pgt) NEXT_PAGE(level1_fixmap_pgt)
.rept (FIXMAP_PMD_NUM)
.fill 512,8,0 .fill 512,8,0
.endr
#undef PMDS #undef PMDS

View File

@ -28,6 +28,7 @@
#include <linux/sched/clock.h> #include <linux/sched/clock.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/set_memory.h>
#include <asm/hypervisor.h> #include <asm/hypervisor.h>
#include <asm/mem_encrypt.h> #include <asm/mem_encrypt.h>
@ -61,9 +62,10 @@ early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall);
(PAGE_SIZE / sizeof(struct pvclock_vsyscall_time_info)) (PAGE_SIZE / sizeof(struct pvclock_vsyscall_time_info))
static struct pvclock_vsyscall_time_info static struct pvclock_vsyscall_time_info
hv_clock_boot[HVC_BOOT_ARRAY_SIZE] __aligned(PAGE_SIZE); hv_clock_boot[HVC_BOOT_ARRAY_SIZE] __bss_decrypted __aligned(PAGE_SIZE);
static struct pvclock_wall_clock wall_clock; static struct pvclock_wall_clock wall_clock __bss_decrypted;
static DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu); static DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu);
static struct pvclock_vsyscall_time_info *hvclock_mem;
static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void) static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void)
{ {
@ -236,6 +238,45 @@ static void kvm_shutdown(void)
native_machine_shutdown(); native_machine_shutdown();
} }
static void __init kvmclock_init_mem(void)
{
unsigned long ncpus;
unsigned int order;
struct page *p;
int r;
if (HVC_BOOT_ARRAY_SIZE >= num_possible_cpus())
return;
ncpus = num_possible_cpus() - HVC_BOOT_ARRAY_SIZE;
order = get_order(ncpus * sizeof(*hvclock_mem));
p = alloc_pages(GFP_KERNEL, order);
if (!p) {
pr_warn("%s: failed to alloc %d pages", __func__, (1U << order));
return;
}
hvclock_mem = page_address(p);
/*
* hvclock is shared between the guest and the hypervisor, must
* be mapped decrypted.
*/
if (sev_active()) {
r = set_memory_decrypted((unsigned long) hvclock_mem,
1UL << order);
if (r) {
__free_pages(p, order);
hvclock_mem = NULL;
pr_warn("kvmclock: set_memory_decrypted() failed. Disabling\n");
return;
}
}
memset(hvclock_mem, 0, PAGE_SIZE << order);
}
static int __init kvm_setup_vsyscall_timeinfo(void) static int __init kvm_setup_vsyscall_timeinfo(void)
{ {
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
@ -250,6 +291,9 @@ static int __init kvm_setup_vsyscall_timeinfo(void)
kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK; kvm_clock.archdata.vclock_mode = VCLOCK_PVCLOCK;
#endif #endif
kvmclock_init_mem();
return 0; return 0;
} }
early_initcall(kvm_setup_vsyscall_timeinfo); early_initcall(kvm_setup_vsyscall_timeinfo);
@ -269,8 +313,10 @@ static int kvmclock_setup_percpu(unsigned int cpu)
/* Use the static page for the first CPUs, allocate otherwise */ /* Use the static page for the first CPUs, allocate otherwise */
if (cpu < HVC_BOOT_ARRAY_SIZE) if (cpu < HVC_BOOT_ARRAY_SIZE)
p = &hv_clock_boot[cpu]; p = &hv_clock_boot[cpu];
else if (hvclock_mem)
p = hvclock_mem + cpu - HVC_BOOT_ARRAY_SIZE;
else else
p = kzalloc(sizeof(*p), GFP_KERNEL); return -ENOMEM;
per_cpu(hv_clock_per_cpu, cpu) = p; per_cpu(hv_clock_per_cpu, cpu) = p;
return p ? 0 : -ENOMEM; return p ? 0 : -ENOMEM;

View File

@ -91,7 +91,7 @@ unsigned paravirt_patch_call(void *insnbuf,
if (len < 5) { if (len < 5) {
#ifdef CONFIG_RETPOLINE #ifdef CONFIG_RETPOLINE
WARN_ONCE("Failing to patch indirect CALL in %ps\n", (void *)addr); WARN_ONCE(1, "Failing to patch indirect CALL in %ps\n", (void *)addr);
#endif #endif
return len; /* call too long for patch site */ return len; /* call too long for patch site */
} }
@ -111,7 +111,7 @@ unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
if (len < 5) { if (len < 5) {
#ifdef CONFIG_RETPOLINE #ifdef CONFIG_RETPOLINE
WARN_ONCE("Failing to patch indirect JMP in %ps\n", (void *)addr); WARN_ONCE(1, "Failing to patch indirect JMP in %ps\n", (void *)addr);
#endif #endif
return len; /* call too long for patch site */ return len; /* call too long for patch site */
} }

View File

@ -65,6 +65,23 @@ jiffies_64 = jiffies;
#define ALIGN_ENTRY_TEXT_BEGIN . = ALIGN(PMD_SIZE); #define ALIGN_ENTRY_TEXT_BEGIN . = ALIGN(PMD_SIZE);
#define ALIGN_ENTRY_TEXT_END . = ALIGN(PMD_SIZE); #define ALIGN_ENTRY_TEXT_END . = ALIGN(PMD_SIZE);
/*
* This section contains data which will be mapped as decrypted. Memory
* encryption operates on a page basis. Make this section PMD-aligned
* to avoid splitting the pages while mapping the section early.
*
* Note: We use a separate section so that only this section gets
* decrypted to avoid exposing more than we wish.
*/
#define BSS_DECRYPTED \
. = ALIGN(PMD_SIZE); \
__start_bss_decrypted = .; \
*(.bss..decrypted); \
. = ALIGN(PAGE_SIZE); \
__start_bss_decrypted_unused = .; \
. = ALIGN(PMD_SIZE); \
__end_bss_decrypted = .; \
#else #else
#define X86_ALIGN_RODATA_BEGIN #define X86_ALIGN_RODATA_BEGIN
@ -74,6 +91,7 @@ jiffies_64 = jiffies;
#define ALIGN_ENTRY_TEXT_BEGIN #define ALIGN_ENTRY_TEXT_BEGIN
#define ALIGN_ENTRY_TEXT_END #define ALIGN_ENTRY_TEXT_END
#define BSS_DECRYPTED
#endif #endif
@ -355,6 +373,7 @@ SECTIONS
__bss_start = .; __bss_start = .;
*(.bss..page_aligned) *(.bss..page_aligned)
*(.bss) *(.bss)
BSS_DECRYPTED
. = ALIGN(PAGE_SIZE); . = ALIGN(PAGE_SIZE);
__bss_stop = .; __bss_stop = .;
} }

View File

@ -1344,9 +1344,8 @@ EXPORT_SYMBOL_GPL(kvm_lapic_reg_read);
static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr) static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr)
{ {
return kvm_apic_hw_enabled(apic) && return addr >= apic->base_address &&
addr >= apic->base_address && addr < apic->base_address + LAPIC_MMIO_LENGTH;
addr < apic->base_address + LAPIC_MMIO_LENGTH;
} }
static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this, static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
@ -1358,6 +1357,15 @@ static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
if (!apic_mmio_in_range(apic, address)) if (!apic_mmio_in_range(apic, address))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (!kvm_apic_hw_enabled(apic) || apic_x2apic_mode(apic)) {
if (!kvm_check_has_quirk(vcpu->kvm,
KVM_X86_QUIRK_LAPIC_MMIO_HOLE))
return -EOPNOTSUPP;
memset(data, 0xff, len);
return 0;
}
kvm_lapic_reg_read(apic, offset, len, data); kvm_lapic_reg_read(apic, offset, len, data);
return 0; return 0;
@ -1917,6 +1925,14 @@ static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
if (!apic_mmio_in_range(apic, address)) if (!apic_mmio_in_range(apic, address))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (!kvm_apic_hw_enabled(apic) || apic_x2apic_mode(apic)) {
if (!kvm_check_has_quirk(vcpu->kvm,
KVM_X86_QUIRK_LAPIC_MMIO_HOLE))
return -EOPNOTSUPP;
return 0;
}
/* /*
* APIC register must be aligned on 128-bits boundary. * APIC register must be aligned on 128-bits boundary.
* 32/64/128 bits registers must be accessed thru 32 bits. * 32/64/128 bits registers must be accessed thru 32 bits.

View File

@ -899,7 +899,7 @@ static void walk_shadow_page_lockless_end(struct kvm_vcpu *vcpu)
{ {
/* /*
* Make sure the write to vcpu->mode is not reordered in front of * Make sure the write to vcpu->mode is not reordered in front of
* reads to sptes. If it does, kvm_commit_zap_page() can see us * reads to sptes. If it does, kvm_mmu_commit_zap_page() can see us
* OUTSIDE_GUEST_MODE and proceed to free the shadow page table. * OUTSIDE_GUEST_MODE and proceed to free the shadow page table.
*/ */
smp_store_release(&vcpu->mode, OUTSIDE_GUEST_MODE); smp_store_release(&vcpu->mode, OUTSIDE_GUEST_MODE);
@ -5417,7 +5417,12 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu)
{ {
MMU_WARN_ON(VALID_PAGE(vcpu->arch.mmu.root_hpa)); MMU_WARN_ON(VALID_PAGE(vcpu->arch.mmu.root_hpa));
kvm_init_mmu(vcpu, true); /*
* kvm_mmu_setup() is called only on vCPU initialization.
* Therefore, no need to reset mmu roots as they are not yet
* initialized.
*/
kvm_init_mmu(vcpu, false);
} }
static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm, static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,

View File

@ -1226,8 +1226,7 @@ static __init int sev_hardware_setup(void)
min_sev_asid = cpuid_edx(0x8000001F); min_sev_asid = cpuid_edx(0x8000001F);
/* Initialize SEV ASID bitmap */ /* Initialize SEV ASID bitmap */
sev_asid_bitmap = kcalloc(BITS_TO_LONGS(max_sev_asid), sev_asid_bitmap = bitmap_zalloc(max_sev_asid, GFP_KERNEL);
sizeof(unsigned long), GFP_KERNEL);
if (!sev_asid_bitmap) if (!sev_asid_bitmap)
return 1; return 1;
@ -1405,7 +1404,7 @@ static __exit void svm_hardware_unsetup(void)
int cpu; int cpu;
if (svm_sev_enabled()) if (svm_sev_enabled())
kfree(sev_asid_bitmap); bitmap_free(sev_asid_bitmap);
for_each_possible_cpu(cpu) for_each_possible_cpu(cpu)
svm_cpu_uninit(cpu); svm_cpu_uninit(cpu);
@ -7149,6 +7148,8 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
.check_intercept = svm_check_intercept, .check_intercept = svm_check_intercept,
.handle_external_intr = svm_handle_external_intr, .handle_external_intr = svm_handle_external_intr,
.request_immediate_exit = __kvm_request_immediate_exit,
.sched_in = svm_sched_in, .sched_in = svm_sched_in,
.pmu_ops = &amd_pmu_ops, .pmu_ops = &amd_pmu_ops,

View File

@ -397,6 +397,7 @@ struct loaded_vmcs {
int cpu; int cpu;
bool launched; bool launched;
bool nmi_known_unmasked; bool nmi_known_unmasked;
bool hv_timer_armed;
/* Support for vnmi-less CPUs */ /* Support for vnmi-less CPUs */
int soft_vnmi_blocked; int soft_vnmi_blocked;
ktime_t entry_time; ktime_t entry_time;
@ -1019,6 +1020,8 @@ struct vcpu_vmx {
int ple_window; int ple_window;
bool ple_window_dirty; bool ple_window_dirty;
bool req_immediate_exit;
/* Support for PML */ /* Support for PML */
#define PML_ENTITY_NUM 512 #define PML_ENTITY_NUM 512
struct page *pml_pg; struct page *pml_pg;
@ -2864,6 +2867,8 @@ static void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
u16 fs_sel, gs_sel; u16 fs_sel, gs_sel;
int i; int i;
vmx->req_immediate_exit = false;
if (vmx->loaded_cpu_state) if (vmx->loaded_cpu_state)
return; return;
@ -5393,9 +5398,10 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
* To use VMXON (and later other VMX instructions), a guest * To use VMXON (and later other VMX instructions), a guest
* must first be able to turn on cr4.VMXE (see handle_vmon()). * must first be able to turn on cr4.VMXE (see handle_vmon()).
* So basically the check on whether to allow nested VMX * So basically the check on whether to allow nested VMX
* is here. * is here. We operate under the default treatment of SMM,
* so VMX cannot be enabled under SMM.
*/ */
if (!nested_vmx_allowed(vcpu)) if (!nested_vmx_allowed(vcpu) || is_smm(vcpu))
return 1; return 1;
} }
@ -6183,6 +6189,27 @@ static void vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
nested_mark_vmcs12_pages_dirty(vcpu); nested_mark_vmcs12_pages_dirty(vcpu);
} }
static bool vmx_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
void *vapic_page;
u32 vppr;
int rvi;
if (WARN_ON_ONCE(!is_guest_mode(vcpu)) ||
!nested_cpu_has_vid(get_vmcs12(vcpu)) ||
WARN_ON_ONCE(!vmx->nested.virtual_apic_page))
return false;
rvi = vmcs_read16(GUEST_INTR_STATUS) & 0xff;
vapic_page = kmap(vmx->nested.virtual_apic_page);
vppr = *((u32 *)(vapic_page + APIC_PROCPRI));
kunmap(vmx->nested.virtual_apic_page);
return ((rvi & 0xf0) > (vppr & 0xf0));
}
static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu, static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
bool nested) bool nested)
{ {
@ -7966,6 +7993,9 @@ static __init int hardware_setup(void)
kvm_x86_ops->enable_log_dirty_pt_masked = NULL; kvm_x86_ops->enable_log_dirty_pt_masked = NULL;
} }
if (!cpu_has_vmx_preemption_timer())
kvm_x86_ops->request_immediate_exit = __kvm_request_immediate_exit;
if (cpu_has_vmx_preemption_timer() && enable_preemption_timer) { if (cpu_has_vmx_preemption_timer() && enable_preemption_timer) {
u64 vmx_msr; u64 vmx_msr;
@ -9208,7 +9238,8 @@ static int handle_pml_full(struct kvm_vcpu *vcpu)
static int handle_preemption_timer(struct kvm_vcpu *vcpu) static int handle_preemption_timer(struct kvm_vcpu *vcpu)
{ {
kvm_lapic_expired_hv_timer(vcpu); if (!to_vmx(vcpu)->req_immediate_exit)
kvm_lapic_expired_hv_timer(vcpu);
return 1; return 1;
} }
@ -10595,24 +10626,43 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
msrs[i].host, false); msrs[i].host, false);
} }
static void vmx_arm_hv_timer(struct kvm_vcpu *vcpu) static void vmx_arm_hv_timer(struct vcpu_vmx *vmx, u32 val)
{
vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, val);
if (!vmx->loaded_vmcs->hv_timer_armed)
vmcs_set_bits(PIN_BASED_VM_EXEC_CONTROL,
PIN_BASED_VMX_PREEMPTION_TIMER);
vmx->loaded_vmcs->hv_timer_armed = true;
}
static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
{ {
struct vcpu_vmx *vmx = to_vmx(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu);
u64 tscl; u64 tscl;
u32 delta_tsc; u32 delta_tsc;
if (vmx->hv_deadline_tsc == -1) if (vmx->req_immediate_exit) {
vmx_arm_hv_timer(vmx, 0);
return; return;
}
tscl = rdtsc(); if (vmx->hv_deadline_tsc != -1) {
if (vmx->hv_deadline_tsc > tscl) tscl = rdtsc();
/* sure to be 32 bit only because checked on set_hv_timer */ if (vmx->hv_deadline_tsc > tscl)
delta_tsc = (u32)((vmx->hv_deadline_tsc - tscl) >> /* set_hv_timer ensures the delta fits in 32-bits */
cpu_preemption_timer_multi); delta_tsc = (u32)((vmx->hv_deadline_tsc - tscl) >>
else cpu_preemption_timer_multi);
delta_tsc = 0; else
delta_tsc = 0;
vmcs_write32(VMX_PREEMPTION_TIMER_VALUE, delta_tsc); vmx_arm_hv_timer(vmx, delta_tsc);
return;
}
if (vmx->loaded_vmcs->hv_timer_armed)
vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL,
PIN_BASED_VMX_PREEMPTION_TIMER);
vmx->loaded_vmcs->hv_timer_armed = false;
} }
static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
@ -10672,7 +10722,7 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
atomic_switch_perf_msrs(vmx); atomic_switch_perf_msrs(vmx);
vmx_arm_hv_timer(vcpu); vmx_update_hv_timer(vcpu);
/* /*
* If this vCPU has touched SPEC_CTRL, restore the guest's value if * If this vCPU has touched SPEC_CTRL, restore the guest's value if
@ -11427,16 +11477,18 @@ static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu)
u64 preemption_timeout = get_vmcs12(vcpu)->vmx_preemption_timer_value; u64 preemption_timeout = get_vmcs12(vcpu)->vmx_preemption_timer_value;
struct vcpu_vmx *vmx = to_vmx(vcpu); struct vcpu_vmx *vmx = to_vmx(vcpu);
if (vcpu->arch.virtual_tsc_khz == 0) /*
return; * A timer value of zero is architecturally guaranteed to cause
* a VMExit prior to executing any instructions in the guest.
/* Make sure short timeouts reliably trigger an immediate vmexit. */
* hrtimer_start does not guarantee this. */ if (preemption_timeout == 0) {
if (preemption_timeout <= 1) {
vmx_preemption_timer_fn(&vmx->nested.preemption_timer); vmx_preemption_timer_fn(&vmx->nested.preemption_timer);
return; return;
} }
if (vcpu->arch.virtual_tsc_khz == 0)
return;
preemption_timeout <<= VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE; preemption_timeout <<= VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE;
preemption_timeout *= 1000000; preemption_timeout *= 1000000;
do_div(preemption_timeout, vcpu->arch.virtual_tsc_khz); do_div(preemption_timeout, vcpu->arch.virtual_tsc_khz);
@ -11646,11 +11698,15 @@ static int nested_vmx_check_apicv_controls(struct kvm_vcpu *vcpu,
* bits 15:8 should be zero in posted_intr_nv, * bits 15:8 should be zero in posted_intr_nv,
* the descriptor address has been already checked * the descriptor address has been already checked
* in nested_get_vmcs12_pages. * in nested_get_vmcs12_pages.
*
* bits 5:0 of posted_intr_desc_addr should be zero.
*/ */
if (nested_cpu_has_posted_intr(vmcs12) && if (nested_cpu_has_posted_intr(vmcs12) &&
(!nested_cpu_has_vid(vmcs12) || (!nested_cpu_has_vid(vmcs12) ||
!nested_exit_intr_ack_set(vcpu) || !nested_exit_intr_ack_set(vcpu) ||
vmcs12->posted_intr_nv & 0xff00)) (vmcs12->posted_intr_nv & 0xff00) ||
(vmcs12->posted_intr_desc_addr & 0x3f) ||
(!page_address_valid(vcpu, vmcs12->posted_intr_desc_addr))))
return -EINVAL; return -EINVAL;
/* tpr shadow is needed by all apicv features. */ /* tpr shadow is needed by all apicv features. */
@ -12076,11 +12132,10 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
exec_control = vmcs12->pin_based_vm_exec_control; exec_control = vmcs12->pin_based_vm_exec_control;
/* Preemption timer setting is only taken from vmcs01. */ /* Preemption timer setting is computed directly in vmx_vcpu_run. */
exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
exec_control |= vmcs_config.pin_based_exec_ctrl; exec_control |= vmcs_config.pin_based_exec_ctrl;
if (vmx->hv_deadline_tsc == -1) exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER;
exec_control &= ~PIN_BASED_VMX_PREEMPTION_TIMER; vmx->loaded_vmcs->hv_timer_armed = false;
/* Posted interrupts setting is only taken from vmcs12. */ /* Posted interrupts setting is only taken from vmcs12. */
if (nested_cpu_has_posted_intr(vmcs12)) { if (nested_cpu_has_posted_intr(vmcs12)) {
@ -12318,6 +12373,9 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT) vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT)
return VMXERR_ENTRY_INVALID_CONTROL_FIELD; return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
if (nested_cpu_has_vpid(vmcs12) && !vmcs12->virtual_processor_id)
return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
if (nested_vmx_check_io_bitmap_controls(vcpu, vmcs12)) if (nested_vmx_check_io_bitmap_controls(vcpu, vmcs12))
return VMXERR_ENTRY_INVALID_CONTROL_FIELD; return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
@ -12863,6 +12921,11 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
return 0; return 0;
} }
static void vmx_request_immediate_exit(struct kvm_vcpu *vcpu)
{
to_vmx(vcpu)->req_immediate_exit = true;
}
static u32 vmx_get_preemption_timer_value(struct kvm_vcpu *vcpu) static u32 vmx_get_preemption_timer_value(struct kvm_vcpu *vcpu)
{ {
ktime_t remaining = ktime_t remaining =
@ -13253,12 +13316,7 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr); vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr); vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset); vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
if (vmx->hv_deadline_tsc == -1)
vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL,
PIN_BASED_VMX_PREEMPTION_TIMER);
else
vmcs_set_bits(PIN_BASED_VM_EXEC_CONTROL,
PIN_BASED_VMX_PREEMPTION_TIMER);
if (kvm_has_tsc_control) if (kvm_has_tsc_control)
decache_tsc_multiplier(vmx); decache_tsc_multiplier(vmx);
@ -13462,18 +13520,12 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
return -ERANGE; return -ERANGE;
vmx->hv_deadline_tsc = tscl + delta_tsc; vmx->hv_deadline_tsc = tscl + delta_tsc;
vmcs_set_bits(PIN_BASED_VM_EXEC_CONTROL,
PIN_BASED_VMX_PREEMPTION_TIMER);
return delta_tsc == 0; return delta_tsc == 0;
} }
static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu) static void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu)
{ {
struct vcpu_vmx *vmx = to_vmx(vcpu); to_vmx(vcpu)->hv_deadline_tsc = -1;
vmx->hv_deadline_tsc = -1;
vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL,
PIN_BASED_VMX_PREEMPTION_TIMER);
} }
#endif #endif
@ -13954,6 +14006,14 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu,
~(KVM_STATE_NESTED_SMM_GUEST_MODE | KVM_STATE_NESTED_SMM_VMXON)) ~(KVM_STATE_NESTED_SMM_GUEST_MODE | KVM_STATE_NESTED_SMM_VMXON))
return -EINVAL; return -EINVAL;
/*
* SMM temporarily disables VMX, so we cannot be in guest mode,
* nor can VMLAUNCH/VMRESUME be pending. Outside SMM, SMM flags
* must be zero.
*/
if (is_smm(vcpu) ? kvm_state->flags : kvm_state->vmx.smm.flags)
return -EINVAL;
if ((kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) && if ((kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_GUEST_MODE) &&
!(kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON)) !(kvm_state->vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON))
return -EINVAL; return -EINVAL;
@ -14097,6 +14157,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
.apicv_post_state_restore = vmx_apicv_post_state_restore, .apicv_post_state_restore = vmx_apicv_post_state_restore,
.hwapic_irr_update = vmx_hwapic_irr_update, .hwapic_irr_update = vmx_hwapic_irr_update,
.hwapic_isr_update = vmx_hwapic_isr_update, .hwapic_isr_update = vmx_hwapic_isr_update,
.guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
.sync_pir_to_irr = vmx_sync_pir_to_irr, .sync_pir_to_irr = vmx_sync_pir_to_irr,
.deliver_posted_interrupt = vmx_deliver_posted_interrupt, .deliver_posted_interrupt = vmx_deliver_posted_interrupt,
@ -14130,6 +14191,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
.umip_emulated = vmx_umip_emulated, .umip_emulated = vmx_umip_emulated,
.check_nested_events = vmx_check_nested_events, .check_nested_events = vmx_check_nested_events,
.request_immediate_exit = vmx_request_immediate_exit,
.sched_in = vmx_sched_in, .sched_in = vmx_sched_in,

View File

@ -628,7 +628,7 @@ bool pdptrs_changed(struct kvm_vcpu *vcpu)
gfn_t gfn; gfn_t gfn;
int r; int r;
if (is_long_mode(vcpu) || !is_pae(vcpu)) if (is_long_mode(vcpu) || !is_pae(vcpu) || !is_paging(vcpu))
return false; return false;
if (!test_bit(VCPU_EXREG_PDPTR, if (!test_bit(VCPU_EXREG_PDPTR,
@ -2537,7 +2537,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break; break;
case MSR_PLATFORM_INFO: case MSR_PLATFORM_INFO:
if (!msr_info->host_initiated || if (!msr_info->host_initiated ||
data & ~MSR_PLATFORM_INFO_CPUID_FAULT ||
(!(data & MSR_PLATFORM_INFO_CPUID_FAULT) && (!(data & MSR_PLATFORM_INFO_CPUID_FAULT) &&
cpuid_fault_enabled(vcpu))) cpuid_fault_enabled(vcpu)))
return 1; return 1;
@ -2780,6 +2779,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
msr_info->data = vcpu->arch.osvw.status; msr_info->data = vcpu->arch.osvw.status;
break; break;
case MSR_PLATFORM_INFO: case MSR_PLATFORM_INFO:
if (!msr_info->host_initiated &&
!vcpu->kvm->arch.guest_can_read_msr_platform_info)
return 1;
msr_info->data = vcpu->arch.msr_platform_info; msr_info->data = vcpu->arch.msr_platform_info;
break; break;
case MSR_MISC_FEATURES_ENABLES: case MSR_MISC_FEATURES_ENABLES:
@ -2927,6 +2929,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_SPLIT_IRQCHIP: case KVM_CAP_SPLIT_IRQCHIP:
case KVM_CAP_IMMEDIATE_EXIT: case KVM_CAP_IMMEDIATE_EXIT:
case KVM_CAP_GET_MSR_FEATURES: case KVM_CAP_GET_MSR_FEATURES:
case KVM_CAP_MSR_PLATFORM_INFO:
r = 1; r = 1;
break; break;
case KVM_CAP_SYNC_REGS: case KVM_CAP_SYNC_REGS:
@ -4007,19 +4010,23 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
break; break;
BUILD_BUG_ON(sizeof(user_data_size) != sizeof(user_kvm_nested_state->size)); BUILD_BUG_ON(sizeof(user_data_size) != sizeof(user_kvm_nested_state->size));
r = -EFAULT;
if (get_user(user_data_size, &user_kvm_nested_state->size)) if (get_user(user_data_size, &user_kvm_nested_state->size))
return -EFAULT; break;
r = kvm_x86_ops->get_nested_state(vcpu, user_kvm_nested_state, r = kvm_x86_ops->get_nested_state(vcpu, user_kvm_nested_state,
user_data_size); user_data_size);
if (r < 0) if (r < 0)
return r; break;
if (r > user_data_size) { if (r > user_data_size) {
if (put_user(r, &user_kvm_nested_state->size)) if (put_user(r, &user_kvm_nested_state->size))
return -EFAULT; r = -EFAULT;
return -E2BIG; else
r = -E2BIG;
break;
} }
r = 0; r = 0;
break; break;
} }
@ -4031,19 +4038,21 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
if (!kvm_x86_ops->set_nested_state) if (!kvm_x86_ops->set_nested_state)
break; break;
r = -EFAULT;
if (copy_from_user(&kvm_state, user_kvm_nested_state, sizeof(kvm_state))) if (copy_from_user(&kvm_state, user_kvm_nested_state, sizeof(kvm_state)))
return -EFAULT; break;
r = -EINVAL;
if (kvm_state.size < sizeof(kvm_state)) if (kvm_state.size < sizeof(kvm_state))
return -EINVAL; break;
if (kvm_state.flags & if (kvm_state.flags &
~(KVM_STATE_NESTED_RUN_PENDING | KVM_STATE_NESTED_GUEST_MODE)) ~(KVM_STATE_NESTED_RUN_PENDING | KVM_STATE_NESTED_GUEST_MODE))
return -EINVAL; break;
/* nested_run_pending implies guest_mode. */ /* nested_run_pending implies guest_mode. */
if (kvm_state.flags == KVM_STATE_NESTED_RUN_PENDING) if (kvm_state.flags == KVM_STATE_NESTED_RUN_PENDING)
return -EINVAL; break;
r = kvm_x86_ops->set_nested_state(vcpu, user_kvm_nested_state, &kvm_state); r = kvm_x86_ops->set_nested_state(vcpu, user_kvm_nested_state, &kvm_state);
break; break;
@ -4350,6 +4359,10 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
kvm->arch.pause_in_guest = true; kvm->arch.pause_in_guest = true;
r = 0; r = 0;
break; break;
case KVM_CAP_MSR_PLATFORM_INFO:
kvm->arch.guest_can_read_msr_platform_info = cap->args[0];
r = 0;
break;
default: default:
r = -EINVAL; r = -EINVAL;
break; break;
@ -7361,6 +7374,12 @@ void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu)
} }
EXPORT_SYMBOL_GPL(kvm_vcpu_reload_apic_access_page); EXPORT_SYMBOL_GPL(kvm_vcpu_reload_apic_access_page);
void __kvm_request_immediate_exit(struct kvm_vcpu *vcpu)
{
smp_send_reschedule(vcpu->cpu);
}
EXPORT_SYMBOL_GPL(__kvm_request_immediate_exit);
/* /*
* Returns 1 to let vcpu_run() continue the guest execution loop without * Returns 1 to let vcpu_run() continue the guest execution loop without
* exiting to the userspace. Otherwise, the value will be returned to the * exiting to the userspace. Otherwise, the value will be returned to the
@ -7565,7 +7584,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
if (req_immediate_exit) { if (req_immediate_exit) {
kvm_make_request(KVM_REQ_EVENT, vcpu); kvm_make_request(KVM_REQ_EVENT, vcpu);
smp_send_reschedule(vcpu->cpu); kvm_x86_ops->request_immediate_exit(vcpu);
} }
trace_kvm_entry(vcpu->vcpu_id); trace_kvm_entry(vcpu->vcpu_id);
@ -7829,6 +7848,29 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
return 0; return 0;
} }
/* Swap (qemu) user FPU context for the guest FPU context. */
static void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
{
preempt_disable();
copy_fpregs_to_fpstate(&vcpu->arch.user_fpu);
/* PKRU is separately restored in kvm_x86_ops->run. */
__copy_kernel_to_fpregs(&vcpu->arch.guest_fpu.state,
~XFEATURE_MASK_PKRU);
preempt_enable();
trace_kvm_fpu(1);
}
/* When vcpu_run ends, restore user space FPU context. */
static void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
{
preempt_disable();
copy_fpregs_to_fpstate(&vcpu->arch.guest_fpu);
copy_kernel_to_fpregs(&vcpu->arch.user_fpu.state);
preempt_enable();
++vcpu->stat.fpu_reload;
trace_kvm_fpu(0);
}
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{ {
int r; int r;
@ -8177,7 +8219,7 @@ static int __set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
kvm_update_cpuid(vcpu); kvm_update_cpuid(vcpu);
idx = srcu_read_lock(&vcpu->kvm->srcu); idx = srcu_read_lock(&vcpu->kvm->srcu);
if (!is_long_mode(vcpu) && is_pae(vcpu)) { if (!is_long_mode(vcpu) && is_pae(vcpu) && is_paging(vcpu)) {
load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu)); load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu));
mmu_reset_needed = 1; mmu_reset_needed = 1;
} }
@ -8406,29 +8448,6 @@ static void fx_init(struct kvm_vcpu *vcpu)
vcpu->arch.cr0 |= X86_CR0_ET; vcpu->arch.cr0 |= X86_CR0_ET;
} }
/* Swap (qemu) user FPU context for the guest FPU context. */
void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
{
preempt_disable();
copy_fpregs_to_fpstate(&vcpu->arch.user_fpu);
/* PKRU is separately restored in kvm_x86_ops->run. */
__copy_kernel_to_fpregs(&vcpu->arch.guest_fpu.state,
~XFEATURE_MASK_PKRU);
preempt_enable();
trace_kvm_fpu(1);
}
/* When vcpu_run ends, restore user space FPU context. */
void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
{
preempt_disable();
copy_fpregs_to_fpstate(&vcpu->arch.guest_fpu);
copy_kernel_to_fpregs(&vcpu->arch.user_fpu.state);
preempt_enable();
++vcpu->stat.fpu_reload;
trace_kvm_fpu(0);
}
void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
{ {
void *wbinvd_dirty_mask = vcpu->arch.wbinvd_dirty_mask; void *wbinvd_dirty_mask = vcpu->arch.wbinvd_dirty_mask;
@ -8852,6 +8871,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
kvm->arch.kvmclock_offset = -ktime_get_boot_ns(); kvm->arch.kvmclock_offset = -ktime_get_boot_ns();
pvclock_update_vm_gtod_copy(kvm); pvclock_update_vm_gtod_copy(kvm);
kvm->arch.guest_can_read_msr_platform_info = true;
INIT_DELAYED_WORK(&kvm->arch.kvmclock_update_work, kvmclock_update_fn); INIT_DELAYED_WORK(&kvm->arch.kvmclock_update_work, kvmclock_update_fn);
INIT_DELAYED_WORK(&kvm->arch.kvmclock_sync_work, kvmclock_sync_fn); INIT_DELAYED_WORK(&kvm->arch.kvmclock_sync_work, kvmclock_sync_fn);
@ -9200,6 +9221,13 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
kvm_page_track_flush_slot(kvm, slot); kvm_page_track_flush_slot(kvm, slot);
} }
static inline bool kvm_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
{
return (is_guest_mode(vcpu) &&
kvm_x86_ops->guest_apic_has_interrupt &&
kvm_x86_ops->guest_apic_has_interrupt(vcpu));
}
static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu) static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
{ {
if (!list_empty_careful(&vcpu->async_pf.done)) if (!list_empty_careful(&vcpu->async_pf.done))
@ -9224,7 +9252,8 @@ static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
return true; return true;
if (kvm_arch_interrupt_allowed(vcpu) && if (kvm_arch_interrupt_allowed(vcpu) &&
kvm_cpu_has_interrupt(vcpu)) (kvm_cpu_has_interrupt(vcpu) ||
kvm_guest_apic_has_interrupt(vcpu)))
return true; return true;
if (kvm_hv_has_stimer_pending(vcpu)) if (kvm_hv_has_stimer_pending(vcpu))

View File

@ -815,10 +815,14 @@ void free_kernel_image_pages(void *begin, void *end)
set_memory_np_noalias(begin_ul, len_pages); set_memory_np_noalias(begin_ul, len_pages);
} }
void __weak mem_encrypt_free_decrypted_mem(void) { }
void __ref free_initmem(void) void __ref free_initmem(void)
{ {
e820__reallocate_tables(); e820__reallocate_tables();
mem_encrypt_free_decrypted_mem();
free_kernel_image_pages(&__init_begin, &__init_end); free_kernel_image_pages(&__init_begin, &__init_end);
} }

View File

@ -348,6 +348,30 @@ bool sev_active(void)
EXPORT_SYMBOL(sev_active); EXPORT_SYMBOL(sev_active);
/* Architecture __weak replacement functions */ /* Architecture __weak replacement functions */
void __init mem_encrypt_free_decrypted_mem(void)
{
unsigned long vaddr, vaddr_end, npages;
int r;
vaddr = (unsigned long)__start_bss_decrypted_unused;
vaddr_end = (unsigned long)__end_bss_decrypted;
npages = (vaddr_end - vaddr) >> PAGE_SHIFT;
/*
* The unused memory range was mapped decrypted, change the encryption
* attribute from decrypted to encrypted before freeing it.
*/
if (mem_encrypt_active()) {
r = set_memory_encrypted(vaddr, npages);
if (r) {
pr_warn("failed to free unused decrypted pages\n");
return;
}
}
free_init_pages("unused decrypted", vaddr, vaddr_end);
}
void __init mem_encrypt_init(void) void __init mem_encrypt_init(void)
{ {
if (!sme_me_mask) if (!sme_me_mask)

View File

@ -637,6 +637,15 @@ void __native_set_fixmap(enum fixed_addresses idx, pte_t pte)
{ {
unsigned long address = __fix_to_virt(idx); unsigned long address = __fix_to_virt(idx);
#ifdef CONFIG_X86_64
/*
* Ensure that the static initial page tables are covering the
* fixmap completely.
*/
BUILD_BUG_ON(__end_of_permanent_fixed_addresses >
(FIXMAP_PMD_NUM * PTRS_PER_PTE));
#endif
if (idx >= __end_of_fixed_addresses) { if (idx >= __end_of_fixed_addresses) {
BUG(); BUG();
return; return;

View File

@ -1907,7 +1907,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
/* L3_k[511] -> level2_fixmap_pgt */ /* L3_k[511] -> level2_fixmap_pgt */
convert_pfn_mfn(level3_kernel_pgt); convert_pfn_mfn(level3_kernel_pgt);
/* L3_k[511][506] -> level1_fixmap_pgt */ /* L3_k[511][508-FIXMAP_PMD_NUM ... 507] -> level1_fixmap_pgt */
convert_pfn_mfn(level2_fixmap_pgt); convert_pfn_mfn(level2_fixmap_pgt);
/* We get [511][511] and have Xen's version of level2_kernel_pgt */ /* We get [511][511] and have Xen's version of level2_kernel_pgt */
@ -1952,7 +1952,11 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO); set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO);
for (i = 0; i < FIXMAP_PMD_NUM; i++) {
set_page_prot(level1_fixmap_pgt + i * PTRS_PER_PTE,
PAGE_KERNEL_RO);
}
/* Pin down new L4 */ /* Pin down new L4 */
pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,

View File

@ -478,7 +478,7 @@ static void xen_convert_regs(const struct xen_pmu_regs *xen_regs,
irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id) irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id)
{ {
int err, ret = IRQ_NONE; int err, ret = IRQ_NONE;
struct pt_regs regs; struct pt_regs regs = {0};
const struct xen_pmu_data *xenpmu_data = get_xenpmu_data(); const struct xen_pmu_data *xenpmu_data = get_xenpmu_data();
uint8_t xenpmu_flags = get_xenpmu_flags(); uint8_t xenpmu_flags = get_xenpmu_flags();

View File

@ -1684,7 +1684,7 @@ void generic_end_io_acct(struct request_queue *q, int req_op,
const int sgrp = op_stat_group(req_op); const int sgrp = op_stat_group(req_op);
int cpu = part_stat_lock(); int cpu = part_stat_lock();
part_stat_add(cpu, part, ticks[sgrp], duration); part_stat_add(cpu, part, nsecs[sgrp], jiffies_to_nsecs(duration));
part_round_stats(q, cpu, part); part_round_stats(q, cpu, part);
part_dec_in_flight(q, part, op_is_write(req_op)); part_dec_in_flight(q, part, op_is_write(req_op));

View File

@ -2733,17 +2733,15 @@ void blk_account_io_done(struct request *req, u64 now)
* containing request is enough. * containing request is enough.
*/ */
if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) { if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) {
unsigned long duration;
const int sgrp = op_stat_group(req_op(req)); const int sgrp = op_stat_group(req_op(req));
struct hd_struct *part; struct hd_struct *part;
int cpu; int cpu;
duration = nsecs_to_jiffies(now - req->start_time_ns);
cpu = part_stat_lock(); cpu = part_stat_lock();
part = req->part; part = req->part;
part_stat_inc(cpu, part, ios[sgrp]); part_stat_inc(cpu, part, ios[sgrp]);
part_stat_add(cpu, part, ticks[sgrp], duration); part_stat_add(cpu, part, nsecs[sgrp], now - req->start_time_ns);
part_round_stats(req->q, cpu, part); part_round_stats(req->q, cpu, part);
part_dec_in_flight(req->q, part, rq_data_dir(req)); part_dec_in_flight(req->q, part, rq_data_dir(req));

View File

@ -322,16 +322,11 @@ void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
/* /*
* __blk_mq_update_nr_hw_queues will update the nr_hw_queues and * __blk_mq_update_nr_hw_queues will update the nr_hw_queues and
* queue_hw_ctx after freeze the queue. So we could use q_usage_counter * queue_hw_ctx after freeze the queue, so we use q_usage_counter
* to avoid race with it. __blk_mq_update_nr_hw_queues will users * to avoid race with it.
* synchronize_rcu to ensure all of the users go out of the critical
* section below and see zeroed q_usage_counter.
*/ */
rcu_read_lock(); if (!percpu_ref_tryget(&q->q_usage_counter))
if (percpu_ref_is_zero(&q->q_usage_counter)) {
rcu_read_unlock();
return; return;
}
queue_for_each_hw_ctx(q, hctx, i) { queue_for_each_hw_ctx(q, hctx, i) {
struct blk_mq_tags *tags = hctx->tags; struct blk_mq_tags *tags = hctx->tags;
@ -347,7 +342,7 @@ void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
bt_for_each(hctx, &tags->breserved_tags, fn, priv, true); bt_for_each(hctx, &tags->breserved_tags, fn, priv, true);
bt_for_each(hctx, &tags->bitmap_tags, fn, priv, false); bt_for_each(hctx, &tags->bitmap_tags, fn, priv, false);
} }
rcu_read_unlock(); blk_queue_exit(q);
} }
static int bt_alloc(struct sbitmap_queue *bt, unsigned int depth, static int bt_alloc(struct sbitmap_queue *bt, unsigned int depth,

View File

@ -1628,7 +1628,7 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
BUG_ON(!rq->q); BUG_ON(!rq->q);
if (rq->mq_ctx != this_ctx) { if (rq->mq_ctx != this_ctx) {
if (this_ctx) { if (this_ctx) {
trace_block_unplug(this_q, depth, from_schedule); trace_block_unplug(this_q, depth, !from_schedule);
blk_mq_sched_insert_requests(this_q, this_ctx, blk_mq_sched_insert_requests(this_q, this_ctx,
&ctx_list, &ctx_list,
from_schedule); from_schedule);
@ -1648,7 +1648,7 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
* on 'ctx_list'. Do those. * on 'ctx_list'. Do those.
*/ */
if (this_ctx) { if (this_ctx) {
trace_block_unplug(this_q, depth, from_schedule); trace_block_unplug(this_q, depth, !from_schedule);
blk_mq_sched_insert_requests(this_q, this_ctx, &ctx_list, blk_mq_sched_insert_requests(this_q, this_ctx, &ctx_list,
from_schedule); from_schedule);
} }

View File

@ -609,7 +609,7 @@ void elv_drain_elevator(struct request_queue *q)
while (e->type->ops.sq.elevator_dispatch_fn(q, 1)) while (e->type->ops.sq.elevator_dispatch_fn(q, 1))
; ;
if (q->nr_sorted && printed++ < 10) { if (q->nr_sorted && !blk_queue_is_zoned(q) && printed++ < 10 ) {
printk(KERN_ERR "%s: forced dispatching is broken " printk(KERN_ERR "%s: forced dispatching is broken "
"(nr_sorted=%u), please report this\n", "(nr_sorted=%u), please report this\n",
q->elevator->type->elevator_name, q->nr_sorted); q->elevator->type->elevator_name, q->nr_sorted);

View File

@ -1343,18 +1343,18 @@ static int diskstats_show(struct seq_file *seqf, void *v)
part_stat_read(hd, ios[STAT_READ]), part_stat_read(hd, ios[STAT_READ]),
part_stat_read(hd, merges[STAT_READ]), part_stat_read(hd, merges[STAT_READ]),
part_stat_read(hd, sectors[STAT_READ]), part_stat_read(hd, sectors[STAT_READ]),
jiffies_to_msecs(part_stat_read(hd, ticks[STAT_READ])), (unsigned int)part_stat_read_msecs(hd, STAT_READ),
part_stat_read(hd, ios[STAT_WRITE]), part_stat_read(hd, ios[STAT_WRITE]),
part_stat_read(hd, merges[STAT_WRITE]), part_stat_read(hd, merges[STAT_WRITE]),
part_stat_read(hd, sectors[STAT_WRITE]), part_stat_read(hd, sectors[STAT_WRITE]),
jiffies_to_msecs(part_stat_read(hd, ticks[STAT_WRITE])), (unsigned int)part_stat_read_msecs(hd, STAT_WRITE),
inflight[0], inflight[0],
jiffies_to_msecs(part_stat_read(hd, io_ticks)), jiffies_to_msecs(part_stat_read(hd, io_ticks)),
jiffies_to_msecs(part_stat_read(hd, time_in_queue)), jiffies_to_msecs(part_stat_read(hd, time_in_queue)),
part_stat_read(hd, ios[STAT_DISCARD]), part_stat_read(hd, ios[STAT_DISCARD]),
part_stat_read(hd, merges[STAT_DISCARD]), part_stat_read(hd, merges[STAT_DISCARD]),
part_stat_read(hd, sectors[STAT_DISCARD]), part_stat_read(hd, sectors[STAT_DISCARD]),
jiffies_to_msecs(part_stat_read(hd, ticks[STAT_DISCARD])) (unsigned int)part_stat_read_msecs(hd, STAT_DISCARD)
); );
} }
disk_part_iter_exit(&piter); disk_part_iter_exit(&piter);

View File

@ -136,18 +136,18 @@ ssize_t part_stat_show(struct device *dev,
part_stat_read(p, ios[STAT_READ]), part_stat_read(p, ios[STAT_READ]),
part_stat_read(p, merges[STAT_READ]), part_stat_read(p, merges[STAT_READ]),
(unsigned long long)part_stat_read(p, sectors[STAT_READ]), (unsigned long long)part_stat_read(p, sectors[STAT_READ]),
jiffies_to_msecs(part_stat_read(p, ticks[STAT_READ])), (unsigned int)part_stat_read_msecs(p, STAT_READ),
part_stat_read(p, ios[STAT_WRITE]), part_stat_read(p, ios[STAT_WRITE]),
part_stat_read(p, merges[STAT_WRITE]), part_stat_read(p, merges[STAT_WRITE]),
(unsigned long long)part_stat_read(p, sectors[STAT_WRITE]), (unsigned long long)part_stat_read(p, sectors[STAT_WRITE]),
jiffies_to_msecs(part_stat_read(p, ticks[STAT_WRITE])), (unsigned int)part_stat_read_msecs(p, STAT_WRITE),
inflight[0], inflight[0],
jiffies_to_msecs(part_stat_read(p, io_ticks)), jiffies_to_msecs(part_stat_read(p, io_ticks)),
jiffies_to_msecs(part_stat_read(p, time_in_queue)), jiffies_to_msecs(part_stat_read(p, time_in_queue)),
part_stat_read(p, ios[STAT_DISCARD]), part_stat_read(p, ios[STAT_DISCARD]),
part_stat_read(p, merges[STAT_DISCARD]), part_stat_read(p, merges[STAT_DISCARD]),
(unsigned long long)part_stat_read(p, sectors[STAT_DISCARD]), (unsigned long long)part_stat_read(p, sectors[STAT_DISCARD]),
jiffies_to_msecs(part_stat_read(p, ticks[STAT_DISCARD]))); (unsigned int)part_stat_read_msecs(p, STAT_DISCARD));
} }
ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr, ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr,

View File

@ -5359,10 +5359,20 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
*/ */
int ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active) int ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active)
{ {
u64 done_mask, ap_qc_active = ap->qc_active;
int nr_done = 0; int nr_done = 0;
u64 done_mask;
done_mask = ap->qc_active ^ qc_active; /*
* If the internal tag is set on ap->qc_active, then we care about
* bit0 on the passed in qc_active mask. Move that bit up to match
* the internal tag.
*/
if (ap_qc_active & (1ULL << ATA_TAG_INTERNAL)) {
qc_active |= (qc_active & 0x01) << ATA_TAG_INTERNAL;
qc_active ^= qc_active & 0x01;
}
done_mask = ap_qc_active ^ qc_active;
if (unlikely(done_mask & qc_active)) { if (unlikely(done_mask & qc_active)) {
ata_port_err(ap, "illegal qc_active transition (%08llx->%08llx)\n", ata_port_err(ap, "illegal qc_active transition (%08llx->%08llx)\n",

View File

@ -3467,6 +3467,9 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
(struct floppy_struct **)&outparam); (struct floppy_struct **)&outparam);
if (ret) if (ret)
return ret; return ret;
memcpy(&inparam.g, outparam,
offsetof(struct floppy_struct, name));
outparam = &inparam.g;
break; break;
case FDMSGON: case FDMSGON:
UDP->flags |= FTD_MSG; UDP->flags |= FTD_MSG;

View File

@ -2670,8 +2670,8 @@ static void purge_persistent_grants(struct blkfront_info *info)
list_del(&gnt_list_entry->node); list_del(&gnt_list_entry->node);
gnttab_end_foreign_access(gnt_list_entry->gref, 0, 0UL); gnttab_end_foreign_access(gnt_list_entry->gref, 0, 0UL);
rinfo->persistent_gnts_c--; rinfo->persistent_gnts_c--;
__free_page(gnt_list_entry->page); gnt_list_entry->gref = GRANT_INVALID_REF;
kfree(gnt_list_entry); list_add_tail(&gnt_list_entry->node, &rinfo->grants);
} }
spin_unlock_irqrestore(&rinfo->ring_lock, flags); spin_unlock_irqrestore(&rinfo->ring_lock, flags);

View File

@ -543,6 +543,8 @@ static void hci_uart_tty_close(struct tty_struct *tty)
} }
clear_bit(HCI_UART_PROTO_SET, &hu->flags); clear_bit(HCI_UART_PROTO_SET, &hu->flags);
percpu_free_rwsem(&hu->proto_lock);
kfree(hu); kfree(hu);
} }

View File

@ -55,6 +55,7 @@ struct clk_plt_data {
u8 nparents; u8 nparents;
struct clk_plt *clks[PMC_CLK_NUM]; struct clk_plt *clks[PMC_CLK_NUM];
struct clk_lookup *mclk_lookup; struct clk_lookup *mclk_lookup;
struct clk_lookup *ether_clk_lookup;
}; };
/* Return an index in parent table */ /* Return an index in parent table */
@ -186,13 +187,6 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,
pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE; pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
spin_lock_init(&pclk->lock); spin_lock_init(&pclk->lock);
/*
* If the clock was already enabled by the firmware mark it as critical
* to avoid it being gated by the clock framework if no driver owns it.
*/
if (plt_clk_is_enabled(&pclk->hw))
init.flags |= CLK_IS_CRITICAL;
ret = devm_clk_hw_register(&pdev->dev, &pclk->hw); ret = devm_clk_hw_register(&pdev->dev, &pclk->hw);
if (ret) { if (ret) {
pclk = ERR_PTR(ret); pclk = ERR_PTR(ret);
@ -351,11 +345,20 @@ static int plt_clk_probe(struct platform_device *pdev)
goto err_unreg_clk_plt; goto err_unreg_clk_plt;
} }
data->ether_clk_lookup = clkdev_hw_create(&data->clks[4]->hw,
"ether_clk", NULL);
if (!data->ether_clk_lookup) {
err = -ENOMEM;
goto err_drop_mclk;
}
plt_clk_free_parent_names_loop(parent_names, data->nparents); plt_clk_free_parent_names_loop(parent_names, data->nparents);
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
return 0; return 0;
err_drop_mclk:
clkdev_drop(data->mclk_lookup);
err_unreg_clk_plt: err_unreg_clk_plt:
plt_clk_unregister_loop(data, i); plt_clk_unregister_loop(data, i);
plt_clk_unregister_parents(data); plt_clk_unregister_parents(data);
@ -369,6 +372,7 @@ static int plt_clk_remove(struct platform_device *pdev)
data = platform_get_drvdata(pdev); data = platform_get_drvdata(pdev);
clkdev_drop(data->ether_clk_lookup);
clkdev_drop(data->mclk_lookup); clkdev_drop(data->mclk_lookup);
plt_clk_unregister_loop(data, PMC_CLK_NUM); plt_clk_unregister_loop(data, PMC_CLK_NUM);
plt_clk_unregister_parents(data); plt_clk_unregister_parents(data);

View File

@ -180,26 +180,29 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
data->base = of_iomap(node, 0); data->base = of_iomap(node, 0);
if (!data->base) { if (!data->base) {
pr_err("Could not map PIT address\n"); pr_err("Could not map PIT address\n");
return -ENXIO; ret = -ENXIO;
goto exit;
} }
data->mck = of_clk_get(node, 0); data->mck = of_clk_get(node, 0);
if (IS_ERR(data->mck)) { if (IS_ERR(data->mck)) {
pr_err("Unable to get mck clk\n"); pr_err("Unable to get mck clk\n");
return PTR_ERR(data->mck); ret = PTR_ERR(data->mck);
goto exit;
} }
ret = clk_prepare_enable(data->mck); ret = clk_prepare_enable(data->mck);
if (ret) { if (ret) {
pr_err("Unable to enable mck\n"); pr_err("Unable to enable mck\n");
return ret; goto exit;
} }
/* Get the interrupts property */ /* Get the interrupts property */
data->irq = irq_of_parse_and_map(node, 0); data->irq = irq_of_parse_and_map(node, 0);
if (!data->irq) { if (!data->irq) {
pr_err("Unable to get IRQ from DT\n"); pr_err("Unable to get IRQ from DT\n");
return -EINVAL; ret = -EINVAL;
goto exit;
} }
/* /*
@ -227,7 +230,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
ret = clocksource_register_hz(&data->clksrc, pit_rate); ret = clocksource_register_hz(&data->clksrc, pit_rate);
if (ret) { if (ret) {
pr_err("Failed to register clocksource\n"); pr_err("Failed to register clocksource\n");
return ret; goto exit;
} }
/* Set up irq handler */ /* Set up irq handler */
@ -236,7 +239,8 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
"at91_tick", data); "at91_tick", data);
if (ret) { if (ret) {
pr_err("Unable to setup IRQ\n"); pr_err("Unable to setup IRQ\n");
return ret; clocksource_unregister(&data->clksrc);
goto exit;
} }
/* Set up and register clockevents */ /* Set up and register clockevents */
@ -254,6 +258,10 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
clockevents_register_device(&data->clkevt); clockevents_register_device(&data->clkevt);
return 0; return 0;
exit:
kfree(data);
return ret;
} }
TIMER_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit", TIMER_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
at91sam926x_pit_dt_init); at91sam926x_pit_dt_init);

View File

@ -130,13 +130,17 @@ static int fttmr010_timer_set_next_event(unsigned long cycles,
cr &= ~fttmr010->t1_enable_val; cr &= ~fttmr010->t1_enable_val;
writel(cr, fttmr010->base + TIMER_CR); writel(cr, fttmr010->base + TIMER_CR);
/* Setup the match register forward/backward in time */ if (fttmr010->count_down) {
cr = readl(fttmr010->base + TIMER1_COUNT); /*
if (fttmr010->count_down) * ASPEED Timer Controller will load TIMER1_LOAD register
cr -= cycles; * into TIMER1_COUNT register when the timer is re-enabled.
else */
cr += cycles; writel(cycles, fttmr010->base + TIMER1_LOAD);
writel(cr, fttmr010->base + TIMER1_MATCH1); } else {
/* Setup the match register forward in time */
cr = readl(fttmr010->base + TIMER1_COUNT);
writel(cr + cycles, fttmr010->base + TIMER1_MATCH1);
}
/* Start */ /* Start */
cr = readl(fttmr010->base + TIMER_CR); cr = readl(fttmr010->base + TIMER_CR);

View File

@ -97,6 +97,9 @@ static int __init ti_32k_timer_init(struct device_node *np)
return -ENXIO; return -ENXIO;
} }
if (!of_machine_is_compatible("ti,am43"))
ti_32k_timer.cs.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
ti_32k_timer.counter = ti_32k_timer.base; ti_32k_timer.counter = ti_32k_timer.base;
/* /*

View File

@ -44,7 +44,7 @@ enum _msm8996_version {
struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev; struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void) static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void)
{ {
size_t len; size_t len;
u32 *msm_id; u32 *msm_id;
@ -222,7 +222,7 @@ static int __init qcom_cpufreq_kryo_init(void)
} }
module_init(qcom_cpufreq_kryo_init); module_init(qcom_cpufreq_kryo_init);
static void __init qcom_cpufreq_kryo_exit(void) static void __exit qcom_cpufreq_kryo_exit(void)
{ {
platform_device_unregister(kryo_cpufreq_pdev); platform_device_unregister(kryo_cpufreq_pdev);
platform_driver_unregister(&qcom_cpufreq_kryo_driver); platform_driver_unregister(&qcom_cpufreq_kryo_driver);

View File

@ -38,6 +38,17 @@ static DEFINE_MUTEX(sev_cmd_mutex);
static struct sev_misc_dev *misc_dev; static struct sev_misc_dev *misc_dev;
static struct psp_device *psp_master; static struct psp_device *psp_master;
static int psp_cmd_timeout = 100;
module_param(psp_cmd_timeout, int, 0644);
MODULE_PARM_DESC(psp_cmd_timeout, " default timeout value, in seconds, for PSP commands");
static int psp_probe_timeout = 5;
module_param(psp_probe_timeout, int, 0644);
MODULE_PARM_DESC(psp_probe_timeout, " default timeout value, in seconds, during PSP device probe");
static bool psp_dead;
static int psp_timeout;
static struct psp_device *psp_alloc_struct(struct sp_device *sp) static struct psp_device *psp_alloc_struct(struct sp_device *sp)
{ {
struct device *dev = sp->dev; struct device *dev = sp->dev;
@ -82,10 +93,19 @@ static irqreturn_t psp_irq_handler(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void sev_wait_cmd_ioc(struct psp_device *psp, unsigned int *reg) static int sev_wait_cmd_ioc(struct psp_device *psp,
unsigned int *reg, unsigned int timeout)
{ {
wait_event(psp->sev_int_queue, psp->sev_int_rcvd); int ret;
ret = wait_event_timeout(psp->sev_int_queue,
psp->sev_int_rcvd, timeout * HZ);
if (!ret)
return -ETIMEDOUT;
*reg = ioread32(psp->io_regs + psp->vdata->cmdresp_reg); *reg = ioread32(psp->io_regs + psp->vdata->cmdresp_reg);
return 0;
} }
static int sev_cmd_buffer_len(int cmd) static int sev_cmd_buffer_len(int cmd)
@ -133,12 +153,15 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
if (!psp) if (!psp)
return -ENODEV; return -ENODEV;
if (psp_dead)
return -EBUSY;
/* Get the physical address of the command buffer */ /* Get the physical address of the command buffer */
phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0; phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0;
phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0; phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0;
dev_dbg(psp->dev, "sev command id %#x buffer 0x%08x%08x\n", dev_dbg(psp->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n",
cmd, phys_msb, phys_lsb); cmd, phys_msb, phys_lsb, psp_timeout);
print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data, print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data,
sev_cmd_buffer_len(cmd), false); sev_cmd_buffer_len(cmd), false);
@ -154,7 +177,18 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
iowrite32(reg, psp->io_regs + psp->vdata->cmdresp_reg); iowrite32(reg, psp->io_regs + psp->vdata->cmdresp_reg);
/* wait for command completion */ /* wait for command completion */
sev_wait_cmd_ioc(psp, &reg); ret = sev_wait_cmd_ioc(psp, &reg, psp_timeout);
if (ret) {
if (psp_ret)
*psp_ret = 0;
dev_err(psp->dev, "sev command %#x timed out, disabling PSP \n", cmd);
psp_dead = true;
return ret;
}
psp_timeout = psp_cmd_timeout;
if (psp_ret) if (psp_ret)
*psp_ret = reg & PSP_CMDRESP_ERR_MASK; *psp_ret = reg & PSP_CMDRESP_ERR_MASK;
@ -888,6 +922,8 @@ void psp_pci_init(void)
psp_master = sp->psp_data; psp_master = sp->psp_data;
psp_timeout = psp_probe_timeout;
if (sev_get_api_version()) if (sev_get_api_version())
goto err; goto err;

View File

@ -535,6 +535,11 @@ static unsigned long dax_get_unmapped_area(struct file *filp,
return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags); return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
} }
static const struct address_space_operations dev_dax_aops = {
.set_page_dirty = noop_set_page_dirty,
.invalidatepage = noop_invalidatepage,
};
static int dax_open(struct inode *inode, struct file *filp) static int dax_open(struct inode *inode, struct file *filp)
{ {
struct dax_device *dax_dev = inode_dax(inode); struct dax_device *dax_dev = inode_dax(inode);
@ -544,6 +549,7 @@ static int dax_open(struct inode *inode, struct file *filp)
dev_dbg(&dev_dax->dev, "trace\n"); dev_dbg(&dev_dax->dev, "trace\n");
inode->i_mapping = __dax_inode->i_mapping; inode->i_mapping = __dax_inode->i_mapping;
inode->i_mapping->host = __dax_inode; inode->i_mapping->host = __dax_inode;
inode->i_mapping->a_ops = &dev_dax_aops;
filp->f_mapping = inode->i_mapping; filp->f_mapping = inode->i_mapping;
filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping); filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping);
filp->private_data = dev_dax; filp->private_data = dev_dax;

View File

@ -90,14 +90,17 @@ config EFI_ARMSTUB
config EFI_ARMSTUB_DTB_LOADER config EFI_ARMSTUB_DTB_LOADER
bool "Enable the DTB loader" bool "Enable the DTB loader"
depends on EFI_ARMSTUB depends on EFI_ARMSTUB
default y
help help
Select this config option to add support for the dtb= command Select this config option to add support for the dtb= command
line parameter, allowing a device tree blob to be loaded into line parameter, allowing a device tree blob to be loaded into
memory from the EFI System Partition by the stub. memory from the EFI System Partition by the stub.
The device tree is typically provided by the platform or by If the device tree is provided by the platform or by
the bootloader, so this option is mostly for development the bootloader this option may not be needed.
purposes only. But, for various development reasons and to maintain existing
functionality for bootloaders that do not have such support
this option is necessary.
config EFI_BOOTLOADER_CONTROL config EFI_BOOTLOADER_CONTROL
tristate "EFI Bootloader Control" tristate "EFI Bootloader Control"

View File

@ -272,7 +272,7 @@ void amdgpu_amdkfd_gpu_reset(struct kgd_dev *kgd)
int alloc_gtt_mem(struct kgd_dev *kgd, size_t size, int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
void **mem_obj, uint64_t *gpu_addr, void **mem_obj, uint64_t *gpu_addr,
void **cpu_ptr) void **cpu_ptr, bool mqd_gfx9)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)kgd; struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
struct amdgpu_bo *bo = NULL; struct amdgpu_bo *bo = NULL;
@ -287,6 +287,10 @@ int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC; bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC;
bp.type = ttm_bo_type_kernel; bp.type = ttm_bo_type_kernel;
bp.resv = NULL; bp.resv = NULL;
if (mqd_gfx9)
bp.flags |= AMDGPU_GEM_CREATE_MQD_GFX9;
r = amdgpu_bo_create(adev, &bp, &bo); r = amdgpu_bo_create(adev, &bp, &bo);
if (r) { if (r) {
dev_err(adev->dev, dev_err(adev->dev,

View File

@ -136,7 +136,7 @@ void amdgpu_amdkfd_gpu_reset(struct kgd_dev *kgd);
/* Shared API */ /* Shared API */
int alloc_gtt_mem(struct kgd_dev *kgd, size_t size, int alloc_gtt_mem(struct kgd_dev *kgd, size_t size,
void **mem_obj, uint64_t *gpu_addr, void **mem_obj, uint64_t *gpu_addr,
void **cpu_ptr); void **cpu_ptr, bool mqd_gfx9);
void free_gtt_mem(struct kgd_dev *kgd, void *mem_obj); void free_gtt_mem(struct kgd_dev *kgd, void *mem_obj);
void get_local_mem_info(struct kgd_dev *kgd, void get_local_mem_info(struct kgd_dev *kgd,
struct kfd_local_mem_info *mem_info); struct kfd_local_mem_info *mem_info);

View File

@ -685,7 +685,7 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
while (true) { while (true) {
temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS); temp = RREG32(sdma_base_addr + mmSDMA0_RLC0_CONTEXT_STATUS);
if (temp & SDMA0_STATUS_REG__RB_CMD_IDLE__SHIFT) if (temp & SDMA0_RLC0_CONTEXT_STATUS__IDLE_MASK)
break; break;
if (time_after(jiffies, end_jiffies)) if (time_after(jiffies, end_jiffies))
return -ETIME; return -ETIME;

View File

@ -367,12 +367,14 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
break; break;
case CHIP_POLARIS10: case CHIP_POLARIS10:
if (type == CGS_UCODE_ID_SMU) { if (type == CGS_UCODE_ID_SMU) {
if ((adev->pdev->device == 0x67df) && if (((adev->pdev->device == 0x67df) &&
((adev->pdev->revision == 0xe0) || ((adev->pdev->revision == 0xe0) ||
(adev->pdev->revision == 0xe3) || (adev->pdev->revision == 0xe3) ||
(adev->pdev->revision == 0xe4) || (adev->pdev->revision == 0xe4) ||
(adev->pdev->revision == 0xe5) || (adev->pdev->revision == 0xe5) ||
(adev->pdev->revision == 0xe7) || (adev->pdev->revision == 0xe7) ||
(adev->pdev->revision == 0xef))) ||
((adev->pdev->device == 0x6fdf) &&
(adev->pdev->revision == 0xef))) { (adev->pdev->revision == 0xef))) {
info->is_kicker = true; info->is_kicker = true;
strcpy(fw_name, "amdgpu/polaris10_k_smc.bin"); strcpy(fw_name, "amdgpu/polaris10_k_smc.bin");

View File

@ -740,6 +740,7 @@ static const struct pci_device_id pciidlist[] = {
{0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, {0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, {0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10}, {0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
{0x1002, 0x6FDF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
/* Polaris12 */ /* Polaris12 */
{0x1002, 0x6980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, {0x1002, 0x6980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
{0x1002, 0x6981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12}, {0x1002, 0x6981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},

View File

@ -258,6 +258,8 @@ int amdgpu_vce_suspend(struct amdgpu_device *adev)
{ {
int i; int i;
cancel_delayed_work_sync(&adev->vce.idle_work);
if (adev->vce.vcpu_bo == NULL) if (adev->vce.vcpu_bo == NULL)
return 0; return 0;
@ -268,7 +270,6 @@ int amdgpu_vce_suspend(struct amdgpu_device *adev)
if (i == AMDGPU_MAX_VCE_HANDLES) if (i == AMDGPU_MAX_VCE_HANDLES)
return 0; return 0;
cancel_delayed_work_sync(&adev->vce.idle_work);
/* TODO: suspending running encoding sessions isn't supported */ /* TODO: suspending running encoding sessions isn't supported */
return -EINVAL; return -EINVAL;
} }

View File

@ -153,11 +153,11 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev)
unsigned size; unsigned size;
void *ptr; void *ptr;
cancel_delayed_work_sync(&adev->vcn.idle_work);
if (adev->vcn.vcpu_bo == NULL) if (adev->vcn.vcpu_bo == NULL)
return 0; return 0;
cancel_delayed_work_sync(&adev->vcn.idle_work);
size = amdgpu_bo_size(adev->vcn.vcpu_bo); size = amdgpu_bo_size(adev->vcn.vcpu_bo);
ptr = adev->vcn.cpu_addr; ptr = adev->vcn.cpu_addr;

View File

@ -457,7 +457,8 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
if (kfd->kfd2kgd->init_gtt_mem_allocation( if (kfd->kfd2kgd->init_gtt_mem_allocation(
kfd->kgd, size, &kfd->gtt_mem, kfd->kgd, size, &kfd->gtt_mem,
&kfd->gtt_start_gpu_addr, &kfd->gtt_start_cpu_ptr)){ &kfd->gtt_start_gpu_addr, &kfd->gtt_start_cpu_ptr,
false)) {
dev_err(kfd_device, "Could not allocate %d bytes\n", size); dev_err(kfd_device, "Could not allocate %d bytes\n", size);
goto out; goto out;
} }

View File

@ -62,9 +62,20 @@ int kfd_iommu_device_init(struct kfd_dev *kfd)
struct amd_iommu_device_info iommu_info; struct amd_iommu_device_info iommu_info;
unsigned int pasid_limit; unsigned int pasid_limit;
int err; int err;
struct kfd_topology_device *top_dev;
if (!kfd->device_info->needs_iommu_device) top_dev = kfd_topology_device_by_id(kfd->id);
/*
* Overwrite ATS capability according to needs_iommu_device to fix
* potential missing corresponding bit in CRAT of BIOS.
*/
if (!kfd->device_info->needs_iommu_device) {
top_dev->node_props.capability &= ~HSA_CAP_ATS_PRESENT;
return 0; return 0;
}
top_dev->node_props.capability |= HSA_CAP_ATS_PRESENT;
iommu_info.flags = 0; iommu_info.flags = 0;
err = amd_iommu_device_info(kfd->pdev, &iommu_info); err = amd_iommu_device_info(kfd->pdev, &iommu_info);

View File

@ -88,7 +88,7 @@ static int init_mqd(struct mqd_manager *mm, void **mqd,
ALIGN(sizeof(struct v9_mqd), PAGE_SIZE), ALIGN(sizeof(struct v9_mqd), PAGE_SIZE),
&((*mqd_mem_obj)->gtt_mem), &((*mqd_mem_obj)->gtt_mem),
&((*mqd_mem_obj)->gpu_addr), &((*mqd_mem_obj)->gpu_addr),
(void *)&((*mqd_mem_obj)->cpu_ptr)); (void *)&((*mqd_mem_obj)->cpu_ptr), true);
} else } else
retval = kfd_gtt_sa_allocate(mm->dev, sizeof(struct v9_mqd), retval = kfd_gtt_sa_allocate(mm->dev, sizeof(struct v9_mqd),
mqd_mem_obj); mqd_mem_obj);

View File

@ -806,6 +806,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu);
int kfd_topology_remove_device(struct kfd_dev *gpu); int kfd_topology_remove_device(struct kfd_dev *gpu);
struct kfd_topology_device *kfd_topology_device_by_proximity_domain( struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
uint32_t proximity_domain); uint32_t proximity_domain);
struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id);
struct kfd_dev *kfd_device_by_id(uint32_t gpu_id); struct kfd_dev *kfd_device_by_id(uint32_t gpu_id);
struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev); struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev);
int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev); int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev);

View File

@ -63,22 +63,33 @@ struct kfd_topology_device *kfd_topology_device_by_proximity_domain(
return device; return device;
} }
struct kfd_dev *kfd_device_by_id(uint32_t gpu_id) struct kfd_topology_device *kfd_topology_device_by_id(uint32_t gpu_id)
{ {
struct kfd_topology_device *top_dev; struct kfd_topology_device *top_dev = NULL;
struct kfd_dev *device = NULL; struct kfd_topology_device *ret = NULL;
down_read(&topology_lock); down_read(&topology_lock);
list_for_each_entry(top_dev, &topology_device_list, list) list_for_each_entry(top_dev, &topology_device_list, list)
if (top_dev->gpu_id == gpu_id) { if (top_dev->gpu_id == gpu_id) {
device = top_dev->gpu; ret = top_dev;
break; break;
} }
up_read(&topology_lock); up_read(&topology_lock);
return device; return ret;
}
struct kfd_dev *kfd_device_by_id(uint32_t gpu_id)
{
struct kfd_topology_device *top_dev;
top_dev = kfd_topology_device_by_id(gpu_id);
if (!top_dev)
return NULL;
return top_dev->gpu;
} }
struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev) struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev)

View File

@ -641,6 +641,87 @@ amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,
return NULL; return NULL;
} }
static void emulated_link_detect(struct dc_link *link)
{
struct dc_sink_init_data sink_init_data = { 0 };
struct display_sink_capability sink_caps = { 0 };
enum dc_edid_status edid_status;
struct dc_context *dc_ctx = link->ctx;
struct dc_sink *sink = NULL;
struct dc_sink *prev_sink = NULL;
link->type = dc_connection_none;
prev_sink = link->local_sink;
if (prev_sink != NULL)
dc_sink_retain(prev_sink);
switch (link->connector_signal) {
case SIGNAL_TYPE_HDMI_TYPE_A: {
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
break;
}
case SIGNAL_TYPE_DVI_SINGLE_LINK: {
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
break;
}
case SIGNAL_TYPE_DVI_DUAL_LINK: {
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
break;
}
case SIGNAL_TYPE_LVDS: {
sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
sink_caps.signal = SIGNAL_TYPE_LVDS;
break;
}
case SIGNAL_TYPE_EDP: {
sink_caps.transaction_type =
DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
sink_caps.signal = SIGNAL_TYPE_EDP;
break;
}
case SIGNAL_TYPE_DISPLAY_PORT: {
sink_caps.transaction_type =
DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
sink_caps.signal = SIGNAL_TYPE_VIRTUAL;
break;
}
default:
DC_ERROR("Invalid connector type! signal:%d\n",
link->connector_signal);
return;
}
sink_init_data.link = link;
sink_init_data.sink_signal = sink_caps.signal;
sink = dc_sink_create(&sink_init_data);
if (!sink) {
DC_ERROR("Failed to create sink!\n");
return;
}
link->local_sink = sink;
edid_status = dm_helpers_read_local_edid(
link->ctx,
link,
sink);
if (edid_status != EDID_OK)
DC_ERROR("Failed to read EDID");
}
static int dm_resume(void *handle) static int dm_resume(void *handle)
{ {
struct amdgpu_device *adev = handle; struct amdgpu_device *adev = handle;
@ -654,6 +735,7 @@ static int dm_resume(void *handle)
struct drm_plane *plane; struct drm_plane *plane;
struct drm_plane_state *new_plane_state; struct drm_plane_state *new_plane_state;
struct dm_plane_state *dm_new_plane_state; struct dm_plane_state *dm_new_plane_state;
enum dc_connection_type new_connection_type = dc_connection_none;
int ret; int ret;
int i; int i;
@ -684,7 +766,13 @@ static int dm_resume(void *handle)
continue; continue;
mutex_lock(&aconnector->hpd_lock); mutex_lock(&aconnector->hpd_lock);
dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
DRM_ERROR("KMS: Failed to detect connector\n");
if (aconnector->base.force && new_connection_type == dc_connection_none)
emulated_link_detect(aconnector->dc_link);
else
dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
if (aconnector->fake_enable && aconnector->dc_link->local_sink) if (aconnector->fake_enable && aconnector->dc_link->local_sink)
aconnector->fake_enable = false; aconnector->fake_enable = false;
@ -922,6 +1010,7 @@ static void handle_hpd_irq(void *param)
struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param;
struct drm_connector *connector = &aconnector->base; struct drm_connector *connector = &aconnector->base;
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
enum dc_connection_type new_connection_type = dc_connection_none;
/* In case of failure or MST no need to update connector status or notify the OS /* In case of failure or MST no need to update connector status or notify the OS
* since (for MST case) MST does this in it's own context. * since (for MST case) MST does this in it's own context.
@ -931,7 +1020,21 @@ static void handle_hpd_irq(void *param)
if (aconnector->fake_enable) if (aconnector->fake_enable)
aconnector->fake_enable = false; aconnector->fake_enable = false;
if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) { if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
DRM_ERROR("KMS: Failed to detect connector\n");
if (aconnector->base.force && new_connection_type == dc_connection_none) {
emulated_link_detect(aconnector->dc_link);
drm_modeset_lock_all(dev);
dm_restore_drm_connector_state(dev, connector);
drm_modeset_unlock_all(dev);
if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
drm_kms_helper_hotplug_event(dev);
} else if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) {
amdgpu_dm_update_connector_after_detect(aconnector); amdgpu_dm_update_connector_after_detect(aconnector);
@ -1031,6 +1134,7 @@ static void handle_hpd_rx_irq(void *param)
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct dc_link *dc_link = aconnector->dc_link; struct dc_link *dc_link = aconnector->dc_link;
bool is_mst_root_connector = aconnector->mst_mgr.mst_state; bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
enum dc_connection_type new_connection_type = dc_connection_none;
/* TODO:Temporary add mutex to protect hpd interrupt not have a gpio /* TODO:Temporary add mutex to protect hpd interrupt not have a gpio
* conflict, after implement i2c helper, this mutex should be * conflict, after implement i2c helper, this mutex should be
@ -1042,7 +1146,24 @@ static void handle_hpd_rx_irq(void *param)
if (dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL) && if (dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL) &&
!is_mst_root_connector) { !is_mst_root_connector) {
/* Downstream Port status changed. */ /* Downstream Port status changed. */
if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) { if (!dc_link_detect_sink(dc_link, &new_connection_type))
DRM_ERROR("KMS: Failed to detect connector\n");
if (aconnector->base.force && new_connection_type == dc_connection_none) {
emulated_link_detect(dc_link);
if (aconnector->fake_enable)
aconnector->fake_enable = false;
amdgpu_dm_update_connector_after_detect(aconnector);
drm_modeset_lock_all(dev);
dm_restore_drm_connector_state(dev, connector);
drm_modeset_unlock_all(dev);
drm_kms_helper_hotplug_event(dev);
} else if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) {
if (aconnector->fake_enable) if (aconnector->fake_enable)
aconnector->fake_enable = false; aconnector->fake_enable = false;
@ -1433,6 +1554,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
struct amdgpu_mode_info *mode_info = &adev->mode_info; struct amdgpu_mode_info *mode_info = &adev->mode_info;
uint32_t link_cnt; uint32_t link_cnt;
int32_t total_overlay_planes, total_primary_planes; int32_t total_overlay_planes, total_primary_planes;
enum dc_connection_type new_connection_type = dc_connection_none;
link_cnt = dm->dc->caps.max_links; link_cnt = dm->dc->caps.max_links;
if (amdgpu_dm_mode_config_init(dm->adev)) { if (amdgpu_dm_mode_config_init(dm->adev)) {
@ -1499,7 +1621,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
link = dc_get_link_at_index(dm->dc, i); link = dc_get_link_at_index(dm->dc, i);
if (dc_link_detect(link, DETECT_REASON_BOOT)) { if (!dc_link_detect_sink(link, &new_connection_type))
DRM_ERROR("KMS: Failed to detect connector\n");
if (aconnector->base.force && new_connection_type == dc_connection_none) {
emulated_link_detect(link);
amdgpu_dm_update_connector_after_detect(aconnector);
} else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
amdgpu_dm_update_connector_after_detect(aconnector); amdgpu_dm_update_connector_after_detect(aconnector);
register_backlight_device(dm, link); register_backlight_device(dm, link);
} }
@ -2494,7 +2623,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (dm_state && dm_state->freesync_capable) if (dm_state && dm_state->freesync_capable)
stream->ignore_msa_timing_param = true; stream->ignore_msa_timing_param = true;
finish: finish:
if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL) if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL && aconnector->base.force != DRM_FORCE_ON)
dc_sink_release(sink); dc_sink_release(sink);
return stream; return stream;

View File

@ -195,7 +195,7 @@ static bool program_hpd_filter(
return result; return result;
} }
static bool detect_sink(struct dc_link *link, enum dc_connection_type *type) bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type)
{ {
uint32_t is_hpd_high = 0; uint32_t is_hpd_high = 0;
struct gpio *hpd_pin; struct gpio *hpd_pin;
@ -604,7 +604,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
if (link->connector_signal == SIGNAL_TYPE_VIRTUAL) if (link->connector_signal == SIGNAL_TYPE_VIRTUAL)
return false; return false;
if (false == detect_sink(link, &new_connection_type)) { if (false == dc_link_detect_sink(link, &new_connection_type)) {
BREAK_TO_DEBUGGER(); BREAK_TO_DEBUGGER();
return false; return false;
} }

View File

@ -215,6 +215,7 @@ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable);
bool dc_link_is_dp_sink_present(struct dc_link *link); bool dc_link_is_dp_sink_present(struct dc_link *link);
bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type);
/* /*
* DPCD access interfaces * DPCD access interfaces
*/ */

View File

@ -2560,7 +2560,7 @@ static void pplib_apply_display_requirements(
dc->prev_display_config = *pp_display_cfg; dc->prev_display_config = *pp_display_cfg;
} }
void dce110_set_bandwidth( static void dce110_set_bandwidth(
struct dc *dc, struct dc *dc,
struct dc_state *context, struct dc_state *context,
bool decrease_allowed) bool decrease_allowed)

View File

@ -68,11 +68,6 @@ void dce110_fill_display_configs(
const struct dc_state *context, const struct dc_state *context,
struct dm_pp_display_configuration *pp_display_cfg); struct dm_pp_display_configuration *pp_display_cfg);
void dce110_set_bandwidth(
struct dc *dc,
struct dc_state *context,
bool decrease_allowed);
uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context); uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context);
void dp_receiver_power_ctrl(struct dc_link *link, bool on); void dp_receiver_power_ctrl(struct dc_link *link, bool on);

View File

@ -244,17 +244,6 @@ static void dce120_update_dchub(
dh_data->dchub_info_valid = false; dh_data->dchub_info_valid = false;
} }
static void dce120_set_bandwidth(
struct dc *dc,
struct dc_state *context,
bool decrease_allowed)
{
if (context->stream_count <= 0)
return;
dce110_set_bandwidth(dc, context, decrease_allowed);
}
void dce120_hw_sequencer_construct(struct dc *dc) void dce120_hw_sequencer_construct(struct dc *dc)
{ {
/* All registers used by dce11.2 match those in dce11 in offset and /* All registers used by dce11.2 match those in dce11 in offset and
@ -263,6 +252,5 @@ void dce120_hw_sequencer_construct(struct dc *dc)
dce110_hw_sequencer_construct(dc); dce110_hw_sequencer_construct(dc);
dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating; dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating;
dc->hwss.update_dchub = dce120_update_dchub; dc->hwss.update_dchub = dce120_update_dchub;
dc->hwss.set_bandwidth = dce120_set_bandwidth;
} }

View File

@ -292,7 +292,7 @@ struct tile_config {
struct kfd2kgd_calls { struct kfd2kgd_calls {
int (*init_gtt_mem_allocation)(struct kgd_dev *kgd, size_t size, int (*init_gtt_mem_allocation)(struct kgd_dev *kgd, size_t size,
void **mem_obj, uint64_t *gpu_addr, void **mem_obj, uint64_t *gpu_addr,
void **cpu_ptr); void **cpu_ptr, bool mqd_gfx9);
void (*free_gtt_mem)(struct kgd_dev *kgd, void *mem_obj); void (*free_gtt_mem)(struct kgd_dev *kgd, void *mem_obj);

View File

@ -754,6 +754,7 @@ static int malidp_bind(struct device *dev)
drm->irq_enabled = true; drm->irq_enabled = true;
ret = drm_vblank_init(drm, drm->mode_config.num_crtc); ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
drm_crtc_vblank_reset(&malidp->crtc);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to initialise vblank\n"); DRM_ERROR("failed to initialise vblank\n");
goto vblank_fail; goto vblank_fail;

View File

@ -384,7 +384,8 @@ static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev, static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
dma_addr_t *addrs, s32 *pitches, dma_addr_t *addrs, s32 *pitches,
int num_planes, u16 w, u16 h, u32 fmt_id) int num_planes, u16 w, u16 h, u32 fmt_id,
const s16 *rgb2yuv_coeffs)
{ {
u32 base = MALIDP500_SE_MEMWRITE_BASE; u32 base = MALIDP500_SE_MEMWRITE_BASE;
u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
@ -416,6 +417,16 @@ static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h), malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
MALIDP500_SE_MEMWRITE_OUT_SIZE); MALIDP500_SE_MEMWRITE_OUT_SIZE);
if (rgb2yuv_coeffs) {
int i;
for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
}
}
malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL); malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
return 0; return 0;
@ -658,7 +669,8 @@ static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev, static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
dma_addr_t *addrs, s32 *pitches, dma_addr_t *addrs, s32 *pitches,
int num_planes, u16 w, u16 h, u32 fmt_id) int num_planes, u16 w, u16 h, u32 fmt_id,
const s16 *rgb2yuv_coeffs)
{ {
u32 base = MALIDP550_SE_MEMWRITE_BASE; u32 base = MALIDP550_SE_MEMWRITE_BASE;
u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
@ -689,6 +701,15 @@ static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN, malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
MALIDP550_SE_CONTROL); MALIDP550_SE_CONTROL);
if (rgb2yuv_coeffs) {
int i;
for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
}
}
return 0; return 0;
} }

View File

@ -191,7 +191,8 @@ struct malidp_hw {
* @param fmt_id - internal format ID of output buffer * @param fmt_id - internal format ID of output buffer
*/ */
int (*enable_memwrite)(struct malidp_hw_device *hwdev, dma_addr_t *addrs, int (*enable_memwrite)(struct malidp_hw_device *hwdev, dma_addr_t *addrs,
s32 *pitches, int num_planes, u16 w, u16 h, u32 fmt_id); s32 *pitches, int num_planes, u16 w, u16 h, u32 fmt_id,
const s16 *rgb2yuv_coeffs);
/* /*
* Disable the writing to memory of the next frame's content. * Disable the writing to memory of the next frame's content.

View File

@ -26,6 +26,8 @@ struct malidp_mw_connector_state {
s32 pitches[2]; s32 pitches[2];
u8 format; u8 format;
u8 n_planes; u8 n_planes;
bool rgb2yuv_initialized;
const s16 *rgb2yuv_coeffs;
}; };
static int malidp_mw_connector_get_modes(struct drm_connector *connector) static int malidp_mw_connector_get_modes(struct drm_connector *connector)
@ -84,7 +86,7 @@ static void malidp_mw_connector_destroy(struct drm_connector *connector)
static struct drm_connector_state * static struct drm_connector_state *
malidp_mw_connector_duplicate_state(struct drm_connector *connector) malidp_mw_connector_duplicate_state(struct drm_connector *connector)
{ {
struct malidp_mw_connector_state *mw_state; struct malidp_mw_connector_state *mw_state, *mw_current_state;
if (WARN_ON(!connector->state)) if (WARN_ON(!connector->state))
return NULL; return NULL;
@ -93,7 +95,10 @@ malidp_mw_connector_duplicate_state(struct drm_connector *connector)
if (!mw_state) if (!mw_state)
return NULL; return NULL;
/* No need to preserve any of our driver-local data */ mw_current_state = to_mw_state(connector->state);
mw_state->rgb2yuv_coeffs = mw_current_state->rgb2yuv_coeffs;
mw_state->rgb2yuv_initialized = mw_current_state->rgb2yuv_initialized;
__drm_atomic_helper_connector_duplicate_state(connector, &mw_state->base); __drm_atomic_helper_connector_duplicate_state(connector, &mw_state->base);
return &mw_state->base; return &mw_state->base;
@ -108,6 +113,13 @@ static const struct drm_connector_funcs malidp_mw_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
}; };
static const s16 rgb2yuv_coeffs_bt709_limited[MALIDP_COLORADJ_NUM_COEFFS] = {
47, 157, 16,
-26, -87, 112,
112, -102, -10,
16, 128, 128
};
static int static int
malidp_mw_encoder_atomic_check(struct drm_encoder *encoder, malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state, struct drm_crtc_state *crtc_state,
@ -157,6 +169,9 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
} }
mw_state->n_planes = n_planes; mw_state->n_planes = n_planes;
if (fb->format->is_yuv)
mw_state->rgb2yuv_coeffs = rgb2yuv_coeffs_bt709_limited;
return 0; return 0;
} }
@ -239,10 +254,12 @@ void malidp_mw_atomic_commit(struct drm_device *drm,
drm_writeback_queue_job(mw_conn, conn_state->writeback_job); drm_writeback_queue_job(mw_conn, conn_state->writeback_job);
conn_state->writeback_job = NULL; conn_state->writeback_job = NULL;
hwdev->hw->enable_memwrite(hwdev, mw_state->addrs, hwdev->hw->enable_memwrite(hwdev, mw_state->addrs,
mw_state->pitches, mw_state->n_planes, mw_state->pitches, mw_state->n_planes,
fb->width, fb->height, mw_state->format); fb->width, fb->height, mw_state->format,
!mw_state->rgb2yuv_initialized ?
mw_state->rgb2yuv_coeffs : NULL);
mw_state->rgb2yuv_initialized = !!mw_state->rgb2yuv_coeffs;
} else { } else {
DRM_DEV_DEBUG_DRIVER(drm->dev, "Disable memwrite\n"); DRM_DEV_DEBUG_DRIVER(drm->dev, "Disable memwrite\n");
hwdev->hw->disable_memwrite(hwdev); hwdev->hw->disable_memwrite(hwdev);

Some files were not shown because too many files have changed in this diff Show More