mirror of https://github.com/torvalds/linux.git
iommupt: Add basic support for SW bits in the page table
SW bits can be placed on items, including table entries, single OA's and individual items within a contiguous OA. They are guaranteed to be ignored by the HW. The API is very basic since the only use case so far is a single bit. Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
parent
36ae67b139
commit
bcc64b57b4
|
|
@ -342,6 +342,35 @@ static inline struct pt_table_p *pt_table_ptr(const struct pt_state *pts)
|
||||||
return __va(pt_table_pa(pts));
|
return __va(pt_table_pa(pts));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pt_max_sw_bit() - Return the maximum software bit usable for any level and
|
||||||
|
* entry
|
||||||
|
* @common: Page table
|
||||||
|
*
|
||||||
|
* The swbit can be passed as bitnr to the other sw_bit functions.
|
||||||
|
*/
|
||||||
|
static inline unsigned int pt_max_sw_bit(struct pt_common *common);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pt_test_sw_bit_acquire() - Read a software bit in an item
|
||||||
|
* @pts: Entry to set
|
||||||
|
*
|
||||||
|
* Software bits are ignored by HW and can be used for any purpose by the
|
||||||
|
* software. This does a test bit and acquire operation.
|
||||||
|
*/
|
||||||
|
static inline bool pt_test_sw_bit_acquire(struct pt_state *pts,
|
||||||
|
unsigned int bitnr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pt_set_sw_bit_release() - Set a software bit in an item
|
||||||
|
* @pts: Entry to set
|
||||||
|
*
|
||||||
|
* Software bits are ignored by HW and can be used for any purpose by the
|
||||||
|
* software. This does a set bit and release operation.
|
||||||
|
*/
|
||||||
|
static inline void pt_set_sw_bit_release(struct pt_state *pts,
|
||||||
|
unsigned int bitnr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pt_load_entry() - Read from the location pts points at into the pts
|
* pt_load_entry() - Read from the location pts points at into the pts
|
||||||
* @pts: Table index to load
|
* @pts: Table index to load
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,68 @@ static inline void pt_clear_entries(struct pt_state *pts,
|
||||||
#define pt_clear_entries pt_clear_entries
|
#define pt_clear_entries pt_clear_entries
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If not supplied then SW bits are not supported */
|
||||||
|
#ifdef pt_sw_bit
|
||||||
|
static inline bool pt_test_sw_bit_acquire(struct pt_state *pts,
|
||||||
|
unsigned int bitnr)
|
||||||
|
{
|
||||||
|
/* Acquire, pairs with pt_set_sw_bit_release() */
|
||||||
|
smp_mb();
|
||||||
|
/* For a contiguous entry the sw bit is only stored in the first item. */
|
||||||
|
return pts->entry & pt_sw_bit(bitnr);
|
||||||
|
}
|
||||||
|
#define pt_test_sw_bit_acquire pt_test_sw_bit_acquire
|
||||||
|
|
||||||
|
static inline void pt_set_sw_bit_release(struct pt_state *pts,
|
||||||
|
unsigned int bitnr)
|
||||||
|
{
|
||||||
|
#if !IS_ENABLED(CONFIG_GENERIC_ATOMIC64)
|
||||||
|
if (PT_ITEM_WORD_SIZE == sizeof(u64)) {
|
||||||
|
u64 *entryp = pt_cur_table(pts, u64) + pts->index;
|
||||||
|
u64 old_entry = pts->entry;
|
||||||
|
u64 new_entry;
|
||||||
|
|
||||||
|
do {
|
||||||
|
new_entry = old_entry | pt_sw_bit(bitnr);
|
||||||
|
} while (!try_cmpxchg64_release(entryp, &old_entry, new_entry));
|
||||||
|
pts->entry = new_entry;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (PT_ITEM_WORD_SIZE == sizeof(u32)) {
|
||||||
|
u32 *entryp = pt_cur_table(pts, u32) + pts->index;
|
||||||
|
u32 old_entry = pts->entry;
|
||||||
|
u32 new_entry;
|
||||||
|
|
||||||
|
do {
|
||||||
|
new_entry = old_entry | pt_sw_bit(bitnr);
|
||||||
|
} while (!try_cmpxchg_release(entryp, &old_entry, new_entry));
|
||||||
|
pts->entry = new_entry;
|
||||||
|
} else
|
||||||
|
BUILD_BUG();
|
||||||
|
}
|
||||||
|
#define pt_set_sw_bit_release pt_set_sw_bit_release
|
||||||
|
#else
|
||||||
|
static inline unsigned int pt_max_sw_bit(struct pt_common *common)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void __pt_no_sw_bit(void);
|
||||||
|
static inline bool pt_test_sw_bit_acquire(struct pt_state *pts,
|
||||||
|
unsigned int bitnr)
|
||||||
|
{
|
||||||
|
__pt_no_sw_bit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pt_set_sw_bit_release(struct pt_state *pts,
|
||||||
|
unsigned int bitnr)
|
||||||
|
{
|
||||||
|
__pt_no_sw_bit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Format can call in the pt_install_leaf_entry() to check the arguments are all
|
* Format can call in the pt_install_leaf_entry() to check the arguments are all
|
||||||
* aligned correctly.
|
* aligned correctly.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue