SCM_READ/WRITE_MEATADATA hcall supports multibyte read/write. This patch
updates the metadata read/write to use 1, 2, 4 or 8 byte read/write as
mentioned in PAPR document.
READ/WRITE_METADATA hcall supports the 1, 2, 4, or 8 bytes read/write.
For other values hcall results H_P3.
Hypervisor stores the metadata contents in big-endian format and in-order
to enable read/write in different granularity, we need to switch the contents
to big-endian before calling HCALL.
Based on an patch from Oliver O'Halloran [off-list ref]
Signed-off-by: Aneesh Kumar K.V <redacted>
---
arch/powerpc/platforms/pseries/papr_scm.c | 104 +++++++++++++++++-----
1 file changed, 82 insertions(+), 22 deletions(-)
@@ -97,42 +97,102 @@ static int drc_pmem_unbind(struct papr_scm_priv *p)}staticintpapr_scm_meta_get(structpapr_scm_priv*p,-structnd_cmd_get_config_data_hdr*hdr)+structnd_cmd_get_config_data_hdr*hdr){unsignedlongdata[PLPAR_HCALL_BUFSIZE];+unsignedlongoffset,data_offset;+intlen,read;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,-hdr->in_offset,1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */--hdr->out_buf[0]=data[0]&0xff;-+for(len=hdr->in_length;len;len-=read){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8)+read=8;+elseif(len>=4)+read=4;+elseif(len>=2)+read=2;+else+read=1;++ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,+offset,read);++if(ret==H_PARAMETER)/* bad DRC index */+return-ENODEV;+if(ret)+return-EINVAL;/* other invalid parameter */++switch(read){+case8:+*(uint64_t*)(hdr->out_buf+data_offset)=be64_to_cpu(data[0]);+break;+case4:+*(uint32_t*)(hdr->out_buf+data_offset)=be32_to_cpu(data[0]&0xffffffff);+break;++case2:+*(uint16_t*)(hdr->out_buf+data_offset)=be16_to_cpu(data[0]&0xffff);+break;++case1:+*(uint32_t*)(hdr->out_buf+data_offset)=(data[0]&0xff);+break;+}+}return0;}staticintpapr_scm_meta_set(structpapr_scm_priv*p,-structnd_cmd_set_config_hdr*hdr)+structnd_cmd_set_config_hdr*hdr){+unsignedlongoffset,data_offset;+intlen,wrote;+unsignedlongdata;+__be64data_be;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall_norets(H_SCM_WRITE_METADATA,-p->drc_index,hdr->in_offset,hdr->in_buf[0],1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */+for(len=hdr->in_length;len;len-=wrote){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8){+data=*(uint64_t*)(hdr->in_buf+data_offset);+data_be=cpu_to_be64(data);+wrote=8;+}elseif(len>=4){+data=*(uint32_t*)(hdr->in_buf+data_offset);+data&=0xffffffff;+data_be=cpu_to_be32(data);+wrote=4;+}elseif(len>=2){+data=*(uint16_t*)(hdr->in_buf+data_offset);+data&=0xffff;+data_be=cpu_to_be16(data);+wrote=2;+}else{+data_be=*(uint8_t*)(hdr->in_buf+data_offset);+data_be&=0xff;+wrote=1;+}++ret=plpar_hcall_norets(H_SCM_WRITE_METADATA,p->drc_index,+offset,data_be,wrote);+if(ret==H_PARAMETER)/* bad DRC index */+return-ENODEV;+if(ret)+return-EINVAL;/* other invalid parameter */+}return0;}
From: Oliver <oohall@gmail.com> Date: 2019-06-03 00:26:58
On Sun, Jun 2, 2019 at 2:44 PM Aneesh Kumar K.V
[off-list ref] wrote:
SCM_READ/WRITE_MEATADATA hcall supports multibyte read/write. This patch
updates the metadata read/write to use 1, 2, 4 or 8 byte read/write as
mentioned in PAPR document.
READ/WRITE_METADATA hcall supports the 1, 2, 4, or 8 bytes read/write.
For other values hcall results H_P3.
You should probably fold the second paragraph here into the first.
quoted hunk
Hypervisor stores the metadata contents in big-endian format and in-order
to enable read/write in different granularity, we need to switch the contents
to big-endian before calling HCALL.
Based on an patch from Oliver O'Halloran [off-list ref]
Signed-off-by: Aneesh Kumar K.V <redacted>
---
arch/powerpc/platforms/pseries/papr_scm.c | 104 +++++++++++++++++-----
1 file changed, 82 insertions(+), 22 deletions(-)
@@ -97,42 +97,102 @@ static int drc_pmem_unbind(struct papr_scm_priv *p)}staticintpapr_scm_meta_get(structpapr_scm_priv*p,-structnd_cmd_get_config_data_hdr*hdr)+structnd_cmd_get_config_data_hdr*hdr){unsignedlongdata[PLPAR_HCALL_BUFSIZE];+unsignedlongoffset,data_offset;+intlen,read;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,-hdr->in_offset,1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */--hdr->out_buf[0]=data[0]&0xff;-+for(len=hdr->in_length;len;len-=read){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8)+read=8;+elseif(len>=4)+read=4;+elseif(len>=2)+read=2;+else+read=1;++ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,+offset,read);++if(ret==H_PARAMETER)/* bad DRC index */+return-ENODEV;+if(ret)+return-EINVAL;/* other invalid parameter */++switch(read){+case8:+*(uint64_t*)(hdr->out_buf+data_offset)=be64_to_cpu(data[0]);+break;+case4:+*(uint32_t*)(hdr->out_buf+data_offset)=be32_to_cpu(data[0]&0xffffffff);+break;++case2:+*(uint16_t*)(hdr->out_buf+data_offset)=be16_to_cpu(data[0]&0xffff);+break;++case1:+*(uint32_t*)(hdr->out_buf+data_offset)=(data[0]&0xff);+break;+}+}return0;}staticintpapr_scm_meta_set(structpapr_scm_priv*p,-structnd_cmd_set_config_hdr*hdr)+structnd_cmd_set_config_hdr*hdr){+unsignedlongoffset,data_offset;+intlen,wrote;+unsignedlongdata;+__be64data_be;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall_norets(H_SCM_WRITE_METADATA,-p->drc_index,hdr->in_offset,hdr->in_buf[0],1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */+for(len=hdr->in_length;len;len-=wrote){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8){+data=*(uint64_t*)(hdr->in_buf+data_offset);+data_be=cpu_to_be64(data);+wrote=8;+}elseif(len>=4){+data=*(uint32_t*)(hdr->in_buf+data_offset);+data&=0xffffffff;+data_be=cpu_to_be32(data);+wrote=4;+}elseif(len>=2){+data=*(uint16_t*)(hdr->in_buf+data_offset);+data&=0xffff;+data_be=cpu_to_be16(data);+wrote=2;+}else{+data_be=*(uint8_t*)(hdr->in_buf+data_offset);+data_be&=0xff;+wrote=1;+}++ret=plpar_hcall_norets(H_SCM_WRITE_METADATA,p->drc_index,+offset,data_be,wrote);+if(ret==H_PARAMETER)/* bad DRC index */+return-ENODEV;+if(ret)+return-EINVAL;/* other invalid parameter */+}return0;}
On Sun, Jun 2, 2019 at 2:44 PM Aneesh Kumar K.V
[off-list ref] wrote:
quoted
SCM_READ/WRITE_MEATADATA hcall supports multibyte read/write. This patch
updates the metadata read/write to use 1, 2, 4 or 8 byte read/write as
mentioned in PAPR document.
READ/WRITE_METADATA hcall supports the 1, 2, 4, or 8 bytes read/write.
For other values hcall results H_P3.
You should probably fold the second paragraph here into the first.
quoted
Hypervisor stores the metadata contents in big-endian format and in-order
to enable read/write in different granularity, we need to switch the contents
to big-endian before calling HCALL.
Based on an patch from Oliver O'Halloran [off-list ref]
Signed-off-by: Aneesh Kumar K.V <redacted>
---
arch/powerpc/platforms/pseries/papr_scm.c | 104 +++++++++++++++++-----
1 file changed, 82 insertions(+), 22 deletions(-)
@@ -97,42 +97,102 @@ static int drc_pmem_unbind(struct papr_scm_priv *p)}staticintpapr_scm_meta_get(structpapr_scm_priv*p,-structnd_cmd_get_config_data_hdr*hdr)+structnd_cmd_get_config_data_hdr*hdr){unsignedlongdata[PLPAR_HCALL_BUFSIZE];+unsignedlongoffset,data_offset;+intlen,read;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,-hdr->in_offset,1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */--hdr->out_buf[0]=data[0]&0xff;-+for(len=hdr->in_length;len;len-=read){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8)+read=8;+elseif(len>=4)+read=4;+elseif(len>=2)+read=2;+else+read=1;++ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,+offset,read);++if(ret==H_PARAMETER)/* bad DRC index */+return-ENODEV;+if(ret)+return-EINVAL;/* other invalid parameter */++switch(read){+case8:+*(uint64_t*)(hdr->out_buf+data_offset)=be64_to_cpu(data[0]);+break;+case4:+*(uint32_t*)(hdr->out_buf+data_offset)=be32_to_cpu(data[0]&0xffffffff);+break;++case2:+*(uint16_t*)(hdr->out_buf+data_offset)=be16_to_cpu(data[0]&0xffff);+break;++case1:+*(uint32_t*)(hdr->out_buf+data_offset)=(data[0]&0xff);+break;+}+}return0;}staticintpapr_scm_meta_set(structpapr_scm_priv*p,-structnd_cmd_set_config_hdr*hdr)+structnd_cmd_set_config_hdr*hdr){+unsignedlongoffset,data_offset;+intlen,wrote;+unsignedlongdata;+__be64data_be;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall_norets(H_SCM_WRITE_METADATA,-p->drc_index,hdr->in_offset,hdr->in_buf[0],1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */+for(len=hdr->in_length;len;len-=wrote){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8){+data=*(uint64_t*)(hdr->in_buf+data_offset);+data_be=cpu_to_be64(data);+wrote=8;+}elseif(len>=4){+data=*(uint32_t*)(hdr->in_buf+data_offset);+data&=0xffffffff;+data_be=cpu_to_be32(data);+wrote=4;+}elseif(len>=2){+data=*(uint16_t*)(hdr->in_buf+data_offset);+data&=0xffff;+data_be=cpu_to_be16(data);+wrote=2;+}else{+data_be=*(uint8_t*)(hdr->in_buf+data_offset);+data_be&=0xff;+wrote=1;+}++ret=plpar_hcall_norets(H_SCM_WRITE_METADATA,p->drc_index,+offset,data_be,wrote);+if(ret==H_PARAMETER)/* bad DRC index */+return-ENODEV;+if(ret)+return-EINVAL;/* other invalid parameter */+}return0;}
SCM_READ/WRITE_MEATADATA hcall supports multibyte read/write. This patch
updates the metadata read/write to use 1, 2, 4 or 8 byte read/write as
mentioned in PAPR document.
READ/WRITE_METADATA hcall supports the 1, 2, 4, or 8 bytes read/write.
For other values hcall results H_P3.
Hypervisor stores the metadata contents in big-endian format and in-order
to enable read/write in different granularity, we need to switch the contents
to big-endian before calling HCALL.
Based on an patch from Oliver O'Halloran [off-list ref]
Signed-off-by: Aneesh Kumar K.V <redacted>
---
arch/powerpc/platforms/pseries/papr_scm.c | 104 +++++++++++++++++-----
1 file changed, 82 insertions(+), 22 deletions(-)
@@ -97,42 +97,102 @@ static int drc_pmem_unbind(struct papr_scm_priv *p)}staticintpapr_scm_meta_get(structpapr_scm_priv*p,-structnd_cmd_get_config_data_hdr*hdr)+structnd_cmd_get_config_data_hdr*hdr){unsignedlongdata[PLPAR_HCALL_BUFSIZE];+unsignedlongoffset,data_offset;+intlen,read;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,-hdr->in_offset,1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */--hdr->out_buf[0]=data[0]&0xff;-+for(len=hdr->in_length;len;len-=read){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8)+read=8;+elseif(len>=4)+read=4;+elseif(len>=2)
@@ -97,42 +97,102 @@ static int drc_pmem_unbind(struct papr_scm_priv *p)}staticintpapr_scm_meta_get(structpapr_scm_priv*p,-structnd_cmd_get_config_data_hdr*hdr)+structnd_cmd_get_config_data_hdr*hdr){unsignedlongdata[PLPAR_HCALL_BUFSIZE];+unsignedlongoffset,data_offset;+intlen,read;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,-hdr->in_offset,1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */--hdr->out_buf[0]=data[0]&0xff;-+for(len=hdr->in_length;len;len-=read){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8)+read=8;+elseif(len>=4)+read=4;+elseif(len>=2)+read=2;+else+read=1;++ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,+offset,read);++if(ret==H_PARAMETER)/* bad DRC index */+return-ENODEV;+if(ret)+return-EINVAL;/* other invalid parameter */++switch(read){+case8:+*(uint64_t*)(hdr->out_buf+data_offset)=be64_to_cpu(data[0]);+break;+case4:+*(uint32_t*)(hdr->out_buf+data_offset)=be32_to_cpu(data[0]&0xffffffff);+break;
...
quoted
I assume you got the qemu bits sorted out with Shiva? Looks good otherwise.
That is correct. I also tested with different xfer values (1, 2, 4, 8)
on both Qemu and PowerVM.
SCM_READ/WRITE_MEATADATA hcall supports multibyte read/write. This patch
updates the metadata read/write to use 1, 2, 4 or 8 byte read/write as
mentioned in PAPR document.
READ/WRITE_METADATA hcall supports the 1, 2, 4, or 8 bytes read/write.
For other values hcall results H_P3.
Hypervisor stores the metadata contents in big-endian format and in-order
to enable read/write in different granularity, we need to switch the contents
to big-endian before calling HCALL.
Based on an patch from Oliver O'Halloran [off-list ref]
Signed-off-by: Aneesh Kumar K.V <redacted>
---
arch/powerpc/platforms/pseries/papr_scm.c | 104 +++++++++++++++++-----
1 file changed, 82 insertions(+), 22 deletions(-)
@@ -97,42 +97,102 @@ static int drc_pmem_unbind(struct papr_scm_priv *p)}staticintpapr_scm_meta_get(structpapr_scm_priv*p,-structnd_cmd_get_config_data_hdr*hdr)+structnd_cmd_get_config_data_hdr*hdr){unsignedlongdata[PLPAR_HCALL_BUFSIZE];+unsignedlongoffset,data_offset;+intlen,read;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,-hdr->in_offset,1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */--hdr->out_buf[0]=data[0]&0xff;-+for(len=hdr->in_length;len;len-=read){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8)+read=8;+elseif(len>=4)+read=4;+elseif(len>=2)
@@ -97,42 +97,102 @@ static int drc_pmem_unbind(struct papr_scm_priv *p)}staticintpapr_scm_meta_get(structpapr_scm_priv*p,-structnd_cmd_get_config_data_hdr*hdr)+structnd_cmd_get_config_data_hdr*hdr){unsignedlongdata[PLPAR_HCALL_BUFSIZE];+unsignedlongoffset,data_offset;+intlen,read;int64_tret;-if(hdr->in_offset>=p->metadata_size||hdr->in_length!=1)+if((hdr->in_offset+hdr->in_length)>=p->metadata_size)return-EINVAL;-ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,-hdr->in_offset,1);--if(ret==H_PARAMETER)/* bad DRC index */-return-ENODEV;-if(ret)-return-EINVAL;/* other invalid parameter */--hdr->out_buf[0]=data[0]&0xff;-+for(len=hdr->in_length;len;len-=read){++data_offset=hdr->in_length-len;+offset=hdr->in_offset+data_offset;++if(len>=8)+read=8;+elseif(len>=4)+read=4;+elseif(len>=2)+read=2;+else+read=1;++ret=plpar_hcall(H_SCM_READ_METADATA,data,p->drc_index,+offset,read);++if(ret==H_PARAMETER)/* bad DRC index */+return-ENODEV;+if(ret)+return-EINVAL;/* other invalid parameter */++switch(read){+case8:+*(uint64_t*)(hdr->out_buf+data_offset)=be64_to_cpu(data[0]);+break;+case4:+*(uint32_t*)(hdr->out_buf+data_offset)=be32_to_cpu(data[0]&0xffffffff);+break;
...
quoted
quoted
I assume you got the qemu bits sorted out with Shiva? Looks good otherwise.
That is correct. I also tested with different xfer values (1, 2, 4, 8)
on both Qemu and PowerVM.
With a big endian kernel?
I completed this testing and found new bugs in other parts of the code.
Thanks for the sugestion.
-aneesh