Merge 5.10.81 into android12-5.10-lts

Changes in 5.10.81
	fortify: Explicitly disable Clang support
	block: Add a helper to validate the block size
	loop: Use blk_validate_block_size() to validate block size
	bootconfig: init: Fix memblock leak in xbc_make_cmdline()
	net: stmmac: add clocks management for gmac driver
	net: stmmac: platform: fix build error with !CONFIG_PM_SLEEP
	net: stmmac: fix missing unlock on error in stmmac_suspend()
	net: stmmac: fix system hang if change mac address after interface ifdown
	net: stmmac: fix issue where clk is being unprepared twice
	net: stmmac: dwmac-rk: fix unbalanced pm_runtime_enable warnings
	x86/iopl: Fake iopl(3) CLI/STI usage
	parisc/entry: fix trace test in syscall exit path
	PCI/MSI: Destroy sysfs before freeing entries
	PCI/MSI: Deal with devices lying about their MSI mask capability
	PCI: Add MSI masking quirk for Nvidia ION AHCI
	erofs: remove the occupied parameter from z_erofs_pagevec_enqueue()
	erofs: fix unsafe pagevec reuse of hooked pclusters
	scripts/lld-version.sh: Rewrite based on upstream ld-version.sh
	perf/core: Avoid put_page() when GUP fails
	thermal: Fix NULL pointer dereferences in of_thermal_ functions
	selftests/x86/iopl: Adjust to the faked iopl CLI/STI usage
	Linux 5.10.81

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Ic5ba37cba892391e62596f4c342d36a8f66e4647
This commit is contained in:
Greg Kroah-Hartman
2021-11-21 14:29:02 +01:00
24 changed files with 370 additions and 129 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
VERSION = 5 VERSION = 5
PATCHLEVEL = 10 PATCHLEVEL = 10
SUBLEVEL = 80 SUBLEVEL = 81
EXTRAVERSION = EXTRAVERSION =
NAME = Dare mighty things NAME = Dare mighty things

View File

@@ -1849,7 +1849,7 @@ syscall_restore:
/* Are we being ptraced? */ /* Are we being ptraced? */
LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
ldi _TIF_SYSCALL_TRACE_MASK,%r2 ldi _TIF_SINGLESTEP|_TIF_BLOCKSTEP,%r2
and,COND(=) %r19,%r2,%r0 and,COND(=) %r19,%r2,%r0
b,n syscall_restore_rfi b,n syscall_restore_rfi

View File

@@ -21,6 +21,7 @@ int insn_get_modrm_rm_off(struct insn *insn, struct pt_regs *regs);
int insn_get_modrm_reg_off(struct insn *insn, struct pt_regs *regs); int insn_get_modrm_reg_off(struct insn *insn, struct pt_regs *regs);
unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx); unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx);
int insn_get_code_seg_params(struct pt_regs *regs); int insn_get_code_seg_params(struct pt_regs *regs);
unsigned long insn_get_effective_ip(struct pt_regs *regs);
int insn_fetch_from_user(struct pt_regs *regs, int insn_fetch_from_user(struct pt_regs *regs,
unsigned char buf[MAX_INSN_SIZE]); unsigned char buf[MAX_INSN_SIZE]);
int insn_fetch_from_user_inatomic(struct pt_regs *regs, int insn_fetch_from_user_inatomic(struct pt_regs *regs,

View File

@@ -534,6 +534,7 @@ struct thread_struct {
*/ */
unsigned long iopl_emul; unsigned long iopl_emul;
unsigned int iopl_warn:1;
unsigned int sig_on_uaccess_err:1; unsigned int sig_on_uaccess_err:1;
/* Floating point and extended processor state */ /* Floating point and extended processor state */

View File

@@ -138,6 +138,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
frame->ret_addr = (unsigned long) ret_from_fork; frame->ret_addr = (unsigned long) ret_from_fork;
p->thread.sp = (unsigned long) fork_frame; p->thread.sp = (unsigned long) fork_frame;
p->thread.io_bitmap = NULL; p->thread.io_bitmap = NULL;
p->thread.iopl_warn = 0;
memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64

View File

@@ -523,6 +523,37 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs,
#define GPFSTR "general protection fault" #define GPFSTR "general protection fault"
static bool fixup_iopl_exception(struct pt_regs *regs)
{
struct thread_struct *t = &current->thread;
unsigned char byte;
unsigned long ip;
if (!IS_ENABLED(CONFIG_X86_IOPL_IOPERM) || t->iopl_emul != 3)
return false;
ip = insn_get_effective_ip(regs);
if (!ip)
return false;
if (get_user(byte, (const char __user *)ip))
return false;
if (byte != 0xfa && byte != 0xfb)
return false;
if (!t->iopl_warn && printk_ratelimit()) {
pr_err("%s[%d] attempts to use CLI/STI, pretending it's a NOP, ip:%lx",
current->comm, task_pid_nr(current), ip);
print_vma_addr(KERN_CONT " in ", ip);
pr_cont("\n");
t->iopl_warn = 1;
}
regs->ip += 1;
return true;
}
DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
{ {
char desc[sizeof(GPFSTR) + 50 + 2*sizeof(unsigned long) + 1] = GPFSTR; char desc[sizeof(GPFSTR) + 50 + 2*sizeof(unsigned long) + 1] = GPFSTR;
@@ -548,6 +579,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
tsk = current; tsk = current;
if (user_mode(regs)) { if (user_mode(regs)) {
if (fixup_iopl_exception(regs))
goto exit;
tsk->thread.error_code = error_code; tsk->thread.error_code = error_code;
tsk->thread.trap_nr = X86_TRAP_GP; tsk->thread.trap_nr = X86_TRAP_GP;

View File

@@ -1415,7 +1415,7 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
} }
} }
static unsigned long insn_get_effective_ip(struct pt_regs *regs) unsigned long insn_get_effective_ip(struct pt_regs *regs)
{ {
unsigned long seg_base = 0; unsigned long seg_base = 0;

View File

@@ -228,19 +228,6 @@ static void __loop_update_dio(struct loop_device *lo, bool dio)
blk_mq_unfreeze_queue(lo->lo_queue); blk_mq_unfreeze_queue(lo->lo_queue);
} }
/**
* loop_validate_block_size() - validates the passed in block size
* @bsize: size to validate
*/
static int
loop_validate_block_size(unsigned short bsize)
{
if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize))
return -EINVAL;
return 0;
}
/** /**
* loop_set_size() - sets device size and notifies userspace * loop_set_size() - sets device size and notifies userspace
* @lo: struct loop_device to set the size for * @lo: struct loop_device to set the size for
@@ -1121,7 +1108,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
} }
if (config->block_size) { if (config->block_size) {
error = loop_validate_block_size(config->block_size); error = blk_validate_block_size(config->block_size);
if (error) if (error)
goto out_unlock; goto out_unlock;
} }
@@ -1617,7 +1604,7 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
if (lo->lo_state != Lo_bound) if (lo->lo_state != Lo_bound)
return -ENXIO; return -ENXIO;
err = loop_validate_block_size(arg); err = blk_validate_block_size(arg);
if (err) if (err)
return err; return err;

View File

@@ -21,7 +21,6 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include "stmmac_platform.h" #include "stmmac_platform.h"
@@ -1336,9 +1335,6 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
return ret; return ret;
} }
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
if (bsp_priv->integrated_phy) if (bsp_priv->integrated_phy)
rk_gmac_integrated_phy_powerup(bsp_priv); rk_gmac_integrated_phy_powerup(bsp_priv);
@@ -1347,14 +1343,9 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
static void rk_gmac_powerdown(struct rk_priv_data *gmac) static void rk_gmac_powerdown(struct rk_priv_data *gmac)
{ {
struct device *dev = &gmac->pdev->dev;
if (gmac->integrated_phy) if (gmac->integrated_phy)
rk_gmac_integrated_phy_powerdown(gmac); rk_gmac_integrated_phy_powerdown(gmac);
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
phy_power_on(gmac, false); phy_power_on(gmac, false);
gmac_clk_enable(gmac, false); gmac_clk_enable(gmac, false);
} }

View File

@@ -270,6 +270,7 @@ void stmmac_disable_eee_mode(struct stmmac_priv *priv);
bool stmmac_eee_init(struct stmmac_priv *priv); bool stmmac_eee_init(struct stmmac_priv *priv);
int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt); int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt);
int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size); int stmmac_reinit_ringparam(struct net_device *dev, u32 rx_size, u32 tx_size);
int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled);
#if IS_ENABLED(CONFIG_STMMAC_SELFTESTS) #if IS_ENABLED(CONFIG_STMMAC_SELFTESTS)
void stmmac_selftest_run(struct net_device *dev, void stmmac_selftest_run(struct net_device *dev,

View File

@@ -28,6 +28,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
@@ -113,6 +114,28 @@ static void stmmac_exit_fs(struct net_device *dev);
#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
int stmmac_bus_clks_config(struct stmmac_priv *priv, bool enabled)
{
int ret = 0;
if (enabled) {
ret = clk_prepare_enable(priv->plat->stmmac_clk);
if (ret)
return ret;
ret = clk_prepare_enable(priv->plat->pclk);
if (ret) {
clk_disable_unprepare(priv->plat->stmmac_clk);
return ret;
}
} else {
clk_disable_unprepare(priv->plat->stmmac_clk);
clk_disable_unprepare(priv->plat->pclk);
}
return ret;
}
EXPORT_SYMBOL_GPL(stmmac_bus_clks_config);
/** /**
* stmmac_verify_args - verify the driver parameters. * stmmac_verify_args - verify the driver parameters.
* Description: it checks the driver parameters and set a default in case of * Description: it checks the driver parameters and set a default in case of
@@ -2792,6 +2815,12 @@ static int stmmac_open(struct net_device *dev)
u32 chan; u32 chan;
int ret; int ret;
ret = pm_runtime_get_sync(priv->device);
if (ret < 0) {
pm_runtime_put_noidle(priv->device);
return ret;
}
if (priv->hw->pcs != STMMAC_PCS_TBI && if (priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI && priv->hw->pcs != STMMAC_PCS_RTBI &&
priv->hw->xpcs == NULL) { priv->hw->xpcs == NULL) {
@@ -2800,7 +2829,7 @@ static int stmmac_open(struct net_device *dev)
netdev_err(priv->dev, netdev_err(priv->dev,
"%s: Cannot attach to PHY (error: %d)\n", "%s: Cannot attach to PHY (error: %d)\n",
__func__, ret); __func__, ret);
return ret; goto init_phy_error;
} }
} }
@@ -2915,6 +2944,8 @@ init_error:
free_dma_desc_resources(priv); free_dma_desc_resources(priv);
dma_desc_error: dma_desc_error:
phylink_disconnect_phy(priv->phylink); phylink_disconnect_phy(priv->phylink);
init_phy_error:
pm_runtime_put(priv->device);
return ret; return ret;
} }
@@ -2965,6 +2996,8 @@ static int stmmac_release(struct net_device *dev)
stmmac_release_ptp(priv); stmmac_release_ptp(priv);
pm_runtime_put(priv->device);
return 0; return 0;
} }
@@ -4291,12 +4324,21 @@ static int stmmac_set_mac_address(struct net_device *ndev, void *addr)
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
int ret = 0; int ret = 0;
ret = pm_runtime_get_sync(priv->device);
if (ret < 0) {
pm_runtime_put_noidle(priv->device);
return ret;
}
ret = eth_mac_addr(ndev, addr); ret = eth_mac_addr(ndev, addr);
if (ret) if (ret)
return ret; goto set_mac_error;
stmmac_set_umac_addr(priv, priv->hw, ndev->dev_addr, 0); stmmac_set_umac_addr(priv, priv->hw, ndev->dev_addr, 0);
set_mac_error:
pm_runtime_put(priv->device);
return ret; return ret;
} }
@@ -4616,6 +4658,12 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
bool is_double = false; bool is_double = false;
int ret; int ret;
ret = pm_runtime_get_sync(priv->device);
if (ret < 0) {
pm_runtime_put_noidle(priv->device);
return ret;
}
if (be16_to_cpu(proto) == ETH_P_8021AD) if (be16_to_cpu(proto) == ETH_P_8021AD)
is_double = true; is_double = true;
@@ -4624,10 +4672,15 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
if (priv->hw->num_vlan) { if (priv->hw->num_vlan) {
ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
if (ret) if (ret)
return ret; goto del_vlan_error;
} }
return stmmac_vlan_update(priv, is_double); ret = stmmac_vlan_update(priv, is_double);
del_vlan_error:
pm_runtime_put(priv->device);
return ret;
} }
static const struct net_device_ops stmmac_netdev_ops = { static const struct net_device_ops stmmac_netdev_ops = {
@@ -5066,6 +5119,10 @@ int stmmac_dvr_probe(struct device *device,
stmmac_check_pcs_mode(priv); stmmac_check_pcs_mode(priv);
pm_runtime_get_noresume(device);
pm_runtime_set_active(device);
pm_runtime_enable(device);
if (priv->hw->pcs != STMMAC_PCS_TBI && if (priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI) { priv->hw->pcs != STMMAC_PCS_RTBI) {
/* MDIO bus Registration */ /* MDIO bus Registration */
@@ -5103,6 +5160,11 @@ int stmmac_dvr_probe(struct device *device,
stmmac_init_fs(ndev); stmmac_init_fs(ndev);
#endif #endif
/* Let pm_runtime_put() disable the clocks.
* If CONFIG_PM is not enabled, the clocks will stay powered.
*/
pm_runtime_put(device);
return ret; return ret;
error_serdes_powerup: error_serdes_powerup:
@@ -5152,8 +5214,8 @@ int stmmac_dvr_remove(struct device *dev)
phylink_destroy(priv->phylink); phylink_destroy(priv->phylink);
if (priv->plat->stmmac_rst) if (priv->plat->stmmac_rst)
reset_control_assert(priv->plat->stmmac_rst); reset_control_assert(priv->plat->stmmac_rst);
clk_disable_unprepare(priv->plat->pclk); pm_runtime_put(dev);
clk_disable_unprepare(priv->plat->stmmac_clk); pm_runtime_disable(dev);
if (priv->hw->pcs != STMMAC_PCS_TBI && if (priv->hw->pcs != STMMAC_PCS_TBI &&
priv->hw->pcs != STMMAC_PCS_RTBI) priv->hw->pcs != STMMAC_PCS_RTBI)
stmmac_mdio_unregister(ndev); stmmac_mdio_unregister(ndev);
@@ -5176,6 +5238,7 @@ int stmmac_suspend(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev); struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
u32 chan; u32 chan;
int ret;
if (!ndev || !netif_running(ndev)) if (!ndev || !netif_running(ndev))
return 0; return 0;
@@ -5219,8 +5282,11 @@ int stmmac_suspend(struct device *dev)
pinctrl_pm_select_sleep_state(priv->device); pinctrl_pm_select_sleep_state(priv->device);
/* Disable clock in case of PWM is off */ /* Disable clock in case of PWM is off */
clk_disable_unprepare(priv->plat->clk_ptp_ref); clk_disable_unprepare(priv->plat->clk_ptp_ref);
clk_disable_unprepare(priv->plat->pclk); ret = pm_runtime_force_suspend(dev);
clk_disable_unprepare(priv->plat->stmmac_clk); if (ret) {
mutex_unlock(&priv->lock);
return ret;
}
} }
mutex_unlock(&priv->lock); mutex_unlock(&priv->lock);
@@ -5286,8 +5352,9 @@ int stmmac_resume(struct device *dev)
} else { } else {
pinctrl_pm_select_default_state(priv->device); pinctrl_pm_select_default_state(priv->device);
/* enable the clk previously disabled */ /* enable the clk previously disabled */
clk_prepare_enable(priv->plat->stmmac_clk); ret = pm_runtime_force_resume(dev);
clk_prepare_enable(priv->plat->pclk); if (ret)
return ret;
if (priv->plat->clk_ptp_ref) if (priv->plat->clk_ptp_ref)
clk_prepare_enable(priv->plat->clk_ptp_ref); clk_prepare_enable(priv->plat->clk_ptp_ref);
/* reset the phy so that it's ready */ /* reset the phy so that it's ready */

View File

@@ -15,6 +15,7 @@
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/mii.h> #include <linux/mii.h>
#include <linux/of_mdio.h> #include <linux/of_mdio.h>
#include <linux/pm_runtime.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/slab.h> #include <linux/slab.h>
@@ -87,21 +88,29 @@ static int stmmac_xgmac2_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
u32 tmp, addr, value = MII_XGMAC_BUSY; u32 tmp, addr, value = MII_XGMAC_BUSY;
int ret; int ret;
ret = pm_runtime_get_sync(priv->device);
if (ret < 0) {
pm_runtime_put_noidle(priv->device);
return ret;
}
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
!(tmp & MII_XGMAC_BUSY), 100, 10000)) !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
return -EBUSY; ret = -EBUSY;
goto err_disable_clks;
}
if (phyreg & MII_ADDR_C45) { if (phyreg & MII_ADDR_C45) {
phyreg &= ~MII_ADDR_C45; phyreg &= ~MII_ADDR_C45;
ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr); ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr);
if (ret) if (ret)
return ret; goto err_disable_clks;
} else { } else {
ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr); ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);
if (ret) if (ret)
return ret; goto err_disable_clks;
value |= MII_XGMAC_SADDR; value |= MII_XGMAC_SADDR;
} }
@@ -112,8 +121,10 @@ static int stmmac_xgmac2_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
!(tmp & MII_XGMAC_BUSY), 100, 10000)) !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
return -EBUSY; ret = -EBUSY;
goto err_disable_clks;
}
/* Set the MII address register to read */ /* Set the MII address register to read */
writel(addr, priv->ioaddr + mii_address); writel(addr, priv->ioaddr + mii_address);
@@ -121,11 +132,18 @@ static int stmmac_xgmac2_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
!(tmp & MII_XGMAC_BUSY), 100, 10000)) !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
return -EBUSY; ret = -EBUSY;
goto err_disable_clks;
}
/* Read the data from the MII data register */ /* Read the data from the MII data register */
return readl(priv->ioaddr + mii_data) & GENMASK(15, 0); ret = (int)readl(priv->ioaddr + mii_data) & GENMASK(15, 0);
err_disable_clks:
pm_runtime_put(priv->device);
return ret;
} }
static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr, static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr,
@@ -138,21 +156,29 @@ static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr,
u32 addr, tmp, value = MII_XGMAC_BUSY; u32 addr, tmp, value = MII_XGMAC_BUSY;
int ret; int ret;
ret = pm_runtime_get_sync(priv->device);
if (ret < 0) {
pm_runtime_put_noidle(priv->device);
return ret;
}
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
!(tmp & MII_XGMAC_BUSY), 100, 10000)) !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
return -EBUSY; ret = -EBUSY;
goto err_disable_clks;
}
if (phyreg & MII_ADDR_C45) { if (phyreg & MII_ADDR_C45) {
phyreg &= ~MII_ADDR_C45; phyreg &= ~MII_ADDR_C45;
ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr); ret = stmmac_xgmac2_c45_format(priv, phyaddr, phyreg, &addr);
if (ret) if (ret)
return ret; goto err_disable_clks;
} else { } else {
ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr); ret = stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);
if (ret) if (ret)
return ret; goto err_disable_clks;
value |= MII_XGMAC_SADDR; value |= MII_XGMAC_SADDR;
} }
@@ -164,16 +190,23 @@ static int stmmac_xgmac2_mdio_write(struct mii_bus *bus, int phyaddr,
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,
!(tmp & MII_XGMAC_BUSY), 100, 10000)) !(tmp & MII_XGMAC_BUSY), 100, 10000)) {
return -EBUSY; ret = -EBUSY;
goto err_disable_clks;
}
/* Set the MII address register to write */ /* Set the MII address register to write */
writel(addr, priv->ioaddr + mii_address); writel(addr, priv->ioaddr + mii_address);
writel(value, priv->ioaddr + mii_data); writel(value, priv->ioaddr + mii_data);
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
return readl_poll_timeout(priv->ioaddr + mii_data, tmp, ret = readl_poll_timeout(priv->ioaddr + mii_data, tmp,
!(tmp & MII_XGMAC_BUSY), 100, 10000); !(tmp & MII_XGMAC_BUSY), 100, 10000);
err_disable_clks:
pm_runtime_put(priv->device);
return ret;
} }
/** /**
@@ -196,6 +229,12 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
int data = 0; int data = 0;
u32 v; u32 v;
data = pm_runtime_get_sync(priv->device);
if (data < 0) {
pm_runtime_put_noidle(priv->device);
return data;
}
value |= (phyaddr << priv->hw->mii.addr_shift) value |= (phyaddr << priv->hw->mii.addr_shift)
& priv->hw->mii.addr_mask; & priv->hw->mii.addr_mask;
value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
@@ -216,19 +255,26 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
} }
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
100, 10000)) 100, 10000)) {
return -EBUSY; data = -EBUSY;
goto err_disable_clks;
}
writel(data, priv->ioaddr + mii_data); writel(data, priv->ioaddr + mii_data);
writel(value, priv->ioaddr + mii_address); writel(value, priv->ioaddr + mii_address);
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
100, 10000)) 100, 10000)) {
return -EBUSY; data = -EBUSY;
goto err_disable_clks;
}
/* Read the data from the MII data register */ /* Read the data from the MII data register */
data = (int)readl(priv->ioaddr + mii_data) & MII_DATA_MASK; data = (int)readl(priv->ioaddr + mii_data) & MII_DATA_MASK;
err_disable_clks:
pm_runtime_put(priv->device);
return data; return data;
} }
@@ -247,10 +293,16 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_address = priv->hw->mii.addr;
unsigned int mii_data = priv->hw->mii.data; unsigned int mii_data = priv->hw->mii.data;
int ret, data = phydata;
u32 value = MII_BUSY; u32 value = MII_BUSY;
int data = phydata;
u32 v; u32 v;
ret = pm_runtime_get_sync(priv->device);
if (ret < 0) {
pm_runtime_put_noidle(priv->device);
return ret;
}
value |= (phyaddr << priv->hw->mii.addr_shift) value |= (phyaddr << priv->hw->mii.addr_shift)
& priv->hw->mii.addr_mask; & priv->hw->mii.addr_mask;
value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
@@ -275,16 +327,23 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
100, 10000)) 100, 10000)) {
return -EBUSY; ret = -EBUSY;
goto err_disable_clks;
}
/* Set the MII address register to write */ /* Set the MII address register to write */
writel(data, priv->ioaddr + mii_data); writel(data, priv->ioaddr + mii_data);
writel(value, priv->ioaddr + mii_address); writel(value, priv->ioaddr + mii_address);
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
return readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), ret = readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
100, 10000); 100, 10000);
err_disable_clks:
pm_runtime_put(priv->device);
return ret;
} }
/** /**

View File

@@ -720,7 +720,6 @@ int stmmac_pltfr_remove(struct platform_device *pdev)
} }
EXPORT_SYMBOL_GPL(stmmac_pltfr_remove); EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
#ifdef CONFIG_PM_SLEEP
/** /**
* stmmac_pltfr_suspend * stmmac_pltfr_suspend
* @dev: device pointer * @dev: device pointer
@@ -728,7 +727,7 @@ EXPORT_SYMBOL_GPL(stmmac_pltfr_remove);
* call the main suspend function and then, if required, on some platform, it * call the main suspend function and then, if required, on some platform, it
* can call an exit helper. * can call an exit helper.
*/ */
static int stmmac_pltfr_suspend(struct device *dev) static int __maybe_unused stmmac_pltfr_suspend(struct device *dev)
{ {
int ret; int ret;
struct net_device *ndev = dev_get_drvdata(dev); struct net_device *ndev = dev_get_drvdata(dev);
@@ -749,7 +748,7 @@ static int stmmac_pltfr_suspend(struct device *dev)
* the main resume function, on some platforms, it can call own init helper * the main resume function, on some platforms, it can call own init helper
* if required. * if required.
*/ */
static int stmmac_pltfr_resume(struct device *dev) static int __maybe_unused stmmac_pltfr_resume(struct device *dev)
{ {
struct net_device *ndev = dev_get_drvdata(dev); struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
@@ -760,10 +759,29 @@ static int stmmac_pltfr_resume(struct device *dev)
return stmmac_resume(dev); return stmmac_resume(dev);
} }
#endif /* CONFIG_PM_SLEEP */
SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend, static int __maybe_unused stmmac_runtime_suspend(struct device *dev)
stmmac_pltfr_resume); {
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
stmmac_bus_clks_config(priv, false);
return 0;
}
static int __maybe_unused stmmac_runtime_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
return stmmac_bus_clks_config(priv, true);
}
const struct dev_pm_ops stmmac_pltfr_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(stmmac_pltfr_suspend, stmmac_pltfr_resume)
SET_RUNTIME_PM_OPS(stmmac_runtime_suspend, stmmac_runtime_resume, NULL)
};
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops); EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support"); MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support");

