mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 23:52:08 +02:00
s390 fixes for 7.1-rc5
- Fix PAI NNPA mismatch between counting and recording, where sampling reports twice the value - Fix loss of PAI counter increments during recording on systems with many CPUs under heavy load, while counting is not affected - On some supported machines, CHSC cannot access memory outside the DMA zone, causing CHSC command failures. Restore GFP_DMA flag when allocating memory for CHSC control blocks - Align the numbering scheme for higher-level topology structures like socket, book, drawer with other hardware identifiers e.g. in sysfs, procfs and tools like lscpu -----BEGIN PGP SIGNATURE----- iI0EABYKADUWIQQrtrZiYVkVzKQcYivNdxKlNrRb8AUCag8nxxccYWdvcmRlZXZA bGludXguaWJtLmNvbQAKCRDNdxKlNrRb8OulAQC/lQlKztFCEUad/yCXhfZnJbwz zqUrq/5+JyKm8w1kPgEAq1cYMpzoUdcQ1D8N889SLe6o5aUPHO1fBu3VC6V0cg0= =OS/x -----END PGP SIGNATURE----- Merge tag 's390-7.1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux Pull s390 fixes from Alexander Gordeev: - Fix PAI NNPA mismatch between counting and recording, where sampling reports twice the value - Fix loss of PAI counter increments during recording on systems with many CPUs under heavy load, while counting is not affected - On some supported machines, CHSC cannot access memory outside the DMA zone, causing CHSC command failures. Restore GFP_DMA flag when allocating memory for CHSC control blocks - Align the numbering scheme for higher-level topology structures like socket, book, drawer with other hardware identifiers e.g. in sysfs, procfs and tools like lscpu * tag 's390-7.1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/topology: Use zero-based numbering for containing entities s390/cio: Restore GFP_DMA for CHSC allocation s390/pai: Fix missing PAI counter increments under heavy load s390/pai: Disable duplicate read of kernel PAI counter value
This commit is contained in:
commit
cbadb98b7c
|
|
@ -186,6 +186,13 @@ static u64 pai_getctr(unsigned long *page, int nr, unsigned long offset)
|
|||
return page[nr];
|
||||
}
|
||||
|
||||
static void pai_setctr(unsigned long *page, int nr, unsigned long offset, u64 v)
|
||||
{
|
||||
if (offset)
|
||||
nr += offset / sizeof(*page);
|
||||
page[nr] = v;
|
||||
}
|
||||
|
||||
/* Read the counter values. Return value from location in CMP. For base
|
||||
* event xxx_ALL sum up all events. Returns counter value.
|
||||
*/
|
||||
|
|
@ -551,6 +558,8 @@ static void paicrypt_del(struct perf_event *event, int flags)
|
|||
/* Create raw data and save it in buffer. Calculate the delta for each
|
||||
* counter between this invocation and the last invocation.
|
||||
* Returns number of bytes copied.
|
||||
* After reading from PAI counter page, save the read value to the old
|
||||
* page to calculate PAI counter deltas.
|
||||
* Saves only entries with positive counter difference of the form
|
||||
* 2 bytes: Number of counter
|
||||
* 8 bytes: Value of counter
|
||||
|
|
@ -562,16 +571,22 @@ static size_t pai_copy(struct pai_userdata *userdata, unsigned long *page,
|
|||
int i, outidx = 0;
|
||||
|
||||
for (i = 1; i <= pp->num_avail; i++) {
|
||||
u64 val = 0, val_old = 0;
|
||||
u64 val = 0, val_old = 0, val_k = 0, val_old_k = 0;
|
||||
|
||||
if (!exclude_kernel) {
|
||||
val += pai_getctr(page, i, pp->kernel_offset);
|
||||
val_old += pai_getctr(page_old, i, pp->kernel_offset);
|
||||
val_k = pai_getctr(page, i, pp->kernel_offset);
|
||||
val_old_k = pai_getctr(page_old, i, pp->kernel_offset);
|
||||
if (val_k != val_old_k)
|
||||
pai_setctr(page_old, i, pp->kernel_offset, val_k);
|
||||
}
|
||||
if (!exclude_user) {
|
||||
val += pai_getctr(page, i, 0);
|
||||
val_old += pai_getctr(page_old, i, 0);
|
||||
val = pai_getctr(page, i, 0);
|
||||
val_old = pai_getctr(page_old, i, 0);
|
||||
if (val != val_old)
|
||||
pai_setctr(page_old, i, 0, val);
|
||||
}
|
||||
val += val_k;
|
||||
val_old += val_old_k;
|
||||
if (val >= val_old)
|
||||
val -= val_old;
|
||||
else
|
||||
|
|
@ -602,8 +617,6 @@ static size_t pai_copy(struct pai_userdata *userdata, unsigned long *page,
|
|||
static int pai_push_sample(size_t rawsize, struct pai_map *cpump,
|
||||
struct perf_event *event)
|
||||
{
|
||||
int idx = PAI_PMU_IDX(event);
|
||||
struct pai_pmu *pp = &pai_pmu[idx];
|
||||
struct perf_sample_data data;
|
||||
struct perf_raw_record raw;
|
||||
struct pt_regs regs;
|
||||
|
|
@ -634,8 +647,6 @@ static int pai_push_sample(size_t rawsize, struct pai_map *cpump,
|
|||
|
||||
overflow = perf_event_overflow(event, &data, ®s);
|
||||
perf_event_update_userpage(event);
|
||||
/* Save crypto counter lowcore page after reading event data. */
|
||||
memcpy((void *)PAI_SAVE_AREA(event), cpump->area, pp->area_size);
|
||||
return overflow;
|
||||
}
|
||||
|
||||
|
|
@ -651,7 +662,7 @@ static void pai_have_sample(struct perf_event *event, struct pai_map *cpump)
|
|||
rawsize = pai_copy(cpump->save, cpump->area, pp,
|
||||
(unsigned long *)PAI_SAVE_AREA(event),
|
||||
event->attr.exclude_user,
|
||||
event->attr.exclude_kernel);
|
||||
!pp->kernel_offset ? true : event->attr.exclude_kernel);
|
||||
if (rawsize) /* No incremented counters */
|
||||
pai_push_sample(rawsize, cpump, event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,17 +192,21 @@ static void tl_to_masks(struct sysinfo_15_1_x *info)
|
|||
end = (union topology_entry *)((unsigned long)info + info->length);
|
||||
while (tle < end) {
|
||||
switch (tle->nl) {
|
||||
/*
|
||||
* Adjust drawer_id, book_id, and socked_id so they match the
|
||||
* numbering scheme of e.g. the hardware management console.
|
||||
*/
|
||||
case 3:
|
||||
drawer = drawer->next;
|
||||
drawer->id = tle->container.id;
|
||||
drawer->id = tle->container.id - 1;
|
||||
break;
|
||||
case 2:
|
||||
book = book->next;
|
||||
book->id = tle->container.id;
|
||||
book->id = tle->container.id - 1;
|
||||
break;
|
||||
case 1:
|
||||
socket = socket->next;
|
||||
socket->id = tle->container.id;
|
||||
socket->id = tle->container.id - 1;
|
||||
break;
|
||||
case 0:
|
||||
add_cpus_to_mask(&tle->cpu, drawer, book, socket);
|
||||
|
|
|
|||
|
|
@ -1142,8 +1142,8 @@ int __init chsc_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
sei_page = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
chsc_page = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
chsc_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!sei_page || !chsc_page) {
|
||||
ret = -ENOMEM;
|
||||
goto out_err;
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ static int chsc_ioctl_start(void __user *user_area)
|
|||
if (!css_general_characteristics.dynio)
|
||||
/* It makes no sense to try. */
|
||||
return -EOPNOTSUPP;
|
||||
chsc_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
chsc_area = (void *)get_zeroed_page(GFP_DMA | GFP_KERNEL);
|
||||
if (!chsc_area)
|
||||
return -ENOMEM;
|
||||
request = kzalloc_obj(*request);
|
||||
|
|
@ -340,7 +340,7 @@ static int chsc_ioctl_on_close_set(void __user *user_area)
|
|||
ret = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
on_close_chsc_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
on_close_chsc_area = (void *)get_zeroed_page(GFP_DMA | GFP_KERNEL);
|
||||
if (!on_close_chsc_area) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free_request;
|
||||
|
|
@ -392,7 +392,7 @@ static int chsc_ioctl_start_sync(void __user *user_area)
|
|||
struct chsc_sync_area *chsc_area;
|
||||
int ret, ccode;
|
||||
|
||||
chsc_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
chsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!chsc_area)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(chsc_area, user_area, PAGE_SIZE)) {
|
||||
|
|
@ -438,7 +438,7 @@ static int chsc_ioctl_info_channel_path(void __user *user_cd)
|
|||
u8 data[PAGE_SIZE - 20];
|
||||
} __attribute__ ((packed)) *scpcd_area;
|
||||
|
||||
scpcd_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
scpcd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!scpcd_area)
|
||||
return -ENOMEM;
|
||||
cd = kzalloc_obj(*cd);
|
||||
|
|
@ -500,7 +500,7 @@ static int chsc_ioctl_info_cu(void __user *user_cd)
|
|||
u8 data[PAGE_SIZE - 20];
|
||||
} __attribute__ ((packed)) *scucd_area;
|
||||
|
||||
scucd_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
scucd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!scucd_area)
|
||||
return -ENOMEM;
|
||||
cd = kzalloc_obj(*cd);
|
||||
|
|
@ -563,7 +563,7 @@ static int chsc_ioctl_info_sch_cu(void __user *user_cud)
|
|||
u8 data[PAGE_SIZE - 20];
|
||||
} __attribute__ ((packed)) *sscud_area;
|
||||
|
||||
sscud_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
sscud_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!sscud_area)
|
||||
return -ENOMEM;
|
||||
cud = kzalloc_obj(*cud);
|
||||
|
|
@ -625,7 +625,7 @@ static int chsc_ioctl_conf_info(void __user *user_ci)
|
|||
u8 data[PAGE_SIZE - 20];
|
||||
} __attribute__ ((packed)) *sci_area;
|
||||
|
||||
sci_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
sci_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!sci_area)
|
||||
return -ENOMEM;
|
||||
ci = kzalloc_obj(*ci);
|
||||
|
|
@ -696,7 +696,7 @@ static int chsc_ioctl_conf_comp_list(void __user *user_ccl)
|
|||
u32 res;
|
||||
} __attribute__ ((packed)) *cssids_parm;
|
||||
|
||||
sccl_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
sccl_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!sccl_area)
|
||||
return -ENOMEM;
|
||||
ccl = kzalloc_obj(*ccl);
|
||||
|
|
@ -756,7 +756,7 @@ static int chsc_ioctl_chpd(void __user *user_chpd)
|
|||
int ret;
|
||||
|
||||
chpd = kzalloc_obj(*chpd);
|
||||
scpd_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!scpd_area || !chpd) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free;
|
||||
|
|
@ -796,7 +796,7 @@ static int chsc_ioctl_dcal(void __user *user_dcal)
|
|||
u8 data[PAGE_SIZE - 36];
|
||||
} __attribute__ ((packed)) *sdcal_area;
|
||||
|
||||
sdcal_area = (void *)get_zeroed_page(GFP_KERNEL);
|
||||
sdcal_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!sdcal_area)
|
||||
return -ENOMEM;
|
||||
dcal = kzalloc_obj(*dcal);
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ int scm_update_information(void)
|
|||
size_t num;
|
||||
int ret;
|
||||
|
||||
scm_info = (void *)__get_free_page(GFP_KERNEL);
|
||||
scm_info = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!scm_info)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user