View File

@@ -395,18 +395,6 @@ static void free_msi_irqs(struct pci_dev *dev)
for (i = 0; i < entry->nvec_used; i++) for (i = 0; i < entry->nvec_used; i++)
BUG_ON(irq_has_action(entry->irq + i)); BUG_ON(irq_has_action(entry->irq + i));
pci_msi_teardown_msi_irqs(dev);
list_for_each_entry_safe(entry, tmp, msi_list, list) {
if (entry->msi_attrib.is_msix) {
if (list_is_last(&entry->list, msi_list))
iounmap(entry->mask_base);
}
list_del(&entry->list);
free_msi_entry(entry);
}
if (dev->msi_irq_groups) { if (dev->msi_irq_groups) {
sysfs_remove_groups(&dev->dev.kobj, dev->msi_irq_groups); sysfs_remove_groups(&dev->dev.kobj, dev->msi_irq_groups);
msi_attrs = dev->msi_irq_groups[0]->attrs; msi_attrs = dev->msi_irq_groups[0]->attrs;
@@ -422,6 +410,18 @@ static void free_msi_irqs(struct pci_dev *dev)
kfree(dev->msi_irq_groups); kfree(dev->msi_irq_groups);
dev->msi_irq_groups = NULL; dev->msi_irq_groups = NULL;
} }
pci_msi_teardown_msi_irqs(dev);
list_for_each_entry_safe(entry, tmp, msi_list, list) {
if (entry->msi_attrib.is_msix) {
if (list_is_last(&entry->list, msi_list))
iounmap(entry->mask_base);
}
list_del(&entry->list);
free_msi_entry(entry);
}
} }
static void pci_intx_for_msi(struct pci_dev *dev, int enable) static void pci_intx_for_msi(struct pci_dev *dev, int enable)
@@ -591,6 +591,9 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd)
goto out; goto out;
pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
/* Lies, damned lies, and MSIs */
if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING)
control |= PCI_MSI_FLAGS_MASKBIT;
entry->msi_attrib.is_msix = 0; entry->msi_attrib.is_msix = 0;
entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT); entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT);

View File

@@ -5756,3 +5756,9 @@ static void apex_pci_fixup_class(struct pci_dev *pdev)
} }
DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a, DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a,
PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class); PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class);
static void nvidia_ion_ahci_fixup(struct pci_dev *pdev)
{
pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup);

View File

@@ -376,11 +376,10 @@ static bool z_erofs_try_inplace_io(struct z_erofs_collector *clt,
/* callers must be with collection lock held */ /* callers must be with collection lock held */
static int z_erofs_attach_page(struct z_erofs_collector *clt, static int z_erofs_attach_page(struct z_erofs_collector *clt,
struct page *page, struct page *page, enum z_erofs_page_type type,
enum z_erofs_page_type type) bool pvec_safereuse)
{ {
int ret; int ret;
bool occupied;
/* give priority for inplaceio */ /* give priority for inplaceio */
if (clt->mode >= COLLECT_PRIMARY && if (clt->mode >= COLLECT_PRIMARY &&
@@ -388,10 +387,9 @@ static int z_erofs_attach_page(struct z_erofs_collector *clt,
z_erofs_try_inplace_io(clt, page)) z_erofs_try_inplace_io(clt, page))
return 0; return 0;
ret = z_erofs_pagevec_enqueue(&clt->vector, ret = z_erofs_pagevec_enqueue(&clt->vector, page, type,
page, type, &occupied); pvec_safereuse);
clt->cl->vcnt += (unsigned int)ret; clt->cl->vcnt += (unsigned int)ret;
return ret ? 0 : -EAGAIN; return ret ? 0 : -EAGAIN;
} }
@@ -737,15 +735,16 @@ hitted:
tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED); tight &= (clt->mode >= COLLECT_PRIMARY_FOLLOWED);
retry: retry:
err = z_erofs_attach_page(clt, page, page_type); err = z_erofs_attach_page(clt, page, page_type,
/* should allocate an additional short-lived page for pagevec */ clt->mode >= COLLECT_PRIMARY_FOLLOWED);
/* should allocate an additional staging page for pagevec */
if (err == -EAGAIN) { if (err == -EAGAIN) {
struct page *const newpage = struct page *const newpage =
alloc_page(GFP_NOFS | __GFP_NOFAIL); alloc_page(GFP_NOFS | __GFP_NOFAIL);
set_page_private(newpage, Z_EROFS_SHORTLIVED_PAGE); set_page_private(newpage, Z_EROFS_SHORTLIVED_PAGE);
err = z_erofs_attach_page(clt, newpage, err = z_erofs_attach_page(clt, newpage,
Z_EROFS_PAGE_TYPE_EXCLUSIVE); Z_EROFS_PAGE_TYPE_EXCLUSIVE, true);
if (!err) if (!err)
goto retry; goto retry;
} }

View File

@@ -108,12 +108,17 @@ static inline void z_erofs_pagevec_ctor_init(struct z_erofs_pagevec_ctor *ctor,
static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor, static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor,
struct page *page, struct page *page,
enum z_erofs_page_type type, enum z_erofs_page_type type,
bool *occupied) bool pvec_safereuse)
{ {
*occupied = false; if (!ctor->next) {
if (!ctor->next && type) /* some pages cannot be reused as pvec safely without I/O */
if (ctor->index + 1 == ctor->nr) if (type == Z_EROFS_PAGE_TYPE_EXCLUSIVE && !pvec_safereuse)
type = Z_EROFS_VLE_PAGE_TYPE_TAIL_SHARED;
if (type != Z_EROFS_PAGE_TYPE_EXCLUSIVE &&
ctor->index + 1 == ctor->nr)
return false; return false;
}
if (ctor->index >= ctor->nr) if (ctor->index >= ctor->nr)
z_erofs_pagevec_ctor_pagedown(ctor, false); z_erofs_pagevec_ctor_pagedown(ctor, false);
@@ -125,7 +130,6 @@ static inline bool z_erofs_pagevec_enqueue(struct z_erofs_pagevec_ctor *ctor,
/* should remind that collector->next never equal to 1, 2 */ /* should remind that collector->next never equal to 1, 2 */
if (type == (uintptr_t)ctor->next) { if (type == (uintptr_t)ctor->next) {
ctor->next = page; ctor->next = page;
*occupied = true;
} }
ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, page, type); ctor->pages[ctor->index++] = tagptr_fold(erofs_vtptr_t, page, type);
return true; return true;

View File

@@ -61,6 +61,14 @@ struct blk_keyslot_manager;
*/ */
#define BLKCG_MAX_POLS 5 #define BLKCG_MAX_POLS 5
static inline int blk_validate_block_size(unsigned int bsize)
{
if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize))
return -EINVAL;
return 0;
}
typedef void (rq_end_io_fn)(struct request *, blk_status_t); typedef void (rq_end_io_fn)(struct request *, blk_status_t);
/* /*

View File

@@ -228,6 +228,8 @@ enum pci_dev_flags {
PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10), PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10),
/* Don't use Relaxed Ordering for TLPs directed at this device */ /* Don't use Relaxed Ordering for TLPs directed at this device */
PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11), PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 11),
/* Device does honor MSI masking despite saying otherwise */
PCI_DEV_FLAGS_HAS_MSI_MASKING = (__force pci_dev_flags_t) (1 << 12),
}; };
enum pci_irq_reroute_variant { enum pci_irq_reroute_variant {

View File

@@ -382,6 +382,7 @@ static char * __init xbc_make_cmdline(const char *key)
ret = xbc_snprint_cmdline(new_cmdline, len + 1, root); ret = xbc_snprint_cmdline(new_cmdline, len + 1, root);
if (ret < 0 || ret > len) { if (ret < 0 || ret > len) {
pr_err("Failed to print extra kernel cmdline.\n"); pr_err("Failed to print extra kernel cmdline.\n");
memblock_free(__pa(new_cmdline), len + 1);
return NULL; return NULL;
} }

View File

@@ -7037,7 +7037,6 @@ void perf_output_sample(struct perf_output_handle *handle,
static u64 perf_virt_to_phys(u64 virt) static u64 perf_virt_to_phys(u64 virt)
{ {
u64 phys_addr = 0; u64 phys_addr = 0;
struct page *p = NULL;
if (!virt) if (!virt)
return 0; return 0;
@@ -7056,14 +7055,15 @@ static u64 perf_virt_to_phys(u64 virt)
* If failed, leave phys_addr as 0. * If failed, leave phys_addr as 0.
*/ */
if (current->mm != NULL) { if (current->mm != NULL) {
struct page *p;
pagefault_disable(); pagefault_disable();
if (get_user_page_fast_only(virt, 0, &p)) if (get_user_page_fast_only(virt, 0, &p)) {
phys_addr = page_to_phys(p) + virt % PAGE_SIZE; phys_addr = page_to_phys(p) + virt % PAGE_SIZE;
put_page(p);
}
pagefault_enable(); pagefault_enable();
} }
if (p)
put_page(p);
} }
return phys_addr; return phys_addr;

View File

@@ -6,15 +6,32 @@
# Print the linker version of `ld.lld' in a 5 or 6-digit form # Print the linker version of `ld.lld' in a 5 or 6-digit form
# such as `100001' for ld.lld 10.0.1 etc. # such as `100001' for ld.lld 10.0.1 etc.
linker_string="$($* --version)" set -e
if ! ( echo $linker_string | grep -q LLD ); then # Convert the version string x.y.z to a canonical 5 or 6-digit form.
get_canonical_version()
{
IFS=.
set -- $1
# If the 2nd or 3rd field is missing, fill it with a zero.
echo $((10000 * $1 + 100 * ${2:-0} + ${3:-0}))
}
# Get the first line of the --version output.
IFS='
'
set -- $(LC_ALL=C "$@" --version)
# Split the line on spaces.
IFS=' '
set -- $1
while [ $# -gt 1 -a "$1" != "LLD" ]; do
shift
done
if [ "$1" = LLD ]; then
echo $(get_canonical_version ${2%-*})
else
echo 0 echo 0
exit 1
fi fi
VERSION=$(echo $linker_string | cut -d ' ' -f 2)
MAJOR=$(echo $VERSION | cut -d . -f 1)
MINOR=$(echo $VERSION | cut -d . -f 2)
PATCHLEVEL=$(echo $VERSION | cut -d . -f 3)
printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL

View File

@@ -191,6 +191,9 @@ config HARDENED_USERCOPY_PAGESPAN
config FORTIFY_SOURCE config FORTIFY_SOURCE
bool "Harden common str/mem functions against buffer overflows" bool "Harden common str/mem functions against buffer overflows"
depends on ARCH_HAS_FORTIFY_SOURCE depends on ARCH_HAS_FORTIFY_SOURCE
# https://bugs.llvm.org/show_bug.cgi?id=50322
# https://bugs.llvm.org/show_bug.cgi?id=41459
depends on !CC_IS_CLANG
help help
Detect overflows of buffers in common string and memory functions Detect overflows of buffers in common string and memory functions
where the compiler can determine and validate the buffer sizes. where the compiler can determine and validate the buffer sizes.

View File

@@ -85,48 +85,88 @@ static void expect_gp_outb(unsigned short port)
printf("[OK]\toutb to 0x%02hx failed\n", port); printf("[OK]\toutb to 0x%02hx failed\n", port);
} }
static bool try_cli(void) #define RET_FAULTED 0
#define RET_FAIL 1
#define RET_EMUL 2
static int try_cli(void)
{ {
unsigned long flags;
sethandler(SIGSEGV, sigsegv, SA_RESETHAND); sethandler(SIGSEGV, sigsegv, SA_RESETHAND);
if (sigsetjmp(jmpbuf, 1) != 0) { if (sigsetjmp(jmpbuf, 1) != 0) {
return false; return RET_FAULTED;
} else { } else {
asm volatile ("cli"); asm volatile("cli; pushf; pop %[flags]"
return true; : [flags] "=rm" (flags));
/* X86_FLAGS_IF */
if (!(flags & (1 << 9)))
return RET_FAIL;
else
return RET_EMUL;
} }
clearhandler(SIGSEGV); clearhandler(SIGSEGV);
} }
static bool try_sti(void) static int try_sti(bool irqs_off)
{ {
unsigned long flags;
sethandler(SIGSEGV, sigsegv, SA_RESETHAND); sethandler(SIGSEGV, sigsegv, SA_RESETHAND);
if (sigsetjmp(jmpbuf, 1) != 0) { if (sigsetjmp(jmpbuf, 1) != 0) {
return false; return RET_FAULTED;
} else { } else {
asm volatile ("sti"); asm volatile("sti; pushf; pop %[flags]"
return true; : [flags] "=rm" (flags));
/* X86_FLAGS_IF */
if (irqs_off && (flags & (1 << 9)))
return RET_FAIL;
else
return RET_EMUL;
} }
clearhandler(SIGSEGV); clearhandler(SIGSEGV);
} }
static void expect_gp_sti(void) static void expect_gp_sti(bool irqs_off)
{ {
if (try_sti()) { int ret = try_sti(irqs_off);
switch (ret) {
case RET_FAULTED:
printf("[OK]\tSTI faulted\n");
break;
case RET_EMUL:
printf("[OK]\tSTI NOPped\n");
break;
default:
printf("[FAIL]\tSTI worked\n"); printf("[FAIL]\tSTI worked\n");
nerrs++; nerrs++;
} else {
printf("[OK]\tSTI faulted\n");
} }
} }
static void expect_gp_cli(void) /*
* Returns whether it managed to disable interrupts.
*/
static bool test_cli(void)
{ {
if (try_cli()) { int ret = try_cli();
switch (ret) {
case RET_FAULTED:
printf("[OK]\tCLI faulted\n");
break;
case RET_EMUL:
printf("[OK]\tCLI NOPped\n");
break;
default:
printf("[FAIL]\tCLI worked\n"); printf("[FAIL]\tCLI worked\n");
nerrs++; nerrs++;
} else { return true;
printf("[OK]\tCLI faulted\n");
} }
return false;
} }
int main(void) int main(void)
@@ -152,8 +192,7 @@ int main(void)
} }
/* Make sure that CLI/STI are blocked even with IOPL level 3 */ /* Make sure that CLI/STI are blocked even with IOPL level 3 */
expect_gp_cli(); expect_gp_sti(test_cli());
expect_gp_sti();
expect_ok_outb(0x80); expect_ok_outb(0x80);
/* Establish an I/O bitmap to test the restore */ /* Establish an I/O bitmap to test the restore */
@@ -204,8 +243,7 @@ int main(void)
printf("[RUN]\tparent: write to 0x80 (should fail)\n"); printf("[RUN]\tparent: write to 0x80 (should fail)\n");
expect_gp_outb(0x80); expect_gp_outb(0x80);
expect_gp_cli(); expect_gp_sti(test_cli());
expect_gp_sti();
/* Test the capability checks. */ /* Test the capability checks. */
printf("\tiopl(3)\n"); printf("\tiopl(3)\n");